* [PATCH v5 0/5] Fix, extend and support OF to mc13xxx pwrbutton
From: Alexander Kurz @ 2025-10-08 6:43 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Dmitry Torokhov, Dzmitry Sankouski, Dr. David Alan Gilbert,
Heiko Stuebner, Uwe Kleine-König, devicetree, linux-input
Cc: linux-kernel, Alexander Kurz
Goal of this patch series is to make the mc13892 PWRON1 button usable,
found e.g. on amazon kindle D01100/D01200/EY21 readers.
A ten-year-old IRQ issue needed a fix, mc13783-pwrbutton had to be
extended to the other to mc13xxx PMIC as well and adding OF support.
The implementation has been tested only with PWRON1 on an mc13892.
Changes in v5:
- Link to v4: https://lore.kernel.org/linux-input/20250914193723.10544-1-akurz@blala.de/
- Rebase to current to include already merged dt-schema patches and
a different mc13xxx related patch.
- Drop patch to use devm_mfd_add_devices and devm_regmap_add_irq_chip -
won't like to do the proposed mutex-cleanup now.
- While adding OF support, remove the platform_data configuration
interface as proposed by Dmitry Torokhov. Also drop the change
to use module_platform_driver_probe.
Changes in v4:
- Link to v3: https://lore.kernel.org/linux-input/20250829201517.15374-1-akurz@blala.de/
- Rebase to git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
tags/ib-mfd-input-rtc-v6.18 in order to include a different mc13xxx
related patch (sorry for that).
- Re-ordered commits since dt-bindings changes already go reviewes by
Rob Herring.
- Following Dmitrys suggestions, resources for irq are now passed from
mfd to input allowing a more simple implementation. Work on other mfd
cells with irq usage might still be a future project.
- Input-related differences between the mc13xxx variants are encoded
in data structures, making the implementation of mc13892 PWRON3 a
simple task.
Changes in v3:
- Link to v2: https://lore.kernel.org/linux-input/20250823144441.12654-1-akurz@blala.de/
- Undo all changes to led-control (rename to fsl,led-control), thanks Rob
- Restructured the new buttons node for unevaluatedProperties: false
- Various other remarks from Rob
- Rebase to current state
Changes in v2:
- Link to v1: https://lore.kernel.org/linux-input/20250817102751.29709-1-akurz@blala.de/
- Convert dt-bindings from txt to fsl,mc13xxx.yaml and add vendor prefix
to led-control property, causing changes in dts and driver.
- Change node name from pwrbuttons to buttons
- Change property debounce-delay-value to debounce-delay-ms
- Fixed a section mismatch error
- Fixed https://lore.kernel.org/r/202508210551.VzAtE5re-lkp@intel.com/
(wrong index used when converting to array access)
- Usage of generic device properties API in mc13783-pwrbutton.c
- Provide chip-specific max button id via platform_device_id, therefore
swap patches 3 and 4.
Alexander Kurz (5):
Input: mc13783-pwrbutton: use managed resources
Input: mc13783-pwrbutton: fix irq mixup and use resources
Input: mc13783-pwrbutton: convert pdata members to array
Input: mc13783-pwrbutton: enable other mc13xxx PMIC
Input: mc13783-pwrbutton: add OF support and drop platform_data
drivers/input/misc/Kconfig | 4 +-
drivers/input/misc/mc13783-pwrbutton.c | 278 ++++++++++++++-----------
drivers/mfd/mc13xxx-core.c | 49 ++++-
drivers/mfd/mc13xxx.h | 2 +
include/linux/mfd/mc13783.h | 4 +-
include/linux/mfd/mc13892.h | 1 +
include/linux/mfd/mc13xxx.h | 20 +-
7 files changed, 207 insertions(+), 151 deletions(-)
--
2.39.5
^ permalink raw reply
* [PATCH v5 1/5] Input: mc13783-pwrbutton: use managed resources
From: Alexander Kurz @ 2025-10-08 6:43 UTC (permalink / raw)
To: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Dmitry Torokhov, Dzmitry Sankouski, Dr. David Alan Gilbert,
Heiko Stuebner, Uwe Kleine-König, devicetree, linux-input
Cc: linux-kernel, Alexander Kurz
In-Reply-To: <20251008064401.13863-1-akurz@blala.de>
Use devres functionality to simplify resource freeing, dev.parent will
be set by devm_input_allocate_device().
Signed-off-by: Alexander Kurz <akurz@blala.de>
---
drivers/input/misc/mc13783-pwrbutton.c | 28 ++++++++------------------
1 file changed, 8 insertions(+), 20 deletions(-)
diff --git a/drivers/input/misc/mc13783-pwrbutton.c b/drivers/input/misc/mc13783-pwrbutton.c
index b83d762ae2e9..82434ea9cca5 100644
--- a/drivers/input/misc/mc13783-pwrbutton.c
+++ b/drivers/input/misc/mc13783-pwrbutton.c
@@ -21,6 +21,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/device.h>
#include <linux/errno.h>
#include <linux/input.h>
#include <linux/interrupt.h>
@@ -102,18 +103,13 @@ static int mc13783_pwrbutton_probe(struct platform_device *pdev)
return -ENODEV;
}
- pwr = input_allocate_device();
- if (!pwr) {
- dev_dbg(&pdev->dev, "Can't allocate power button\n");
+ pwr = devm_input_allocate_device(&pdev->dev);
+ if (!pwr)
return -ENOMEM;
- }
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- err = -ENOMEM;
- dev_dbg(&pdev->dev, "Can't allocate power button\n");
- goto free_input_dev;
- }
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
reg |= (pdata->b1on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON1BDBNC;
reg |= (pdata->b2on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON2BDBNC;
@@ -139,7 +135,7 @@ static int mc13783_pwrbutton_probe(struct platform_device *pdev)
button_irq, "b1on", priv);
if (err) {
dev_dbg(&pdev->dev, "Can't request irq\n");
- goto free_priv;
+ goto free_mc13xxx_lock;
}
}
@@ -187,7 +183,6 @@ static int mc13783_pwrbutton_probe(struct platform_device *pdev)
pwr->name = "mc13783_pwrbutton";
pwr->phys = "mc13783_pwrbutton/input0";
- pwr->dev.parent = &pdev->dev;
pwr->keycode = priv->keymap;
pwr->keycodemax = ARRAY_SIZE(priv->keymap);
@@ -218,12 +213,8 @@ static int mc13783_pwrbutton_probe(struct platform_device *pdev)
if (pdata->b1on_flags & MC13783_BUTTON_ENABLE)
mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD1, priv);
-free_priv:
+free_mc13xxx_lock:
mc13xxx_unlock(mc13783);
- kfree(priv);
-
-free_input_dev:
- input_free_device(pwr);
return err;
}
@@ -245,9 +236,6 @@ static void mc13783_pwrbutton_remove(struct platform_device *pdev)
mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD1, priv);
mc13xxx_unlock(priv->mc13783);
-
- input_unregister_device(priv->pwr);
- kfree(priv);
}
static struct platform_driver mc13783_pwrbutton_driver = {
--
2.39.5
^ permalink raw reply related
* [git pull] Input updates for v6.18-rc0
From: Dmitry Torokhov @ 2025-10-08 5:23 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel, linux-input
Hi Linus,
Please pull from:
git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git tags/input-for-v6.18-rc0
to receive updates for the input subsystem. You will get:
- a number of conversions to yaml/json schema and fixes for
input-related device tree bindings
- a new driver for Awinic AW86927 haptic chip
- a new driver for Hynitron CST816x series controller
- a new driver for add Himax HX852x(ES) touchscreen controller
- a fix to uinput to not leak kernel memory via a gap in
uinput_ff_upload_compat structure
- a fix to prevent overflow in pressure calculation in tsc2007 driver
causing phantom touches
- a change to Atmel maxTouch driver to support generic touchscreen
configuration (flip, rotate, etc.)
- support for platform data was dropped in tca8418_keypad,
pxa27x-keypad, spear-keyboard and twl4030_keypad drivers, they all
now rely on generic device properties for configuration
- other assorted changes and fixes
Changelog:
---------
Andreas Kemnade (1):
dt-bindings: input: tsc2007: use comma in filename
Dan Carpenter (1):
Input: aw86927 - fix error code in probe()
Dario Binacchi (9):
Input: imx6ul_tsc - use BIT, FIELD_{GET,PREP} and GENMASK macros
dt-bindings: touchscreen: convert bu21013 bindings to json schema
dt-bindings: touchscreen: convert zet6223 bindings to json schema
dt-bindings: touchscreen: add debounce-delay-us property
dt-bindings: touchscreen: fsl,imx6ul-tsc: support glitch thresold
Input: imx6ul_tsc - set glitch threshold by DTS property
dt-bindings: touchscreen: convert eeti bindings to json schema
dt-bindings: arm: bcm: raspberrypi,bcm2835-firmware: Add touchscreen child node
dt-bindings: touchscreen: remove touchscreen.txt
Dmitry Torokhov (10):
Input: tca6416-keypad - remove the driver
Input: tca8418_keypad - switch to using module_i2c_driver()
Input: move input_bits_to_string() to input-compat.c
Input: include export.h in modules using EXPORT_SYMBOL*()
Input: pxa27x-keypad - replace uint32_t with u32
Input: pxa27x-keypad - use BIT, GENMASK, FIELD_GET, etc
Input: pxa27x-keypad - drop support for platform data
Input: spear-keyboard - drop support for platform data
Input: synaptics-rmi4 - add includes for types used in rmi_2d_sensor.h
Input: twl4030_keypad - drop support for platform data
Duje Mihanović (1):
dt-bindings: input: touchscreen: imagis: add missing minItems
Fabio Estevam (1):
dt-bindings: input: touchscreen: tsc2007: Document 'wakeup-source'
Frank Li (6):
dt-bindings: input: convert lpc32xx-key.txt to yaml format
dt-bindings: input: exc3000: move eeti,egalax_ts from egalax-ts.txt to eeti,exc3000.yaml
dt-bindings: input: convert semtech,sx8654 to yaml format
dt-bindings: input: convert max11801-ts to yaml format
dt-bindings: input: convert tca8418_keypad.txt to yaml format
dt-bindings: touchscreen: resistive-adc-touch: change to unevaluatedProperties
Griffin Kroah-Hartman (2):
dt-bindings: input: Add Awinic AW86927
Input: aw86927 - add driver for Awinic AW86927
Haotian Zhang (1):
Input: psxpad-spi - add a check for the return value of spi_setup()
J. Neuschäfer (1):
Input: ps2-gpio - fix typo
Johannes Kirchmair (1):
Input: tsc2007 - prevent overflow in pressure calculation
Krzysztof Kozlowski (1):
dt-bindings: input: qcom,pm8941-pwrkey: Fix formatting of descriptions
Luca Weiss (2):
dt-bindings: input: pm8941-pwrkey: Document wakeup-source property
Input: pm8941-pwrkey - disable wakeup for resin by default
Marek Vasut (2):
dt-bindings: input: touchscreen: goodix: Drop 'interrupts' requirement
Input: atmel_mxt_ts - allow reset GPIO to sleep
Michael Trimarchi (1):
Input: imx6ul_tsc - fix typo in register name
Oleh Kuzhylnyi (2):
dt-bindings: input: touchscreen: add hynitron cst816x series
Input: add driver for Hynitron CST816x series
Stephan Gerhold (2):
dt-bindings: input: touchscreen: document Himax HX852x(ES)
Input: add Himax HX852x(ES) touchscreen driver
Svyatoslav Ryhel (4):
Input: tsc2007 - change warning to debug message if pen GPIO is not defined
Input: tsc2007 - make interrupt optional
dt-bindings: input: maxtouch: add common touchscreen properties
Input: atmel_mxt_ts - add support for generic touchscreen configurations
Wolfram Sang (1):
Input: remove unneeded 'fast_io' parameter in regmap_config
Zhen Ni (1):
Input: uinput - zero-initialize uinput_ff_upload_compat to avoid info leak
Diffstat:
--------
.../arm/bcm/raspberrypi,bcm2835-firmware.yaml | 28 +
.../devicetree/bindings/input/atmel,maxtouch.yaml | 3 +-
.../devicetree/bindings/input/awinic,aw86927.yaml | 48 ++
.../devicetree/bindings/input/lpc32xx-key.txt | 34 -
.../devicetree/bindings/input/nxp,lpc3220-key.yaml | 61 ++
.../bindings/input/qcom,pm8941-pwrkey.yaml | 42 +-
.../devicetree/bindings/input/tca8418_keypad.txt | 10 -
.../devicetree/bindings/input/ti,tca8418.yaml | 61 ++
.../bindings/input/touchscreen/bu21013.txt | 43 --
.../bindings/input/touchscreen/eeti,exc3000.yaml | 42 +-
.../devicetree/bindings/input/touchscreen/eeti.txt | 30 -
.../bindings/input/touchscreen/egalax-ts.txt | 18 -
.../bindings/input/touchscreen/fsl,imx6ul-tsc.yaml | 14 +
.../bindings/input/touchscreen/goodix.yaml | 1 -
.../bindings/input/touchscreen/himax,hx852es.yaml | 81 ++
.../input/touchscreen/hynitron,cst816x.yaml | 65 ++
.../input/touchscreen/imagis,ist3038c.yaml | 18 +
.../bindings/input/touchscreen/max11801-ts.txt | 17 -
.../bindings/input/touchscreen/maxim,max11801.yaml | 46 ++
.../input/touchscreen/raspberrypi,firmware-ts.txt | 26 -
.../input/touchscreen/resistive-adc-touch.yaml | 2 +-
.../bindings/input/touchscreen/rohm,bu21013.yaml | 95 +++
.../bindings/input/touchscreen/semtech,sx8654.yaml | 52 ++
.../bindings/input/touchscreen/sx8654.txt | 23 -
.../{ti.tsc2007.yaml => ti,tsc2007.yaml} | 4 +-
.../bindings/input/touchscreen/touchscreen.txt | 1 -
.../bindings/input/touchscreen/touchscreen.yaml | 4 +
.../bindings/input/touchscreen/zeitec,zet6223.yaml | 62 ++
.../bindings/input/touchscreen/zet6223.txt | 30 -
MAINTAINERS | 7 +
drivers/input/ff-core.c | 2 +-
drivers/input/ff-memless.c | 1 +
drivers/input/gameport/gameport.c | 1 +
drivers/input/input-compat.c | 30 +
drivers/input/input-compat.h | 3 +
drivers/input/input-poller.c | 1 +
drivers/input/input.c | 36 +-
drivers/input/joystick/iforce/iforce-main.c | 1 +
drivers/input/joystick/iforce/iforce-packets.c | 1 +
drivers/input/joystick/psxpad-spi.c | 6 +-
drivers/input/keyboard/Kconfig | 18 -
drivers/input/keyboard/Makefile | 1 -
drivers/input/keyboard/pxa27x_keypad.c | 530 +++++--------
drivers/input/keyboard/spear-keyboard.c | 71 +-
drivers/input/keyboard/tca6416-keypad.c | 305 --------
drivers/input/keyboard/tca8418_keypad.c | 13 +-
drivers/input/keyboard/twl4030_keypad.c | 35 +-
drivers/input/misc/Kconfig | 11 +
drivers/input/misc/Makefile | 1 +
drivers/input/misc/ad714x.c | 1 +
drivers/input/misc/adxl34x.c | 1 +
drivers/input/misc/aw86927.c | 846 +++++++++++++++++++++
drivers/input/misc/cma3000_d0x.c | 1 +
drivers/input/misc/pm8941-pwrkey.c | 12 +-
drivers/input/misc/uinput.c | 1 +
drivers/input/rmi4/rmi_2d_sensor.c | 1 +
drivers/input/rmi4/rmi_2d_sensor.h | 3 +
drivers/input/rmi4/rmi_bus.c | 1 +
drivers/input/rmi4/rmi_driver.c | 1 +
drivers/input/serio/hil_mlc.c | 1 +
drivers/input/serio/hp_sdc.c | 1 +
drivers/input/serio/i8042.c | 1 +
drivers/input/serio/libps2.c | 1 +
drivers/input/serio/ps2-gpio.c | 2 +-
drivers/input/serio/serio.c | 1 +
drivers/input/sparse-keymap.c | 1 +
drivers/input/touch-overlay.c | 1 +
drivers/input/touchscreen.c | 1 +
drivers/input/touchscreen/Kconfig | 22 +
drivers/input/touchscreen/Makefile | 2 +
drivers/input/touchscreen/ad7879.c | 1 +
drivers/input/touchscreen/atmel_mxt_ts.c | 13 +-
drivers/input/touchscreen/cyttsp_core.c | 1 +
drivers/input/touchscreen/fsl-imx25-tcq.c | 1 -
drivers/input/touchscreen/goodix_berlin_core.c | 1 +
drivers/input/touchscreen/himax_hx852x.c | 503 ++++++++++++
drivers/input/touchscreen/hynitron-cst816x.c | 253 ++++++
drivers/input/touchscreen/imx6ul_tsc.c | 121 +--
drivers/input/touchscreen/tsc2007_core.c | 39 +-
drivers/input/touchscreen/tsc200x-core.c | 1 +
drivers/input/touchscreen/wm9705.c | 1 +
drivers/input/touchscreen/wm9712.c | 1 +
drivers/input/touchscreen/wm9713.c | 1 +
drivers/input/touchscreen/wm97xx-core.c | 1 +
include/linux/platform_data/keyboard-spear.h | 164 ----
include/linux/platform_data/keypad-pxa27x.h | 73 --
include/linux/tca6416_keypad.h | 30 -
87 files changed, 2764 insertions(+), 1378 deletions(-)
create mode 100644 Documentation/devicetree/bindings/input/awinic,aw86927.yaml
delete mode 100644 Documentation/devicetree/bindings/input/lpc32xx-key.txt
create mode 100644 Documentation/devicetree/bindings/input/nxp,lpc3220-key.yaml
delete mode 100644 Documentation/devicetree/bindings/input/tca8418_keypad.txt
create mode 100644 Documentation/devicetree/bindings/input/ti,tca8418.yaml
delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/bu21013.txt
delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/eeti.txt
delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/himax,hx852es.yaml
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/hynitron,cst816x.yaml
delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/max11801-ts.txt
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/maxim,max11801.yaml
delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/raspberrypi,firmware-ts.txt
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/rohm,bu21013.yaml
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/semtech,sx8654.yaml
delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/sx8654.txt
rename Documentation/devicetree/bindings/input/touchscreen/{ti.tsc2007.yaml => ti,tsc2007.yaml} (95%)
delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/zeitec,zet6223.yaml
delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/zet6223.txt
delete mode 100644 drivers/input/keyboard/tca6416-keypad.c
create mode 100644 drivers/input/misc/aw86927.c
create mode 100644 drivers/input/touchscreen/himax_hx852x.c
create mode 100644 drivers/input/touchscreen/hynitron-cst816x.c
delete mode 100644 include/linux/platform_data/keyboard-spear.h
delete mode 100644 include/linux/platform_data/keypad-pxa27x.h
delete mode 100644 include/linux/tca6416_keypad.h
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH] Input: pegasus-notetaker - fix out-of-bounds access vulnerability in pegasus_parse_packet() function of the pegasus driver
From: Greg KH @ 2025-10-08 4:58 UTC (permalink / raw)
To: pip-izony
Cc: Dmitry Torokhov, Kyungtae Kim, linux-input, linux-kernel, stable
In-Reply-To: <20251007214131.3737115-2-eeodqql09@gmail.com>
On Tue, Oct 07, 2025 at 05:41:32PM -0400, pip-izony wrote:
> From: Seungjin Bae <eeodqql09@gmail.com>
>
> In the pegasus_notetaker driver, the pegasus_probe() function allocates
> the URB transfer buffer using the wMaxPacketSize value from
> the endpoint descriptor. An attacker can use a malicious USB descriptor
> to force the allocation of a very small buffer.
>
> Subsequently, if the device sends an interrupt packet with a specific
> pattern (e.g., where the first byte is 0x80 or 0x42),
> the pegasus_parse_packet() function parses the packet without checking
> the allocated buffer size. This leads to an out-of-bounds memory access,
> which could result in a system panic.
>
> Fixes: 948bf18 ("Input: remove third argument of usb_maxpacket()")
> Signed-off-by: Seungjin Bae <eeodqql09@gmail.com>
> ---
> drivers/input/tablet/pegasus_notetaker.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/drivers/input/tablet/pegasus_notetaker.c b/drivers/input/tablet/pegasus_notetaker.c
> index 8d6b71d59793..6c4199712a4e 100644
> --- a/drivers/input/tablet/pegasus_notetaker.c
> +++ b/drivers/input/tablet/pegasus_notetaker.c
> @@ -311,6 +311,11 @@ static int pegasus_probe(struct usb_interface *intf,
> }
>
> pegasus->data_len = usb_maxpacket(dev, pipe);
> + if (pegasus->data_len < 5) {
> + dev_err(&intf->dev, "Invalid number of wMaxPacketSize\n");
> + error = -EINVAL;
> + goto err_free_mem;
> + }
>
> pegasus->data = usb_alloc_coherent(dev, pegasus->data_len, GFP_KERNEL,
> &pegasus->data_dma);
> --
> 2.43.0
>
>
<formletter>
This is not the correct way to submit patches for inclusion in the
stable kernel tree. Please read:
https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html
for how to do this properly.
</formletter>
^ permalink raw reply
* [PATCH] Input: pegasus-notetaker - fix out-of-bounds access vulnerability in pegasus_parse_packet() function of the pegasus driver
From: pip-izony @ 2025-10-07 21:41 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Seungjin Bae, Kyungtae Kim, linux-input, linux-kernel, stable
From: Seungjin Bae <eeodqql09@gmail.com>
In the pegasus_notetaker driver, the pegasus_probe() function allocates
the URB transfer buffer using the wMaxPacketSize value from
the endpoint descriptor. An attacker can use a malicious USB descriptor
to force the allocation of a very small buffer.
Subsequently, if the device sends an interrupt packet with a specific
pattern (e.g., where the first byte is 0x80 or 0x42),
the pegasus_parse_packet() function parses the packet without checking
the allocated buffer size. This leads to an out-of-bounds memory access,
which could result in a system panic.
Fixes: 948bf18 ("Input: remove third argument of usb_maxpacket()")
Signed-off-by: Seungjin Bae <eeodqql09@gmail.com>
---
drivers/input/tablet/pegasus_notetaker.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/input/tablet/pegasus_notetaker.c b/drivers/input/tablet/pegasus_notetaker.c
index 8d6b71d59793..6c4199712a4e 100644
--- a/drivers/input/tablet/pegasus_notetaker.c
+++ b/drivers/input/tablet/pegasus_notetaker.c
@@ -311,6 +311,11 @@ static int pegasus_probe(struct usb_interface *intf,
}
pegasus->data_len = usb_maxpacket(dev, pipe);
+ if (pegasus->data_len < 5) {
+ dev_err(&intf->dev, "Invalid number of wMaxPacketSize\n");
+ error = -EINVAL;
+ goto err_free_mem;
+ }
pegasus->data = usb_alloc_coherent(dev, pegasus->data_len, GFP_KERNEL,
&pegasus->data_dma);
--
2.43.0
^ permalink raw reply related
* RE: [PATCH v2 07/19 5.15.y] minmax: simplify and clarify min_t()/max_t() implementation
From: Farber, Eliav @ 2025-10-07 20:43 UTC (permalink / raw)
To: David Laight, Greg KH
Cc: dave.hansen@linux.intel.com, peterz@infradead.org,
tglx@linutronix.de, mingo@redhat.com, bp@alien8.de,
x86@kernel.org, hpa@zytor.com, james.morse@arm.com,
rric@kernel.org, daniel@ffwll.ch,
maarten.lankhorst@linux.intel.com, mripard@kernel.org,
tzimmermann@suse.de, sean@poorly.run, jdelvare@suse.com,
linux@roeck-us.net, linus.walleij@linaro.org,
dmitry.torokhov@gmail.com, maz@kernel.org, wens@csie.org,
jernej.skrabec@gmail.com, agk@redhat.com, snitzer@redhat.com,
dm-devel@redhat.com, davem@davemloft.net, kuba@kernel.org,
mcoquelin.stm32@gmail.com, krzysztof.kozlowski@canonical.com,
malattia@linux.it, hdegoede@redhat.com, mgross@linux.intel.com,
jejb@linux.ibm.com, martin.petersen@oracle.com,
sakari.ailus@linux.intel.com, clm@fb.com, josef@toxicpanda.com,
dsterba@suse.com, jack@suse.com, tytso@mit.edu,
adilger.kernel@dilger.ca, dushistov@mail.ru,
luc.vanoostenryck@gmail.com, rostedt@goodmis.org,
pmladek@suse.com, senozhatsky@chromium.org,
andriy.shevchenko@linux.intel.com, linux@rasmusvillemoes.dk,
minchan@kernel.org, ngupta@vflare.org, akpm@linux-foundation.org,
yoshfuji@linux-ipv6.org, dsahern@kernel.org, pablo@netfilter.org,
kadlec@netfilter.org, fw@strlen.de, jmaloy@redhat.com,
ying.xue@windriver.com, shuah@kernel.org, willy@infradead.org,
sashal@kernel.org, quic_akhilpo@quicinc.com,
ruanjinjie@huawei.com, David.Laight@aculab.com,
herve.codina@bootlin.com, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-um@lists.infradead.org,
linux-edac@vger.kernel.org, amd-gfx@lists.freedesktop.org,
dri-devel@lists.freedesktop.org, linux-arm-msm@vger.kernel.org,
freedreno@lists.freedesktop.org, linux-hwmon@vger.kernel.org,
linux-input@vger.kernel.org, linux-sunxi@lists.linux.dev,
linux-media@vger.kernel.org, netdev@vger.kernel.org,
linux-stm32@st-md-mailman.stormreply.com,
platform-driver-x86@vger.kernel.org, linux-scsi@vger.kernel.org,
linux-staging@lists.linux.dev, linux-btrfs@vger.kernel.org,
linux-ext4@vger.kernel.org, linux-sparse@vger.kernel.org,
linux-mm@kvack.org, netfilter-devel@vger.kernel.org,
coreteam@netfilter.org, tipc-discussion@lists.sourceforge.net,
linux-kselftest@vger.kernel.org, stable@vger.kernel.org,
Linus Torvalds, Lorenzo Stoakes
In-Reply-To: <20251006213242.3462e746@pumpkin>
> On Mon, 6 Oct 2025 12:47:45 +0200
> Greg KH <gregkh@linuxfoundation.org> wrote:
>
> (I've had to trim the 'To' list to send this...)
>
> > On Fri, Oct 03, 2025 at 12:59:54PM +0000, Eliav Farber wrote:
> > > From: Linus Torvalds <torvalds@linux-foundation.org>
> > >
> > > [ Upstream commit 017fa3e89187848fd056af757769c9e66ac3e93d ]
> > >
> > > This simplifies the min_t() and max_t() macros by no longer making
> > > them work in the context of a C constant expression.
> > >
> > > That means that you can no longer use them for static initializers
> > > or for array sizes in type definitions, but there were only a couple
> > > of such uses, and all of them were converted (famous last words) to
> > > use MIN_T/MAX_T instead.
> > >
> > > Cc: David Laight <David.Laight@aculab.com>
> > > Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> > > Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
> > > Signed-off-by: Eliav Farber <farbere@amazon.com>
> >
> > Eliav, your testing infrastructure needs some work, this patch breaks
> > the build on this kernel tree:
> >
> > In file included from ./include/linux/kernel.h:16,
> > from ./include/linux/list.h:9,
> > from ./include/linux/wait.h:7,
> > from ./include/linux/wait_bit.h:8,
> > from ./include/linux/fs.h:6,
> > from fs/erofs/internal.h:10,
> > from fs/erofs/zdata.h:9,
> > from fs/erofs/zdata.c:6:
> > fs/erofs/zdata.c: In function ‘z_erofs_decompress_pcluster’:
> > fs/erofs/zdata.h:185:61: error: ISO C90 forbids variable length array ‘pages_onstack’ [-Werror=vla]
> > 185 | min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U)
> > | ^~~~
>
> That constant seems to get (renamed and) changed to 32 in a later patch.
> I'm not sure of the rational for the min() at all.
> I think THREAD_SIZE is the size of the kernel stack? Or at least related to it.
> The default seems to be 8k on x86-64 and 4k or 8k on i386.
> So it is pretty much always going to be 96.
>
> Linus added MIN() that can be used for array sizes.
> But I'd guess this could just be changed to 32 - need to ask the erofs guys.
Changing the definition of Z_EROFS_VMAP_ONSTACK_PAGES to use
MIN_T(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U)
instead of
min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U).
fixes the build failure.
This aligns with the change made in upstream commit
4477b39c32fd("minmax: add a few more MIN_T/MAX_T users"):
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4477b39c32fdc03363affef4b11d48391e6dc9ff
---
Regards, Eliav
^ permalink raw reply
* [PATCH] drivers: hid: renegotiate resolution multipliers with device after reset
From: Benedek Kupper @ 2025-10-07 20:35 UTC (permalink / raw)
To: linux-input; +Cc: linux-kernel, bentiss, jikos, Benedek Kupper
The scroll resolution multipliers are set in the context of
hidinput_connect(), which is only called at probe time: when the host
changes the value on the device with a SET_REPORT(FEATURE), and the device
accepts it, these multipliers are stored on the host side, and used to
calculate the final scroll event values sent to userspace.
After a USB suspend, the resume operation on many hubs and chipsets
involve a USB reset signal as well. A reset on the device side clears all
previous state information, including the value of the multiplier report.
This reset is not handled by the multiplier handling logic, so what ends up
happening is the host is still expecting high-resolution scroll events,
but the device is reset to default resolution, making the effective,
user-perceived scroll speed incredibly slow.
The solution is to renegotiate the multiplier selection after each reset.
This is not the only bug related to the high-resolution scrolling
implementation in the kernel (the other one is
https://bugzilla.kernel.org/show_bug.cgi?id=220144), but for this one,
there is no device side workaround for,
leading to poor user experience with our product:
https://github.com/UltimateHackingKeyboard/firmware/issues/1155
https://github.com/UltimateHackingKeyboard/firmware/issues/1261
https://github.com/UltimateHackingKeyboard/firmware/pull/1355
This patch was tested by an affected user and has been reported to
fix the issue (see discussion in 1355).
Signed-off-by: Benedek Kupper <kupper.benedek@gmail.com>
---
drivers/hid/hid-generic.c | 9 +++++++++
drivers/hid/hid-input.c | 7 +++++++
include/linux/hid.h | 1 +
3 files changed, 17 insertions(+)
diff --git a/drivers/hid/hid-generic.c b/drivers/hid/hid-generic.c
index 9e04c6d0fcc8..c2de916747de 100644
--- a/drivers/hid/hid-generic.c
+++ b/drivers/hid/hid-generic.c
@@ -70,6 +70,14 @@ static int hid_generic_probe(struct hid_device *hdev,
return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
}
+static int hid_generic_reset_resume(struct hid_device *hdev)
+{
+ if (hdev->claimed & HID_CLAIMED_INPUT)
+ hidinput_reset_resume(hdev);
+
+ return 0;
+}
+
static const struct hid_device_id hid_table[] = {
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, HID_ANY_ID, HID_ANY_ID) },
{ }
@@ -81,6 +89,7 @@ static struct hid_driver hid_generic = {
.id_table = hid_table,
.match = hid_generic_match,
.probe = hid_generic_probe,
+ .reset_resume = hid_generic_reset_resume,
};
module_hid_driver(hid_generic);
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index f45f856a127f..3dd3822cc549 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -2382,6 +2382,13 @@ void hidinput_disconnect(struct hid_device *hid)
}
EXPORT_SYMBOL_GPL(hidinput_disconnect);
+void hidinput_reset_resume(struct hid_device *hid)
+{
+ /* renegotiate host-device shared state after reset */
+ hidinput_change_resolution_multipliers(hid);
+}
+EXPORT_SYMBOL_GPL(hidinput_reset_resume);
+
#ifdef CONFIG_HID_KUNIT_TEST
#include "hid-input-test.c"
#endif
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 2cc4f1e4ea96..b78fb55ea85e 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -953,6 +953,7 @@ extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct h
extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report);
extern int hidinput_connect(struct hid_device *hid, unsigned int force);
extern void hidinput_disconnect(struct hid_device *);
+void hidinput_reset_resume(struct hid_device *hid);
struct hid_field *hid_find_field(struct hid_device *hdev, unsigned int report_type,
unsigned int application, unsigned int usage);
--
2.43.0
^ permalink raw reply related
* Re: [PATCH] input: goodix: Remove setting of RST pin to input
From: Hans de Goede @ 2025-10-07 14:06 UTC (permalink / raw)
To: Martyn Welch, Dmitry Torokhov; +Cc: kernel, linux-input, linux-kernel
In-Reply-To: <20251007102305.445515-1-martyn.welch@collabora.com>
Hi Martyn,
On 7-Oct-25 12:23, Martyn Welch wrote:
> The reset line is being set to input on non-ACPI devices apparently to
> save power. This isn't being done on ACPI devices as it's been found
> that some ACPI devices don't have a pull-up resistor fitted. This can
> also be the case for non-ACPI devices, resulting in:
>
> [ 941.672207] Goodix-TS 1-0014: Error reading 10 bytes from 0x814e: -110
> [ 942.696168] Goodix-TS 1-0014: Error reading 10 bytes from 0x814e: -110
> [ 945.832208] Goodix-TS 1-0014: Error reading 10 bytes from 0x814e: -110
>
> This behaviour appears to have been initially introduced in ec6e1b4082d9.
> This doesn't seem to be based on information in either the GT911 or GT9271
> datasheets cited as sources of information for this change. Thus it seems
> likely that it is based on functionality in the Android driver which it
> also lists. This behaviour may be viable in very specific instances where
> the hardware is known to have a pull-up fitted, but seems unwise in the
> upstream kernel where such hardware requirements can't be guaranteed.
>
> Remove this over optimisation to improve reliability on non-ACPI
> devices.
>
> Signed-off-by: Martyn Welch <martyn.welch@collabora.com>
I have no objection against this simplification of the code, but the reset
pin will still be set to input mode when requested after this change,
see the use of gpiod_rst_flags in the driver.
For v2 it would be best to drop gpiod_rst_flags and directly pass
GPIOD_ASIS when requesting the reset pin.
Note for ACPI we want GPIOD_ASIS because there the driver only resets
the chip if it is non-responsive since typically it has already been
reset by the BIOS.
For non ACPI goodix_reset() will immediately call:
gpiod_direction_output(ts->gpiod_rst, 0)
followed by a msleep(20) so there using GPIOD_ASIS does not matter
as the direction + value will get set immediately after requesting it.
Regards,
Hans
>
> ---
> drivers/input/touchscreen/goodix.c | 11 -----------
> 1 file changed, 11 deletions(-)
>
> diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
> index 252dcae039f8..e7ef744011ad 100644
> --- a/drivers/input/touchscreen/goodix.c
> +++ b/drivers/input/touchscreen/goodix.c
> @@ -796,17 +796,6 @@ int goodix_reset_no_int_sync(struct goodix_ts_data *ts)
>
> usleep_range(6000, 10000); /* T4: > 5ms */
>
> - /*
> - * Put the reset pin back in to input / high-impedance mode to save
> - * power. Only do this in the non ACPI case since some ACPI boards
> - * don't have a pull-up, so there the reset pin must stay active-high.
> - */
> - if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_GPIO) {
> - error = gpiod_direction_input(ts->gpiod_rst);
> - if (error)
> - goto error;
> - }
> -
> return 0;
>
> error:
^ permalink raw reply
* [PATCH v3 13/13] arm64: dts: apple: t8103, t60xx, t8112: Add common hwmon nodes to devices
From: James Calligeros @ 2025-10-07 11:16 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Alexandre Belloni, Jean Delvare, Guenter Roeck, Dmitry Torokhov,
Jonathan Corbet, James Calligeros
Cc: asahi, linux-arm-kernel, devicetree, linux-kernel, linux-rtc,
linux-hwmon, linux-input, linux-doc
In-Reply-To: <20251007-macsmc-subdevs-v3-0-d7d3bfd7ae02@gmail.com>
Add the known, common hwmon-related SMC keys to the DTs for the devices
they pertain to.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Co-developed-by: Janne Grunau <j@jannau.net>
Signed-off-by: Janne Grunau <j@jannau.net>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
.../arm64/boot/dts/apple/t6001-j375c.dts | 2 ++
arch/arm64/boot/dts/apple/t6001.dtsi | 2 ++
.../arm64/boot/dts/apple/t6002-j375d.dts | 2 ++
.../boot/dts/apple/t600x-j314-j316.dtsi | 3 +++
arch/arm64/boot/dts/apple/t8103-j274.dts | 2 ++
arch/arm64/boot/dts/apple/t8103-j293.dts | 3 +++
arch/arm64/boot/dts/apple/t8103-j313.dts | 2 ++
arch/arm64/boot/dts/apple/t8103-j456.dts | 2 ++
arch/arm64/boot/dts/apple/t8103-j457.dts | 2 ++
arch/arm64/boot/dts/apple/t8103.dtsi | 1 +
arch/arm64/boot/dts/apple/t8112-j413.dts | 2 ++
arch/arm64/boot/dts/apple/t8112-j473.dts | 2 ++
arch/arm64/boot/dts/apple/t8112-j493.dts | 3 +++
arch/arm64/boot/dts/apple/t8112.dtsi | 1 +
14 files changed, 29 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t6001-j375c.dts b/arch/arm64/boot/dts/apple/t6001-j375c.dts
index 2e7c23714d4d..08276114c1d8 100644
--- a/arch/arm64/boot/dts/apple/t6001-j375c.dts
+++ b/arch/arm64/boot/dts/apple/t6001-j375c.dts
@@ -24,3 +24,5 @@ &wifi0 {
&bluetooth0 {
brcm,board-type = "apple,okinawa";
};
+
+#include "hwmon-fan-dual.dtsi"
diff --git a/arch/arm64/boot/dts/apple/t6001.dtsi b/arch/arm64/boot/dts/apple/t6001.dtsi
index ffbe823b71bc..264df90f07d8 100644
--- a/arch/arm64/boot/dts/apple/t6001.dtsi
+++ b/arch/arm64/boot/dts/apple/t6001.dtsi
@@ -66,3 +66,5 @@ p-core-pmu-affinity {
&gpu {
compatible = "apple,agx-g13c", "apple,agx-g13s";
};
+
+#include "hwmon-common.dtsi"
diff --git a/arch/arm64/boot/dts/apple/t6002-j375d.dts b/arch/arm64/boot/dts/apple/t6002-j375d.dts
index 2b7f80119618..d12c0ae418f7 100644
--- a/arch/arm64/boot/dts/apple/t6002-j375d.dts
+++ b/arch/arm64/boot/dts/apple/t6002-j375d.dts
@@ -56,3 +56,5 @@ &bluetooth0 {
/delete-node/ &ps_disp0_cpu0_die1;
/delete-node/ &ps_disp0_fe_die1;
+
+#include "hwmon-fan-dual.dtsi"
diff --git a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
index c0aac59a6fae..127814a9dfa4 100644
--- a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
@@ -131,3 +131,6 @@ &fpwm0 {
};
#include "spi1-nvram.dtsi"
+
+#include "hwmon-laptop.dtsi"
+#include "hwmon-fan-dual.dtsi"
diff --git a/arch/arm64/boot/dts/apple/t8103-j274.dts b/arch/arm64/boot/dts/apple/t8103-j274.dts
index 1c3e37f86d46..f5b8cc087882 100644
--- a/arch/arm64/boot/dts/apple/t8103-j274.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j274.dts
@@ -61,3 +61,5 @@ &pcie0_dart_2 {
&i2c2 {
status = "okay";
};
+
+#include "hwmon-mac-mini.dtsi"
diff --git a/arch/arm64/boot/dts/apple/t8103-j293.dts b/arch/arm64/boot/dts/apple/t8103-j293.dts
index 5b3c42e9f0e6..abb88391635f 100644
--- a/arch/arm64/boot/dts/apple/t8103-j293.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j293.dts
@@ -119,3 +119,6 @@ dfr_panel_in: endpoint {
&displaydfr_dart {
status = "okay";
};
+
+#include "hwmon-laptop.dtsi"
+#include "hwmon-fan.dtsi"
diff --git a/arch/arm64/boot/dts/apple/t8103-j313.dts b/arch/arm64/boot/dts/apple/t8103-j313.dts
index 97a4344d8dca..491ead016b21 100644
--- a/arch/arm64/boot/dts/apple/t8103-j313.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j313.dts
@@ -41,3 +41,5 @@ &wifi0 {
&fpwm1 {
status = "okay";
};
+
+#include "hwmon-laptop.dtsi"
diff --git a/arch/arm64/boot/dts/apple/t8103-j456.dts b/arch/arm64/boot/dts/apple/t8103-j456.dts
index 58c8e43789b4..c2ec6fbb633c 100644
--- a/arch/arm64/boot/dts/apple/t8103-j456.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j456.dts
@@ -75,3 +75,5 @@ &pcie0_dart_1 {
&pcie0_dart_2 {
status = "okay";
};
+
+#include "hwmon-fan-dual.dtsi"
diff --git a/arch/arm64/boot/dts/apple/t8103-j457.dts b/arch/arm64/boot/dts/apple/t8103-j457.dts
index 7089ccf3ce55..aeaab2482d54 100644
--- a/arch/arm64/boot/dts/apple/t8103-j457.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j457.dts
@@ -56,3 +56,5 @@ ethernet0: ethernet@0,0 {
&pcie0_dart_2 {
status = "okay";
};
+
+#include "hwmon-fan.dtsi"
diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index 78eb931d6fb7..f1820bdc0910 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -1145,3 +1145,4 @@ port02: pci@2,0 {
};
#include "t8103-pmgr.dtsi"
+#include "hwmon-common.dtsi"
diff --git a/arch/arm64/boot/dts/apple/t8112-j413.dts b/arch/arm64/boot/dts/apple/t8112-j413.dts
index 6f69658623bf..500dcdf2d4b5 100644
--- a/arch/arm64/boot/dts/apple/t8112-j413.dts
+++ b/arch/arm64/boot/dts/apple/t8112-j413.dts
@@ -78,3 +78,5 @@ &i2c4 {
&fpwm1 {
status = "okay";
};
+
+#include "hwmon-laptop.dtsi"
diff --git a/arch/arm64/boot/dts/apple/t8112-j473.dts b/arch/arm64/boot/dts/apple/t8112-j473.dts
index 06fe257f08be..11db6a92493f 100644
--- a/arch/arm64/boot/dts/apple/t8112-j473.dts
+++ b/arch/arm64/boot/dts/apple/t8112-j473.dts
@@ -52,3 +52,5 @@ &pcie1_dart {
&pcie2_dart {
status = "okay";
};
+
+#include "hwmon-mac-mini.dtsi"
diff --git a/arch/arm64/boot/dts/apple/t8112-j493.dts b/arch/arm64/boot/dts/apple/t8112-j493.dts
index fb8ad7d4c65a..a0da02c00f15 100644
--- a/arch/arm64/boot/dts/apple/t8112-j493.dts
+++ b/arch/arm64/boot/dts/apple/t8112-j493.dts
@@ -133,3 +133,6 @@ touchbar0: touchbar@0 {
touchscreen-inverted-y;
};
};
+
+#include "hwmon-laptop.dtsi"
+#include "hwmon-fan.dtsi"
diff --git a/arch/arm64/boot/dts/apple/t8112.dtsi b/arch/arm64/boot/dts/apple/t8112.dtsi
index 5a8fa6daa00a..c4d1e5ffaee9 100644
--- a/arch/arm64/boot/dts/apple/t8112.dtsi
+++ b/arch/arm64/boot/dts/apple/t8112.dtsi
@@ -1184,3 +1184,4 @@ port03: pci@3,0 {
};
#include "t8112-pmgr.dtsi"
+#include "hwmon-common.dtsi"
--
2.51.0
^ permalink raw reply related
* [PATCH v3 12/13] arm64: dts: apple: Add common hwmon sensors and fans
From: James Calligeros @ 2025-10-07 11:16 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Alexandre Belloni, Jean Delvare, Guenter Roeck, Dmitry Torokhov,
Jonathan Corbet, James Calligeros
Cc: asahi, linux-arm-kernel, devicetree, linux-kernel, linux-rtc,
linux-hwmon, linux-input, linux-doc
In-Reply-To: <20251007-macsmc-subdevs-v3-0-d7d3bfd7ae02@gmail.com>
Each Apple Silicon device exposes a unique set of sensors and fans,
however some have been found to be reliably common across devices.
Add these as .dtsi files so that they can be combined with any
device-specific sensors without excessive repetition.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
.../boot/dts/apple/hwmon-common.dtsi | 33 +++++++++++++++++++++++++
.../boot/dts/apple/hwmon-fan-dual.dtsi | 22 +++++++++++++++++
arch/arm64/boot/dts/apple/hwmon-fan.dtsi | 17 +++++++++++++
.../boot/dts/apple/hwmon-laptop.dtsi | 33 +++++++++++++++++++++++++
.../boot/dts/apple/hwmon-mac-mini.dtsi | 15 +++++++++++
5 files changed, 120 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/hwmon-common.dtsi b/arch/arm64/boot/dts/apple/hwmon-common.dtsi
new file mode 100644
index 000000000000..b87021855fdf
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/hwmon-common.dtsi
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Hardware monitoring sensors expected to be found on all Apple Silicon devices
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+&smc_hwmon {
+ current-ID0R {
+ apple,key-id = "ID0R";
+ label = "AC Input Current";
+ };
+ power-PSTR {
+ apple,key-id = "PSTR";
+ label = "Total System Power";
+ };
+ power-PDTR {
+ apple,key-id = "PDTR";
+ label = "AC Input Power";
+ };
+ power-PMVR {
+ apple,key-id = "PMVR";
+ label = "3.8 V Rail Power";
+ };
+ temperature-TH0x {
+ apple,key-id = "TH0x";
+ label = "NAND Flash Temperature";
+ };
+ voltage-VD0R {
+ apple,key-id = "VD0R";
+ label = "AC Input Voltage";
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/hwmon-fan-dual.dtsi b/arch/arm64/boot/dts/apple/hwmon-fan-dual.dtsi
new file mode 100644
index 000000000000..3eef0721bcca
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/hwmon-fan-dual.dtsi
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * SMC hwmon fan keys for Apple Silicon desktops/laptops with two fans
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+#include "hwmon-fan.dtsi"
+
+&smc_hwmon {
+ fan-F0Ac {
+ label = "Fan 1";
+ };
+ fan-F1Ac {
+ apple,key-id = "F1Ac";
+ label = "Fan 2";
+ apple,fan-minimum = "F1Mn";
+ apple,fan-maximum = "F1Mx";
+ apple,fan-target = "F1Tg";
+ apple,fan-mode = "F1Md";
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/hwmon-fan.dtsi b/arch/arm64/boot/dts/apple/hwmon-fan.dtsi
new file mode 100644
index 000000000000..fba9faf38f4b
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/hwmon-fan.dtsi
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * hwmon fan keys for Apple Silicon desktops/laptops with a single fan.
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+&smc_hwmon {
+ fan-F0Ac {
+ apple,key-id = "F0Ac";
+ label = "Fan";
+ apple,fan-minimum = "F0Mn";
+ apple,fan-maximum = "F0Mx";
+ apple,fan-target = "F0Tg";
+ apple,fan-mode = "F0Md";
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/hwmon-laptop.dtsi b/arch/arm64/boot/dts/apple/hwmon-laptop.dtsi
new file mode 100644
index 000000000000..0c4666282a5c
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/hwmon-laptop.dtsi
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Hardware monitoring sensors expected on all Apple Silicon laptops
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+&smc_hwmon {
+ power-PHPC {
+ apple,key-id = "PHPC";
+ label = "Heatpipe Power";
+ };
+ temperature-TB0T {
+ apple,key-id = "TB0T";
+ label = "Battery Hotspot Temperature";
+ };
+ temperature-TCHP {
+ apple,key-id = "TCHP";
+ label = "Charge Regulator Temperature";
+ };
+ temperature-TW0P {
+ apple,key-id = "TW0P";
+ label = "WiFi/BT Module Temperature";
+ };
+ voltage-SBAV {
+ apple,key-id = "SBAV";
+ label = "Battery Voltage";
+ };
+ voltage-VD0R {
+ apple,key-id = "VD0R";
+ label = "Charger Input Voltage";
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/hwmon-mac-mini.dtsi b/arch/arm64/boot/dts/apple/hwmon-mac-mini.dtsi
new file mode 100644
index 000000000000..f32627336ae7
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/hwmon-mac-mini.dtsi
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * hwmon sensors expected on all Mac mini models
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+#include "hwmon-fan.dtsi"
+
+&smc_hwmon {
+ temperature-TW0P {
+ apple,key-id = "TW0P";
+ label = "WiFi/BT Module Temperature";
+ };
+};
--
2.51.0
^ permalink raw reply related
* [PATCH v3 11/13] arm64: dts: apple: t8103, t8112, t60xx: add hwmon SMC subdevice
From: James Calligeros @ 2025-10-07 11:16 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Alexandre Belloni, Jean Delvare, Guenter Roeck, Dmitry Torokhov,
Jonathan Corbet, James Calligeros
Cc: asahi, linux-arm-kernel, devicetree, linux-kernel, linux-rtc,
linux-hwmon, linux-input, linux-doc
In-Reply-To: <20251007-macsmc-subdevs-v3-0-d7d3bfd7ae02@gmail.com>
Apple's System Management Controller integrates numerous sensors
that can be exposed via hwmon. Add the subdevice and compatible
in preparation for the sensors that need to be described
for each device.
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
.../arm64/boot/dts/apple/t600x-die0.dtsi | 4 ++++
.../arm64/boot/dts/apple/t602x-die0.dtsi | 4 ++++
arch/arm64/boot/dts/apple/t8103.dtsi | 4 ++++
arch/arm64/boot/dts/apple/t8112.dtsi | 4 ++++
4 files changed, 16 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
index f715b19efd16..e6647c1a9173 100644
--- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
@@ -37,6 +37,10 @@ smc_gpio: gpio {
#gpio-cells = <2>;
};
+ smc_hwmon: hwmon {
+ compatible = "apple,smc-hwmon";
+ };
+
smc_reboot: reboot {
compatible = "apple,smc-reboot";
nvmem-cells = <&shutdown_flag>, <&boot_stage>,
diff --git a/arch/arm64/boot/dts/apple/t602x-die0.dtsi b/arch/arm64/boot/dts/apple/t602x-die0.dtsi
index 8622ddea7b44..680c103c1c0f 100644
--- a/arch/arm64/boot/dts/apple/t602x-die0.dtsi
+++ b/arch/arm64/boot/dts/apple/t602x-die0.dtsi
@@ -114,6 +114,10 @@ smc_gpio: gpio {
#gpio-cells = <2>;
};
+ smc_hwmon: hwmon {
+ compatible = "apple,smc-hwmon";
+ };
+
smc_reboot: reboot {
compatible = "apple,smc-reboot";
nvmem-cells = <&shutdown_flag>, <&boot_stage>,
diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index 59f2678639cf..78eb931d6fb7 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -909,6 +909,10 @@ smc_gpio: gpio {
#gpio-cells = <2>;
};
+ smc_hwmon: hwmon {
+ compatible = "apple,smc-hwmon";
+ };
+
smc_reboot: reboot {
compatible = "apple,smc-reboot";
nvmem-cells = <&shutdown_flag>, <&boot_stage>,
diff --git a/arch/arm64/boot/dts/apple/t8112.dtsi b/arch/arm64/boot/dts/apple/t8112.dtsi
index 6bc3f58b06f7..5a8fa6daa00a 100644
--- a/arch/arm64/boot/dts/apple/t8112.dtsi
+++ b/arch/arm64/boot/dts/apple/t8112.dtsi
@@ -912,6 +912,10 @@ smc_gpio: gpio {
#gpio-cells = <2>;
};
+ smc_hwmon: hwmon {
+ compatible = "apple,smc-hwmon";
+ };
+
smc_reboot: reboot {
compatible = "apple,smc-reboot";
nvmem-cells = <&shutdown_flag>, <&boot_stage>,
--
2.51.0
^ permalink raw reply related
* [PATCH v3 10/13] arm64: dts: apple: t8103,t60xx,t8112: Add SMC RTC node
From: James Calligeros @ 2025-10-07 11:16 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Alexandre Belloni, Jean Delvare, Guenter Roeck, Dmitry Torokhov,
Jonathan Corbet, James Calligeros
Cc: asahi, linux-arm-kernel, devicetree, linux-kernel, linux-rtc,
linux-hwmon, linux-input, linux-doc
In-Reply-To: <20251007-macsmc-subdevs-v3-0-d7d3bfd7ae02@gmail.com>
From: Sven Peter <sven@kernel.org>
The System Manager Controller of all M1/M2 SoCs supports the RTC
sub-device.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Sven Peter <sven@kernel.org>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
.../arm64/boot/dts/apple/t600x-die0.dtsi | 6 ++++++
.../arm64/boot/dts/apple/t602x-die0.dtsi | 6 ++++++
arch/arm64/boot/dts/apple/t8103.dtsi | 6 ++++++
arch/arm64/boot/dts/apple/t8112.dtsi | 6 ++++++
4 files changed, 24 insertions(+)
diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
index 3603b276a2ab..f715b19efd16 100644
--- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi
+++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
@@ -44,6 +44,12 @@ smc_reboot: reboot {
nvmem-cell-names = "shutdown_flag", "boot_stage",
"boot_error_count", "panic_count";
};
+
+ rtc {
+ compatible = "apple,smc-rtc";
+ nvmem-cells = <&rtc_offset>;
+ nvmem-cell-names = "rtc_offset";
+ };
};
smc_mbox: mbox@290408000 {
diff --git a/arch/arm64/boot/dts/apple/t602x-die0.dtsi b/arch/arm64/boot/dts/apple/t602x-die0.dtsi
index 2e7d2bf08ddc..8622ddea7b44 100644
--- a/arch/arm64/boot/dts/apple/t602x-die0.dtsi
+++ b/arch/arm64/boot/dts/apple/t602x-die0.dtsi
@@ -121,6 +121,12 @@ smc_reboot: reboot {
nvmem-cell-names = "shutdown_flag", "boot_stage",
"boot_error_count", "panic_count";
};
+
+ rtc {
+ compatible = "apple,smc-rtc";
+ nvmem-cells = <&rtc_offset>;
+ nvmem-cell-names = "rtc_offset";
+ };
};
pinctrl_smc: pinctrl@2a2820000 {
diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index 8b7b27887968..59f2678639cf 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -916,6 +916,12 @@ smc_reboot: reboot {
nvmem-cell-names = "shutdown_flag", "boot_stage",
"boot_error_count", "panic_count";
};
+
+ rtc {
+ compatible = "apple,smc-rtc";
+ nvmem-cells = <&rtc_offset>;
+ nvmem-cell-names = "rtc_offset";
+ };
};
smc_mbox: mbox@23e408000 {
diff --git a/arch/arm64/boot/dts/apple/t8112.dtsi b/arch/arm64/boot/dts/apple/t8112.dtsi
index 3f79878b25af..6bc3f58b06f7 100644
--- a/arch/arm64/boot/dts/apple/t8112.dtsi
+++ b/arch/arm64/boot/dts/apple/t8112.dtsi
@@ -919,6 +919,12 @@ smc_reboot: reboot {
nvmem-cell-names = "shutdown_flag", "boot_stage",
"boot_error_count", "panic_count";
};
+
+ rtc {
+ compatible = "apple,smc-rtc";
+ nvmem-cells = <&rtc_offset>;
+ nvmem-cell-names = "rtc_offset";
+ };
};
smc_mbox: mbox@23e408000 {
--
2.51.0
^ permalink raw reply related
* [PATCH v3 09/13] mfd: macsmc: Wire up Apple SMC input subdevice
From: James Calligeros @ 2025-10-07 11:16 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Alexandre Belloni, Jean Delvare, Guenter Roeck, Dmitry Torokhov,
Jonathan Corbet, James Calligeros
Cc: asahi, linux-arm-kernel, devicetree, linux-kernel, linux-rtc,
linux-hwmon, linux-input, linux-doc
In-Reply-To: <20251007-macsmc-subdevs-v3-0-d7d3bfd7ae02@gmail.com>
Add the new SMC input function to the mfd device
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
drivers/mfd/macsmc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/mfd/macsmc.c b/drivers/mfd/macsmc.c
index 51dd667d3b5f..3b69eb6d032a 100644
--- a/drivers/mfd/macsmc.c
+++ b/drivers/mfd/macsmc.c
@@ -45,6 +45,7 @@
#define SMC_TIMEOUT_MS 500
static const struct mfd_cell apple_smc_devs[] = {
+ MFD_CELL_NAME("macsmc-input"),
MFD_CELL_OF("macsmc-gpio", NULL, NULL, 0, 0, "apple,smc-gpio"),
MFD_CELL_OF("macsmc-hwmon", NULL, NULL, 0, 0, "apple,smc-hwmon"),
MFD_CELL_OF("macsmc-reboot", NULL, NULL, 0, 0, "apple,smc-reboot"),
--
2.51.0
^ permalink raw reply related
* [PATCH v3 08/13] input: macsmc-input: New driver to handle the Apple Mac SMC buttons/lid
From: James Calligeros @ 2025-10-07 11:16 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Alexandre Belloni, Jean Delvare, Guenter Roeck, Dmitry Torokhov,
Jonathan Corbet, James Calligeros
Cc: asahi, linux-arm-kernel, devicetree, linux-kernel, linux-rtc,
linux-hwmon, linux-input, linux-doc, Hector Martin
In-Reply-To: <20251007-macsmc-subdevs-v3-0-d7d3bfd7ae02@gmail.com>
From: Hector Martin <marcan@marcan.st>
This driver implements power button and lid switch support for Apple Mac
devices using SMC controllers driven by the macsmc driver.
In addition to basic input support, this also responds to the final
shutdown warning (when the power button is held down long enough) by
doing an emergency kernel poweroff. This allows the NVMe controller to
be cleanly shut down, which prevents data loss for in-cache data.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Hector Martin <marcan@marcan.st>
Co-developed-by: Sven Peter <sven@kernel.org>
Signed-off-by: Sven Peter <sven@kernel.org>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
MAINTAINERS | 1 +
drivers/input/misc/Kconfig | 11 ++
drivers/input/misc/Makefile | 1 +
drivers/input/misc/macsmc-input.c | 208 +++++++++++++++++++++++++
4 files changed, 221 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 79b9f40224a9..e8283f127f11 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2451,6 +2451,7 @@ F: drivers/hwmon/macsmc-hwmon.c
F: drivers/pmdomain/apple/
F: drivers/i2c/busses/i2c-pasemi-core.c
F: drivers/i2c/busses/i2c-pasemi-platform.c
+F: drivers/input/misc/macsmc-input.c
F: drivers/input/touchscreen/apple_z2.c
F: drivers/iommu/apple-dart.c
F: drivers/iommu/io-pgtable-dart.c
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 0e6b49fb54bc..5ab8a4729e0a 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -981,4 +981,15 @@ config INPUT_STPMIC1_ONKEY
To compile this driver as a module, choose M here: the
module will be called stpmic1_onkey.
+config INPUT_MACSMC_INPUT
+ tristate "Apple Mac SMC lid/buttons"
+ depends on MFD_MACSMC
+ help
+ Say Y here if you want to use the input events delivered via the
+ SMC controller on Apple Mac machines using the macsmc driver.
+ This includes lid open/close and the power button.
+
+ To compile this driver as a module, choose M here: the
+ module will be called macsmc-input.
+
endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index ae857c24f48e..480a0d08d4ae 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_INPUT_IQS7222) += iqs7222.o
obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o
obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
+obj-$(CONFIG_INPUT_MACSMC_INPUT) += macsmc-input.o
obj-$(CONFIG_INPUT_MAX7360_ROTARY) += max7360-rotary.o
obj-$(CONFIG_INPUT_MAX77650_ONKEY) += max77650-onkey.o
obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o
diff --git a/drivers/input/misc/macsmc-input.c b/drivers/input/misc/macsmc-input.c
new file mode 100644
index 000000000000..ebbc7dfc31f5
--- /dev/null
+++ b/drivers/input/misc/macsmc-input.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Apple SMC input event driver
+ * Copyright The Asahi Linux Contributors
+ *
+ * This driver exposes HID events from the SMC as an input device.
+ * This includes the lid open/close and power button notifications.
+ */
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/macsmc.h>
+#include <linux/module.h>
+#include <linux/reboot.h>
+
+/**
+ * struct macsmc_input
+ * @dev: Underlying struct device for the input sub-device
+ * @smc: Pointer to apple_smc struct of the mfd parent
+ * @input: Allocated input_dev; devres managed
+ * @nb: Notifier block used for incoming events from SMC (e.g. button pressed down)
+ * @wakeup_mode: Set to true when system is suspended and power button events should wake it
+ */
+struct macsmc_input {
+ struct device *dev;
+ struct apple_smc *smc;
+ struct input_dev *input;
+ struct notifier_block nb;
+ bool wakeup_mode;
+};
+
+#define SMC_EV_BTN 0x7201
+#define SMC_EV_LID 0x7203
+
+#define BTN_POWER 0x01 /* power button on e.g. Mac Mini chasis pressed */
+#define BTN_TOUCHID 0x06 /* combined TouchID / power button on MacBooks pressed */
+#define BTN_POWER_HELD_SHORT 0xfe /* power button briefly held down */
+#define BTN_POWER_HELD_LONG 0x00 /* power button held down; sent just before forced poweroff */
+
+static void macsmc_input_event_button(struct macsmc_input *smcin, unsigned long event)
+{
+ u8 button = (event >> 8) & 0xff;
+ u8 state = !!(event & 0xff);
+
+ switch (button) {
+ case BTN_POWER:
+ case BTN_TOUCHID:
+ if (smcin->wakeup_mode) {
+ if (state)
+ pm_wakeup_event(smcin->dev, 0);
+ } else {
+ input_report_key(smcin->input, KEY_POWER, state);
+ input_sync(smcin->input);
+ }
+ break;
+ case BTN_POWER_HELD_SHORT: /* power button held down; ignore */
+ break;
+ case BTN_POWER_HELD_LONG:
+ /*
+ * If we get here the power button has been held down for a while and
+ * we have about 4 seconds before forced power-off is triggered by SMC.
+ * Try to do an emergency shutdown to make sure the NVMe cache is
+ * flushed. macOS actually does this by panicing (!)...
+ */
+ if (state) {
+ dev_crit(smcin->dev, "Triggering forced shutdown!\n");
+ if (kernel_can_power_off())
+ kernel_power_off();
+ else /* Missing macsmc-reboot driver? */
+ kernel_restart("SMC power button triggered restart");
+ }
+ break;
+ default:
+ dev_warn(smcin->dev, "Unknown SMC button event: %04lx\n", event & 0xffff);
+ }
+}
+
+static void macsmc_input_event_lid(struct macsmc_input *smcin, unsigned long event)
+{
+ u8 lid_state = !!((event >> 8) & 0xff);
+
+ if (smcin->wakeup_mode && !lid_state)
+ pm_wakeup_event(smcin->dev, 0);
+
+ input_report_switch(smcin->input, SW_LID, lid_state);
+ input_sync(smcin->input);
+}
+
+static int macsmc_input_event(struct notifier_block *nb, unsigned long event, void *data)
+{
+ struct macsmc_input *smcin = container_of(nb, struct macsmc_input, nb);
+ u16 type = event >> 16;
+
+ switch (type) {
+ case SMC_EV_BTN:
+ macsmc_input_event_button(smcin, event);
+ return NOTIFY_OK;
+ case SMC_EV_LID:
+ macsmc_input_event_lid(smcin, event);
+ return NOTIFY_OK;
+ default:
+ /* SMC event meant for another driver */
+ return NOTIFY_DONE;
+ }
+}
+
+static int macsmc_input_probe(struct platform_device *pdev)
+{
+ struct apple_smc *smc = dev_get_drvdata(pdev->dev.parent);
+ struct macsmc_input *smcin;
+ bool have_lid, have_power;
+ int error;
+
+ /* Bail early if this SMC neither supports power button nor lid events */
+ have_lid = apple_smc_key_exists(smc, SMC_KEY(MSLD));
+ have_power = apple_smc_key_exists(smc, SMC_KEY(bHLD));
+ if (!have_lid && !have_power)
+ return -ENODEV;
+
+ smcin = devm_kzalloc(&pdev->dev, sizeof(*smcin), GFP_KERNEL);
+ if (!smcin)
+ return -ENOMEM;
+
+ smcin->dev = &pdev->dev;
+ smcin->smc = smc;
+ platform_set_drvdata(pdev, smcin);
+
+ smcin->input = devm_input_allocate_device(&pdev->dev);
+ if (!smcin->input)
+ return -ENOMEM;
+
+ smcin->input->phys = "macsmc-input (0)";
+ smcin->input->name = "Apple SMC power/lid events";
+
+ if (have_lid)
+ input_set_capability(smcin->input, EV_SW, SW_LID);
+ if (have_power)
+ input_set_capability(smcin->input, EV_KEY, KEY_POWER);
+
+ if (have_lid) {
+ u8 val;
+
+ error = apple_smc_read_u8(smc, SMC_KEY(MSLD), &val);
+ if (error < 0)
+ dev_warn(&pdev->dev, "Failed to read initial lid state\n");
+ else
+ input_report_switch(smcin->input, SW_LID, val);
+ }
+
+ if (have_power) {
+ u32 val;
+
+ error = apple_smc_read_u32(smc, SMC_KEY(bHLD), &val);
+ if (error < 0)
+ dev_warn(&pdev->dev, "Failed to read initial power button state\n");
+ else
+ input_report_key(smcin->input, KEY_POWER, val & 1);
+ }
+
+ error = input_register_device(smcin->input);
+ if (error) {
+ dev_err(&pdev->dev, "Failed to register input device: %d\n", error);
+ return error;
+ }
+
+ input_sync(smcin->input);
+
+ smcin->nb.notifier_call = macsmc_input_event;
+ blocking_notifier_chain_register(&smc->event_handlers, &smcin->nb);
+
+ device_init_wakeup(&pdev->dev, 1);
+
+ return 0;
+}
+
+static int macsmc_input_pm_prepare(struct device *dev)
+{
+ struct macsmc_input *smcin = dev_get_drvdata(dev);
+
+ smcin->wakeup_mode = true;
+ return 0;
+}
+
+static void macsmc_input_pm_complete(struct device *dev)
+{
+ struct macsmc_input *smcin = dev_get_drvdata(dev);
+
+ smcin->wakeup_mode = false;
+}
+
+static const struct dev_pm_ops macsmc_input_pm_ops = {
+ .prepare = macsmc_input_pm_prepare,
+ .complete = macsmc_input_pm_complete,
+};
+
+static struct platform_driver macsmc_input_driver = {
+ .driver = {
+ .name = "macsmc-input",
+ .pm = &macsmc_input_pm_ops,
+ },
+ .probe = macsmc_input_probe,
+};
+module_platform_driver(macsmc_input_driver);
+
+MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
+MODULE_LICENSE("Dual MIT/GPL");
+MODULE_DESCRIPTION("Apple SMC input driver");
--
2.51.0
^ permalink raw reply related
* [PATCH v3 07/13] mfd: macsmc: Wire up Apple SMC hwmon subdevice
From: James Calligeros @ 2025-10-07 11:16 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Alexandre Belloni, Jean Delvare, Guenter Roeck, Dmitry Torokhov,
Jonathan Corbet, James Calligeros
Cc: asahi, linux-arm-kernel, devicetree, linux-kernel, linux-rtc,
linux-hwmon, linux-input, linux-doc
In-Reply-To: <20251007-macsmc-subdevs-v3-0-d7d3bfd7ae02@gmail.com>
Add the SMC hwmon functionality to the mfd device
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
drivers/mfd/macsmc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/mfd/macsmc.c b/drivers/mfd/macsmc.c
index 500395bb48da..51dd667d3b5f 100644
--- a/drivers/mfd/macsmc.c
+++ b/drivers/mfd/macsmc.c
@@ -46,6 +46,7 @@
static const struct mfd_cell apple_smc_devs[] = {
MFD_CELL_OF("macsmc-gpio", NULL, NULL, 0, 0, "apple,smc-gpio"),
+ MFD_CELL_OF("macsmc-hwmon", NULL, NULL, 0, 0, "apple,smc-hwmon"),
MFD_CELL_OF("macsmc-reboot", NULL, NULL, 0, 0, "apple,smc-reboot"),
MFD_CELL_OF("macsmc-rtc", NULL, NULL, 0, 0, "apple,smc-rtc"),
};
--
2.51.0
^ permalink raw reply related
* [PATCH v3 06/13] hwmon: Add Apple Silicon SMC hwmon driver
From: James Calligeros @ 2025-10-07 11:16 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Alexandre Belloni, Jean Delvare, Guenter Roeck, Dmitry Torokhov,
Jonathan Corbet, James Calligeros
Cc: asahi, linux-arm-kernel, devicetree, linux-kernel, linux-rtc,
linux-hwmon, linux-input, linux-doc
In-Reply-To: <20251007-macsmc-subdevs-v3-0-d7d3bfd7ae02@gmail.com>
The System Management Controller on Apple Silicon devices is responsible
for integrating and exposing the data reported by the vast array of
hardware monitoring sensors present on these devices. It is also
responsible for fan control, and allows users to manually set fan
speeds if they so desire. Add a hwmon driver to expose current,
power, temperature, and voltage monitoring sensors, as well as
fan speed monitoring and control via the SMC on Apple Silicon devices.
The SMC firmware has no consistency between devices, even when they
share an SoC. The FourCC keys used to access sensors are almost
random. An M1 Mac mini will have different FourCCs for its CPU core
temperature sensors to an M1 MacBook Pro, for example. For this
reason, the valid sensors for a given device are specified in a
child of the SMC Devicetree node. The driver uses this information
to determine which sensors to make available at runtime.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Co-developed-by: Janne Grunau <j@jannau.net>
Signed-off-by: Janne Grunau <j@jannau.net>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
Documentation/hwmon/macsmc-hwmon.rst | 71 +++
MAINTAINERS | 2 +
drivers/hwmon/Kconfig | 12 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/macsmc-hwmon.c | 850 +++++++++++++++++++++++++
5 files changed, 936 insertions(+)
diff --git a/Documentation/hwmon/macsmc-hwmon.rst b/Documentation/hwmon/macsmc-hwmon.rst
new file mode 100644
index 000000000000..6903f76df62b
--- /dev/null
+++ b/Documentation/hwmon/macsmc-hwmon.rst
@@ -0,0 +1,71 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+Kernel driver macsmc-hwmon
+==========================
+
+Supported hardware
+
+ * Apple Silicon Macs (M1 and up)
+
+Author: James Calligeros <jcalligeros99@gmail.com>
+
+Description
+-----------
+
+macsmc-hwmon exposes the Apple System Management controller's
+temperature, voltage, current and power sensors, as well as
+fan speed and control capabilities, via hwmon.
+
+Because each Apple Silicon Mac exposes a different set of sensors
+(e.g. the MacBooks expose battery telemetry that is not present on
+the desktop Macs), sensors present on any given machine are described
+via Devicetree. The driver picks these up and registers them with
+hwmon when probed.
+
+Manual fan speed is supported via the fan_control module parameter. This
+is disabled by default and marked as unsafe, as it cannot be proven that
+the system will fail safe if overheating due to manual fan control being
+used.
+
+sysfs interface
+---------------
+
+currX_input
+ Ammeter value
+
+currX_label
+ Ammeter label
+
+fanX_input
+ Current fan speed
+
+fanX_label
+ Fan label
+
+fanX_min
+ Minimum possible fan speed
+
+fanX_max
+ Maximum possible fan speed
+
+fanX_target
+ Current fan setpoint
+
+inX_input
+ Voltmeter value
+
+inX_label
+ Voltmeter label
+
+powerX_input
+ Power meter value
+
+powerX_label
+ Power meter label
+
+tempX_input
+ Temperature sensor value
+
+tempX_label
+ Temperature sensor label
+
diff --git a/MAINTAINERS b/MAINTAINERS
index 3c6322872dd1..79b9f40224a9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2440,12 +2440,14 @@ F: Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml
F: Documentation/devicetree/bindings/spi/apple,spi.yaml
F: Documentation/devicetree/bindings/spmi/apple,spmi.yaml
F: Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
+F: Documentation/hwmon/macsmc-hwmon.rst
F: arch/arm64/boot/dts/apple/
F: drivers/bluetooth/hci_bcm4377.c
F: drivers/clk/clk-apple-nco.c
F: drivers/cpufreq/apple-soc-cpufreq.c
F: drivers/dma/apple-admac.c
F: drivers/gpio/gpio-macsmc.c
+F: drivers/hwmon/macsmc-hwmon.c
F: drivers/pmdomain/apple/
F: drivers/i2c/busses/i2c-pasemi-core.c
F: drivers/i2c/busses/i2c-pasemi-platform.c
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 2760feb9f83b..d6e9e39d2762 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1174,6 +1174,18 @@ config SENSORS_LTQ_CPUTEMP
If you say yes here you get support for the temperature
sensor inside your CPU.
+config SENSORS_MACSMC_HWMON
+ tristate "Apple SMC (Apple Silicon)"
+ depends on MFD_MACSMC && OF
+ help
+ This driver enables hwmon support for current, power, temperature,
+ and voltage sensors, as well as fan speed reporting and control
+ on Apple Silicon devices. Say Y here if you have an Apple Silicon
+ device.
+
+ This driver can also be built as a module. If so, the module will
+ be called macsmc-hwmon.
+
config SENSORS_MAX1111
tristate "Maxim MAX1111 Serial 8-bit ADC chip and compatibles"
depends on SPI_MASTER
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 73b2abdcc6dd..f9c049ce9124 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -148,6 +148,7 @@ obj-$(CONFIG_SENSORS_LTC4260) += ltc4260.o
obj-$(CONFIG_SENSORS_LTC4261) += ltc4261.o
obj-$(CONFIG_SENSORS_LTC4282) += ltc4282.o
obj-$(CONFIG_SENSORS_LTQ_CPUTEMP) += ltq-cputemp.o
+obj-$(CONFIG_SENSORS_MACSMC_HWMON) += macsmc-hwmon.o
obj-$(CONFIG_SENSORS_MAX1111) += max1111.o
obj-$(CONFIG_SENSORS_MAX127) += max127.o
obj-$(CONFIG_SENSORS_MAX16065) += max16065.o
diff --git a/drivers/hwmon/macsmc-hwmon.c b/drivers/hwmon/macsmc-hwmon.c
new file mode 100644
index 000000000000..342fe3a5ff62
--- /dev/null
+++ b/drivers/hwmon/macsmc-hwmon.c
@@ -0,0 +1,850 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Apple SMC hwmon driver for Apple Silicon platforms
+ *
+ * The System Management Controller on Apple Silicon devices is responsible for
+ * measuring data from sensors across the SoC and machine. These include power,
+ * temperature, voltage and current sensors. Some "sensors" actually expose
+ * derived values. An example of this is the key PHPC, which is an estimate
+ * of the heat energy being dissipated by the SoC.
+ *
+ * While each SoC only has one SMC variant, each platform exposes a different
+ * set of sensors. For example, M1 MacBooks expose battery telemetry sensors
+ * which are not present on the M1 Mac mini. For this reason, the available
+ * sensors for a given platform are described in the device tree in a child
+ * node of the SMC device. We must walk this list of available sensors and
+ * populate the required hwmon data structures at runtime.
+ *
+ * Originally based on a concept by Jean-Francois Bortolotti <jeff@borto.fr>
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+#include <linux/hwmon.h>
+#include <linux/mfd/macsmc.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define MAX_LABEL_LENGTH 32
+
+/* Temperature, voltage, current, power, fan(s) */
+#define NUM_SENSOR_TYPES 5
+
+#define FLT_EXP_BIAS 127
+#define FLT_EXP_MASK GENMASK(30, 23)
+#define FLT_MANT_BIAS 23
+#define FLT_MANT_MASK GENMASK(22, 0)
+#define FLT_SIGN_MASK BIT(31)
+
+static bool fan_control;
+module_param_unsafe(fan_control, bool, 0644);
+MODULE_PARM_DESC(fan_control,
+ "Override the SMC to set your own fan speeds on supported machines");
+
+struct macsmc_hwmon_sensor {
+ struct apple_smc_key_info info;
+ smc_key macsmc_key;
+ char label[MAX_LABEL_LENGTH];
+ u32 attrs;
+};
+
+struct macsmc_hwmon_fan {
+ struct macsmc_hwmon_sensor now;
+ struct macsmc_hwmon_sensor min;
+ struct macsmc_hwmon_sensor max;
+ struct macsmc_hwmon_sensor set;
+ struct macsmc_hwmon_sensor mode;
+ char label[MAX_LABEL_LENGTH];
+ u32 attrs;
+ bool manual;
+};
+
+struct macsmc_hwmon_sensors {
+ struct hwmon_channel_info channel_info;
+ struct macsmc_hwmon_sensor *sensors;
+ u32 count;
+};
+
+struct macsmc_hwmon_fans {
+ struct hwmon_channel_info channel_info;
+ struct macsmc_hwmon_fan *fans;
+ u32 count;
+};
+
+struct macsmc_hwmon {
+ struct device *dev;
+ struct apple_smc *smc;
+ struct device *hwmon_dev;
+ struct hwmon_chip_info chip_info;
+ /* Chip + sensor types + NULL */
+ const struct hwmon_channel_info *channel_infos[1 + NUM_SENSOR_TYPES + 1];
+ struct macsmc_hwmon_sensors temp;
+ struct macsmc_hwmon_sensors volt;
+ struct macsmc_hwmon_sensors curr;
+ struct macsmc_hwmon_sensors power;
+ struct macsmc_hwmon_fans fan;
+};
+
+static int macsmc_hwmon_read_label(struct device *dev,
+ enum hwmon_sensor_types type, u32 attr,
+ int channel, const char **str)
+{
+ struct macsmc_hwmon *hwmon = dev_get_drvdata(dev);
+
+ switch (type) {
+ case hwmon_temp:
+ *str = hwmon->temp.sensors[channel].label;
+ break;
+ case hwmon_in:
+ *str = hwmon->volt.sensors[channel].label;
+ break;
+ case hwmon_curr:
+ *str = hwmon->curr.sensors[channel].label;
+ break;
+ case hwmon_power:
+ *str = hwmon->power.sensors[channel].label;
+ break;
+ case hwmon_fan:
+ *str = hwmon->fan.fans[channel].label;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+/*
+ * A number of sensors report data in a 48.16 fixed-point decimal format that is
+ * not used by any other function of the SMC.
+ */
+static int macsmc_hwmon_read_ioft_scaled(struct apple_smc *smc, smc_key key,
+ u64 *p, int scale)
+{
+ u64 val;
+ int ret;
+
+ ret = apple_smc_read_u64(smc, key, &val);
+ if (ret < 0)
+ return ret;
+
+ *p = mult_frac(val, scale, 65536);
+
+ return 0;
+}
+
+/*
+ * Many sensors report their data as IEEE-754 floats. No other SMC function uses
+ * them.
+ */
+static int macsmc_hwmon_read_f32_scaled(struct apple_smc *smc, smc_key key,
+ int *p, int scale)
+{
+ u32 fval;
+ u64 val;
+ int ret, exp;
+
+ ret = apple_smc_read_u32(smc, key, &fval);
+ if (ret < 0)
+ return ret;
+
+ val = ((u64)((fval & FLT_MANT_MASK) | BIT(23)));
+ exp = ((fval >> 23) & 0xff) - FLT_EXP_BIAS - FLT_MANT_BIAS;
+
+ /* We never have negatively scaled SMC floats */
+ val *= scale;
+
+ if (exp > 63)
+ val = U64_MAX;
+ else if (exp < -63)
+ val = 0;
+ else if (exp < 0)
+ val >>= -exp;
+ else if (exp != 0 && (val & ~((1UL << (64 - exp)) - 1))) /* overflow */
+ val = U64_MAX;
+ else
+ val <<= exp;
+
+ if (fval & FLT_SIGN_MASK) {
+ if (val > (-(s64)INT_MIN))
+ *p = INT_MIN;
+ else
+ *p = -val;
+ } else {
+ if (val > INT_MAX)
+ *p = INT_MAX;
+ else
+ *p = val;
+ }
+
+ return 0;
+}
+
+/*
+ * The SMC has keys of multiple types, denoted by a FourCC of the same format
+ * as the key ID. We don't know what data type a key encodes until we poke at it.
+ */
+static int macsmc_hwmon_read_key(struct apple_smc *smc,
+ struct macsmc_hwmon_sensor *sensor, int scale,
+ long *val)
+{
+ int ret;
+
+ switch (sensor->info.type_code) {
+ /* 32-bit IEEE 754 float */
+ case __SMC_KEY('f', 'l', 't', ' '): {
+ u32 flt_ = 0;
+
+ ret = macsmc_hwmon_read_f32_scaled(smc, sensor->macsmc_key,
+ &flt_, scale);
+ if (ret)
+ return ret;
+
+ *val = flt_;
+ break;
+ }
+ /* 48.16 fixed point decimal */
+ case __SMC_KEY('i', 'o', 'f', 't'): {
+ u64 ioft = 0;
+
+ ret = macsmc_hwmon_read_ioft_scaled(smc, sensor->macsmc_key,
+ &ioft, scale);
+ if (ret)
+ return ret;
+
+ *val = (long)ioft;
+ break;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int macsmc_hwmon_write_f32(struct apple_smc *smc, smc_key key, int value)
+{
+ u64 val;
+ u32 fval = 0;
+ int exp = 0, neg;
+
+ val = abs(value);
+ neg = val != value;
+
+ if (val) {
+ int msb = __fls(val) - exp;
+
+ if (msb > 23) {
+ val >>= msb - FLT_MANT_BIAS;
+ exp -= msb - FLT_MANT_BIAS;
+ } else if (msb < 23) {
+ val <<= FLT_MANT_BIAS - msb;
+ exp += msb;
+ }
+
+ fval = FIELD_PREP(FLT_SIGN_MASK, neg) |
+ FIELD_PREP(FLT_EXP_MASK, exp + FLT_EXP_BIAS) |
+ FIELD_PREP(FLT_MANT_MASK, val);
+ }
+
+ return apple_smc_write_u32(smc, key, fval);
+}
+
+static int macsmc_hwmon_write_key(struct apple_smc *smc,
+ struct macsmc_hwmon_sensor *sensor, long val)
+{
+ switch (sensor->info.type_code) {
+ /* 32-bit IEEE 754 float */
+ case __SMC_KEY('f', 'l', 't', ' '):
+ return macsmc_hwmon_write_f32(smc, sensor->macsmc_key, val);
+ /* unsigned 8-bit integer */
+ case __SMC_KEY('u', 'i', '8', ' '):
+ return apple_smc_write_u8(smc, sensor->macsmc_key, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int macsmc_hwmon_read_fan(struct macsmc_hwmon *hwmon, u32 attr, int chan,
+ long *val)
+{
+ switch (attr) {
+ case hwmon_fan_input:
+ return macsmc_hwmon_read_key(hwmon->smc,
+ &hwmon->fan.fans[chan].now, 1, val);
+ case hwmon_fan_min:
+ return macsmc_hwmon_read_key(hwmon->smc,
+ &hwmon->fan.fans[chan].min, 1, val);
+ case hwmon_fan_max:
+ return macsmc_hwmon_read_key(hwmon->smc,
+ &hwmon->fan.fans[chan].max, 1, val);
+ case hwmon_fan_target:
+ return macsmc_hwmon_read_key(hwmon->smc,
+ &hwmon->fan.fans[chan].set, 1, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int macsmc_hwmon_write_fan(struct device *dev, u32 attr, int channel,
+ long val)
+{
+ struct macsmc_hwmon *hwmon = dev_get_drvdata(dev);
+ long min, max;
+ int ret;
+
+ if (!fan_control || hwmon->fan.fans[channel].mode.macsmc_key == 0)
+ return -EOPNOTSUPP;
+
+ /*
+ * The SMC does no sanity checks on requested fan speeds, so we need to.
+ */
+ ret = macsmc_hwmon_read_key(hwmon->smc, &hwmon->fan.fans[channel].min,
+ 1, &min);
+ if (ret)
+ return ret;
+
+ ret = macsmc_hwmon_read_key(hwmon->smc, &hwmon->fan.fans[channel].max,
+ 1, &max);
+ if (ret)
+ return ret;
+
+ if (val >= min && val <= max) {
+ if (!hwmon->fan.fans[channel].manual) {
+ /* Write 1 to mode key for manual control */
+ ret = macsmc_hwmon_write_key(hwmon->smc,
+ &hwmon->fan.fans[channel].mode, 1);
+ if (ret < 0)
+ return ret;
+
+ hwmon->fan.fans[channel].manual = true;
+ }
+ return macsmc_hwmon_write_key(hwmon->smc,
+ &hwmon->fan.fans[channel].set, val);
+ } else if (!val) {
+ if (hwmon->fan.fans[channel].manual) {
+ ret = macsmc_hwmon_write_key(hwmon->smc,
+ &hwmon->fan.fans[channel].mode, 0);
+ if (ret < 0)
+ return ret;
+
+ hwmon->fan.fans[channel].manual = false;
+ }
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int macsmc_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct macsmc_hwmon *hwmon = dev_get_drvdata(dev);
+ int ret = 0;
+
+ switch (type) {
+ case hwmon_temp:
+ ret = macsmc_hwmon_read_key(hwmon->smc,
+ &hwmon->temp.sensors[channel], 1000, val);
+ break;
+ case hwmon_in:
+ ret = macsmc_hwmon_read_key(hwmon->smc,
+ &hwmon->volt.sensors[channel], 1000, val);
+ break;
+ case hwmon_curr:
+ ret = macsmc_hwmon_read_key(hwmon->smc,
+ &hwmon->curr.sensors[channel], 1000, val);
+ break;
+ case hwmon_power:
+ /* SMC returns power in Watts with acceptable precision to scale to uW */
+ ret = macsmc_hwmon_read_key(hwmon->smc,
+ &hwmon->power.sensors[channel],
+ 1000000, val);
+ break;
+ case hwmon_fan:
+ ret = macsmc_hwmon_read_fan(hwmon, attr, channel, val);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+static int macsmc_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long val)
+{
+ switch (type) {
+ case hwmon_fan:
+ return macsmc_hwmon_write_fan(dev, attr, channel, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t macsmc_hwmon_fan_is_visible(const struct macsmc_hwmon_fan *fan,
+ u32 attr)
+{
+ if (fan->attrs & BIT(attr)) {
+ if (attr == hwmon_fan_target && fan_control && fan->mode.macsmc_key)
+ return 0644;
+
+ return 0444;
+ }
+
+ return 0;
+}
+
+static umode_t macsmc_hwmon_is_visible(const void *data,
+ enum hwmon_sensor_types type, u32 attr,
+ int channel)
+{
+ const struct macsmc_hwmon *hwmon = data;
+ struct macsmc_hwmon_sensor *sensor;
+
+ switch (type) {
+ case hwmon_in:
+ sensor = &hwmon->volt.sensors[channel];
+ break;
+ case hwmon_curr:
+ sensor = &hwmon->curr.sensors[channel];
+ break;
+ case hwmon_power:
+ sensor = &hwmon->power.sensors[channel];
+ break;
+ case hwmon_temp:
+ sensor = &hwmon->temp.sensors[channel];
+ break;
+ case hwmon_fan:
+ return macsmc_hwmon_fan_is_visible(&hwmon->fan.fans[channel], attr);
+ default:
+ return 0;
+ }
+
+ /* Sensors only register ro attributes */
+ if (sensor->attrs & BIT(attr))
+ return 0444;
+
+ return 0;
+}
+
+static const struct hwmon_ops macsmc_hwmon_ops = {
+ .is_visible = macsmc_hwmon_is_visible,
+ .read = macsmc_hwmon_read,
+ .read_string = macsmc_hwmon_read_label,
+ .write = macsmc_hwmon_write,
+};
+
+/*
+ * Get the key metadata, including key data type, from the SMC.
+ */
+static int macsmc_hwmon_parse_key(struct device *dev, struct apple_smc *smc,
+ struct macsmc_hwmon_sensor *sensor,
+ const char *key)
+{
+ int ret;
+
+ ret = apple_smc_get_key_info(smc, _SMC_KEY(key), &sensor->info);
+ if (ret) {
+ dev_dbg(dev, "Failed to retrieve key info for %s\n", key);
+ return ret;
+ }
+
+ sensor->macsmc_key = _SMC_KEY(key);
+
+ return 0;
+}
+
+/*
+ * A sensor is a single key-value pair as made available by the SMC.
+ * The devicetree gives us the SMC key ID and a friendly name where the
+ * purpose of the sensor is known.
+ */
+static int macsmc_hwmon_create_sensor(struct device *dev, struct apple_smc *smc,
+ struct device_node *sensor_node,
+ struct macsmc_hwmon_sensor *sensor)
+{
+ const char *key, *label;
+ int ret;
+
+ ret = of_property_read_string(sensor_node, "apple,key-id", &key);
+ if (ret) {
+ dev_dbg(dev, "Could not find apple,key-id in sensor node\n");
+ return ret;
+ }
+
+ ret = macsmc_hwmon_parse_key(dev, smc, sensor, key);
+ if (ret)
+ return ret;
+
+ ret = of_property_read_string(sensor_node, "label", &label);
+ if (ret)
+ dev_dbg(dev, "No label found for sensor %s\n", key);
+ else
+ strscpy_pad(sensor->label, label, sizeof(sensor->label));
+
+ return 0;
+}
+
+/*
+ * Fan data is exposed by the SMC as multiple sensors.
+ *
+ * The devicetree schema reuses apple,key-id for the actual fan speed sensor.
+ * Min, max and target keys do not need labels, so we can reuse label
+ * for naming the entire fan.
+ */
+static int macsmc_hwmon_create_fan(struct device *dev, struct apple_smc *smc,
+ struct device_node *fan_node,
+ struct macsmc_hwmon_fan *fan)
+{
+ const char *label, *now, *min, *max, *set, *mode;
+ int ret;
+
+ ret = of_property_read_string(fan_node, "apple,key-id", &now);
+ if (ret) {
+ dev_err(dev, "apple,key-id not found in fan node!\n");
+ return ret;
+ }
+
+ ret = macsmc_hwmon_parse_key(dev, smc, &fan->now, now);
+ if (ret)
+ return ret;
+
+ fan->attrs = HWMON_F_INPUT;
+
+ ret = of_property_read_string(fan_node, "label", &label);
+ if (ret) {
+ dev_dbg(dev, "No label found for fan %s\n", now);
+ } else {
+ strscpy_pad(fan->label, label, sizeof(fan->label));
+ fan->attrs |= HWMON_F_LABEL;
+ }
+
+ /* The following keys are not required to simply monitor fan speed */
+ if (!of_property_read_string(fan_node, "apple,fan-minimum", &min)) {
+ ret = macsmc_hwmon_parse_key(dev, smc, &fan->min, min);
+ if (ret)
+ return ret;
+
+ fan->attrs |= HWMON_F_MIN;
+ }
+
+ if (!of_property_read_string(fan_node, "apple,fan-maximum", &max)) {
+ ret = macsmc_hwmon_parse_key(dev, smc, &fan->max, max);
+ if (ret)
+ return ret;
+
+ fan->attrs |= HWMON_F_MAX;
+ }
+
+ if (!of_property_read_string(fan_node, "apple,fan-target", &set)) {
+ ret = macsmc_hwmon_parse_key(dev, smc, &fan->set, set);
+ if (ret)
+ return ret;
+
+ fan->attrs |= HWMON_F_TARGET;
+ }
+
+ if (!of_property_read_string(fan_node, "apple,fan-mode", &mode)) {
+ ret = macsmc_hwmon_parse_key(dev, smc, &fan->mode, mode);
+ if (ret)
+ return ret;
+ }
+
+ /* Initialise fan control mode to automatic */
+ fan->manual = false;
+
+ return 0;
+}
+
+static int macsmc_hwmon_populate_sensors(struct macsmc_hwmon *hwmon,
+ struct device_node *hwmon_node)
+{
+ struct device_node *key_node __maybe_unused;
+ struct macsmc_hwmon_sensor *sensor;
+ u32 n_current = 0, n_fan = 0, n_power = 0, n_temperature = 0, n_voltage = 0;
+
+ for_each_child_of_node_with_prefix(hwmon_node, key_node, "current-") {
+ n_current++;
+ }
+
+ if (n_current) {
+ hwmon->curr.sensors = devm_kcalloc(hwmon->dev, n_current,
+ sizeof(struct macsmc_hwmon_sensor), GFP_KERNEL);
+ if (!hwmon->curr.sensors)
+ return -ENOMEM;
+
+ for_each_child_of_node_with_prefix(hwmon_node, key_node, "current-") {
+ sensor = &hwmon->curr.sensors[hwmon->curr.count];
+ if (!macsmc_hwmon_create_sensor(hwmon->dev, hwmon->smc, key_node, sensor)) {
+ sensor->attrs = HWMON_C_INPUT;
+
+ if (*sensor->label)
+ sensor->attrs |= HWMON_C_LABEL;
+
+ hwmon->curr.count++;
+ }
+ }
+ }
+
+ for_each_child_of_node_with_prefix(hwmon_node, key_node, "fan-") {
+ n_fan++;
+ }
+
+ if (n_fan) {
+ hwmon->fan.fans = devm_kcalloc(hwmon->dev, n_fan,
+ sizeof(struct macsmc_hwmon_fan), GFP_KERNEL);
+ if (!hwmon->fan.fans)
+ return -ENOMEM;
+
+ for_each_child_of_node_with_prefix(hwmon_node, key_node, "fan-") {
+ if (!macsmc_hwmon_create_fan(hwmon->dev, hwmon->smc, key_node,
+ &hwmon->fan.fans[hwmon->fan.count]))
+ hwmon->fan.count++;
+ }
+ }
+
+ for_each_child_of_node_with_prefix(hwmon_node, key_node, "power-") {
+ n_power++;
+ }
+
+ if (n_power) {
+ hwmon->power.sensors = devm_kcalloc(hwmon->dev, n_power,
+ sizeof(struct macsmc_hwmon_sensor), GFP_KERNEL);
+ if (!hwmon->power.sensors)
+ return -ENOMEM;
+
+ for_each_child_of_node_with_prefix(hwmon_node, key_node, "power-") {
+ sensor = &hwmon->power.sensors[hwmon->power.count];
+ if (!macsmc_hwmon_create_sensor(hwmon->dev, hwmon->smc, key_node, sensor)) {
+ sensor->attrs = HWMON_P_INPUT;
+
+ if (*sensor->label)
+ sensor->attrs |= HWMON_P_LABEL;
+
+ hwmon->power.count++;
+ }
+ }
+ }
+
+ for_each_child_of_node_with_prefix(hwmon_node, key_node, "temperature-") {
+ n_temperature++;
+ }
+
+ if (n_temperature) {
+ hwmon->temp.sensors = devm_kcalloc(hwmon->dev, n_temperature,
+ sizeof(struct macsmc_hwmon_sensor), GFP_KERNEL);
+ if (!hwmon->temp.sensors)
+ return -ENOMEM;
+
+ for_each_child_of_node_with_prefix(hwmon_node, key_node, "temperature-") {
+ sensor = &hwmon->temp.sensors[hwmon->temp.count];
+ if (!macsmc_hwmon_create_sensor(hwmon->dev, hwmon->smc, key_node, sensor)) {
+ sensor->attrs = HWMON_T_INPUT;
+
+ if (*sensor->label)
+ sensor->attrs |= HWMON_T_LABEL;
+
+ hwmon->temp.count++;
+ }
+ }
+ }
+
+ for_each_child_of_node_with_prefix(hwmon_node, key_node, "voltage-") {
+ n_voltage++;
+ }
+
+ if (n_voltage) {
+ hwmon->volt.sensors = devm_kcalloc(hwmon->dev, n_voltage,
+ sizeof(struct macsmc_hwmon_sensor), GFP_KERNEL);
+ if (!hwmon->volt.sensors)
+ return -ENOMEM;
+
+ for_each_child_of_node_with_prefix(hwmon_node, key_node, "volt-") {
+ sensor = &hwmon->temp.sensors[hwmon->temp.count];
+ if (!macsmc_hwmon_create_sensor(hwmon->dev, hwmon->smc, key_node, sensor)) {
+ sensor->attrs = HWMON_I_INPUT;
+
+ if (*sensor->label)
+ sensor->attrs |= HWMON_I_LABEL;
+
+ hwmon->volt.count++;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* Create NULL-terminated config arrays */
+static void macsmc_hwmon_populate_configs(u32 *configs, const struct macsmc_hwmon_sensors *sensors)
+{
+ int idx;
+
+ for (idx = 0; idx < sensors->count; idx++)
+ configs[idx] = sensors->sensors[idx].attrs;
+}
+
+static void macsmc_hwmon_populate_fan_configs(u32 *configs, const struct macsmc_hwmon_fans *fans)
+{
+ int idx;
+
+ for (idx = 0; idx < fans->count; idx++)
+ configs[idx] = fans->fans[idx].attrs;
+}
+
+static const struct hwmon_channel_info *const macsmc_chip_channel_info =
+ HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ);
+
+static int macsmc_hwmon_create_infos(struct macsmc_hwmon *hwmon)
+{
+ struct hwmon_channel_info *channel_info;
+ int i = 0;
+
+ /* chip */
+ hwmon->channel_infos[i++] = macsmc_chip_channel_info;
+
+ if (hwmon->curr.count) {
+ channel_info = &hwmon->curr.channel_info;
+ channel_info->type = hwmon_curr;
+ channel_info->config = devm_kcalloc(hwmon->dev, hwmon->curr.count + 1,
+ sizeof(u32), GFP_KERNEL);
+ if (!channel_info->config)
+ return -ENOMEM;
+
+ macsmc_hwmon_populate_configs((u32 *)channel_info->config, &hwmon->curr);
+ hwmon->channel_infos[i++] = channel_info;
+ }
+
+ if (hwmon->fan.count) {
+ channel_info = &hwmon->fan.channel_info;
+ channel_info->type = hwmon_fan;
+ channel_info->config = devm_kcalloc(hwmon->dev, hwmon->fan.count + 1,
+ sizeof(u32), GFP_KERNEL);
+ if (!channel_info->config)
+ return -ENOMEM;
+
+ macsmc_hwmon_populate_fan_configs((u32 *)channel_info->config, &hwmon->fan);
+ hwmon->channel_infos[i++] = channel_info;
+ }
+
+ if (hwmon->power.count) {
+ channel_info = &hwmon->power.channel_info;
+ channel_info->type = hwmon_power;
+ channel_info->config = devm_kcalloc(hwmon->dev, hwmon->power.count + 1,
+ sizeof(u32), GFP_KERNEL);
+ if (!channel_info->config)
+ return -ENOMEM;
+
+ macsmc_hwmon_populate_configs((u32 *)channel_info->config, &hwmon->power);
+ hwmon->channel_infos[i++] = channel_info;
+ }
+
+ if (hwmon->temp.count) {
+ channel_info = &hwmon->temp.channel_info;
+ channel_info->type = hwmon_temp;
+ channel_info->config = devm_kcalloc(hwmon->dev, hwmon->temp.count + 1,
+ sizeof(u32), GFP_KERNEL);
+ if (!channel_info->config)
+ return -ENOMEM;
+
+ macsmc_hwmon_populate_configs((u32 *)channel_info->config, &hwmon->temp);
+ hwmon->channel_infos[i++] = channel_info;
+ }
+
+ if (hwmon->volt.count) {
+ channel_info = &hwmon->volt.channel_info;
+ channel_info->type = hwmon_in;
+ channel_info->config = devm_kcalloc(hwmon->dev, hwmon->volt.count + 1,
+ sizeof(u32), GFP_KERNEL);
+ if (!channel_info->config)
+ return -ENOMEM;
+
+ macsmc_hwmon_populate_configs((u32 *)channel_info->config, &hwmon->volt);
+ hwmon->channel_infos[i++] = channel_info;
+ }
+
+ return 0;
+}
+
+static int macsmc_hwmon_probe(struct platform_device *pdev)
+{
+ struct apple_smc *smc = dev_get_drvdata(pdev->dev.parent);
+ struct macsmc_hwmon *hwmon;
+ int ret;
+
+ /*
+ * The MFD driver will try to probe us unconditionally. Some devices
+ * with the SMC do not have hwmon capabilities. Only probe if we have
+ * a hwmon node.
+ */
+ if (!pdev->dev.of_node)
+ return -ENODEV;
+
+ hwmon = devm_kzalloc(&pdev->dev, sizeof(*hwmon),
+ GFP_KERNEL);
+ if (!hwmon)
+ return -ENOMEM;
+
+ hwmon->dev = &pdev->dev;
+ hwmon->smc = smc;
+
+ ret = macsmc_hwmon_populate_sensors(hwmon, hwmon->dev->of_node);
+ if (ret) {
+ dev_err(hwmon->dev, "Could not parse sensors\n");
+ return ret;
+ }
+
+ if (!hwmon->curr.count && !hwmon->fan.count &&
+ !hwmon->power.count && !hwmon->temp.count &&
+ !hwmon->volt.count) {
+ dev_err(hwmon->dev,
+ "No valid sensors found of any supported type\n");
+ return -ENODEV;
+ }
+
+ ret = macsmc_hwmon_create_infos(hwmon);
+ if (ret)
+ return ret;
+
+ hwmon->chip_info.ops = &macsmc_hwmon_ops;
+ hwmon->chip_info.info =
+ (const struct hwmon_channel_info *const *)&hwmon->channel_infos;
+
+ hwmon->hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev,
+ "macsmc_hwmon", hwmon,
+ &hwmon->chip_info, NULL);
+ if (IS_ERR(hwmon->hwmon_dev))
+ return dev_err_probe(hwmon->dev, PTR_ERR(hwmon->hwmon_dev),
+ "Probing SMC hwmon device failed\n");
+
+ dev_info(hwmon->dev, "Registered SMC hwmon device. Sensors:");
+ dev_info(hwmon->dev,
+ "Current: %d, Fans: %d, Power: %d, Temperature: %d, Voltage: %d",
+ hwmon->curr.count, hwmon->fan.count,
+ hwmon->power.count, hwmon->temp.count,
+ hwmon->volt.count);
+
+ return 0;
+}
+
+static const struct of_device_id macsmc_hwmon_of_table[] = {
+ { .compatible = "apple,smc-hwmon" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, macsmc_hwmon_of_table);
+
+static struct platform_driver macsmc_hwmon_driver = {
+ .probe = macsmc_hwmon_probe,
+ .driver = {
+ .name = "macsmc-hwmon",
+ .of_match_table = macsmc_hwmon_of_table,
+ },
+};
+module_platform_driver(macsmc_hwmon_driver);
+
+MODULE_DESCRIPTION("Apple Silicon SMC hwmon driver");
+MODULE_AUTHOR("James Calligeros <jcalligeros99@gmail.com>");
+MODULE_LICENSE("Dual MIT/GPL");
--
2.51.0
^ permalink raw reply related
* [PATCH v3 05/13] mfd: macsmc: add new __SMC_KEY macro
From: James Calligeros @ 2025-10-07 11:16 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Alexandre Belloni, Jean Delvare, Guenter Roeck, Dmitry Torokhov,
Jonathan Corbet, James Calligeros
Cc: asahi, linux-arm-kernel, devicetree, linux-kernel, linux-rtc,
linux-hwmon, linux-input, linux-doc
In-Reply-To: <20251007-macsmc-subdevs-v3-0-d7d3bfd7ae02@gmail.com>
When using the _SMC_KEY macro in switch/case statements, GCC 15.2.1 errors
out with 'case label does not reduce to an integer constant'. Introduce
a new __SMC_KEY macro that can be used instead.
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
include/linux/mfd/macsmc.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/linux/mfd/macsmc.h b/include/linux/mfd/macsmc.h
index 6b13f01a8592..f6f80c33b5cf 100644
--- a/include/linux/mfd/macsmc.h
+++ b/include/linux/mfd/macsmc.h
@@ -41,6 +41,7 @@ typedef u32 smc_key;
*/
#define SMC_KEY(s) (smc_key)(_SMC_KEY(#s))
#define _SMC_KEY(s) (((s)[0] << 24) | ((s)[1] << 16) | ((s)[2] << 8) | (s)[3])
+#define __SMC_KEY(a, b, c, d) (((u32)(a) << 24) | ((u32)(b) << 16) | ((u32)(c) << 8) | ((u32)(d)))
#define APPLE_SMC_READABLE BIT(7)
#define APPLE_SMC_WRITABLE BIT(6)
--
2.51.0
^ permalink raw reply related
* [PATCH v3 04/13] mfd: macsmc: Wire up Apple SMC RTC subdevice
From: James Calligeros @ 2025-10-07 11:16 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Alexandre Belloni, Jean Delvare, Guenter Roeck, Dmitry Torokhov,
Jonathan Corbet, James Calligeros
Cc: asahi, linux-arm-kernel, devicetree, linux-kernel, linux-rtc,
linux-hwmon, linux-input, linux-doc
In-Reply-To: <20251007-macsmc-subdevs-v3-0-d7d3bfd7ae02@gmail.com>
Add the new SMC RTC function to the mfd device
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
drivers/mfd/macsmc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/mfd/macsmc.c b/drivers/mfd/macsmc.c
index e6cdae221f1d..500395bb48da 100644
--- a/drivers/mfd/macsmc.c
+++ b/drivers/mfd/macsmc.c
@@ -47,6 +47,7 @@
static const struct mfd_cell apple_smc_devs[] = {
MFD_CELL_OF("macsmc-gpio", NULL, NULL, 0, 0, "apple,smc-gpio"),
MFD_CELL_OF("macsmc-reboot", NULL, NULL, 0, 0, "apple,smc-reboot"),
+ MFD_CELL_OF("macsmc-rtc", NULL, NULL, 0, 0, "apple,smc-rtc"),
};
static int apple_smc_cmd_locked(struct apple_smc *smc, u64 cmd, u64 arg,
--
2.51.0
^ permalink raw reply related
* [PATCH v3 03/13] rtc: Add new rtc-macsmc driver for Apple Silicon Macs
From: James Calligeros @ 2025-10-07 11:16 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Alexandre Belloni, Jean Delvare, Guenter Roeck, Dmitry Torokhov,
Jonathan Corbet, James Calligeros
Cc: asahi, linux-arm-kernel, devicetree, linux-kernel, linux-rtc,
linux-hwmon, linux-input, linux-doc, Hector Martin
In-Reply-To: <20251007-macsmc-subdevs-v3-0-d7d3bfd7ae02@gmail.com>
From: Hector Martin <marcan@marcan.st>
Apple Silicon Macs (M1, etc.) have an RTC that is part of the PMU IC,
but most of the PMU functionality is abstracted out by the SMC.
On T600x machines, the RTC counter must be accessed via the SMC to
get full functionality, and it seems likely that future machines
will move towards making SMC handle all RTC functionality.
The SMC RTC counter access is implemented on all current machines
as of the time of this writing, on firmware 12.x. However, the RTC
offset (needed to set the time) is still only accessible via direct
PMU access. To handle this, we expose the RTC offset as an NVMEM
cell from the SPMI PMU device node, and this driver consumes that
cell and uses it to compute/set the current time.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Sven Peter <sven@kernel.org>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
MAINTAINERS | 1 +
drivers/rtc/Kconfig | 11 ++
drivers/rtc/Makefile | 1 +
drivers/rtc/rtc-macsmc.c | 141 +++++++++++++++++++++++++
4 files changed, 154 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 10f4c0034b5e..3c6322872dd1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2460,6 +2460,7 @@ F: drivers/nvmem/apple-spmi-nvmem.c
F: drivers/pinctrl/pinctrl-apple-gpio.c
F: drivers/power/reset/macsmc-reboot.c
F: drivers/pwm/pwm-apple.c
+F: drivers/rtc/rtc-macsmc.c
F: drivers/soc/apple/*
F: drivers/spi/spi-apple.c
F: drivers/spmi/spmi-apple-controller.c
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 4a8dc8d0a4b7..e165301d4abb 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -2078,6 +2078,17 @@ config RTC_DRV_WILCO_EC
This can also be built as a module. If so, the module will
be named "rtc_wilco_ec".
+config RTC_DRV_MACSMC
+ tristate "Apple Mac System Management Controller RTC"
+ depends on MFD_MACSMC
+ help
+ If you say yes here you get support for RTC functions
+ inside Apple SPMI PMUs accessed through the SoC's
+ System Management Controller
+
+ To compile this driver as a module, choose M here: the
+ module will be called rtc-macsmc.
+
config RTC_DRV_MSC313
tristate "MStar MSC313 RTC"
depends on ARCH_MSTARV7 || COMPILE_TEST
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 610a9ee5fd33..32083bd5bb81 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -93,6 +93,7 @@ obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o
obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
obj-$(CONFIG_RTC_DRV_MA35D1) += rtc-ma35d1.o
+obj-$(CONFIG_RTC_DRV_MACSMC) += rtc-macsmc.o
obj-$(CONFIG_RTC_DRV_MAX31335) += rtc-max31335.o
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
diff --git a/drivers/rtc/rtc-macsmc.c b/drivers/rtc/rtc-macsmc.c
new file mode 100644
index 000000000000..05e360277f63
--- /dev/null
+++ b/drivers/rtc/rtc-macsmc.c
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Apple SMC RTC driver
+ * Copyright The Asahi Linux Contributors
+ */
+
+#include <linux/bitops.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/macsmc.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/slab.h>
+
+/* 48-bit RTC */
+#define RTC_BYTES 6
+#define RTC_BITS (8 * RTC_BYTES)
+
+/* 32768 Hz clock */
+#define RTC_SEC_SHIFT 15
+
+struct macsmc_rtc {
+ struct device *dev;
+ struct apple_smc *smc;
+ struct rtc_device *rtc_dev;
+ struct nvmem_cell *rtc_offset;
+};
+
+static int macsmc_rtc_get_time(struct device *dev, struct rtc_time *tm)
+{
+ struct macsmc_rtc *rtc = dev_get_drvdata(dev);
+ u64 ctr = 0, off = 0;
+ time64_t now;
+ void *p_off;
+ size_t len;
+ int ret;
+
+ ret = apple_smc_read(rtc->smc, SMC_KEY(CLKM), &ctr, RTC_BYTES);
+ if (ret < 0)
+ return ret;
+ if (ret != RTC_BYTES)
+ return -EIO;
+
+ p_off = nvmem_cell_read(rtc->rtc_offset, &len);
+ if (IS_ERR(p_off))
+ return PTR_ERR(p_off);
+ if (len < RTC_BYTES) {
+ kfree(p_off);
+ return -EIO;
+ }
+
+ memcpy(&off, p_off, RTC_BYTES);
+ kfree(p_off);
+
+ /* Sign extend from 48 to 64 bits, then arithmetic shift right 15 bits to get seconds */
+ now = sign_extend64(ctr + off, RTC_BITS - 1) >> RTC_SEC_SHIFT;
+ rtc_time64_to_tm(now, tm);
+
+ return ret;
+}
+
+static int macsmc_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct macsmc_rtc *rtc = dev_get_drvdata(dev);
+ u64 ctr = 0, off = 0;
+ int ret;
+
+ ret = apple_smc_read(rtc->smc, SMC_KEY(CLKM), &ctr, RTC_BYTES);
+ if (ret < 0)
+ return ret;
+ if (ret != RTC_BYTES)
+ return -EIO;
+
+ /* This sets the offset such that the set second begins now */
+ off = (rtc_tm_to_time64(tm) << RTC_SEC_SHIFT) - ctr;
+ return nvmem_cell_write(rtc->rtc_offset, &off, RTC_BYTES);
+}
+
+static const struct rtc_class_ops macsmc_rtc_ops = {
+ .read_time = macsmc_rtc_get_time,
+ .set_time = macsmc_rtc_set_time,
+};
+
+static int macsmc_rtc_probe(struct platform_device *pdev)
+{
+ struct apple_smc *smc = dev_get_drvdata(pdev->dev.parent);
+ struct macsmc_rtc *rtc;
+
+ /*
+ * MFD will probe this device even without a node in the device tree,
+ * thus bail out early if the SMC on the current machines does not
+ * support RTC and has no node in the device tree.
+ */
+ if (!pdev->dev.of_node)
+ return -ENODEV;
+
+ rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ rtc->dev = &pdev->dev;
+ rtc->smc = smc;
+
+ rtc->rtc_offset = devm_nvmem_cell_get(&pdev->dev, "rtc_offset");
+ if (IS_ERR(rtc->rtc_offset))
+ return dev_err_probe(&pdev->dev, PTR_ERR(rtc->rtc_offset),
+ "Failed to get rtc_offset NVMEM cell\n");
+
+ rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(rtc->rtc_dev))
+ return PTR_ERR(rtc->rtc_dev);
+
+ rtc->rtc_dev->ops = &macsmc_rtc_ops;
+ rtc->rtc_dev->range_min = S64_MIN >> (RTC_SEC_SHIFT + (64 - RTC_BITS));
+ rtc->rtc_dev->range_max = S64_MAX >> (RTC_SEC_SHIFT + (64 - RTC_BITS));
+
+ platform_set_drvdata(pdev, rtc);
+
+ return devm_rtc_register_device(rtc->rtc_dev);
+}
+
+static const struct of_device_id macsmc_rtc_of_table[] = {
+ { .compatible = "apple,smc-rtc", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, macsmc_rtc_of_table);
+
+static struct platform_driver macsmc_rtc_driver = {
+ .driver = {
+ .name = "macsmc-rtc",
+ .of_match_table = macsmc_rtc_of_table,
+ },
+ .probe = macsmc_rtc_probe,
+};
+module_platform_driver(macsmc_rtc_driver);
+
+MODULE_LICENSE("Dual MIT/GPL");
+MODULE_DESCRIPTION("Apple SMC RTC driver");
+MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
--
2.51.0
^ permalink raw reply related
* [PATCH v3 02/13] dt-bindings: hwmon: Add Apple System Management Controller hwmon schema
From: James Calligeros @ 2025-10-07 11:16 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Alexandre Belloni, Jean Delvare, Guenter Roeck, Dmitry Torokhov,
Jonathan Corbet, James Calligeros
Cc: asahi, linux-arm-kernel, devicetree, linux-kernel, linux-rtc,
linux-hwmon, linux-input, linux-doc
In-Reply-To: <20251007-macsmc-subdevs-v3-0-d7d3bfd7ae02@gmail.com>
Apple Silicon devices integrate a vast array of sensors, monitoring
current, power, temperature, and voltage across almost every part of
the system. The sensors themselves are all connected to the System
Management Controller (SMC). The SMC firmware exposes the data
reported by these sensors via its standard FourCC-based key-value
API. The SMC is also responsible for monitoring and controlling any
fans connected to the system, exposing them in the same way.
For reasons known only to Apple, each device exposes its sensors with
an almost totally unique set of keys. This is true even for devices
which share an SoC. An M1 Mac mini, for example, will report its core
temperatures on different keys to an M1 MacBook Pro. Worse still, the
SMC does not provide a way to enumerate the available keys at runtime,
nor do the keys follow any sort of reasonable or consistent naming
rules that could be used to deduce their purpose. We must therefore
know which keys are present on any given device, and which function
they serve, ahead of time.
Add a schema so that we can describe the available sensors for a given
Apple Silicon device in the Devicetree.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
.../bindings/hwmon/apple,smc-hwmon.yaml | 86 +++++++++++++++++++++++++
.../bindings/mfd/apple,smc.yaml | 36 +++++++++++
MAINTAINERS | 1 +
3 files changed, 123 insertions(+)
diff --git a/Documentation/devicetree/bindings/hwmon/apple,smc-hwmon.yaml b/Documentation/devicetree/bindings/hwmon/apple,smc-hwmon.yaml
new file mode 100644
index 000000000000..2eec317bc4b3
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/apple,smc-hwmon.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/apple,smc-hwmon.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Apple SMC Hardware Monitoring
+
+description:
+ Apple's System Management Controller (SMC) exposes a vast array of
+ hardware monitoring sensors, including temperature probes, current and
+ voltage sense, power meters, and fan speeds. It also provides endpoints
+ to manually control the speed of each fan individually. Each Apple
+ Silicon device exposes a different set of endpoints via SMC keys. This
+ is true even when two machines share an SoC. The CPU core temperature
+ sensor keys on an M1 Mac mini are different to those on an M1 MacBook
+ Pro, for example.
+
+maintainers:
+ - James Calligeros <jcalligeros99@gmail.com>
+
+$defs:
+ sensor:
+ type: object
+
+ properties:
+ apple,key-id:
+ $ref: /schemas/types.yaml#/definitions/string
+ pattern: "^[A-Za-z0-9]{4}$"
+ description: The SMC FourCC key of the desired sensor.
+ Must match the node's suffix.
+
+ label:
+ description: Human-readable name for the sensor
+
+ required:
+ - apple,key-id
+
+properties:
+ compatible:
+ const: apple,smc-hwmon
+
+patternProperties:
+ "^current-[A-Za-z0-9]{4}$":
+ $ref: "#/$defs/sensor"
+ unevaluatedProperties: false
+
+ "^fan-[A-Za-z0-9]{4}$":
+ $ref: "#/$defs/sensor"
+ unevaluatedProperties: false
+
+ properties:
+ apple,fan-minimum:
+ $ref: /schemas/types.yaml#/definitions/string
+ pattern: "^[A-Za-z0-9]{4}$"
+ description: SMC key containing the fan's minimum speed
+
+ apple,fan-maximum:
+ $ref: /schemas/types.yaml#/definitions/string
+ pattern: "^[A-Za-z0-9]{4}$"
+ description: SMC key containing the fan's maximum speed
+
+ apple,fan-target:
+ $ref: /schemas/types.yaml#/definitions/string
+ pattern: "^[A-Za-z0-9]{4}$"
+ description: Writeable endpoint for setting desired fan speed
+
+ apple,fan-mode:
+ $ref: /schemas/types.yaml#/definitions/string
+ pattern: "^[A-Za-z0-9]{4}$"
+ description: Writeable key to enable/disable manual fan control
+
+
+ "^power-[A-Za-z0-9]{4}$":
+ $ref: "#/$defs/sensor"
+ unevaluatedProperties: false
+
+ "^temperature-[A-Za-z0-9]{4}$":
+ $ref: "#/$defs/sensor"
+ unevaluatedProperties: false
+
+ "^voltage-[A-Za-z0-9]{4}$":
+ $ref: "#/$defs/sensor"
+ unevaluatedProperties: false
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/mfd/apple,smc.yaml b/Documentation/devicetree/bindings/mfd/apple,smc.yaml
index 0410e712c900..34ce048619f5 100644
--- a/Documentation/devicetree/bindings/mfd/apple,smc.yaml
+++ b/Documentation/devicetree/bindings/mfd/apple,smc.yaml
@@ -49,6 +49,9 @@ properties:
rtc:
$ref: /schemas/rtc/apple,smc-rtc.yaml
+ hwmon:
+ $ref: /schemas/hwmon/apple,smc-hwmon.yaml
+
additionalProperties: false
required:
@@ -89,5 +92,38 @@ examples:
nvmem-cells = <&rtc_offset>;
nvmem-cell-names = "rtc_offset";
};
+
+ hwmon {
+ compatible = "apple,smc-hwmon";
+
+ current-ID0R {
+ apple,key-id = "ID0R";
+ label = "AC Input Current";
+ };
+
+ fan-F0Ac {
+ apple,key-id = "F0Ac";
+ apple,fan-minimum = "F0Mn";
+ apple,fan-maximum = "F0Mx";
+ apple,fan-target = "F0Tg";
+ apple,fan-mode = "F0Md";
+ label = "Fan 1";
+ };
+
+ power-PSTR {
+ apple,key-id = "PSTR";
+ label = "Total System Power";
+ };
+
+ temperature-TW0P {
+ apple,key-id = "TW0P";
+ label = "WiFi/BT Module Temperature";
+ };
+
+ voltage-VD0R {
+ apple,key-id = "VD0R";
+ label = "AC Input Voltage";
+ };
+ };
};
};
diff --git a/MAINTAINERS b/MAINTAINERS
index 745d85b66365..10f4c0034b5e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2418,6 +2418,7 @@ F: Documentation/devicetree/bindings/cpufreq/apple,cluster-cpufreq.yaml
F: Documentation/devicetree/bindings/dma/apple,admac.yaml
F: Documentation/devicetree/bindings/gpio/apple,smc-gpio.yaml
F: Documentation/devicetree/bindings/gpu/apple,agx.yaml
+F: Documentation/devicetree/bindings/hwmon/apple,smc-hwmon.yaml
F: Documentation/devicetree/bindings/i2c/apple,i2c.yaml
F: Documentation/devicetree/bindings/input/touchscreen/apple,z2-multitouch.yaml
F: Documentation/devicetree/bindings/interrupt-controller/apple,*
--
2.51.0
^ permalink raw reply related
* [PATCH v3 01/13] dt-bindings: rtc: Add Apple SMC RTC
From: James Calligeros @ 2025-10-07 11:16 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Alexandre Belloni, Jean Delvare, Guenter Roeck, Dmitry Torokhov,
Jonathan Corbet, James Calligeros
Cc: asahi, linux-arm-kernel, devicetree, linux-kernel, linux-rtc,
linux-hwmon, linux-input, linux-doc, Mark Kettenis
In-Reply-To: <20251007-macsmc-subdevs-v3-0-d7d3bfd7ae02@gmail.com>
From: Sven Peter <sven@kernel.org>
Apple Silicon Macs (M1, etc.) have an RTC that is part of the PMU IC,
but most of the PMU functionality is abstracted out by the SMC.
An additional RTC offset stored inside NVMEM is required to compute
the current date/time.
Reviewed-by: Mark Kettenis <kettenis@openbsd.org>
Reviewed-by: Neal Gompa <neal@gompa.dev>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Sven Peter <sven@kernel.org>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
.../bindings/mfd/apple,smc.yaml | 9 +++++++
.../bindings/rtc/apple,smc-rtc.yaml | 35 +++++++++++++++++++++++++
MAINTAINERS | 1 +
3 files changed, 45 insertions(+)
diff --git a/Documentation/devicetree/bindings/mfd/apple,smc.yaml b/Documentation/devicetree/bindings/mfd/apple,smc.yaml
index 5429538f7e2e..0410e712c900 100644
--- a/Documentation/devicetree/bindings/mfd/apple,smc.yaml
+++ b/Documentation/devicetree/bindings/mfd/apple,smc.yaml
@@ -46,6 +46,9 @@ properties:
reboot:
$ref: /schemas/power/reset/apple,smc-reboot.yaml
+ rtc:
+ $ref: /schemas/rtc/apple,smc-rtc.yaml
+
additionalProperties: false
required:
@@ -80,5 +83,11 @@ examples:
nvmem-cell-names = "shutdown_flag", "boot_stage",
"boot_error_count", "panic_count";
};
+
+ rtc {
+ compatible = "apple,smc-rtc";
+ nvmem-cells = <&rtc_offset>;
+ nvmem-cell-names = "rtc_offset";
+ };
};
};
diff --git a/Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml b/Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml
new file mode 100644
index 000000000000..607b610665a2
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/apple,smc-rtc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Apple SMC RTC
+
+description:
+ Apple Silicon Macs (M1, etc.) have an RTC that is part of the PMU IC,
+ but most of the PMU functionality is abstracted out by the SMC.
+ An additional RTC offset stored inside NVMEM is required to compute
+ the current date/time.
+
+maintainers:
+ - Sven Peter <sven@kernel.org>
+
+properties:
+ compatible:
+ const: apple,smc-rtc
+
+ nvmem-cells:
+ items:
+ - description: 48bit RTC offset, specified in 32768 (2^15) Hz clock ticks
+
+ nvmem-cell-names:
+ items:
+ - const: rtc_offset
+
+required:
+ - compatible
+ - nvmem-cells
+ - nvmem-cell-names
+
+additionalProperties: false
diff --git a/MAINTAINERS b/MAINTAINERS
index b45db73e55df..745d85b66365 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2435,6 +2435,7 @@ F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
F: Documentation/devicetree/bindings/power/apple*
F: Documentation/devicetree/bindings/power/reset/apple,smc-reboot.yaml
F: Documentation/devicetree/bindings/pwm/apple,s5l-fpwm.yaml
+F: Documentation/devicetree/bindings/rtc/apple,smc-rtc.yaml
F: Documentation/devicetree/bindings/spi/apple,spi.yaml
F: Documentation/devicetree/bindings/spmi/apple,spmi.yaml
F: Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
--
2.51.0
^ permalink raw reply related
* [PATCH v3 00/13] mfd: macsmc: add rtc, hwmon and hid subdevices
From: James Calligeros @ 2025-10-07 11:16 UTC (permalink / raw)
To: Sven Peter, Janne Grunau, Alyssa Rosenzweig, Neal Gompa,
Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Alexandre Belloni, Jean Delvare, Guenter Roeck, Dmitry Torokhov,
Jonathan Corbet, James Calligeros
Cc: asahi, linux-arm-kernel, devicetree, linux-kernel, linux-rtc,
linux-hwmon, linux-input, linux-doc, Mark Kettenis, Hector Martin
Hi all,
This series adds support for the remaining SMC subdevices. These are the
RTC, hwmon, and HID devices. They are being submitted together as the RTC
and hwmon drivers both require changes to the SMC DT schema.
The RTC driver is responsible for getting and setting the system clock,
and requires an NVMEM cell. This series replaces Sven's original RTC driver
submission [1].
The hwmon function is an interesting one. While each Apple Silicon device
exposes pretty similar sets of sensors, these all seem to be paired to
different SMC keys in the firmware interface. This is true even when the
sensors are on the SoC. For example, an M1 MacBook Pro will use different
keys to access the LITTLE core temperature sensors to an M1 Mac mini. This
necessitates describing which keys correspond to which sensors for each
device individually, and populating the hwmon structs at runtime. We do
this with a node in the device tree. This series includes only the keys
for sensors which we know to be common to all devices. The SMC is also
responsible for monitoring and controlling fan speeds on systems with fans,
which we expose via the hwmon driver.
The SMC also handles the hardware power button and lid switch. Power
button presses and lid opening/closing are emitted as HID events, so we
add an input subdevice to handle them.
This series originally cherry-picked three Devicetree commits to build
cleanly, however these have now been merged and were dropped.
Regards,
James
[1] https://lore.kernel.org/asahi/CAEg-Je84XxLWH7vznQmPRfjf6GxWOu75ZetwN7AdseAwfMLLrQ@mail.gmail.com/T/#t
---
Changes in v3:
- Renamed macsmc-hid to macsmc-input
- Switched to pm_wakeup_event in macsmc-input
- macsmc-input now configures its capabilities before registering the device
- Renamed macsmc_hwmon to macsmc-hwmon
- Dropped module aliases in macsmc-input and macsmc_hwmon
- Introduced new SMC FourCC macro to silence GCC errors
- Condensed hwmon binding using $defs
- Made label property optional for hwmon sensors
- Fixed incorrect hwmon is_visible implementation
- Dropped 64-bit math from SMC float ops
- Fixed incorrect use of error numbers in hwmon driver
- Replaced a number of non-fatal dev_errs with dev_dbgs in hwmon driver
- Added hwmon driver documentation
- Added hwmon subdevice directly to the DT SMC node
- Included "common" hwmon sensors in SoC .dtsi files
- Fixed typo in hwmon-common.dtsi
- Added Neal's R-b to series
- Added required nodes to t602x Devicetrees
- Link to v2: https://lore.kernel.org/r/20250827-macsmc-subdevs-v2-0-ce5e99d54c28@gmail.com
Changes in v2:
- Added Rob's R-b tag to RTC DT binding
- Removed redundant nesting from hwmon DT binding
- Dedpulicated property definitions in hwmon DT schema
- Made label a required property for hwmon DT nodes
- Clarified semantics in hwmon DT schema definitions
- Split mfd tree changes into separate commits
- Fixed numerous style errors in hwmon driver
- Removed log messages sysfs read/write functions in hwmon driver
- Removed ignored errors from hwmon driver
- Removed uses of dev_err for non-errors in hwmon driver
- Made it more obvious that a number of hwmon fan properties are optional
- Modified hwmon driver to reflect DT schema changes
- Added compatible property to hwmon node
- Link to v1: https://lore.kernel.org/r/20250819-macsmc-subdevs-v1-0-57df6c3e5f19@gmail.com
---
Hector Martin (2):
rtc: Add new rtc-macsmc driver for Apple Silicon Macs
input: macsmc-input: New driver to handle the Apple Mac SMC buttons/lid
James Calligeros (9):
dt-bindings: hwmon: Add Apple System Management Controller hwmon schema
mfd: macsmc: Wire up Apple SMC RTC subdevice
mfd: macsmc: add new __SMC_KEY macro
hwmon: Add Apple Silicon SMC hwmon driver
mfd: macsmc: Wire up Apple SMC hwmon subdevice
mfd: macsmc: Wire up Apple SMC input subdevice
arm64: dts: apple: t8103, t8112, t60xx: add hwmon SMC subdevice
arm64: dts: apple: Add common hwmon sensors and fans
arm64: dts: apple: t8103, t60xx, t8112: Add common hwmon nodes to devices
Sven Peter (2):
dt-bindings: rtc: Add Apple SMC RTC
arm64: dts: apple: t8103,t60xx,t8112: Add SMC RTC node
.../bindings/hwmon/apple,smc-hwmon.yaml | 86 +++
.../bindings/mfd/apple,smc.yaml | 45 ++
.../bindings/rtc/apple,smc-rtc.yaml | 35 +
Documentation/hwmon/macsmc-hwmon.rst | 71 +++
MAINTAINERS | 6 +
.../boot/dts/apple/hwmon-common.dtsi | 33 +
.../boot/dts/apple/hwmon-fan-dual.dtsi | 22 +
arch/arm64/boot/dts/apple/hwmon-fan.dtsi | 17 +
.../boot/dts/apple/hwmon-laptop.dtsi | 33 +
.../boot/dts/apple/hwmon-mac-mini.dtsi | 15 +
.../arm64/boot/dts/apple/t6001-j375c.dts | 2 +
arch/arm64/boot/dts/apple/t6001.dtsi | 2 +
.../arm64/boot/dts/apple/t6002-j375d.dts | 2 +
.../arm64/boot/dts/apple/t600x-die0.dtsi | 10 +
.../boot/dts/apple/t600x-j314-j316.dtsi | 3 +
.../arm64/boot/dts/apple/t602x-die0.dtsi | 10 +
arch/arm64/boot/dts/apple/t8103-j274.dts | 2 +
arch/arm64/boot/dts/apple/t8103-j293.dts | 3 +
arch/arm64/boot/dts/apple/t8103-j313.dts | 2 +
arch/arm64/boot/dts/apple/t8103-j456.dts | 2 +
arch/arm64/boot/dts/apple/t8103-j457.dts | 2 +
arch/arm64/boot/dts/apple/t8103.dtsi | 11 +
arch/arm64/boot/dts/apple/t8112-j413.dts | 2 +
arch/arm64/boot/dts/apple/t8112-j473.dts | 2 +
arch/arm64/boot/dts/apple/t8112-j493.dts | 3 +
arch/arm64/boot/dts/apple/t8112.dtsi | 11 +
drivers/hwmon/Kconfig | 12 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/macsmc-hwmon.c | 850 +++++++++++++++++++++++++
drivers/input/misc/Kconfig | 11 +
drivers/input/misc/Makefile | 1 +
drivers/input/misc/macsmc-input.c | 208 ++++++
drivers/mfd/macsmc.c | 3 +
drivers/rtc/Kconfig | 11 +
drivers/rtc/Makefile | 1 +
drivers/rtc/rtc-macsmc.c | 141 ++++
include/linux/mfd/macsmc.h | 1 +
37 files changed, 1672 insertions(+)
---
base-commit: c746c3b5169831d7fb032a1051d8b45592ae8d78
change-id: 20250816-macsmc-subdevs-87032c017d0c
Best regards,
--
James Calligeros <jcalligeros99@gmail.com>
^ permalink raw reply
* [PATCH] input: goodix: Remove setting of RST pin to input
From: Martyn Welch @ 2025-10-07 10:23 UTC (permalink / raw)
To: Hans de Goede, Dmitry Torokhov
Cc: kernel, Martyn Welch, linux-input, linux-kernel
The reset line is being set to input on non-ACPI devices apparently to
save power. This isn't being done on ACPI devices as it's been found
that some ACPI devices don't have a pull-up resistor fitted. This can
also be the case for non-ACPI devices, resulting in:
[ 941.672207] Goodix-TS 1-0014: Error reading 10 bytes from 0x814e: -110
[ 942.696168] Goodix-TS 1-0014: Error reading 10 bytes from 0x814e: -110
[ 945.832208] Goodix-TS 1-0014: Error reading 10 bytes from 0x814e: -110
This behaviour appears to have been initially introduced in ec6e1b4082d9.
This doesn't seem to be based on information in either the GT911 or GT9271
datasheets cited as sources of information for this change. Thus it seems
likely that it is based on functionality in the Android driver which it
also lists. This behaviour may be viable in very specific instances where
the hardware is known to have a pull-up fitted, but seems unwise in the
upstream kernel where such hardware requirements can't be guaranteed.
Remove this over optimisation to improve reliability on non-ACPI
devices.
Signed-off-by: Martyn Welch <martyn.welch@collabora.com>
---
drivers/input/touchscreen/goodix.c | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index 252dcae039f8..e7ef744011ad 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -796,17 +796,6 @@ int goodix_reset_no_int_sync(struct goodix_ts_data *ts)
usleep_range(6000, 10000); /* T4: > 5ms */
- /*
- * Put the reset pin back in to input / high-impedance mode to save
- * power. Only do this in the non ACPI case since some ACPI boards
- * don't have a pull-up, so there the reset pin must stay active-high.
- */
- if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_GPIO) {
- error = gpiod_direction_input(ts->gpiod_rst);
- if (error)
- goto error;
- }
-
return 0;
error:
--
2.39.5
^ permalink raw reply related
* Re: hid_multitouch - random non-responsive, multitouch, scrolling and zooming
From: Benjamin Tissoires @ 2025-10-07 9:10 UTC (permalink / raw)
To: Steven Haigh; +Cc: Stéphane Chatty, Peter Hutterer, linux-input
In-Reply-To: <fd7e0577-a992-4761-823b-b5fe41a7ee74@crc.id.au>
On Tue, Oct 7, 2025, at 3:42 AM, Steven Haigh wrote:
> On 6/10/25 19:30, Benjamin Tissoires wrote:
>> Hi Steven,
>>
>> On Sat, Oct 4, 2025, at 12:23 PM, Steven Haigh wrote:
>>> Hi guys,
>>>
>>> Firstly, I apologise for contacting you directly - I couldn't find a bug
>>> reporting / method to try to debug this issue.
>>
>> No worries. Though usually it's best to Cc the LKML with linux-input@vger.kernel.org. So unless you prefer not to, I'd like to include this in feature emails so that other will benefit from the same.
>
> Thanks, I've added that address to this reply.
>>>
>>> I have a Dell Inspiron 5515 which has a touchpad that seems to be
>>> controled via hid_multitouch.
>>>
>>> While using it in Fedora (Currently the F43 beta with kernel 6.17), I
>>> have random times where the keypad stops responding, or gets locked into
>>> zoom mode, or scroll mode.
>>>
>>> When it gets like this, I can't move the cursor and basically smooshing
>>> the touchpad with clicks or other input seems to be the only way I've
>>> found it to recover.
>>
>> This remembers me about https://gitlab.freedesktop.org/libinput/libinput/-/issues/1194
>>
>> TL;DR is that there is a bug in the hid-multitouch driver that doesn't entirely mimic the Windows driver, and some touches might get stuck because the firmware forgets to send the releases. I have a better kernel fix for that but because we are in the middle of the v6.18 kernel merge window, I can not post and merge it yet.
>
> From the description of this, it sounds very much like the problem.
> It's been driving me nuts for quite a long time - to the point where I
> just close the laptop and go use a desktop sometimes. I figured I'd
> finally try to get a fix instead - because if it affects me, it will
> affect others at some point.
>
> Logically, yes, it does make sense that the trackpad is thinking there
> are touches that just don't exist. I also thought that because I have
> bigger hands than average, that maybe its also detecting a single touch
> as double sometimes - but your description seems to be more fitting to
> the situation.
great, now we "just" need to test the fixes.
>
>> Meanwhile, for people having the DLL0945 I've opened a temporary stop gap through https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/204
>>
>> There is a high chance this works for you too (I've tested this on 3 different laptops with different DLL* numbers), but to be sure it's not messing with your system, can you send me the full output of `sudo libinput record` with the touchpad node?
>
> I've followed the "installing from CI" instructions with the artifacts
> from that Merge Request and run the install.sh.
>
> I can see the firmware files in /usr/local/lib/firmware/hid/bpf
>
> I rebooted, but I don't see anything in /sys/fs/bpf/hid
>
> I thought that maybe they need to be in the initramfs, so ran `dracut
> --regenerate-all -f` and rebooted again - but still nothing in
> /sys/fs/bpf/hid.
>
> Do I need to do something else here?
Yes, that's normal. Each HID-BPF file is supposed to only register to a certain vendor ID and product ID, and in your case, the touchpad doesn't match.
But there is also a slight difference with your touchpad. If you looks at your C translation of the input report[0], we get:
```
struct touch_report {
__u8 report_id; /* Report ID 4 */
struct {
__u8 confidence:1;
__u8 tip_switch:1;
__u8 padding1:2;
__u8 contact_id:4;
__u16 x; /* Logical max: 1919 */
__u16 y; /* Logical max: 1079 */
} __attribute__((packed)) fingers[5];
__u16 scan_time;
__u8 contact_count;
__u8 button:1;
__u8 padding2:7;
} __attribute__((packed));
```
While the one the HID-BPF expects is:
```
struct touch_report {
__u8 report_id; /* Report ID 3 */
struct {
__u8 confidence:1;
__u8 tip_switch:1;
__u8 contact_id:3;
__u8 padding:3;
__u16 x; /* Logical max: 1296 */
__u16 y; /* Logical max: 752 */
} __attribute__((packed)) fingers[5];
__u16 scan_time;
__u8 contact_count;
__u8 button:1;
__u8 padding:7;
} __attribute__((packed));
```
So a couple of diffs:
- report ID is 4 in your case, when it's 3 in the other touchpad case
- the position and number of bits of the contact_id field is not the same (4 bits in yours, 3 in the other).
That means that I need to either edit that HID-BPF to account for those 2 variants, or just copy/paste it into a new file. But that also means we probably need more logs to be able to ensure we are fixing the issue.
The third option consist in getting the hid-multitouch more generic fix upstream (in v6.18-rc1 or -rc2) and get it backported in all stable and for you to just wait. (which should hopefully happen anyway).
>
> I ran `libinput record -o recording.yml /dev/event/input6` and have
> attached the compressed output. Annoyingly, it seems like the touchpad
> is working fine at the moment - so it may confirm the hardware
> information, but not a recording of the problem right now.
Yeah, same on one of the Dell laptops I have here. I know it has the bug, but whenever I try to reproduce it it never shows meaning I was never able to pin point the issue :(
Cheers,
Benjamin
>
>>>
>>> This seems to be worse if the kernel clock is not synced via NTP - I
>>> have no idea why.
>>>
>>> Are you able to give me some hints / pointers in how I could start to
>>> debug this?
>>
>> Hopefully this is the exact same bug, and we already have a fix (and a temporary band aid).
>>
>> Cheers,
>> Benjamin
>>
>>>
>>> evtest shows the devices as:
>>> /dev/input/event5: DELL0A78:00 27C6:0D42 Mouse
>>> /dev/input/event6: DELL0A78:00 27C6:0D42 Touchpad
> --
> Steven Haigh
>
> 📧 netwiz@crc.id.au
> 💻 https://crc.id.au
>
> Attachments:
> * recording.yml.xz
[0] that was obtained by running hid-decode on your yaml file to get the hid-recorder file format, and then we can read the report descriptor.
^ permalink raw reply
* Re: hid_multitouch - random non-responsive, multitouch, scrolling and zooming
From: Steven Haigh @ 2025-10-07 1:42 UTC (permalink / raw)
To: Benjamin Tissoires; +Cc: Stéphane Chatty, Peter Hutterer, linux-input
In-Reply-To: <d058871a-a2c6-4197-a77c-08edb0ce70b4@app.fastmail.com>
[-- Attachment #1: Type: text/plain, Size: 3645 bytes --]
On 6/10/25 19:30, Benjamin Tissoires wrote:
> Hi Steven,
>
> On Sat, Oct 4, 2025, at 12:23 PM, Steven Haigh wrote:
>> Hi guys,
>>
>> Firstly, I apologise for contacting you directly - I couldn't find a bug
>> reporting / method to try to debug this issue.
>
> No worries. Though usually it's best to Cc the LKML with linux-input@vger.kernel.org. So unless you prefer not to, I'd like to include this in feature emails so that other will benefit from the same.
Thanks, I've added that address to this reply.
>>
>> I have a Dell Inspiron 5515 which has a touchpad that seems to be
>> controled via hid_multitouch.
>>
>> While using it in Fedora (Currently the F43 beta with kernel 6.17), I
>> have random times where the keypad stops responding, or gets locked into
>> zoom mode, or scroll mode.
>>
>> When it gets like this, I can't move the cursor and basically smooshing
>> the touchpad with clicks or other input seems to be the only way I've
>> found it to recover.
>
> This remembers me about https://gitlab.freedesktop.org/libinput/libinput/-/issues/1194
>
> TL;DR is that there is a bug in the hid-multitouch driver that doesn't entirely mimic the Windows driver, and some touches might get stuck because the firmware forgets to send the releases. I have a better kernel fix for that but because we are in the middle of the v6.18 kernel merge window, I can not post and merge it yet.
From the description of this, it sounds very much like the problem.
It's been driving me nuts for quite a long time - to the point where I
just close the laptop and go use a desktop sometimes. I figured I'd
finally try to get a fix instead - because if it affects me, it will
affect others at some point.
Logically, yes, it does make sense that the trackpad is thinking there
are touches that just don't exist. I also thought that because I have
bigger hands than average, that maybe its also detecting a single touch
as double sometimes - but your description seems to be more fitting to
the situation.
> Meanwhile, for people having the DLL0945 I've opened a temporary stop gap through https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/204
>
> There is a high chance this works for you too (I've tested this on 3 different laptops with different DLL* numbers), but to be sure it's not messing with your system, can you send me the full output of `sudo libinput record` with the touchpad node?
I've followed the "installing from CI" instructions with the artifacts
from that Merge Request and run the install.sh.
I can see the firmware files in /usr/local/lib/firmware/hid/bpf
I rebooted, but I don't see anything in /sys/fs/bpf/hid
I thought that maybe they need to be in the initramfs, so ran `dracut
--regenerate-all -f` and rebooted again - but still nothing in
/sys/fs/bpf/hid.
Do I need to do something else here?
I ran `libinput record -o recording.yml /dev/event/input6` and have
attached the compressed output. Annoyingly, it seems like the touchpad
is working fine at the moment - so it may confirm the hardware
information, but not a recording of the problem right now.
>>
>> This seems to be worse if the kernel clock is not synced via NTP - I
>> have no idea why.
>>
>> Are you able to give me some hints / pointers in how I could start to
>> debug this?
>
> Hopefully this is the exact same bug, and we already have a fix (and a temporary band aid).
>
> Cheers,
> Benjamin
>
>>
>> evtest shows the devices as:
>> /dev/input/event5: DELL0A78:00 27C6:0D42 Mouse
>> /dev/input/event6: DELL0A78:00 27C6:0D42 Touchpad
--
Steven Haigh
📧 netwiz@crc.id.au
💻 https://crc.id.au
[-- Attachment #2: recording.yml.xz --]
[-- Type: application/x-xz, Size: 54172 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox