mirror of
https://github.com/armbian/build.git
synced 2026-01-06 09:58:46 -08:00
uefi-x86-6.19: copy patches from 6.18
This commit is contained in:
5864
patch/kernel/archive/uefi-x86-6.19/1001-Add-apple-bce-driver.patch
Normal file
5864
patch/kernel/archive/uefi-x86-6.19/1001-Add-apple-bce-driver.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,77 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Redecorating <69827514+Redecorating@users.noreply.github.com>
|
||||
Date: Mon, 7 Nov 2022 14:56:34 +0530
|
||||
Subject: Put apple-bce in drivers/staging
|
||||
|
||||
- rpardini: 6.12: in drivers/staging/Makefile do it at the top to avoid
|
||||
conflicts with Armbian's (wifi?) patching.
|
||||
|
||||
Signed-off-by: Ricardo Pardini <ricardo@pardini.net>
|
||||
---
|
||||
drivers/staging/Kconfig | 2 ++
|
||||
drivers/staging/Makefile | 1 +
|
||||
drivers/staging/apple-bce/Kconfig | 18 ++++++++++
|
||||
drivers/staging/apple-bce/Makefile | 2 +-
|
||||
4 files changed, 22 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/staging/Kconfig
|
||||
+++ b/drivers/staging/Kconfig
|
||||
@@ -52,4 +52,6 @@ source "drivers/staging/gpib/Kconfig"
|
||||
|
||||
source "drivers/staging/rtl8723cs/Kconfig"
|
||||
|
||||
+source "drivers/staging/apple-bce/Kconfig"
|
||||
+
|
||||
endif # STAGING
|
||||
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/staging/Makefile
|
||||
+++ b/drivers/staging/Makefile
|
||||
@@ -2,6 +2,7 @@
|
||||
# Makefile for staging directory
|
||||
|
||||
obj-y += media/
|
||||
+obj-$(CONFIG_APPLE_BCE) += apple-bce/
|
||||
obj-$(CONFIG_RTL8723BS) += rtl8723bs/
|
||||
obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
|
||||
obj-$(CONFIG_VME_BUS) += vme_user/
|
||||
diff --git a/drivers/staging/apple-bce/Kconfig b/drivers/staging/apple-bce/Kconfig
|
||||
new file mode 100644
|
||||
index 000000000000..111111111111
|
||||
--- /dev/null
|
||||
+++ b/drivers/staging/apple-bce/Kconfig
|
||||
@@ -0,0 +1,18 @@
|
||||
+config APPLE_BCE
|
||||
+ tristate "Apple BCE driver (VHCI and Audio support)"
|
||||
+ default m
|
||||
+ depends on X86
|
||||
+ select SOUND
|
||||
+ select SND
|
||||
+ select SND_PCM
|
||||
+ select SND_JACK
|
||||
+ help
|
||||
+ VHCI and audio support on Apple MacBooks with the T2 Chip.
|
||||
+ This driver is divided in three components:
|
||||
+ - BCE (Buffer Copy Engine): which establishes a basic communication
|
||||
+ channel with the T2 chip. This component is required by the other two:
|
||||
+ - VHCI (Virtual Host Controller Interface): Access to keyboard, mouse
|
||||
+ and other system devices depend on this virtual USB host controller
|
||||
+ - Audio: a driver for the T2 audio interface.
|
||||
+
|
||||
+ If "M" is selected, the module will be called apple-bce.'
|
||||
diff --git a/drivers/staging/apple-bce/Makefile b/drivers/staging/apple-bce/Makefile
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/staging/apple-bce/Makefile
|
||||
+++ b/drivers/staging/apple-bce/Makefile
|
||||
@@ -1,5 +1,5 @@
|
||||
modname := apple-bce
|
||||
-obj-m += $(modname).o
|
||||
+obj-$(CONFIG_APPLE_BCE) += $(modname).o
|
||||
|
||||
apple-bce-objs := apple_bce.o mailbox.o queue.o queue_dma.o vhci/vhci.o vhci/queue.o vhci/transfer.o audio/audio.o audio/protocol.o audio/protocol_bce.o audio/pcm.o
|
||||
|
||||
--
|
||||
Armbian
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: mnural <mehmet.nrl@hotmail.com>
|
||||
Date: Mon, 14 Apr 2025 14:44:20 +0530
|
||||
Subject: Fix freezing on turning off camera
|
||||
|
||||
Detailed logs and reason behind can be seen here:
|
||||
https://github.com/t2linux/T2-Debian-and-Ubuntu-Kernel/issues/130#issuecomment-2799130835
|
||||
---
|
||||
drivers/staging/apple-bce/vhci/transfer.c | 16 ++++++++--
|
||||
drivers/staging/apple-bce/vhci/transfer.h | 4 ++-
|
||||
2 files changed, 17 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/apple-bce/vhci/transfer.c b/drivers/staging/apple-bce/vhci/transfer.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/staging/apple-bce/vhci/transfer.c
|
||||
+++ b/drivers/staging/apple-bce/vhci/transfer.c
|
||||
@@ -400,6 +400,7 @@ int bce_vhci_urb_request_cancel(struct bce_vhci_transfer_queue *q, struct urb *u
|
||||
struct bce_vhci_urb *vurb;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
+ enum bce_vhci_urb_state old_state;
|
||||
|
||||
spin_lock_irqsave(&q->urb_lock, flags);
|
||||
if ((ret = usb_hcd_check_unlink_urb(q->vhci->hcd, urb, status))) {
|
||||
@@ -408,8 +409,19 @@ int bce_vhci_urb_request_cancel(struct bce_vhci_transfer_queue *q, struct urb *u
|
||||
}
|
||||
|
||||
vurb = urb->hcpriv;
|
||||
+
|
||||
+ old_state = vurb->state; /* save old state to use later because we'll set state as cancelled */
|
||||
+
|
||||
+ if (old_state == BCE_VHCI_URB_CANCELLED) {
|
||||
+ spin_unlock_irqrestore(&q->urb_lock, flags);
|
||||
+ pr_debug("bce-vhci: URB %p is already cancelled, skipping\n", urb);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ vurb->state = BCE_VHCI_URB_CANCELLED;
|
||||
+
|
||||
/* If the URB wasn't posted to the device yet, we can still remove it on the host without pausing the queue. */
|
||||
- if (vurb->state != BCE_VHCI_URB_INIT_PENDING) {
|
||||
+ if (old_state != BCE_VHCI_URB_INIT_PENDING) {
|
||||
pr_debug("bce-vhci: [%02x] Cancelling URB\n", q->endp_addr);
|
||||
|
||||
spin_unlock_irqrestore(&q->urb_lock, flags);
|
||||
@@ -425,7 +437,7 @@ int bce_vhci_urb_request_cancel(struct bce_vhci_transfer_queue *q, struct urb *u
|
||||
|
||||
usb_hcd_giveback_urb(q->vhci->hcd, urb, status);
|
||||
|
||||
- if (vurb->state != BCE_VHCI_URB_INIT_PENDING)
|
||||
+ if (old_state != BCE_VHCI_URB_INIT_PENDING)
|
||||
bce_vhci_transfer_queue_resume(q, BCE_VHCI_PAUSE_INTERNAL_WQ);
|
||||
|
||||
kfree(vurb);
|
||||
diff --git a/drivers/staging/apple-bce/vhci/transfer.h b/drivers/staging/apple-bce/vhci/transfer.h
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/staging/apple-bce/vhci/transfer.h
|
||||
+++ b/drivers/staging/apple-bce/vhci/transfer.h
|
||||
@@ -44,7 +44,9 @@ enum bce_vhci_urb_state {
|
||||
|
||||
BCE_VHCI_URB_CONTROL_WAITING_FOR_SETUP_REQUEST,
|
||||
BCE_VHCI_URB_CONTROL_WAITING_FOR_SETUP_COMPLETION,
|
||||
- BCE_VHCI_URB_CONTROL_COMPLETE
|
||||
+ BCE_VHCI_URB_CONTROL_COMPLETE,
|
||||
+
|
||||
+ BCE_VHCI_URB_CANCELLED
|
||||
};
|
||||
struct bce_vhci_urb {
|
||||
struct urb *urb;
|
||||
--
|
||||
Armbian
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Orlando Chamberlain <orlandoch.dev@gmail.com>
|
||||
Date: Fri, 28 Jun 2024 04:43:50 +0000
|
||||
Subject: i915: 4 lane quirk for mbp15,1
|
||||
|
||||
Needed to use iGPU when dGPU was boot GPU
|
||||
|
||||
Patch written by Kerem Karabay <kekrby@gmail.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/display/intel_ddi.c | 3 ++
|
||||
drivers/gpu/drm/i915/display/intel_quirks.c | 15 ++++++++++
|
||||
drivers/gpu/drm/i915/display/intel_quirks.h | 1 +
|
||||
3 files changed, 19 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
|
||||
@@ -4868,6 +4868,9 @@ static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port)
|
||||
if (dig_port->ddi_a_4_lanes)
|
||||
return false;
|
||||
|
||||
+ if (intel_has_quirk(display, QUIRK_DDI_A_FORCE_4_LANES))
|
||||
+ return true;
|
||||
+
|
||||
/* Broxton/Geminilake: Bspec says that DDI_A_4_LANES is the only
|
||||
* supported configuration
|
||||
*/
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_quirks.c
|
||||
@@ -66,6 +66,18 @@ static void quirk_increase_ddi_disabled_time(struct intel_display *display)
|
||||
drm_info(display->drm, "Applying Increase DDI Disabled quirk\n");
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * In some cases, the firmware might not set the lane count to 4 (for example,
|
||||
+ * when booting in some dual GPU Macs with the dGPU as the default GPU), this
|
||||
+ * quirk is used to force it as otherwise it might not be possible to compute a
|
||||
+ * valid link configuration.
|
||||
+ */
|
||||
+static void quirk_ddi_a_force_4_lanes(struct intel_display *display)
|
||||
+{
|
||||
+ intel_set_quirk(display, QUIRK_DDI_A_FORCE_4_LANES);
|
||||
+ drm_info(display->drm, "Applying DDI A Forced 4 Lanes quirk\n");
|
||||
+}
|
||||
+
|
||||
static void quirk_no_pps_backlight_power_hook(struct intel_display *display)
|
||||
{
|
||||
intel_set_quirk(display, QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK);
|
||||
@@ -240,6 +252,9 @@ static struct intel_quirk intel_quirks[] = {
|
||||
|
||||
/* Dell XPS 13 7390 2-in-1 */
|
||||
{ 0x8a12, 0x1028, 0x08b0, quirk_edp_limit_rate_hbr2 },
|
||||
+
|
||||
+ /* Apple MacBookPro15,1 */
|
||||
+ { 0x3e9b, 0x106b, 0x0176, quirk_ddi_a_force_4_lanes },
|
||||
};
|
||||
|
||||
static const struct intel_dpcd_quirk intel_dpcd_quirks[] = {
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_quirks.h b/drivers/gpu/drm/i915/display/intel_quirks.h
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/gpu/drm/i915/display/intel_quirks.h
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_quirks.h
|
||||
@@ -21,6 +21,7 @@ enum intel_quirk_id {
|
||||
QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK,
|
||||
QUIRK_FW_SYNC_LEN,
|
||||
QUIRK_EDP_LIMIT_RATE_HBR2,
|
||||
+ QUIRK_DDI_A_FORCE_4_LANES,
|
||||
};
|
||||
|
||||
void intel_init_quirks(struct intel_display *display);
|
||||
--
|
||||
Armbian
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Orlando Chamberlain <orlandoch.dev@gmail.com>
|
||||
Date: Fri, 10 Feb 2023 22:45:00 +1100
|
||||
Subject: apple-gmux: allow switching to igpu at probe
|
||||
|
||||
This means user don't need to set the gpu-power-prefs efivar to use the
|
||||
igpu while runtime switching isn't working, so macOS will be unaffected.
|
||||
|
||||
This isn't really upstreamable, what we want upstream is the ability to
|
||||
switch at runtime (so both gpus need to be able to probe the eDP panel).
|
||||
|
||||
Based off of work by Kerem Karabay <kekrby@gmail.com>
|
||||
---
|
||||
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 ++
|
||||
drivers/gpu/vga/vga_switcheroo.c | 7 +---
|
||||
drivers/pci/vgaarb.c | 1 +
|
||||
drivers/platform/x86/apple-gmux.c | 18 ++++++++++
|
||||
4 files changed, 23 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
|
||||
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
|
||||
@@ -2322,6 +2322,9 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
|
||||
int ret, retry = 0, i;
|
||||
bool supports_atomic = false;
|
||||
|
||||
+ if (vga_switcheroo_client_probe_defer(pdev))
|
||||
+ return -EPROBE_DEFER;
|
||||
+
|
||||
if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA ||
|
||||
(pdev->class >> 8) == PCI_CLASS_DISPLAY_OTHER) {
|
||||
if (drm_firmware_drivers_only() && amdgpu_modeset == -1)
|
||||
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/gpu/vga/vga_switcheroo.c
|
||||
+++ b/drivers/gpu/vga/vga_switcheroo.c
|
||||
@@ -438,12 +438,7 @@ find_active_client(struct list_head *head)
|
||||
bool vga_switcheroo_client_probe_defer(struct pci_dev *pdev)
|
||||
{
|
||||
if (pci_is_display(pdev)) {
|
||||
- /*
|
||||
- * apple-gmux is needed on pre-retina MacBook Pro
|
||||
- * to probe the panel if pdev is the inactive GPU.
|
||||
- */
|
||||
- if (apple_gmux_present() && pdev != vga_default_device() &&
|
||||
- !vgasr_priv.handler_flags)
|
||||
+ if (apple_gmux_present() && !vgasr_priv.handler_flags)
|
||||
return true;
|
||||
}
|
||||
|
||||
diff --git a/drivers/pci/vgaarb.c b/drivers/pci/vgaarb.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/pci/vgaarb.c
|
||||
+++ b/drivers/pci/vgaarb.c
|
||||
@@ -143,6 +143,7 @@ void vga_set_default_device(struct pci_dev *pdev)
|
||||
pci_dev_put(vga_default);
|
||||
vga_default = pci_dev_get(pdev);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(vga_set_default_device);
|
||||
|
||||
/**
|
||||
* vga_remove_vgacon - deactivate VGA console
|
||||
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/platform/x86/apple-gmux.c
|
||||
+++ b/drivers/platform/x86/apple-gmux.c
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/vga_switcheroo.h>
|
||||
+#include <linux/vgaarb.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <acpi/video.h>
|
||||
#include <asm/io.h>
|
||||
@@ -107,6 +108,10 @@ struct apple_gmux_config {
|
||||
|
||||
# define MMIO_GMUX_MAX_BRIGHTNESS 0xffff
|
||||
|
||||
+static bool force_igd;
|
||||
+module_param(force_igd, bool, 0);
|
||||
+MODULE_PARM_DESC(force_idg, "Switch gpu to igd on module load. Make sure that you have apple-set-os set up and the iGPU is in `lspci -s 00:02.0`. (default: false) (bool)");
|
||||
+
|
||||
static u8 gmux_pio_read8(struct apple_gmux_data *gmux_data, int port)
|
||||
{
|
||||
return inb(gmux_data->iostart + port);
|
||||
@@ -945,6 +950,19 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
|
||||
gmux_enable_interrupts(gmux_data);
|
||||
gmux_read_switch_state(gmux_data);
|
||||
|
||||
+ if (force_igd) {
|
||||
+ struct pci_dev *pdev;
|
||||
+
|
||||
+ pdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(2, 0));
|
||||
+ if (pdev) {
|
||||
+ pr_info("Switching to IGD");
|
||||
+ gmux_switchto(VGA_SWITCHEROO_IGD);
|
||||
+ vga_set_default_device(pdev);
|
||||
+ } else {
|
||||
+ pr_err("force_idg is true, but couldn't find iGPU at 00:02.0! Is apple-set-os working?");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* Retina MacBook Pros cannot switch the panel's AUX separately
|
||||
* and need eDP pre-calibration. They are distinguishable from
|
||||
--
|
||||
Armbian
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,312 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Pawlowski <paul@mrarm.io>
|
||||
Date: Sun, 17 Nov 2019 23:11:56 +0100
|
||||
Subject: applesmc: make io port base addr dynamic
|
||||
|
||||
This change makes the port base runtime configurable.
|
||||
The reason why this change is made is so that when we switch to an
|
||||
acpi_device we can resolve the port base addr from ACPI.
|
||||
|
||||
This change is not strictly required for T2 support - the base
|
||||
address is still 0x300 on T2 Macs.
|
||||
|
||||
Signed-off-by: Aun-Ali Zaidi <admin@kodeit.net>
|
||||
---
|
||||
drivers/hwmon/applesmc.c | 91 +++++-----
|
||||
1 file changed, 49 insertions(+), 42 deletions(-)
|
||||
|
||||
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/hwmon/applesmc.c
|
||||
+++ b/drivers/hwmon/applesmc.c
|
||||
@@ -35,10 +35,11 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/bits.h>
|
||||
|
||||
+#define APPLESMC_PORT_BASE 0x300
|
||||
/* data port used by Apple SMC */
|
||||
-#define APPLESMC_DATA_PORT 0x300
|
||||
+#define APPLESMC_DATA_PORT 0
|
||||
/* command/status port used by Apple SMC */
|
||||
-#define APPLESMC_CMD_PORT 0x304
|
||||
+#define APPLESMC_CMD_PORT 4
|
||||
|
||||
#define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */
|
||||
|
||||
@@ -140,6 +141,8 @@ struct applesmc_device {
|
||||
struct platform_device *dev;
|
||||
struct applesmc_registers reg;
|
||||
|
||||
+ u16 port_base;
|
||||
+
|
||||
s16 rest_x;
|
||||
s16 rest_y;
|
||||
|
||||
@@ -169,7 +172,7 @@ static const int debug;
|
||||
* run out past 500ms.
|
||||
*/
|
||||
|
||||
-static int wait_status(u8 val, u8 mask)
|
||||
+static int wait_status(struct applesmc_device *smc, u8 val, u8 mask)
|
||||
{
|
||||
u8 status;
|
||||
int us;
|
||||
@@ -177,7 +180,7 @@ static int wait_status(u8 val, u8 mask)
|
||||
|
||||
us = APPLESMC_MIN_WAIT;
|
||||
for (i = 0; i < 24 ; i++) {
|
||||
- status = inb(APPLESMC_CMD_PORT);
|
||||
+ status = inb(smc->port_base + APPLESMC_CMD_PORT);
|
||||
if ((status & mask) == val)
|
||||
return 0;
|
||||
usleep_range(us, us * 2);
|
||||
@@ -189,11 +192,11 @@ static int wait_status(u8 val, u8 mask)
|
||||
|
||||
/* send_byte - Write to SMC data port. Callers must hold applesmc_lock. */
|
||||
|
||||
-static int send_byte(u8 cmd, u16 port)
|
||||
+static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port)
|
||||
{
|
||||
int status;
|
||||
|
||||
- status = wait_status(0, SMC_STATUS_IB_CLOSED);
|
||||
+ status = wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
|
||||
if (status)
|
||||
return status;
|
||||
/*
|
||||
@@ -202,24 +205,24 @@ static int send_byte(u8 cmd, u16 port)
|
||||
* this extra read may not happen if status returns both
|
||||
* simultaneously and this would appear to be required.
|
||||
*/
|
||||
- status = wait_status(SMC_STATUS_BUSY, SMC_STATUS_BUSY);
|
||||
+ status = wait_status(smc, SMC_STATUS_BUSY, SMC_STATUS_BUSY);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
- outb(cmd, port);
|
||||
+ outb(cmd, smc->port_base + port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* send_command - Write a command to the SMC. Callers must hold applesmc_lock. */
|
||||
|
||||
-static int send_command(u8 cmd)
|
||||
+static int send_command(struct applesmc_device *smc, u8 cmd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
- ret = wait_status(0, SMC_STATUS_IB_CLOSED);
|
||||
+ ret = wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
|
||||
if (ret)
|
||||
return ret;
|
||||
- outb(cmd, APPLESMC_CMD_PORT);
|
||||
+ outb(cmd, smc->port_base + APPLESMC_CMD_PORT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -229,108 +232,112 @@ static int send_command(u8 cmd)
|
||||
* If busy is stuck high after the command then the SMC is jammed.
|
||||
*/
|
||||
|
||||
-static int smc_sane(void)
|
||||
+static int smc_sane(struct applesmc_device *smc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
- ret = wait_status(0, SMC_STATUS_BUSY);
|
||||
+ ret = wait_status(smc, 0, SMC_STATUS_BUSY);
|
||||
if (!ret)
|
||||
return ret;
|
||||
- ret = send_command(APPLESMC_READ_CMD);
|
||||
+ ret = send_command(smc, APPLESMC_READ_CMD);
|
||||
if (ret)
|
||||
return ret;
|
||||
- return wait_status(0, SMC_STATUS_BUSY);
|
||||
+ return wait_status(smc, 0, SMC_STATUS_BUSY);
|
||||
}
|
||||
|
||||
-static int send_argument(const char *key)
|
||||
+static int send_argument(struct applesmc_device *smc, const char *key)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
- if (send_byte(key[i], APPLESMC_DATA_PORT))
|
||||
+ if (send_byte(smc, key[i], APPLESMC_DATA_PORT))
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
|
||||
+static int read_smc(struct applesmc_device *smc, u8 cmd, const char *key,
|
||||
+ u8 *buffer, u8 len)
|
||||
{
|
||||
u8 status, data = 0;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
- ret = smc_sane();
|
||||
+ ret = smc_sane(smc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- if (send_command(cmd) || send_argument(key)) {
|
||||
+ if (send_command(smc, cmd) || send_argument(smc, key)) {
|
||||
pr_warn("%.4s: read arg fail\n", key);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* This has no effect on newer (2012) SMCs */
|
||||
- if (send_byte(len, APPLESMC_DATA_PORT)) {
|
||||
+ if (send_byte(smc, len, APPLESMC_DATA_PORT)) {
|
||||
pr_warn("%.4s: read len fail\n", key);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
- if (wait_status(SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY,
|
||||
+ if (wait_status(smc,
|
||||
+ SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY,
|
||||
SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY)) {
|
||||
pr_warn("%.4s: read data[%d] fail\n", key, i);
|
||||
return -EIO;
|
||||
}
|
||||
- buffer[i] = inb(APPLESMC_DATA_PORT);
|
||||
+ buffer[i] = inb(smc->port_base + APPLESMC_DATA_PORT);
|
||||
}
|
||||
|
||||
/* Read the data port until bit0 is cleared */
|
||||
for (i = 0; i < 16; i++) {
|
||||
udelay(APPLESMC_MIN_WAIT);
|
||||
- status = inb(APPLESMC_CMD_PORT);
|
||||
+ status = inb(smc->port_base + APPLESMC_CMD_PORT);
|
||||
if (!(status & SMC_STATUS_AWAITING_DATA))
|
||||
break;
|
||||
- data = inb(APPLESMC_DATA_PORT);
|
||||
+ data = inb(smc->port_base + APPLESMC_DATA_PORT);
|
||||
}
|
||||
if (i)
|
||||
pr_warn("flushed %d bytes, last value is: %d\n", i, data);
|
||||
|
||||
- return wait_status(0, SMC_STATUS_BUSY);
|
||||
+ return wait_status(smc, 0, SMC_STATUS_BUSY);
|
||||
}
|
||||
|
||||
-static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
|
||||
+static int write_smc(struct applesmc_device *smc, u8 cmd, const char *key,
|
||||
+ const u8 *buffer, u8 len)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
- ret = smc_sane();
|
||||
+ ret = smc_sane(smc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- if (send_command(cmd) || send_argument(key)) {
|
||||
+ if (send_command(smc, cmd) || send_argument(smc, key)) {
|
||||
pr_warn("%s: write arg fail\n", key);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
- if (send_byte(len, APPLESMC_DATA_PORT)) {
|
||||
+ if (send_byte(smc, len, APPLESMC_DATA_PORT)) {
|
||||
pr_warn("%.4s: write len fail\n", key);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
- if (send_byte(buffer[i], APPLESMC_DATA_PORT)) {
|
||||
+ if (send_byte(smc, buffer[i], APPLESMC_DATA_PORT)) {
|
||||
pr_warn("%s: write data fail\n", key);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
- return wait_status(0, SMC_STATUS_BUSY);
|
||||
+ return wait_status(smc, 0, SMC_STATUS_BUSY);
|
||||
}
|
||||
|
||||
-static int read_register_count(unsigned int *count)
|
||||
+static int read_register_count(struct applesmc_device *smc,
|
||||
+ unsigned int *count)
|
||||
{
|
||||
__be32 be;
|
||||
int ret;
|
||||
|
||||
- ret = read_smc(APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4);
|
||||
+ ret = read_smc(smc, APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -353,7 +360,7 @@ static int applesmc_read_entry(struct applesmc_device *smc,
|
||||
if (entry->len != len)
|
||||
return -EINVAL;
|
||||
mutex_lock(&smc->reg.mutex);
|
||||
- ret = read_smc(APPLESMC_READ_CMD, entry->key, buf, len);
|
||||
+ ret = read_smc(smc, APPLESMC_READ_CMD, entry->key, buf, len);
|
||||
mutex_unlock(&smc->reg.mutex);
|
||||
|
||||
return ret;
|
||||
@@ -367,7 +374,7 @@ static int applesmc_write_entry(struct applesmc_device *smc,
|
||||
if (entry->len != len)
|
||||
return -EINVAL;
|
||||
mutex_lock(&smc->reg.mutex);
|
||||
- ret = write_smc(APPLESMC_WRITE_CMD, entry->key, buf, len);
|
||||
+ ret = write_smc(smc, APPLESMC_WRITE_CMD, entry->key, buf, len);
|
||||
mutex_unlock(&smc->reg.mutex);
|
||||
return ret;
|
||||
}
|
||||
@@ -388,10 +395,10 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(
|
||||
if (cache->valid)
|
||||
goto out;
|
||||
be = cpu_to_be32(index);
|
||||
- ret = read_smc(APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4);
|
||||
+ ret = read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4);
|
||||
if (ret)
|
||||
goto out;
|
||||
- ret = read_smc(APPLESMC_GET_KEY_TYPE_CMD, key, info, 6);
|
||||
+ ret = read_smc(smc, APPLESMC_GET_KEY_TYPE_CMD, key, info, 6);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -589,7 +596,7 @@ static int applesmc_init_smcreg_try(struct applesmc_device *smc)
|
||||
if (s->init_complete)
|
||||
return 0;
|
||||
|
||||
- ret = read_register_count(&count);
|
||||
+ ret = read_register_count(smc, &count);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1472,7 +1479,7 @@ static int __init applesmc_init(void)
|
||||
goto out;
|
||||
}
|
||||
|
||||
- if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS,
|
||||
+ if (!request_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS,
|
||||
"applesmc")) {
|
||||
ret = -ENXIO;
|
||||
goto out;
|
||||
@@ -1494,7 +1501,7 @@ static int __init applesmc_init(void)
|
||||
out_driver:
|
||||
platform_driver_unregister(&applesmc_driver);
|
||||
out_region:
|
||||
- release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
|
||||
+ release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS);
|
||||
out:
|
||||
pr_warn("driver init failed (ret=%d)!\n", ret);
|
||||
return ret;
|
||||
@@ -1504,7 +1511,7 @@ static void __exit applesmc_exit(void)
|
||||
{
|
||||
platform_device_unregister(pdev);
|
||||
platform_driver_unregister(&applesmc_driver);
|
||||
- release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS);
|
||||
+ release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS);
|
||||
}
|
||||
|
||||
module_init(applesmc_init);
|
||||
--
|
||||
Armbian
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Pawlowski <paul@mrarm.io>
|
||||
Date: Sat, 29 Jun 2024 04:49:16 +0000
|
||||
Subject: applesmc: switch to acpi_device (from platform)
|
||||
|
||||
This change makes the change from platform_device
|
||||
to acpi_device. The rationale for this change is
|
||||
that on T2 Macs, an additional FixedMemory32
|
||||
region is needed for device operation, and it can
|
||||
be easily resolved via ACPI tables (this will be
|
||||
done in another commit).
|
||||
|
||||
Additionally, on older Macs, the OS X driver also
|
||||
looks for the specified ACPI device to resolve
|
||||
its memory regions, and therefore this change
|
||||
should not result in any incompatibilities.
|
||||
|
||||
Signed-off-by: Aun-Ali Zaidi <admin@kodeit.net>
|
||||
---
|
||||
drivers/hwmon/applesmc.c | 124 +++++++---
|
||||
1 file changed, 84 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/hwmon/applesmc.c
|
||||
+++ b/drivers/hwmon/applesmc.c
|
||||
@@ -19,7 +19,7 @@
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/delay.h>
|
||||
-#include <linux/platform_device.h>
|
||||
+#include <linux/acpi.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -35,7 +35,6 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/bits.h>
|
||||
|
||||
-#define APPLESMC_PORT_BASE 0x300
|
||||
/* data port used by Apple SMC */
|
||||
#define APPLESMC_DATA_PORT 0
|
||||
/* command/status port used by Apple SMC */
|
||||
@@ -138,9 +137,10 @@ struct applesmc_registers {
|
||||
};
|
||||
|
||||
struct applesmc_device {
|
||||
- struct platform_device *dev;
|
||||
+ struct acpi_device *dev;
|
||||
struct applesmc_registers reg;
|
||||
|
||||
+ bool port_base_set;
|
||||
u16 port_base;
|
||||
|
||||
s16 rest_x;
|
||||
@@ -692,9 +692,13 @@ static int applesmc_init_smcreg(struct applesmc_device *smc)
|
||||
}
|
||||
|
||||
/* Device model stuff */
|
||||
+
|
||||
+static int applesmc_init_resources(struct applesmc_device *smc);
|
||||
+static void applesmc_free_resources(struct applesmc_device *smc);
|
||||
static int applesmc_create_modules(struct applesmc_device *smc);
|
||||
static void applesmc_destroy_modules(struct applesmc_device *smc);
|
||||
-static int applesmc_probe(struct platform_device *dev)
|
||||
+
|
||||
+static int applesmc_add(struct acpi_device *dev)
|
||||
{
|
||||
struct applesmc_device *smc;
|
||||
int ret;
|
||||
@@ -705,12 +709,16 @@ static int applesmc_probe(struct platform_device *dev)
|
||||
smc->dev = dev;
|
||||
mutex_init(&smc->reg.mutex);
|
||||
|
||||
- platform_set_drvdata(dev, smc);
|
||||
+ dev_set_drvdata(&dev->dev, smc);
|
||||
|
||||
- ret = applesmc_init_smcreg(smc);
|
||||
+ ret = applesmc_init_resources(smc);
|
||||
if (ret)
|
||||
goto out_mem;
|
||||
|
||||
+ ret = applesmc_init_smcreg(smc);
|
||||
+ if (ret)
|
||||
+ goto out_res;
|
||||
+
|
||||
applesmc_device_init(smc);
|
||||
|
||||
ret = applesmc_create_modules(smc);
|
||||
@@ -721,20 +729,23 @@ static int applesmc_probe(struct platform_device *dev)
|
||||
|
||||
out_reg:
|
||||
applesmc_destroy_smcreg(smc);
|
||||
+out_res:
|
||||
+ applesmc_free_resources(smc);
|
||||
out_mem:
|
||||
- platform_set_drvdata(dev, NULL);
|
||||
+ dev_set_drvdata(&dev->dev, NULL);
|
||||
mutex_destroy(&smc->reg.mutex);
|
||||
kfree(smc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int applesmc_remove(struct platform_device *dev)
|
||||
+static int applesmc_remove(struct acpi_device *dev)
|
||||
{
|
||||
- struct applesmc_device *smc = platform_get_drvdata(dev);
|
||||
+ struct applesmc_device *smc = dev_get_drvdata(&dev->dev);
|
||||
|
||||
applesmc_destroy_modules(smc);
|
||||
applesmc_destroy_smcreg(smc);
|
||||
+ applesmc_free_resources(smc);
|
||||
|
||||
mutex_destroy(&smc->reg.mutex);
|
||||
kfree(smc);
|
||||
@@ -742,6 +753,52 @@ static int applesmc_remove(struct platform_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static acpi_status applesmc_walk_resources(struct acpi_resource *res,
|
||||
+ void *data)
|
||||
+{
|
||||
+ struct applesmc_device *smc = data;
|
||||
+
|
||||
+ switch (res->type) {
|
||||
+ case ACPI_RESOURCE_TYPE_IO:
|
||||
+ if (!smc->port_base_set) {
|
||||
+ if (res->data.io.address_length < APPLESMC_NR_PORTS)
|
||||
+ return AE_ERROR;
|
||||
+ smc->port_base = res->data.io.minimum;
|
||||
+ smc->port_base_set = true;
|
||||
+ }
|
||||
+ return AE_OK;
|
||||
+
|
||||
+ case ACPI_RESOURCE_TYPE_END_TAG:
|
||||
+ if (smc->port_base_set)
|
||||
+ return AE_OK;
|
||||
+ else
|
||||
+ return AE_NOT_FOUND;
|
||||
+
|
||||
+ default:
|
||||
+ return AE_OK;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int applesmc_init_resources(struct applesmc_device *smc)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = acpi_walk_resources(smc->dev->handle, METHOD_NAME__CRS,
|
||||
+ applesmc_walk_resources, smc);
|
||||
+ if (ACPI_FAILURE(ret))
|
||||
+ return -ENXIO;
|
||||
+
|
||||
+ if (!request_region(smc->port_base, APPLESMC_NR_PORTS, "applesmc"))
|
||||
+ return -ENXIO;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void applesmc_free_resources(struct applesmc_device *smc)
|
||||
+{
|
||||
+ release_region(smc->port_base, APPLESMC_NR_PORTS);
|
||||
+}
|
||||
+
|
||||
/* Synchronize device with memorized backlight state */
|
||||
static int applesmc_pm_resume(struct device *dev)
|
||||
{
|
||||
@@ -763,17 +820,26 @@ static int applesmc_pm_restore(struct device *dev)
|
||||
return applesmc_pm_resume(dev);
|
||||
}
|
||||
|
||||
+static const struct acpi_device_id applesmc_ids[] = {
|
||||
+ {"APP0001", 0},
|
||||
+ {"", 0},
|
||||
+};
|
||||
+
|
||||
static const struct dev_pm_ops applesmc_pm_ops = {
|
||||
.resume = applesmc_pm_resume,
|
||||
.restore = applesmc_pm_restore,
|
||||
};
|
||||
|
||||
-static struct platform_driver applesmc_driver = {
|
||||
- .probe = applesmc_probe,
|
||||
- .remove = applesmc_remove,
|
||||
- .driver = {
|
||||
- .name = "applesmc",
|
||||
- .pm = &applesmc_pm_ops,
|
||||
+static struct acpi_driver applesmc_driver = {
|
||||
+ .name = "applesmc",
|
||||
+ .class = "applesmc",
|
||||
+ .ids = applesmc_ids,
|
||||
+ .ops = {
|
||||
+ .add = applesmc_add,
|
||||
+ .remove = applesmc_remove
|
||||
+ },
|
||||
+ .drv = {
|
||||
+ .pm = &applesmc_pm_ops
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1262,7 +1328,6 @@ static int applesmc_create_nodes(struct applesmc_device *smc,
|
||||
static int applesmc_create_accelerometer(struct applesmc_device *smc)
|
||||
{
|
||||
int ret;
|
||||
-
|
||||
if (!smc->reg.has_accelerometer)
|
||||
return 0;
|
||||
|
||||
@@ -1467,8 +1532,6 @@ static void applesmc_destroy_modules(struct applesmc_device *smc)
|
||||
applesmc_destroy_nodes(smc, info_group);
|
||||
}
|
||||
|
||||
-static struct platform_device *pdev;
|
||||
-
|
||||
static int __init applesmc_init(void)
|
||||
{
|
||||
int ret;
|
||||
@@ -1479,29 +1542,12 @@ static int __init applesmc_init(void)
|
||||
goto out;
|
||||
}
|
||||
|
||||
- if (!request_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS,
|
||||
- "applesmc")) {
|
||||
- ret = -ENXIO;
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- ret = platform_driver_register(&applesmc_driver);
|
||||
+ ret = acpi_bus_register_driver(&applesmc_driver);
|
||||
if (ret)
|
||||
- goto out_region;
|
||||
-
|
||||
- pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT,
|
||||
- NULL, 0);
|
||||
- if (IS_ERR(pdev)) {
|
||||
- ret = PTR_ERR(pdev);
|
||||
- goto out_driver;
|
||||
- }
|
||||
+ goto out;
|
||||
|
||||
return 0;
|
||||
|
||||
-out_driver:
|
||||
- platform_driver_unregister(&applesmc_driver);
|
||||
-out_region:
|
||||
- release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS);
|
||||
out:
|
||||
pr_warn("driver init failed (ret=%d)!\n", ret);
|
||||
return ret;
|
||||
@@ -1509,9 +1555,7 @@ static int __init applesmc_init(void)
|
||||
|
||||
static void __exit applesmc_exit(void)
|
||||
{
|
||||
- platform_device_unregister(pdev);
|
||||
- platform_driver_unregister(&applesmc_driver);
|
||||
- release_region(APPLESMC_PORT_BASE, APPLESMC_NR_PORTS);
|
||||
+ acpi_bus_unregister_driver(&applesmc_driver);
|
||||
}
|
||||
|
||||
module_init(applesmc_init);
|
||||
--
|
||||
Armbian
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Pawlowski <paul@mrarm.io>
|
||||
Date: Sun, 17 Nov 2019 23:12:14 +0100
|
||||
Subject: applesmc: key interface wrappers
|
||||
|
||||
This change replaces the read_smc and write_smc
|
||||
methods with wrappers, additionally removing the
|
||||
command id parameter from them (and introducing
|
||||
get_smc_key_by_index and get_smc_key_info).
|
||||
|
||||
This is done as to allow simple implementation
|
||||
replacement on T2 Macs. The newly introduced
|
||||
methods mentioned in the previous paragraph need
|
||||
special handling on T2 and as such had to be
|
||||
separated.
|
||||
|
||||
Signed-off-by: Aun-Ali Zaidi <admin@kodeit.net>
|
||||
---
|
||||
drivers/hwmon/applesmc.c | 119 ++++++----
|
||||
1 file changed, 79 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/hwmon/applesmc.c
|
||||
+++ b/drivers/hwmon/applesmc.c
|
||||
@@ -172,7 +172,7 @@ static const int debug;
|
||||
* run out past 500ms.
|
||||
*/
|
||||
|
||||
-static int wait_status(struct applesmc_device *smc, u8 val, u8 mask)
|
||||
+static int port_wait_status(struct applesmc_device *smc, u8 val, u8 mask)
|
||||
{
|
||||
u8 status;
|
||||
int us;
|
||||
@@ -190,13 +190,13 @@ static int wait_status(struct applesmc_device *smc, u8 val, u8 mask)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
-/* send_byte - Write to SMC data port. Callers must hold applesmc_lock. */
|
||||
+/* port_send_byte - Write to SMC data port. Callers must hold applesmc_lock. */
|
||||
|
||||
-static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port)
|
||||
+static int port_send_byte(struct applesmc_device *smc, u8 cmd, u16 port)
|
||||
{
|
||||
int status;
|
||||
|
||||
- status = wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
|
||||
+ status = port_wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
|
||||
if (status)
|
||||
return status;
|
||||
/*
|
||||
@@ -205,7 +205,7 @@ static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port)
|
||||
* this extra read may not happen if status returns both
|
||||
* simultaneously and this would appear to be required.
|
||||
*/
|
||||
- status = wait_status(smc, SMC_STATUS_BUSY, SMC_STATUS_BUSY);
|
||||
+ status = port_wait_status(smc, SMC_STATUS_BUSY, SMC_STATUS_BUSY);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
@@ -213,15 +213,16 @@ static int send_byte(struct applesmc_device *smc, u8 cmd, u16 port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-/* send_command - Write a command to the SMC. Callers must hold applesmc_lock. */
|
||||
+/* port_send_command - Write a command to the SMC. Callers must hold applesmc_lock. */
|
||||
|
||||
-static int send_command(struct applesmc_device *smc, u8 cmd)
|
||||
+static int port_send_command(struct applesmc_device *smc, u8 cmd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
- ret = wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
|
||||
+ ret = port_wait_status(smc, 0, SMC_STATUS_IB_CLOSED);
|
||||
if (ret)
|
||||
return ret;
|
||||
+
|
||||
outb(cmd, smc->port_base + APPLESMC_CMD_PORT);
|
||||
return 0;
|
||||
}
|
||||
@@ -232,53 +233,53 @@ static int send_command(struct applesmc_device *smc, u8 cmd)
|
||||
* If busy is stuck high after the command then the SMC is jammed.
|
||||
*/
|
||||
|
||||
-static int smc_sane(struct applesmc_device *smc)
|
||||
+static int port_smc_sane(struct applesmc_device *smc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
- ret = wait_status(smc, 0, SMC_STATUS_BUSY);
|
||||
+ ret = port_wait_status(smc, 0, SMC_STATUS_BUSY);
|
||||
if (!ret)
|
||||
return ret;
|
||||
- ret = send_command(smc, APPLESMC_READ_CMD);
|
||||
+ ret = port_send_command(smc, APPLESMC_READ_CMD);
|
||||
if (ret)
|
||||
return ret;
|
||||
- return wait_status(smc, 0, SMC_STATUS_BUSY);
|
||||
+ return port_wait_status(smc, 0, SMC_STATUS_BUSY);
|
||||
}
|
||||
|
||||
-static int send_argument(struct applesmc_device *smc, const char *key)
|
||||
+static int port_send_argument(struct applesmc_device *smc, const char *key)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
- if (send_byte(smc, key[i], APPLESMC_DATA_PORT))
|
||||
+ if (port_send_byte(smc, key[i], APPLESMC_DATA_PORT))
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int read_smc(struct applesmc_device *smc, u8 cmd, const char *key,
|
||||
+static int port_read_smc(struct applesmc_device *smc, u8 cmd, const char *key,
|
||||
u8 *buffer, u8 len)
|
||||
{
|
||||
u8 status, data = 0;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
- ret = smc_sane(smc);
|
||||
+ ret = port_smc_sane(smc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- if (send_command(smc, cmd) || send_argument(smc, key)) {
|
||||
+ if (port_send_command(smc, cmd) || port_send_argument(smc, key)) {
|
||||
pr_warn("%.4s: read arg fail\n", key);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* This has no effect on newer (2012) SMCs */
|
||||
- if (send_byte(smc, len, APPLESMC_DATA_PORT)) {
|
||||
+ if (port_send_byte(smc, len, APPLESMC_DATA_PORT)) {
|
||||
pr_warn("%.4s: read len fail\n", key);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
- if (wait_status(smc,
|
||||
+ if (port_wait_status(smc,
|
||||
SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY,
|
||||
SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY)) {
|
||||
pr_warn("%.4s: read data[%d] fail\n", key, i);
|
||||
@@ -298,37 +299,80 @@ static int read_smc(struct applesmc_device *smc, u8 cmd, const char *key,
|
||||
if (i)
|
||||
pr_warn("flushed %d bytes, last value is: %d\n", i, data);
|
||||
|
||||
- return wait_status(smc, 0, SMC_STATUS_BUSY);
|
||||
+ return port_wait_status(smc, 0, SMC_STATUS_BUSY);
|
||||
}
|
||||
|
||||
-static int write_smc(struct applesmc_device *smc, u8 cmd, const char *key,
|
||||
+static int port_write_smc(struct applesmc_device *smc, u8 cmd, const char *key,
|
||||
const u8 *buffer, u8 len)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
- ret = smc_sane(smc);
|
||||
+ ret = port_smc_sane(smc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- if (send_command(smc, cmd) || send_argument(smc, key)) {
|
||||
+ if (port_send_command(smc, cmd) || port_send_argument(smc, key)) {
|
||||
pr_warn("%s: write arg fail\n", key);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
- if (send_byte(smc, len, APPLESMC_DATA_PORT)) {
|
||||
+ if (port_send_byte(smc, len, APPLESMC_DATA_PORT)) {
|
||||
pr_warn("%.4s: write len fail\n", key);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
- if (send_byte(smc, buffer[i], APPLESMC_DATA_PORT)) {
|
||||
+ if (port_send_byte(smc, buffer[i], APPLESMC_DATA_PORT)) {
|
||||
pr_warn("%s: write data fail\n", key);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
- return wait_status(smc, 0, SMC_STATUS_BUSY);
|
||||
+ return port_wait_status(smc, 0, SMC_STATUS_BUSY);
|
||||
+}
|
||||
+
|
||||
+static int port_get_smc_key_info(struct applesmc_device *smc,
|
||||
+ const char *key, struct applesmc_entry *info)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u8 raw[6];
|
||||
+
|
||||
+ ret = port_read_smc(smc, APPLESMC_GET_KEY_TYPE_CMD, key, raw, 6);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ info->len = raw[0];
|
||||
+ memcpy(info->type, &raw[1], 4);
|
||||
+ info->flags = raw[5];
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int read_smc(struct applesmc_device *smc, const char *key,
|
||||
+ u8 *buffer, u8 len)
|
||||
+{
|
||||
+ return port_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len);
|
||||
+}
|
||||
+
|
||||
+static int write_smc(struct applesmc_device *smc, const char *key,
|
||||
+ const u8 *buffer, u8 len)
|
||||
+{
|
||||
+ return port_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len);
|
||||
+}
|
||||
+
|
||||
+static int get_smc_key_by_index(struct applesmc_device *smc,
|
||||
+ unsigned int index, char *key)
|
||||
+{
|
||||
+ __be32 be;
|
||||
+
|
||||
+ be = cpu_to_be32(index);
|
||||
+ return port_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD,
|
||||
+ (const char *) &be, (u8 *) key, 4);
|
||||
+}
|
||||
+
|
||||
+static int get_smc_key_info(struct applesmc_device *smc, const char *key,
|
||||
+ struct applesmc_entry *info)
|
||||
+{
|
||||
+ return port_get_smc_key_info(smc, key, info);
|
||||
}
|
||||
|
||||
static int read_register_count(struct applesmc_device *smc,
|
||||
@@ -337,8 +381,8 @@ static int read_register_count(struct applesmc_device *smc,
|
||||
__be32 be;
|
||||
int ret;
|
||||
|
||||
- ret = read_smc(smc, APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4);
|
||||
- if (ret)
|
||||
+ ret = read_smc(smc, KEY_COUNT_KEY, (u8 *)&be, 4);
|
||||
+ if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*count = be32_to_cpu(be);
|
||||
@@ -360,7 +404,7 @@ static int applesmc_read_entry(struct applesmc_device *smc,
|
||||
if (entry->len != len)
|
||||
return -EINVAL;
|
||||
mutex_lock(&smc->reg.mutex);
|
||||
- ret = read_smc(smc, APPLESMC_READ_CMD, entry->key, buf, len);
|
||||
+ ret = read_smc(smc, entry->key, buf, len);
|
||||
mutex_unlock(&smc->reg.mutex);
|
||||
|
||||
return ret;
|
||||
@@ -374,7 +418,7 @@ static int applesmc_write_entry(struct applesmc_device *smc,
|
||||
if (entry->len != len)
|
||||
return -EINVAL;
|
||||
mutex_lock(&smc->reg.mutex);
|
||||
- ret = write_smc(smc, APPLESMC_WRITE_CMD, entry->key, buf, len);
|
||||
+ ret = write_smc(smc, entry->key, buf, len);
|
||||
mutex_unlock(&smc->reg.mutex);
|
||||
return ret;
|
||||
}
|
||||
@@ -383,8 +427,7 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(
|
||||
struct applesmc_device *smc, int index)
|
||||
{
|
||||
struct applesmc_entry *cache = &smc->reg.cache[index];
|
||||
- u8 key[4], info[6];
|
||||
- __be32 be;
|
||||
+ char key[4];
|
||||
int ret = 0;
|
||||
|
||||
if (cache->valid)
|
||||
@@ -394,18 +437,14 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(
|
||||
|
||||
if (cache->valid)
|
||||
goto out;
|
||||
- be = cpu_to_be32(index);
|
||||
- ret = read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4);
|
||||
+ ret = get_smc_key_by_index(smc, index, key);
|
||||
if (ret)
|
||||
goto out;
|
||||
- ret = read_smc(smc, APPLESMC_GET_KEY_TYPE_CMD, key, info, 6);
|
||||
+ memcpy(cache->key, key, 4);
|
||||
+
|
||||
+ ret = get_smc_key_info(smc, key, cache);
|
||||
if (ret)
|
||||
goto out;
|
||||
-
|
||||
- memcpy(cache->key, key, 4);
|
||||
- cache->len = info[0];
|
||||
- memcpy(cache->type, &info[1], 4);
|
||||
- cache->flags = info[5];
|
||||
cache->valid = true;
|
||||
|
||||
out:
|
||||
--
|
||||
Armbian
|
||||
|
||||
@@ -0,0 +1,343 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aun-Ali Zaidi <admin@kodeit.net>
|
||||
Date: Sun, 17 Nov 2019 23:12:16 +0100
|
||||
Subject: applesmc: basic mmio interface implementation
|
||||
|
||||
This change introduces a basic MMIO-based
|
||||
interface implementation required to communicate
|
||||
with the SMC on T2 Macs. The MMIO interface is
|
||||
enabled only when it's supported on the running
|
||||
system.
|
||||
|
||||
The MMIO interface replaces legacy port-based SMC
|
||||
key reads, writes and metadata requests (getting
|
||||
key by index and getting key info).
|
||||
|
||||
(Based on patch by @mcmrarm)
|
||||
|
||||
Signed-off-by: Aun-Ali Zaidi <admin@kodeit.net>
|
||||
---
|
||||
drivers/hwmon/applesmc.c | 237 +++++++++-
|
||||
1 file changed, 231 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/hwmon/applesmc.c
|
||||
+++ b/drivers/hwmon/applesmc.c
|
||||
@@ -42,6 +42,18 @@
|
||||
|
||||
#define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */
|
||||
|
||||
+#define APPLESMC_IOMEM_KEY_DATA 0
|
||||
+#define APPLESMC_IOMEM_KEY_STATUS 0x4005
|
||||
+#define APPLESMC_IOMEM_KEY_NAME 0x78
|
||||
+#define APPLESMC_IOMEM_KEY_DATA_LEN 0x7D
|
||||
+#define APPLESMC_IOMEM_KEY_SMC_ID 0x7E
|
||||
+#define APPLESMC_IOMEM_KEY_CMD 0x7F
|
||||
+#define APPLESMC_IOMEM_MIN_SIZE 0x4006
|
||||
+
|
||||
+#define APPLESMC_IOMEM_KEY_TYPE_CODE 0
|
||||
+#define APPLESMC_IOMEM_KEY_TYPE_DATA_LEN 5
|
||||
+#define APPLESMC_IOMEM_KEY_TYPE_FLAGS 6
|
||||
+
|
||||
#define APPLESMC_MAX_DATA_LENGTH 32
|
||||
|
||||
/* Apple SMC status bits */
|
||||
@@ -138,10 +150,13 @@ struct applesmc_registers {
|
||||
|
||||
struct applesmc_device {
|
||||
struct acpi_device *dev;
|
||||
+ struct device *ldev;
|
||||
struct applesmc_registers reg;
|
||||
|
||||
- bool port_base_set;
|
||||
+ bool port_base_set, iomem_base_set;
|
||||
u16 port_base;
|
||||
+ u8 *__iomem iomem_base;
|
||||
+ u32 iomem_base_addr, iomem_base_size;
|
||||
|
||||
s16 rest_x;
|
||||
s16 rest_y;
|
||||
@@ -347,16 +362,156 @@ static int port_get_smc_key_info(struct applesmc_device *smc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+
|
||||
+/*
|
||||
+ * MMIO based communication.
|
||||
+ * TODO: Use updated mechanism for cmd timeout/retry
|
||||
+ */
|
||||
+
|
||||
+static void iomem_clear_status(struct applesmc_device *smc)
|
||||
+{
|
||||
+ if (ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_STATUS))
|
||||
+ iowrite8(0, smc->iomem_base + APPLESMC_IOMEM_KEY_STATUS);
|
||||
+}
|
||||
+
|
||||
+static int iomem_wait_read(struct applesmc_device *smc)
|
||||
+{
|
||||
+ u8 status;
|
||||
+ int us;
|
||||
+ int i;
|
||||
+
|
||||
+ us = APPLESMC_MIN_WAIT;
|
||||
+ for (i = 0; i < 24 ; i++) {
|
||||
+ status = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_STATUS);
|
||||
+ if (status & 0x20)
|
||||
+ return 0;
|
||||
+ usleep_range(us, us * 2);
|
||||
+ if (i > 9)
|
||||
+ us <<= 1;
|
||||
+ }
|
||||
+
|
||||
+ dev_warn(smc->ldev, "%s... timeout\n", __func__);
|
||||
+ return -EIO;
|
||||
+}
|
||||
+
|
||||
+static int iomem_read_smc(struct applesmc_device *smc, u8 cmd, const char *key,
|
||||
+ u8 *buffer, u8 len)
|
||||
+{
|
||||
+ u8 err, remote_len;
|
||||
+ u32 key_int = *((u32 *) key);
|
||||
+
|
||||
+ iomem_clear_status(smc);
|
||||
+ iowrite32(key_int, smc->iomem_base + APPLESMC_IOMEM_KEY_NAME);
|
||||
+ iowrite32(0, smc->iomem_base + APPLESMC_IOMEM_KEY_SMC_ID);
|
||||
+ iowrite32(cmd, smc->iomem_base + APPLESMC_IOMEM_KEY_CMD);
|
||||
+
|
||||
+ if (iomem_wait_read(smc))
|
||||
+ return -EIO;
|
||||
+
|
||||
+ err = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_CMD);
|
||||
+ if (err != 0) {
|
||||
+ dev_warn(smc->ldev, "read_smc_mmio(%x %8x/%.4s) failed: %u\n",
|
||||
+ cmd, key_int, key, err);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ if (cmd == APPLESMC_READ_CMD) {
|
||||
+ remote_len = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_DATA_LEN);
|
||||
+ if (remote_len != len) {
|
||||
+ dev_warn(smc->ldev,
|
||||
+ "read_smc_mmio(%x %8x/%.4s) failed: buffer length mismatch (remote = %u, requested = %u)\n",
|
||||
+ cmd, key_int, key, remote_len, len);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ } else {
|
||||
+ remote_len = len;
|
||||
+ }
|
||||
+
|
||||
+ memcpy_fromio(buffer, smc->iomem_base + APPLESMC_IOMEM_KEY_DATA,
|
||||
+ remote_len);
|
||||
+
|
||||
+ dev_dbg(smc->ldev, "read_smc_mmio(%x %8x/%.4s): buflen=%u reslen=%u\n",
|
||||
+ cmd, key_int, key, len, remote_len);
|
||||
+ print_hex_dump_bytes("read_smc_mmio(): ", DUMP_PREFIX_NONE, buffer, remote_len);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int iomem_get_smc_key_type(struct applesmc_device *smc, const char *key,
|
||||
+ struct applesmc_entry *e)
|
||||
+{
|
||||
+ u8 err;
|
||||
+ u8 cmd = APPLESMC_GET_KEY_TYPE_CMD;
|
||||
+ u32 key_int = *((u32 *) key);
|
||||
+
|
||||
+ iomem_clear_status(smc);
|
||||
+ iowrite32(key_int, smc->iomem_base + APPLESMC_IOMEM_KEY_NAME);
|
||||
+ iowrite32(0, smc->iomem_base + APPLESMC_IOMEM_KEY_SMC_ID);
|
||||
+ iowrite32(cmd, smc->iomem_base + APPLESMC_IOMEM_KEY_CMD);
|
||||
+
|
||||
+ if (iomem_wait_read(smc))
|
||||
+ return -EIO;
|
||||
+
|
||||
+ err = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_CMD);
|
||||
+ if (err != 0) {
|
||||
+ dev_warn(smc->ldev, "get_smc_key_type_mmio(%.4s) failed: %u\n", key, err);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ e->len = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_TYPE_DATA_LEN);
|
||||
+ *((uint32_t *) e->type) = ioread32(
|
||||
+ smc->iomem_base + APPLESMC_IOMEM_KEY_TYPE_CODE);
|
||||
+ e->flags = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_TYPE_FLAGS);
|
||||
+
|
||||
+ dev_dbg(smc->ldev, "get_smc_key_type_mmio(%.4s): len=%u type=%.4s flags=%x\n",
|
||||
+ key, e->len, e->type, e->flags);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int iomem_write_smc(struct applesmc_device *smc, u8 cmd, const char *key,
|
||||
+ const u8 *buffer, u8 len)
|
||||
+{
|
||||
+ u8 err;
|
||||
+ u32 key_int = *((u32 *) key);
|
||||
+
|
||||
+ iomem_clear_status(smc);
|
||||
+ iowrite32(key_int, smc->iomem_base + APPLESMC_IOMEM_KEY_NAME);
|
||||
+ memcpy_toio(smc->iomem_base + APPLESMC_IOMEM_KEY_DATA, buffer, len);
|
||||
+ iowrite32(len, smc->iomem_base + APPLESMC_IOMEM_KEY_DATA_LEN);
|
||||
+ iowrite32(0, smc->iomem_base + APPLESMC_IOMEM_KEY_SMC_ID);
|
||||
+ iowrite32(cmd, smc->iomem_base + APPLESMC_IOMEM_KEY_CMD);
|
||||
+
|
||||
+ if (iomem_wait_read(smc))
|
||||
+ return -EIO;
|
||||
+
|
||||
+ err = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_CMD);
|
||||
+ if (err != 0) {
|
||||
+ dev_warn(smc->ldev, "write_smc_mmio(%x %.4s) failed: %u\n", cmd, key, err);
|
||||
+ print_hex_dump_bytes("write_smc_mmio(): ", DUMP_PREFIX_NONE, buffer, len);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ dev_dbg(smc->ldev, "write_smc_mmio(%x %.4s): buflen=%u\n", cmd, key, len);
|
||||
+ print_hex_dump_bytes("write_smc_mmio(): ", DUMP_PREFIX_NONE, buffer, len);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
static int read_smc(struct applesmc_device *smc, const char *key,
|
||||
u8 *buffer, u8 len)
|
||||
{
|
||||
- return port_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len);
|
||||
+ if (smc->iomem_base_set)
|
||||
+ return iomem_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len);
|
||||
+ else
|
||||
+ return port_read_smc(smc, APPLESMC_READ_CMD, key, buffer, len);
|
||||
}
|
||||
|
||||
static int write_smc(struct applesmc_device *smc, const char *key,
|
||||
const u8 *buffer, u8 len)
|
||||
{
|
||||
- return port_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len);
|
||||
+ if (smc->iomem_base_set)
|
||||
+ return iomem_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len);
|
||||
+ else
|
||||
+ return port_write_smc(smc, APPLESMC_WRITE_CMD, key, buffer, len);
|
||||
}
|
||||
|
||||
static int get_smc_key_by_index(struct applesmc_device *smc,
|
||||
@@ -365,14 +520,21 @@ static int get_smc_key_by_index(struct applesmc_device *smc,
|
||||
__be32 be;
|
||||
|
||||
be = cpu_to_be32(index);
|
||||
- return port_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD,
|
||||
- (const char *) &be, (u8 *) key, 4);
|
||||
+ if (smc->iomem_base_set)
|
||||
+ return iomem_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD,
|
||||
+ (const char *) &be, (u8 *) key, 4);
|
||||
+ else
|
||||
+ return port_read_smc(smc, APPLESMC_GET_KEY_BY_INDEX_CMD,
|
||||
+ (const char *) &be, (u8 *) key, 4);
|
||||
}
|
||||
|
||||
static int get_smc_key_info(struct applesmc_device *smc, const char *key,
|
||||
struct applesmc_entry *info)
|
||||
{
|
||||
- return port_get_smc_key_info(smc, key, info);
|
||||
+ if (smc->iomem_base_set)
|
||||
+ return iomem_get_smc_key_type(smc, key, info);
|
||||
+ else
|
||||
+ return port_get_smc_key_info(smc, key, info);
|
||||
}
|
||||
|
||||
static int read_register_count(struct applesmc_device *smc,
|
||||
@@ -746,6 +908,7 @@ static int applesmc_add(struct acpi_device *dev)
|
||||
if (!smc)
|
||||
return -ENOMEM;
|
||||
smc->dev = dev;
|
||||
+ smc->ldev = &dev->dev;
|
||||
mutex_init(&smc->reg.mutex);
|
||||
|
||||
dev_set_drvdata(&dev->dev, smc);
|
||||
@@ -807,6 +970,20 @@ static acpi_status applesmc_walk_resources(struct acpi_resource *res,
|
||||
}
|
||||
return AE_OK;
|
||||
|
||||
+ case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
|
||||
+ if (!smc->iomem_base_set) {
|
||||
+ if (res->data.fixed_memory32.address_length <
|
||||
+ APPLESMC_IOMEM_MIN_SIZE) {
|
||||
+ dev_warn(smc->ldev, "found iomem but it's too small: %u\n",
|
||||
+ res->data.fixed_memory32.address_length);
|
||||
+ return AE_OK;
|
||||
+ }
|
||||
+ smc->iomem_base_addr = res->data.fixed_memory32.address;
|
||||
+ smc->iomem_base_size = res->data.fixed_memory32.address_length;
|
||||
+ smc->iomem_base_set = true;
|
||||
+ }
|
||||
+ return AE_OK;
|
||||
+
|
||||
case ACPI_RESOURCE_TYPE_END_TAG:
|
||||
if (smc->port_base_set)
|
||||
return AE_OK;
|
||||
@@ -818,6 +995,8 @@ static acpi_status applesmc_walk_resources(struct acpi_resource *res,
|
||||
}
|
||||
}
|
||||
|
||||
+static int applesmc_try_enable_iomem(struct applesmc_device *smc);
|
||||
+
|
||||
static int applesmc_init_resources(struct applesmc_device *smc)
|
||||
{
|
||||
int ret;
|
||||
@@ -830,11 +1009,57 @@ static int applesmc_init_resources(struct applesmc_device *smc)
|
||||
if (!request_region(smc->port_base, APPLESMC_NR_PORTS, "applesmc"))
|
||||
return -ENXIO;
|
||||
|
||||
+ if (smc->iomem_base_set) {
|
||||
+ if (applesmc_try_enable_iomem(smc))
|
||||
+ smc->iomem_base_set = false;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int applesmc_try_enable_iomem(struct applesmc_device *smc)
|
||||
+{
|
||||
+ u8 test_val, ldkn_version;
|
||||
+
|
||||
+ dev_dbg(smc->ldev, "Trying to enable iomem based communication\n");
|
||||
+ smc->iomem_base = ioremap(smc->iomem_base_addr, smc->iomem_base_size);
|
||||
+ if (!smc->iomem_base)
|
||||
+ goto out;
|
||||
+
|
||||
+ /* Apple's driver does this check for some reason */
|
||||
+ test_val = ioread8(smc->iomem_base + APPLESMC_IOMEM_KEY_STATUS);
|
||||
+ if (test_val == 0xff) {
|
||||
+ dev_warn(smc->ldev,
|
||||
+ "iomem enable failed: initial status is 0xff (is %x)\n",
|
||||
+ test_val);
|
||||
+ goto out_iomem;
|
||||
+ }
|
||||
+
|
||||
+ if (read_smc(smc, "LDKN", &ldkn_version, 1)) {
|
||||
+ dev_warn(smc->ldev, "iomem enable failed: ldkn read failed\n");
|
||||
+ goto out_iomem;
|
||||
+ }
|
||||
+
|
||||
+ if (ldkn_version < 2) {
|
||||
+ dev_warn(smc->ldev,
|
||||
+ "iomem enable failed: ldkn version %u is less than minimum (2)\n",
|
||||
+ ldkn_version);
|
||||
+ goto out_iomem;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+out_iomem:
|
||||
+ iounmap(smc->iomem_base);
|
||||
+
|
||||
+out:
|
||||
+ return -ENXIO;
|
||||
+}
|
||||
+
|
||||
static void applesmc_free_resources(struct applesmc_device *smc)
|
||||
{
|
||||
+ if (smc->iomem_base_set)
|
||||
+ iounmap(smc->iomem_base);
|
||||
release_region(smc->port_base, APPLESMC_NR_PORTS);
|
||||
}
|
||||
|
||||
--
|
||||
Armbian
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Pawlowski <paul@mrarm.io>
|
||||
Date: Sun, 17 Nov 2019 23:12:18 +0100
|
||||
Subject: applesmc: fan support on T2 Macs
|
||||
|
||||
T2 Macs changed the fan values from shorts to
|
||||
floats, and changed the fan manual override
|
||||
setting from a bitmask to a per-fan boolean
|
||||
named F0Md (thanks to @kleuter for mentioning
|
||||
it).
|
||||
|
||||
A minimal soft-float implementation has been
|
||||
written for convert floats to integers (and vice
|
||||
versa).
|
||||
|
||||
Signed-off-by: Aun-Ali Zaidi <admin@kodeit.net>
|
||||
---
|
||||
drivers/hwmon/applesmc.c | 119 ++++++++--
|
||||
1 file changed, 102 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/hwmon/applesmc.c
|
||||
+++ b/drivers/hwmon/applesmc.c
|
||||
@@ -87,6 +87,7 @@
|
||||
#define FAN_ID_FMT "F%dID" /* r-o char[16] */
|
||||
|
||||
#define TEMP_SENSOR_TYPE "sp78"
|
||||
+#define FLOAT_TYPE "flt "
|
||||
|
||||
/* List of keys used to read/write fan speeds */
|
||||
static const char *const fan_speed_fmt[] = {
|
||||
@@ -96,6 +97,7 @@ static const char *const fan_speed_fmt[] = {
|
||||
"F%dSf", /* safe speed - not all models */
|
||||
"F%dTg", /* target speed (manual: rw) */
|
||||
};
|
||||
+#define FAN_MANUAL_FMT "F%dMd"
|
||||
|
||||
#define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */
|
||||
#define INIT_WAIT_MSECS 50 /* ... in 50ms increments */
|
||||
@@ -734,6 +736,42 @@ static int applesmc_read_s16(struct applesmc_device *smc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * applesmc_float_to_u32 - Retrieve the integral part of a float.
|
||||
+ * This is needed because Apple made fans use float values in the T2.
|
||||
+ * The fractional point is not significantly useful though, and the integral
|
||||
+ * part can be easily extracted.
|
||||
+ */
|
||||
+static inline u32 applesmc_float_to_u32(u32 d)
|
||||
+{
|
||||
+ u8 sign = (u8) ((d >> 31) & 1);
|
||||
+ s32 exp = (s32) ((d >> 23) & 0xff) - 0x7f;
|
||||
+ u32 fr = d & ((1u << 23) - 1);
|
||||
+
|
||||
+ if (sign || exp < 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ return (u32) ((1u << exp) + (fr >> (23 - exp)));
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * applesmc_u32_to_float - Convert an u32 into a float.
|
||||
+ * See applesmc_float_to_u32 for a rationale.
|
||||
+ */
|
||||
+static inline u32 applesmc_u32_to_float(u32 d)
|
||||
+{
|
||||
+ u32 dc = d, bc = 0, exp;
|
||||
+
|
||||
+ if (!d)
|
||||
+ return 0;
|
||||
+
|
||||
+ while (dc >>= 1)
|
||||
+ ++bc;
|
||||
+ exp = 0x7f + bc;
|
||||
+
|
||||
+ return (u32) ((exp << 23) |
|
||||
+ ((d << (23 - (exp - 0x7f))) & ((1u << 23) - 1)));
|
||||
+}
|
||||
/*
|
||||
* applesmc_device_init - initialize the accelerometer. Can sleep.
|
||||
*/
|
||||
@@ -1241,6 +1279,7 @@ static ssize_t applesmc_show_fan_speed(struct device *dev,
|
||||
struct device_attribute *attr, char *sysfsbuf)
|
||||
{
|
||||
struct applesmc_device *smc = dev_get_drvdata(dev);
|
||||
+ const struct applesmc_entry *entry;
|
||||
int ret;
|
||||
unsigned int speed = 0;
|
||||
char newkey[5];
|
||||
@@ -1249,11 +1288,21 @@ static ssize_t applesmc_show_fan_speed(struct device *dev,
|
||||
scnprintf(newkey, sizeof(newkey), fan_speed_fmt[to_option(attr)],
|
||||
to_index(attr));
|
||||
|
||||
- ret = applesmc_read_key(smc, newkey, buffer, 2);
|
||||
+ entry = applesmc_get_entry_by_key(smc, newkey);
|
||||
+ if (IS_ERR(entry))
|
||||
+ return PTR_ERR(entry);
|
||||
+
|
||||
+ if (!strcmp(entry->type, FLOAT_TYPE)) {
|
||||
+ ret = applesmc_read_entry(smc, entry, (u8 *) &speed, 4);
|
||||
+ speed = applesmc_float_to_u32(speed);
|
||||
+ } else {
|
||||
+ ret = applesmc_read_entry(smc, entry, buffer, 2);
|
||||
+ speed = ((buffer[0] << 8 | buffer[1]) >> 2);
|
||||
+ }
|
||||
+
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- speed = ((buffer[0] << 8 | buffer[1]) >> 2);
|
||||
return sysfs_emit(sysfsbuf, "%u\n", speed);
|
||||
}
|
||||
|
||||
@@ -1262,6 +1311,7 @@ static ssize_t applesmc_store_fan_speed(struct device *dev,
|
||||
const char *sysfsbuf, size_t count)
|
||||
{
|
||||
struct applesmc_device *smc = dev_get_drvdata(dev);
|
||||
+ const struct applesmc_entry *entry;
|
||||
int ret;
|
||||
unsigned long speed;
|
||||
char newkey[5];
|
||||
@@ -1273,9 +1323,18 @@ static ssize_t applesmc_store_fan_speed(struct device *dev,
|
||||
scnprintf(newkey, sizeof(newkey), fan_speed_fmt[to_option(attr)],
|
||||
to_index(attr));
|
||||
|
||||
- buffer[0] = (speed >> 6) & 0xff;
|
||||
- buffer[1] = (speed << 2) & 0xff;
|
||||
- ret = applesmc_write_key(smc, newkey, buffer, 2);
|
||||
+ entry = applesmc_get_entry_by_key(smc, newkey);
|
||||
+ if (IS_ERR(entry))
|
||||
+ return PTR_ERR(entry);
|
||||
+
|
||||
+ if (!strcmp(entry->type, FLOAT_TYPE)) {
|
||||
+ speed = applesmc_u32_to_float(speed);
|
||||
+ ret = applesmc_write_entry(smc, entry, (u8 *) &speed, 4);
|
||||
+ } else {
|
||||
+ buffer[0] = (speed >> 6) & 0xff;
|
||||
+ buffer[1] = (speed << 2) & 0xff;
|
||||
+ ret = applesmc_write_key(smc, newkey, buffer, 2);
|
||||
+ }
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -1290,12 +1349,26 @@ static ssize_t applesmc_show_fan_manual(struct device *dev,
|
||||
int ret;
|
||||
u16 manual = 0;
|
||||
u8 buffer[2];
|
||||
+ char newkey[5];
|
||||
+ bool has_newkey = false;
|
||||
+
|
||||
+ scnprintf(newkey, sizeof(newkey), FAN_MANUAL_FMT, to_index(attr));
|
||||
+
|
||||
+ ret = applesmc_has_key(smc, newkey, &has_newkey);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (has_newkey) {
|
||||
+ ret = applesmc_read_key(smc, newkey, buffer, 1);
|
||||
+ manual = buffer[0];
|
||||
+ } else {
|
||||
+ ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2);
|
||||
+ manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01;
|
||||
+ }
|
||||
|
||||
- ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01;
|
||||
return sysfs_emit(sysfsbuf, "%d\n", manual);
|
||||
}
|
||||
|
||||
@@ -1306,27 +1379,39 @@ static ssize_t applesmc_store_fan_manual(struct device *dev,
|
||||
struct applesmc_device *smc = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
u8 buffer[2];
|
||||
+ char newkey[5];
|
||||
+ bool has_newkey = false;
|
||||
unsigned long input;
|
||||
u16 val;
|
||||
|
||||
if (kstrtoul(sysfsbuf, 10, &input) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
- ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2);
|
||||
+ scnprintf(newkey, sizeof(newkey), FAN_MANUAL_FMT, to_index(attr));
|
||||
+
|
||||
+ ret = applesmc_has_key(smc, newkey, &has_newkey);
|
||||
if (ret)
|
||||
- goto out;
|
||||
+ return ret;
|
||||
|
||||
- val = (buffer[0] << 8 | buffer[1]);
|
||||
+ if (has_newkey) {
|
||||
+ buffer[0] = input & 1;
|
||||
+ ret = applesmc_write_key(smc, newkey, buffer, 1);
|
||||
+ } else {
|
||||
+ ret = applesmc_read_key(smc, FANS_MANUAL, buffer, 2);
|
||||
+ val = (buffer[0] << 8 | buffer[1]);
|
||||
+ if (ret)
|
||||
+ goto out;
|
||||
|
||||
- if (input)
|
||||
- val = val | (0x01 << to_index(attr));
|
||||
- else
|
||||
- val = val & ~(0x01 << to_index(attr));
|
||||
+ if (input)
|
||||
+ val = val | (0x01 << to_index(attr));
|
||||
+ else
|
||||
+ val = val & ~(0x01 << to_index(attr));
|
||||
|
||||
- buffer[0] = (val >> 8) & 0xFF;
|
||||
- buffer[1] = val & 0xFF;
|
||||
+ buffer[0] = (val >> 8) & 0xFF;
|
||||
+ buffer[1] = val & 0xFF;
|
||||
|
||||
- ret = applesmc_write_key(smc, FANS_MANUAL, buffer, 2);
|
||||
+ ret = applesmc_write_key(smc, FANS_MANUAL, buffer, 2);
|
||||
+ }
|
||||
|
||||
out:
|
||||
if (ret)
|
||||
--
|
||||
Armbian
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Orlando Chamberlain <redecorating@protonmail.com>
|
||||
Date: Sun, 9 Oct 2022 15:59:01 +0530
|
||||
Subject: applesmc: Add iMacPro to applesmc_whitelist
|
||||
|
||||
The iMacPro1,1 is the only iMacPro released before the line was
|
||||
discontinued. Add it to the applesmc_whitelist.
|
||||
|
||||
Signed-off-by: Orlando Chamberlain <redecorating@protonmail.com>
|
||||
---
|
||||
drivers/hwmon/applesmc.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/hwmon/applesmc.c
|
||||
+++ b/drivers/hwmon/applesmc.c
|
||||
@@ -1803,6 +1803,10 @@ static const struct dmi_system_id applesmc_whitelist[] __initconst = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Macmini") },
|
||||
},
|
||||
+ { applesmc_dmi_match, "Apple iMacPro", {
|
||||
+ DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMacPro") },
|
||||
+ },
|
||||
{ applesmc_dmi_match, "Apple MacPro", {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") },
|
||||
--
|
||||
Armbian
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Orlando Chamberlain <orlandoch.dev@gmail.com>
|
||||
Date: Tue, 24 Jan 2023 15:46:48 +1100
|
||||
Subject: applesmc: make applesmc_remove void
|
||||
|
||||
for linux6.2 compatibility
|
||||
---
|
||||
drivers/hwmon/applesmc.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/hwmon/applesmc.c
|
||||
+++ b/drivers/hwmon/applesmc.c
|
||||
@@ -979,7 +979,7 @@ static int applesmc_add(struct acpi_device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int applesmc_remove(struct acpi_device *dev)
|
||||
+static void applesmc_remove(struct acpi_device *dev)
|
||||
{
|
||||
struct applesmc_device *smc = dev_get_drvdata(&dev->dev);
|
||||
|
||||
@@ -990,7 +990,7 @@ static int applesmc_remove(struct acpi_device *dev)
|
||||
mutex_destroy(&smc->reg.mutex);
|
||||
kfree(smc);
|
||||
|
||||
- return 0;
|
||||
+ return;
|
||||
}
|
||||
|
||||
static acpi_status applesmc_walk_resources(struct acpi_resource *res,
|
||||
--
|
||||
Armbian
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Orlando Chamberlain <orlandoch.dev@gmail.com>
|
||||
Date: Mon, 30 Jan 2023 18:42:21 +1100
|
||||
Subject: applesmc: battery charge limiter
|
||||
|
||||
---
|
||||
drivers/hwmon/applesmc.c | 42 +++++++++-
|
||||
1 file changed, 41 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/hwmon/applesmc.c
|
||||
+++ b/drivers/hwmon/applesmc.c
|
||||
@@ -1477,6 +1477,35 @@ static void applesmc_brightness_set(struct led_classdev *led_cdev,
|
||||
dev_dbg(led_cdev->dev, "work was already on the queue.\n");
|
||||
}
|
||||
|
||||
+static ssize_t applesmc_BCLM_store(struct device *dev,
|
||||
+ struct device_attribute *attr, char *sysfsbuf, size_t count)
|
||||
+{
|
||||
+ struct applesmc_device *smc = dev_get_drvdata(dev);
|
||||
+ u8 val;
|
||||
+
|
||||
+ if (kstrtou8(sysfsbuf, 10, &val) < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (val < 0 || val > 100)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (applesmc_write_key(smc, "BCLM", &val, 1))
|
||||
+ return -ENODEV;
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static ssize_t applesmc_BCLM_show(struct device *dev,
|
||||
+ struct device_attribute *attr, char *sysfsbuf)
|
||||
+{
|
||||
+ struct applesmc_device *smc = dev_get_drvdata(dev);
|
||||
+ u8 val;
|
||||
+
|
||||
+ if (applesmc_read_key(smc, "BCLM", &val, 1))
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ return sysfs_emit(sysfsbuf, "%d\n", val);
|
||||
+}
|
||||
+
|
||||
static ssize_t applesmc_key_count_show(struct device *dev,
|
||||
struct device_attribute *attr, char *sysfsbuf)
|
||||
{
|
||||
@@ -1611,6 +1640,11 @@ static struct applesmc_node_group temp_group[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
+static struct applesmc_node_group BCLM_group[] = {
|
||||
+ { "battery_charge_limit", applesmc_BCLM_show, applesmc_BCLM_store },
|
||||
+ { }
|
||||
+};
|
||||
+
|
||||
/* Module stuff */
|
||||
|
||||
/*
|
||||
@@ -1829,10 +1863,13 @@ static int applesmc_create_modules(struct applesmc_device *smc)
|
||||
ret = applesmc_create_nodes(smc, info_group, 1);
|
||||
if (ret)
|
||||
goto out;
|
||||
+ ret = applesmc_create_nodes(smc, BCLM_group, 1);
|
||||
+ if (ret)
|
||||
+ goto out_info;
|
||||
|
||||
ret = applesmc_create_nodes(smc, fan_group, smc->reg.fan_count);
|
||||
if (ret)
|
||||
- goto out_info;
|
||||
+ goto out_bclm;
|
||||
|
||||
ret = applesmc_create_nodes(smc, temp_group, smc->reg.index_count);
|
||||
if (ret)
|
||||
@@ -1868,6 +1905,8 @@ static int applesmc_create_modules(struct applesmc_device *smc)
|
||||
applesmc_destroy_nodes(smc, temp_group);
|
||||
out_fans:
|
||||
applesmc_destroy_nodes(smc, fan_group);
|
||||
+out_bclm:
|
||||
+ applesmc_destroy_nodes(smc, BCLM_group);
|
||||
out_info:
|
||||
applesmc_destroy_nodes(smc, info_group);
|
||||
out:
|
||||
@@ -1882,6 +1921,7 @@ static void applesmc_destroy_modules(struct applesmc_device *smc)
|
||||
applesmc_release_accelerometer(smc);
|
||||
applesmc_destroy_nodes(smc, temp_group);
|
||||
applesmc_destroy_nodes(smc, fan_group);
|
||||
+ applesmc_destroy_nodes(smc, BCLM_group);
|
||||
applesmc_destroy_nodes(smc, info_group);
|
||||
}
|
||||
|
||||
--
|
||||
Armbian
|
||||
|
||||
5052
patch/kernel/archive/uefi-x86-6.19/4001-asahi-trackpad.patch
Normal file
5052
patch/kernel/archive/uefi-x86-6.19/4001-asahi-trackpad.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,81 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aditya Garg <gargaditya08@live.com>
|
||||
Date: Fri, 12 Sep 2025 12:09:01 +0000
|
||||
Subject: HID: apple: ignore the trackpad on T2 Macs
|
||||
|
||||
In order to manage the trackpad on T2 Macs by hid-magicmouse driver
|
||||
we need to ensure that it is not bound by the hid-apple driver. Use
|
||||
the existing APPLE_IGNORE_MOUSE quirk for the same.
|
||||
|
||||
Signed-off-by: Aditya Garg <gargaditya08@live.com>
|
||||
---
|
||||
drivers/hid/hid-apple.c | 27 ++++++----
|
||||
1 file changed, 17 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/hid/hid-apple.c
|
||||
+++ b/drivers/hid/hid-apple.c
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "hid-ids.h"
|
||||
|
||||
#define APPLE_RDESC_JIS BIT(0)
|
||||
-/* BIT(1) reserved, was: APPLE_IGNORE_MOUSE */
|
||||
+#define APPLE_IGNORE_MOUSE BIT(1)
|
||||
#define APPLE_HAS_FN BIT(2)
|
||||
/* BIT(3) reserved, was: APPLE_HIDDEV */
|
||||
#define APPLE_ISO_TILDE_QUIRK BIT(4)
|
||||
@@ -951,6 +951,9 @@ static int apple_probe(struct hid_device *hdev,
|
||||
hdev->type != HID_TYPE_SPI_KEYBOARD)
|
||||
return -ENODEV;
|
||||
|
||||
+ if (quirks & APPLE_IGNORE_MOUSE && hdev->type == HID_TYPE_USBMOUSE)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
asc = devm_kzalloc(&hdev->dev, sizeof(*asc), GFP_KERNEL);
|
||||
if (asc == NULL) {
|
||||
hid_err(hdev, "can't alloc apple descriptor\n");
|
||||
@@ -1173,27 +1176,31 @@ static const struct hid_device_id apple_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K),
|
||||
- .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK },
|
||||
+ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK |
|
||||
+ APPLE_IGNORE_MOUSE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK |
|
||||
- APPLE_DISABLE_FKEYS },
|
||||
+ APPLE_DISABLE_FKEYS | APPLE_IGNORE_MOUSE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK |
|
||||
- APPLE_DISABLE_FKEYS },
|
||||
+ APPLE_DISABLE_FKEYS | APPLE_IGNORE_MOUSE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK |
|
||||
- APPLE_DISABLE_FKEYS },
|
||||
+ APPLE_DISABLE_FKEYS | APPLE_IGNORE_MOUSE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK |
|
||||
- APPLE_DISABLE_FKEYS },
|
||||
+ APPLE_DISABLE_FKEYS | APPLE_IGNORE_MOUSE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K),
|
||||
- .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_DISABLE_FKEYS },
|
||||
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_DISABLE_FKEYS |
|
||||
+ APPLE_IGNORE_MOUSE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223),
|
||||
- .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_DISABLE_FKEYS },
|
||||
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_DISABLE_FKEYS |
|
||||
+ APPLE_IGNORE_MOUSE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K),
|
||||
- .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_IGNORE_MOUSE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F),
|
||||
- .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_DISABLE_FKEYS },
|
||||
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_DISABLE_FKEYS |
|
||||
+ APPLE_IGNORE_MOUSE },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
|
||||
--
|
||||
Armbian
|
||||
|
||||
@@ -0,0 +1,417 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aditya Garg <gargaditya08@live.com>
|
||||
Date: Tue, 11 Mar 2025 18:44:06 +0530
|
||||
Subject: HID: magicmouse: Add support for trackpads found on T2 Macs
|
||||
|
||||
This patch adds support for trackpads found on Macs with the T2
|
||||
Security Chip. The touch report format differs from other trackpads.
|
||||
It is the same format as type 4 in bcm5974.c
|
||||
|
||||
Signed-off-by: Aditya Garg <gargaditya08@live.com>
|
||||
---
|
||||
drivers/hid/hid-magicmouse.c | 296 +++++++++-
|
||||
1 file changed, 275 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/hid/hid-magicmouse.c
|
||||
+++ b/drivers/hid/hid-magicmouse.c
|
||||
@@ -118,6 +118,105 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
|
||||
#define TRACKPAD2_RES_Y \
|
||||
((TRACKPAD2_MAX_Y - TRACKPAD2_MIN_Y) / (TRACKPAD2_DIMENSION_Y / 100))
|
||||
|
||||
+#define J140K_TP_DIMENSION_X (float)12100
|
||||
+#define J140K_TP_MIN_X -5318
|
||||
+#define J140K_TP_MAX_X 5787
|
||||
+#define J140K_TP_RES_X \
|
||||
+ ((J140K_TP_MAX_X - J140K_TP_MIN_X) / (J140K_TP_DIMENSION_X / 100))
|
||||
+#define J140K_TP_DIMENSION_Y (float)8200
|
||||
+#define J140K_TP_MIN_Y -157
|
||||
+#define J140K_TP_MAX_Y 7102
|
||||
+#define J140K_TP_RES_Y \
|
||||
+ ((J140K_TP_MAX_Y - J140K_TP_MIN_Y) / (J140K_TP_DIMENSION_Y / 100))
|
||||
+
|
||||
+#define J132_TP_DIMENSION_X (float)13500
|
||||
+#define J132_TP_MIN_X -6243
|
||||
+#define J132_TP_MAX_X 6749
|
||||
+#define J132_TP_RES_X \
|
||||
+ ((J132_TP_MAX_X - J132_TP_MIN_X) / (J132_TP_DIMENSION_X / 100))
|
||||
+#define J132_TP_DIMENSION_Y (float)8400
|
||||
+#define J132_TP_MIN_Y -170
|
||||
+#define J132_TP_MAX_Y 7685
|
||||
+#define J132_TP_RES_Y \
|
||||
+ ((J132_TP_MAX_Y - J132_TP_MIN_Y) / (J132_TP_DIMENSION_Y / 100))
|
||||
+
|
||||
+#define J680_TP_DIMENSION_X (float)16000
|
||||
+#define J680_TP_MIN_X -7456
|
||||
+#define J680_TP_MAX_X 7976
|
||||
+#define J680_TP_RES_X \
|
||||
+ ((J680_TP_MAX_X - J680_TP_MIN_X) / (J680_TP_DIMENSION_X / 100))
|
||||
+#define J680_TP_DIMENSION_Y (float)10000
|
||||
+#define J680_TP_MIN_Y -163
|
||||
+#define J680_TP_MAX_Y 9283
|
||||
+#define J680_TP_RES_Y \
|
||||
+ ((J680_TP_MAX_Y - J680_TP_MIN_Y) / (J680_TP_DIMENSION_Y / 100))
|
||||
+
|
||||
+#define J680_ALT_TP_DIMENSION_X (float)16000
|
||||
+#define J680_ALT_TP_MIN_X -7456
|
||||
+#define J680_ALT_TP_MAX_X 7976
|
||||
+#define J680_ALT_TP_RES_X \
|
||||
+ ((J680_ALT_TP_MAX_X - J680_ALT_TP_MIN_X) / (J680_ALT_TP_DIMENSION_X / 100))
|
||||
+#define J680_ALT_TP_DIMENSION_Y (float)10000
|
||||
+#define J680_ALT_TP_MIN_Y -163
|
||||
+#define J680_ALT_TP_MAX_Y 9283
|
||||
+#define J680_ALT_TP_RES_Y \
|
||||
+ ((J680_ALT_TP_MAX_Y - J680_ALT_TP_MIN_Y) / (J680_ALT_TP_DIMENSION_Y / 100))
|
||||
+
|
||||
+#define J213_TP_DIMENSION_X (float)13500
|
||||
+#define J213_TP_MIN_X -6243
|
||||
+#define J213_TP_MAX_X 6749
|
||||
+#define J213_TP_RES_X \
|
||||
+ ((J213_TP_MAX_X - J213_TP_MIN_X) / (J213_TP_DIMENSION_X / 100))
|
||||
+#define J213_TP_DIMENSION_Y (float)8400
|
||||
+#define J213_TP_MIN_Y -170
|
||||
+#define J213_TP_MAX_Y 7685
|
||||
+#define J213_TP_RES_Y \
|
||||
+ ((J213_TP_MAX_Y - J213_TP_MIN_Y) / (J213_TP_DIMENSION_Y / 100))
|
||||
+
|
||||
+#define J214K_TP_DIMENSION_X (float)13200
|
||||
+#define J214K_TP_MIN_X -6046
|
||||
+#define J214K_TP_MAX_X 6536
|
||||
+#define J214K_TP_RES_X \
|
||||
+ ((J214K_TP_MAX_X - J214K_TP_MIN_X) / (J214K_TP_DIMENSION_X / 100))
|
||||
+#define J214K_TP_DIMENSION_Y (float)8200
|
||||
+#define J214K_TP_MIN_Y -164
|
||||
+#define J214K_TP_MAX_Y 7439
|
||||
+#define J214K_TP_RES_Y \
|
||||
+ ((J214K_TP_MAX_Y - J214K_TP_MIN_Y) / (J214K_TP_DIMENSION_Y / 100))
|
||||
+
|
||||
+#define J223_TP_DIMENSION_X (float)13200
|
||||
+#define J223_TP_MIN_X -6046
|
||||
+#define J223_TP_MAX_X 6536
|
||||
+#define J223_TP_RES_X \
|
||||
+ ((J223_TP_MAX_X - J223_TP_MIN_X) / (J223_TP_DIMENSION_X / 100))
|
||||
+#define J223_TP_DIMENSION_Y (float)8200
|
||||
+#define J223_TP_MIN_Y -164
|
||||
+#define J223_TP_MAX_Y 7439
|
||||
+#define J223_TP_RES_Y \
|
||||
+ ((J223_TP_MAX_Y - J223_TP_MIN_Y) / (J223_TP_DIMENSION_Y / 100))
|
||||
+
|
||||
+#define J230K_TP_DIMENSION_X (float)12100
|
||||
+#define J230K_TP_MIN_X -5318
|
||||
+#define J230K_TP_MAX_X 5787
|
||||
+#define J230K_TP_RES_X \
|
||||
+ ((J230K_TP_MAX_X - J230K_TP_MIN_X) / (J230K_TP_DIMENSION_X / 100))
|
||||
+#define J230K_TP_DIMENSION_Y (float)8200
|
||||
+#define J230K_TP_MIN_Y -157
|
||||
+#define J230K_TP_MAX_Y 7102
|
||||
+#define J230K_TP_RES_Y \
|
||||
+ ((J230K_TP_MAX_Y - J230K_TP_MIN_Y) / (J230K_TP_DIMENSION_Y / 100))
|
||||
+
|
||||
+#define J152F_TP_DIMENSION_X (float)16000
|
||||
+#define J152F_TP_MIN_X -7456
|
||||
+#define J152F_TP_MAX_X 7976
|
||||
+#define J152F_TP_RES_X \
|
||||
+ ((J152F_TP_MAX_X - J152F_TP_MIN_X) / (J152F_TP_DIMENSION_X / 100))
|
||||
+#define J152F_TP_DIMENSION_Y (float)10000
|
||||
+#define J152F_TP_MIN_Y -163
|
||||
+#define J152F_TP_MAX_Y 9283
|
||||
+#define J152F_TP_RES_Y \
|
||||
+ ((J152F_TP_MAX_Y - J152F_TP_MIN_Y) / (J152F_TP_DIMENSION_Y / 100))
|
||||
+
|
||||
/* These are fallback values, since the real values will be queried from the device. */
|
||||
#define J314_TP_DIMENSION_X (float)13000
|
||||
#define J314_TP_MIN_X -5900
|
||||
@@ -130,7 +229,11 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
|
||||
#define J314_TP_RES_Y \
|
||||
((J314_TP_MAX_Y - J314_TP_MIN_Y) / (J314_TP_DIMENSION_Y / 100))
|
||||
|
||||
-#define J314_TP_MAX_FINGER_ORIENTATION 16384
|
||||
+#define T2_TOUCHPAD_ENTRY(model) \
|
||||
+ { USB_DEVICE_ID_APPLE_WELLSPRINGT2_##model, model##_TP_MIN_X, model##_TP_MIN_Y, \
|
||||
+model##_TP_MAX_X, model##_TP_MAX_Y, model##_TP_RES_X, model##_TP_RES_Y }
|
||||
+
|
||||
+#define INTERNAL_TP_MAX_FINGER_ORIENTATION 16384
|
||||
|
||||
struct magicmouse_input_ops {
|
||||
int (*raw_event)(struct hid_device *hdev,
|
||||
@@ -733,7 +836,7 @@ static void report_finger_data(struct input_dev *input, int slot,
|
||||
input_report_abs(input, ABS_MT_WIDTH_MINOR,
|
||||
le16_to_int(f->tool_minor) << 1);
|
||||
input_report_abs(input, ABS_MT_ORIENTATION,
|
||||
- J314_TP_MAX_FINGER_ORIENTATION - le16_to_int(f->orientation));
|
||||
+ INTERNAL_TP_MAX_FINGER_ORIENTATION - le16_to_int(f->orientation));
|
||||
input_report_abs(input, ABS_MT_PRESSURE, le16_to_int(f->pressure));
|
||||
input_report_abs(input, ABS_MT_POSITION_X, pos->x);
|
||||
input_report_abs(input, ABS_MT_POSITION_Y, pos->y);
|
||||
@@ -821,6 +924,20 @@ static int magicmouse_raw_event_spi(struct hid_device *hdev,
|
||||
return magicmouse_raw_event_mtp(hdev, report, data + hdr_sz, size - hdr_sz);
|
||||
}
|
||||
|
||||
+static int magicmouse_raw_event_t2(struct hid_device *hdev,
|
||||
+ struct hid_report *report, u8 *data, int size)
|
||||
+{
|
||||
+ const size_t hdr_sz = sizeof(struct tp_mouse_report);
|
||||
+
|
||||
+ if (!size)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (data[0] != TRACKPAD2_USB_REPORT_ID || size < hdr_sz)
|
||||
+ return 0;
|
||||
+
|
||||
+ return magicmouse_raw_event_mtp(hdev, report, data + hdr_sz, size - hdr_sz);
|
||||
+}
|
||||
+
|
||||
static int magicmouse_event(struct hid_device *hdev, struct hid_field *field,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
{
|
||||
@@ -1018,8 +1135,32 @@ static int magicmouse_setup_input_usb(struct input_dev *input,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int magicmouse_setup_input_mtp(struct input_dev *input,
|
||||
- struct hid_device *hdev)
|
||||
+struct magicmouse_t2_properties {
|
||||
+ u32 id;
|
||||
+ int min_x;
|
||||
+ int min_y;
|
||||
+ int max_x;
|
||||
+ int max_y;
|
||||
+ int res_x;
|
||||
+ int res_y;
|
||||
+};
|
||||
+
|
||||
+static const struct magicmouse_t2_properties magicmouse_t2_configs[] = {
|
||||
+ T2_TOUCHPAD_ENTRY(J140K),
|
||||
+ T2_TOUCHPAD_ENTRY(J132),
|
||||
+ T2_TOUCHPAD_ENTRY(J680),
|
||||
+ T2_TOUCHPAD_ENTRY(J680_ALT),
|
||||
+ T2_TOUCHPAD_ENTRY(J213),
|
||||
+ T2_TOUCHPAD_ENTRY(J214K),
|
||||
+ T2_TOUCHPAD_ENTRY(J223),
|
||||
+ T2_TOUCHPAD_ENTRY(J230K),
|
||||
+ T2_TOUCHPAD_ENTRY(J152F),
|
||||
+};
|
||||
+
|
||||
+static int magicmouse_setup_input_int_tpd(struct input_dev *input,
|
||||
+ struct hid_device *hdev, int min_x, int min_y,
|
||||
+ int max_x, int max_y, int res_x, int res_y,
|
||||
+ bool query_dimensions)
|
||||
{
|
||||
int error;
|
||||
int mt_flags = 0;
|
||||
@@ -1060,19 +1201,17 @@ static int magicmouse_setup_input_mtp(struct input_dev *input,
|
||||
input_abs_set_res(input, ABS_MT_PRESSURE, 1);
|
||||
|
||||
/* finger orientation */
|
||||
- input_set_abs_params(input, ABS_MT_ORIENTATION, -J314_TP_MAX_FINGER_ORIENTATION,
|
||||
- J314_TP_MAX_FINGER_ORIENTATION, 0, 0);
|
||||
+ input_set_abs_params(input, ABS_MT_ORIENTATION, -INTERNAL_TP_MAX_FINGER_ORIENTATION,
|
||||
+ INTERNAL_TP_MAX_FINGER_ORIENTATION, 0, 0);
|
||||
|
||||
/* finger position */
|
||||
- input_set_abs_params(input, ABS_MT_POSITION_X, J314_TP_MIN_X, J314_TP_MAX_X,
|
||||
- 0, 0);
|
||||
+ input_set_abs_params(input, ABS_MT_POSITION_X, min_x, max_x, 0, 0);
|
||||
/* Y axis is inverted */
|
||||
- input_set_abs_params(input, ABS_MT_POSITION_Y, -J314_TP_MAX_Y, -J314_TP_MIN_Y,
|
||||
- 0, 0);
|
||||
+ input_set_abs_params(input, ABS_MT_POSITION_Y, -max_y, -min_y, 0, 0);
|
||||
|
||||
/* X/Y resolution */
|
||||
- input_abs_set_res(input, ABS_MT_POSITION_X, J314_TP_RES_X);
|
||||
- input_abs_set_res(input, ABS_MT_POSITION_Y, J314_TP_RES_Y);
|
||||
+ input_abs_set_res(input, ABS_MT_POSITION_X, res_x);
|
||||
+ input_abs_set_res(input, ABS_MT_POSITION_Y, res_y);
|
||||
|
||||
input_set_events_per_packet(input, 60);
|
||||
|
||||
@@ -1099,7 +1238,20 @@ static int magicmouse_setup_input_mtp(struct input_dev *input,
|
||||
*/
|
||||
input->open = magicmouse_open;
|
||||
input->close = magicmouse_close;
|
||||
- msc->query_dimensions = true;
|
||||
+ msc->query_dimensions = query_dimensions;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int magicmouse_setup_input_mtp(struct input_dev *input,
|
||||
+ struct hid_device *hdev)
|
||||
+{
|
||||
+ int ret = magicmouse_setup_input_int_tpd(input, hdev, J314_TP_MIN_X,
|
||||
+ J314_TP_MIN_Y, J314_TP_MAX_X,
|
||||
+ J314_TP_MAX_Y, J314_TP_RES_X,
|
||||
+ J314_TP_RES_Y, true);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1107,7 +1259,34 @@ static int magicmouse_setup_input_mtp(struct input_dev *input,
|
||||
static int magicmouse_setup_input_spi(struct input_dev *input,
|
||||
struct hid_device *hdev)
|
||||
{
|
||||
- int ret = magicmouse_setup_input_mtp(input, hdev);
|
||||
+ int ret = magicmouse_setup_input_int_tpd(input, hdev, J314_TP_MIN_X,
|
||||
+ J314_TP_MIN_Y, J314_TP_MAX_X,
|
||||
+ J314_TP_MAX_Y, J314_TP_RES_X,
|
||||
+ J314_TP_RES_Y, true);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int magicmouse_setup_input_t2(struct input_dev *input,
|
||||
+ struct hid_device *hdev)
|
||||
+{
|
||||
+ int min_x, min_y, max_x, max_y, res_x, res_y;
|
||||
+
|
||||
+ for (size_t i = 0; i < ARRAY_SIZE(magicmouse_t2_configs); i++) {
|
||||
+ if (magicmouse_t2_configs[i].id == hdev->product) {
|
||||
+ min_x = magicmouse_t2_configs[i].min_x;
|
||||
+ min_y = magicmouse_t2_configs[i].min_y;
|
||||
+ max_x = magicmouse_t2_configs[i].max_x;
|
||||
+ max_y = magicmouse_t2_configs[i].max_y;
|
||||
+ res_x = magicmouse_t2_configs[i].res_x;
|
||||
+ res_y = magicmouse_t2_configs[i].res_y;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ int ret = magicmouse_setup_input_int_tpd(input, hdev, min_x, min_y,
|
||||
+ max_x, max_y, res_x, res_y, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1180,6 +1359,18 @@ static int magicmouse_enable_multitouch(struct hid_device *hdev)
|
||||
feature = feature_mt_trackpad2_usb;
|
||||
}
|
||||
break;
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F:
|
||||
+ feature_size = sizeof(feature_mt_trackpad2_usb);
|
||||
+ feature = feature_mt_trackpad2_usb;
|
||||
+ break;
|
||||
case USB_DEVICE_ID_APPLE_MAGICMOUSE2:
|
||||
case USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC:
|
||||
feature_size = sizeof(feature_mt_mouse2);
|
||||
@@ -1273,8 +1464,23 @@ static int magicmouse_probe(struct hid_device *hdev,
|
||||
int ret;
|
||||
|
||||
if ((id->bus == BUS_SPI || id->bus == BUS_HOST) && id->vendor == SPI_VENDOR_ID_APPLE &&
|
||||
- hdev->type != HID_TYPE_SPI_MOUSE)
|
||||
- return -ENODEV;
|
||||
+ hdev->type != HID_TYPE_SPI_MOUSE)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ switch (id->product) {
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F:
|
||||
+ if (hdev->type != HID_TYPE_USBMOUSE)
|
||||
+ return -ENODEV;
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
msc = devm_kzalloc(&hdev->dev, sizeof(*msc), GFP_KERNEL);
|
||||
if (msc == NULL) {
|
||||
@@ -1284,15 +1490,33 @@ static int magicmouse_probe(struct hid_device *hdev,
|
||||
|
||||
// internal trackpad use a data format use input ops to avoid
|
||||
// conflicts with the report ID.
|
||||
- if (id->bus == BUS_HOST) {
|
||||
+ switch (id->bus) {
|
||||
+ case BUS_HOST:
|
||||
msc->input_ops.raw_event = magicmouse_raw_event_mtp;
|
||||
msc->input_ops.setup_input = magicmouse_setup_input_mtp;
|
||||
- } else if (id->bus == BUS_SPI) {
|
||||
+ break;
|
||||
+ case BUS_SPI:
|
||||
msc->input_ops.raw_event = magicmouse_raw_event_spi;
|
||||
msc->input_ops.setup_input = magicmouse_setup_input_spi;
|
||||
- } else {
|
||||
- msc->input_ops.raw_event = magicmouse_raw_event_usb;
|
||||
- msc->input_ops.setup_input = magicmouse_setup_input_usb;
|
||||
+ break;
|
||||
+ default:
|
||||
+ switch (id->product) {
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F:
|
||||
+ msc->input_ops.raw_event = magicmouse_raw_event_t2;
|
||||
+ msc->input_ops.setup_input = magicmouse_setup_input_t2;
|
||||
+ break;
|
||||
+ default:
|
||||
+ msc->input_ops.raw_event = magicmouse_raw_event_usb;
|
||||
+ msc->input_ops.setup_input = magicmouse_setup_input_usb;
|
||||
+ }
|
||||
}
|
||||
|
||||
msc->scroll_accel = SCROLL_ACCEL_DEFAULT;
|
||||
@@ -1353,6 +1577,18 @@ static int magicmouse_probe(struct hid_device *hdev,
|
||||
TRACKPAD2_USB_REPORT_ID, 0);
|
||||
}
|
||||
break;
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K:
|
||||
+ case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F:
|
||||
+ report = hid_register_report(hdev, HID_INPUT_REPORT,
|
||||
+ TRACKPAD2_USB_REPORT_ID, 0);
|
||||
+ break;
|
||||
case HID_ANY_ID:
|
||||
switch (id->bus) {
|
||||
case BUS_HOST:
|
||||
@@ -1464,6 +1700,24 @@ static const struct hid_device_id magic_mice[] = {
|
||||
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC), .driver_data = 0 },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
|
||||
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC), .driver_data = 0 },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
|
||||
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K), .driver_data = 0 },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
|
||||
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132), .driver_data = 0 },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
|
||||
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680), .driver_data = 0 },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
|
||||
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT), .driver_data = 0 },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
|
||||
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213), .driver_data = 0 },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
|
||||
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K), .driver_data = 0 },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
|
||||
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223), .driver_data = 0 },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
|
||||
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K), .driver_data = 0 },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
|
||||
+ USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F), .driver_data = 0 },
|
||||
{ HID_SPI_DEVICE(SPI_VENDOR_ID_APPLE, HID_ANY_ID),
|
||||
.driver_data = 0 },
|
||||
{ HID_DEVICE(BUS_HOST, HID_GROUP_ANY, HOST_VENDOR_ID_APPLE,
|
||||
--
|
||||
Armbian
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aditya Garg <gargaditya08@live.com>
|
||||
Date: Wed, 8 Oct 2025 01:48:18 +0000
|
||||
Subject: HID: magicmouse: fix regression breaking support for Magic Trackpad 1
|
||||
|
||||
The case HID_ANY_ID and default are technically the same, but the first
|
||||
one was assigning no report to the Magic Trackpad 1, while the second
|
||||
one assigns the correct report. Since the first case is matched first,
|
||||
the Magic Trackpad 1 was not being assigned any report, breaking
|
||||
support for it.
|
||||
|
||||
Signed-off-by: Aditya Garg <gargaditya08@live.com>
|
||||
---
|
||||
drivers/hid/hid-magicmouse.c | 15 ++++------
|
||||
1 file changed, 6 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/hid/hid-magicmouse.c
|
||||
+++ b/drivers/hid/hid-magicmouse.c
|
||||
@@ -1589,7 +1589,7 @@ static int magicmouse_probe(struct hid_device *hdev,
|
||||
report = hid_register_report(hdev, HID_INPUT_REPORT,
|
||||
TRACKPAD2_USB_REPORT_ID, 0);
|
||||
break;
|
||||
- case HID_ANY_ID:
|
||||
+ default:
|
||||
switch (id->bus) {
|
||||
case BUS_HOST:
|
||||
report = hid_register_report(hdev, HID_INPUT_REPORT, MTP_REPORT_ID, 0);
|
||||
@@ -1597,15 +1597,12 @@ static int magicmouse_probe(struct hid_device *hdev,
|
||||
case BUS_SPI:
|
||||
report = hid_register_report(hdev, HID_INPUT_REPORT, SPI_REPORT_ID, 0);
|
||||
break;
|
||||
- default:
|
||||
- break;
|
||||
+ default: /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
|
||||
+ report = hid_register_report(hdev, HID_INPUT_REPORT,
|
||||
+ TRACKPAD_REPORT_ID, 0);
|
||||
+ report = hid_register_report(hdev, HID_INPUT_REPORT,
|
||||
+ DOUBLE_REPORT_ID, 0);
|
||||
}
|
||||
- break;
|
||||
- default: /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
|
||||
- report = hid_register_report(hdev, HID_INPUT_REPORT,
|
||||
- TRACKPAD_REPORT_ID, 0);
|
||||
- report = hid_register_report(hdev, HID_INPUT_REPORT,
|
||||
- DOUBLE_REPORT_ID, 0);
|
||||
}
|
||||
|
||||
if (!report) {
|
||||
--
|
||||
Armbian
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ashish Arora <ashisharora.linux@outlook.com>
|
||||
Date: Sat, 8 Jan 2022 21:43:18 +1100
|
||||
Subject: drm/i915: Discard large BIOS framebuffers causing display corruption
|
||||
|
||||
On certain 4k panels, the BIOS framebuffer is larger than what panel
|
||||
requires causing display corruption. Introduce a check for the same.
|
||||
|
||||
Signed-off-by: Ashish Arora <ashisharora.linux@outlook.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/display/intel_fbdev.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c
|
||||
index 111111111111..222222222222 100644
|
||||
--- a/drivers/gpu/drm/i915/display/intel_fbdev.c
|
||||
+++ b/drivers/gpu/drm/i915/display/intel_fbdev.c
|
||||
@@ -224,10 +224,10 @@ int intel_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
|
||||
ifbdev->fb = NULL;
|
||||
|
||||
if (fb &&
|
||||
- (sizes->fb_width > fb->base.width ||
|
||||
- sizes->fb_height > fb->base.height)) {
|
||||
+ (sizes->fb_width != fb->base.width ||
|
||||
+ sizes->fb_height != fb->base.height)) {
|
||||
drm_dbg_kms(display->drm,
|
||||
- "BIOS fb too small (%dx%d), we require (%dx%d),"
|
||||
+ "BIOS fb not valid (%dx%d), we require (%dx%d),"
|
||||
" releasing it\n",
|
||||
fb->base.width, fb->base.height,
|
||||
sizes->fb_width, sizes->fb_height);
|
||||
--
|
||||
Armbian
|
||||
|
||||
Reference in New Issue
Block a user