From: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
Cc: "Atharva Tiwari" <atharvatiwarilinuxdev@gmail.com>,
"Bjorn Helgaas" <bhelgaas@google.com>,
"Thomas Gleixner" <tglx@kernel.org>,
"Ingo Molnar" <mingo@redhat.com>,
"Borislav Petkov" <bp@alien8.de>,
"Dave Hansen" <dave.hansen@linux.intel.com>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
"Rafael J. Wysocki" <rafael@kernel.org>,
"Len Brown" <lenb@kernel.org>,
"Linus Walleij" <linusw@kernel.org>,
"Bartosz Golaszewski" <brgl@kernel.org>,
"Sven Peter" <sven@kernel.org>, "Janne Grunau" <j@jannau.net>,
"Neal Gompa" <neal@gompa.dev>,
"Guenter Roeck" <linux@roeck-us.net>,
"Jonathan Cameron" <jic23@kernel.org>,
"David Lechner" <dlechner@baylibre.com>,
"Nuno Sá" <nuno.sa@analog.com>,
"Andy Shevchenko" <andy@kernel.org>, "Lee Jones" <lee@kernel.org>,
"Pavel Machek" <pavel@kernel.org>,
"Griffin Kroah-Hartman" <griffin@kroah.com>,
"Hans de Goede" <hansg@kernel.org>,
"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
"Sebastian Reichel" <sre@kernel.org>,
"Alexandre Belloni" <alexandre.belloni@bootlin.com>,
"Wim Van Sebroeck" <wim@linux-watchdog.org>,
"Jarkko Sakkinen" <jarkko@kernel.org>,
"Mimi Zohar" <zohar@linux.ibm.com>,
"Roberto Sassu" <roberto.sassu@huawei.com>,
"Dmitry Kasatkin" <dmitry.kasatkin@gmail.com>,
"Eric Snowberg" <eric.snowberg@oracle.com>,
"Paul Moore" <paul@paul-moore.com>,
"James Morris" <jmorris@namei.org>,
"Serge E. Hallyn" <serge@hallyn.com>,
linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org,
linux-acpi@vger.kernel.org, linux-gpio@vger.kernel.org,
asahi@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-hwmon@vger.kernel.org, linux-iio@vger.kernel.org,
linux-leds@vger.kernel.org, mfd@lists.linux.dev,
platform-driver-x86@vger.kernel.org, linux-pm@vger.kernel.org,
linux-rtc@vger.kernel.org, linux-watchdog@vger.kernel.org,
linux-integrity@vger.kernel.org, keyrings@vger.kernel.org,
linux-security-module@vger.kernel.org
Subject: [RFC PATCH 01/14] treewide: Add backend for macsmc
Date: Thu, 29 Oct 2026 04:51:58 -0400 [thread overview]
Message-ID: <20261029085504.3547-2-atharvatiwarilinuxdev@gmail.com> (raw)
In-Reply-To: <20261029085504.3547-1-atharvatiwarilinuxdev@gmail.com>
Split the Apple SMC driver into a common core and a backend
that handles the actual communication. The existing RTKit
code moves to its own backend, and nothing changes for
Apple Silicon.
This lets the same SMC drivers run on other kinds of
hardware, starting with Intel Macs, as a replacement for
applesmc.
Signed-off-by: Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
---
MAINTAINERS | 2 +-
drivers/gpio/Kconfig | 2 +-
drivers/gpio/gpio-macsmc.c | 13 +-
drivers/hwmon/Kconfig | 2 +-
drivers/mfd/Kconfig | 15 +-
drivers/mfd/Makefile | 2 +-
drivers/mfd/macsmc-core.c | 164 ++++++++++++++++
drivers/power/reset/Kconfig | 2 +-
drivers/power/supply/Kconfig | 2 +-
drivers/power/supply/macsmc-power.c | 4 +-
drivers/rtc/Kconfig | 2 +-
drivers/soc/apple/Kconfig | 14 ++
drivers/soc/apple/Makefile | 2 +
.../macsmc.c => soc/apple/macsmc-rtkit.c} | 185 ++++++++----------
include/linux/mfd/macsmc.h | 81 +++++---
15 files changed, 326 insertions(+), 166 deletions(-)
create mode 100644 drivers/mfd/macsmc-core.c
rename drivers/{mfd/macsmc.c => soc/apple/macsmc-rtkit.c} (70%)
diff --git a/MAINTAINERS b/MAINTAINERS
index 03649f08c..1e5ae12ce 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2727,7 +2727,7 @@ F: drivers/input/touchscreen/apple_z2.c
F: drivers/iommu/apple-dart.c
F: drivers/iommu/io-pgtable-dart.c
F: drivers/irqchip/irq-apple-aic.c
-F: drivers/mfd/macsmc.c
+F: drivers/mfd/macsmc-core.c
F: drivers/nvme/host/apple.c
F: drivers/nvmem/apple-efuses.c
F: drivers/nvmem/apple-spmi-nvmem.c
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 55e428002..63a2b1e2e 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1582,7 +1582,7 @@ config GPIO_LP87565
config GPIO_MACSMC
tristate "Apple Mac SMC GPIO"
- depends on MFD_MACSMC
+ depends on MACSMC_RTKIT
help
Support for GPIOs controlled by the SMC microcontroller on Apple Mac
systems.
diff --git a/drivers/gpio/gpio-macsmc.c b/drivers/gpio/gpio-macsmc.c
index b0952d066..8c7a942ad 100644
--- a/drivers/gpio/gpio-macsmc.c
+++ b/drivers/gpio/gpio-macsmc.c
@@ -97,20 +97,9 @@ static int macsmc_gpio_find_first_gpio_index(struct macsmc_gpio *smcgp)
{
struct apple_smc *smc = smcgp->smc;
smc_key key = macsmc_gpio_key(0);
- smc_key first_key, last_key;
int start, count, ret;
- /* Return early if the key is out of bounds */
- ret = apple_smc_get_key_by_index(smc, 0, &first_key);
- if (ret)
- return ret;
- if (key <= first_key)
- return -ENODEV;
-
- ret = apple_smc_get_key_by_index(smc, smc->key_count - 1, &last_key);
- if (ret)
- return ret;
- if (key > last_key)
+ if (key <= smc->first_key || key > smc->last_key)
return -ENODEV;
/* Binary search to find index of first SMC key bigger or equal to key */
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 18c682e1a..91ca7031c 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1245,7 +1245,7 @@ config SENSORS_LTQ_CPUTEMP
config SENSORS_MACSMC_HWMON
tristate "Apple SMC (Apple Silicon)"
- depends on MFD_MACSMC && OF
+ depends on MFD_MACSMC_CORE
help
This driver enables hwmon support for current, power, temperature,
and voltage sensors, as well as fan speed reporting and control
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 87ed55c15..c58cc3315 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -339,24 +339,15 @@ config MFD_LOCHNAGAR
help
Support for Cirrus Logic Lochnagar audio development board.
-config MFD_MACSMC
- tristate "Apple Silicon System Management Controller (SMC)"
- depends on ARCH_APPLE || COMPILE_TEST
- depends on OF
- depends on APPLE_RTKIT
+config MFD_MACSMC_CORE
+ tristate "Apple System Management Controller (SMC) Core"
select MFD_CORE
help
- The System Management Controller (SMC) on Apple Silicon machines is a
+ The System Management Controller (SMC) on Apple machines is a
piece of hardware that exposes various functionalities such as
temperature sensors, voltage/power meters, shutdown/reboot handling,
GPIOs and more.
- Communication happens via a shared mailbox using the RTKit protocol
- which is also used for other co-processors. The SMC protocol then
- allows reading and writing many different keys which implement the
- various features. The MFD core device handles this protocol and
- exposes it to the sub-devices.
-
config MFD_MADERA
tristate "Cirrus Logic Madera codecs"
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index f8101d2a9..0b0ccf91e 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -22,7 +22,7 @@ obj-$(CONFIG_MFD_CS42L43_SDW) += cs42l43-sdw.o
obj-$(CONFIG_MFD_ENE_KB3930) += ene-kb3930.o
obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o
obj-$(CONFIG_MFD_GATEWORKS_GSC) += gateworks-gsc.o
-obj-$(CONFIG_MFD_MACSMC) += macsmc.o
+obj-$(CONFIG_MFD_MACSMC_CORE) += macsmc-core.o
obj-$(CONFIG_MFD_TI_LP873X) += lp873x.o
obj-$(CONFIG_MFD_TI_LP87565) += lp87565.o
diff --git a/drivers/mfd/macsmc-core.c b/drivers/mfd/macsmc-core.c
new file mode 100644
index 000000000..b8905c834
--- /dev/null
+++ b/drivers/mfd/macsmc-core.c
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Apple SMC core framework
+ * Copyright (C) 2026 Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/device.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/macsmc.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
+static const struct mfd_cell apple_smc_rtkit_devs[] = {
+ MFD_CELL_NAME("macsmc-input"),
+ MFD_CELL_NAME("macsmc-power"),
+ 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"),
+};
+
+/*
+ * There isn't device tree on acpi backend, so we need to use
+ * apple_smc_key_exists to register mfd devs
+ */
+static const struct mfd_cell apple_smc_acpi_common[] = {
+ MFD_CELL_NAME("macsmc-hwmon"),
+ MFD_CELL_NAME("macsmc-power"),
+};
+
+static const struct mfd_cell apple_smc_acpi_rtc[] = {
+ MFD_CELL_NAME("macsmc-rtc"),
+};
+
+int apple_smc_read(struct apple_smc *smc, smc_key key, void *buf, size_t size)
+{
+ guard(mutex)(&smc->mutex);
+ return smc->be->read(smc->be_cookie, key, buf, size);
+}
+EXPORT_SYMBOL(apple_smc_read);
+
+int apple_smc_write(struct apple_smc *smc, smc_key key, const void *buf, size_t size)
+{
+ guard(mutex)(&smc->mutex);
+ return smc->be->write(smc->be_cookie, key, buf, size);
+}
+EXPORT_SYMBOL(apple_smc_write);
+
+int apple_smc_enter_atomic(struct apple_smc *smc)
+{
+ guard(mutex)(&smc->mutex);
+ return smc->be->enter_atomic(smc->be_cookie);
+}
+EXPORT_SYMBOL(apple_smc_enter_atomic);
+
+int apple_smc_write_atomic(struct apple_smc *smc, smc_key key, const void *buf, size_t size)
+{
+ guard(spinlock_irqsave)(&smc->lock);
+ return smc->be->write_atomic(smc->be_cookie, key, buf, size);
+}
+EXPORT_SYMBOL(apple_smc_write_atomic);
+
+int apple_smc_rw(struct apple_smc *smc, smc_key key, const void *wbuf, size_t wsize,
+ void *rbuf, size_t rsize)
+{
+ guard(mutex)(&smc->mutex);
+ return smc->be->rw(smc->be_cookie, key, wbuf, wsize, rbuf, rsize);
+}
+EXPORT_SYMBOL(apple_smc_rw);
+
+int apple_smc_get_key_by_index(struct apple_smc *smc, int index, smc_key *key)
+{
+ guard(mutex)(&smc->mutex);
+ int ret;
+
+ ret = smc->be->get_key_by_index(smc->be_cookie, index, key);
+ *key = swab32(*key);
+
+ return ret;
+}
+EXPORT_SYMBOL(apple_smc_get_key_by_index);
+
+int apple_smc_get_key_info(struct apple_smc *smc, smc_key key, struct apple_smc_key_info *info)
+{
+ guard(mutex)(&smc->mutex);
+ return smc->be->get_key_info(smc->be_cookie, key, info);
+}
+EXPORT_SYMBOL(apple_smc_get_key_info);
+
+static void apple_smc_disable_notifications(void *data)
+{
+ struct apple_smc *smc = data;
+
+ guard(mutex)(&smc->mutex);
+ smc->be->disable_notifications(smc->be_cookie);
+}
+
+int apple_smc_probe(struct device *dev, const struct apple_smc_backend_ops *ops,
+ void *cookie, struct blocking_notifier_head *event_handlers, bool is_acpi)
+{
+ struct apple_smc *smc;
+ __be32 count;
+ int ret;
+
+ smc = devm_kzalloc(dev, sizeof(*smc), GFP_KERNEL);
+ if (!smc)
+ return -ENOMEM;
+
+ smc->dev = dev;
+ smc->be_cookie = cookie;
+ smc->be = ops;
+ smc->is_acpi = is_acpi;
+ smc->event_handlers = event_handlers;
+ mutex_init(&smc->mutex);
+ spin_lock_init(&smc->lock);
+
+ ret = apple_smc_read_u32(smc, SMC_KEY(#KEY), &count);
+ if (ret < 0)
+ return ret;
+ smc->key_count = be32_to_cpu(count);
+
+ ret = apple_smc_get_key_by_index(smc, 0, &smc->first_key);
+ if (ret < 0)
+ return ret;
+
+ ret = apple_smc_get_key_by_index(smc, smc->key_count - 1, &smc->last_key);
+ if (ret < 0)
+ return ret;
+
+ dev_set_drvdata(dev, smc);
+
+ ret = devm_add_action_or_reset(dev, apple_smc_disable_notifications, smc);
+ if (ret)
+ return ret;
+
+ if (smc->is_acpi) {
+ ret = devm_mfd_add_devices(dev, -1, apple_smc_acpi_common,
+ ARRAY_SIZE(apple_smc_acpi_common), NULL, 0, NULL);
+ if (ret < 0)
+ return ret;
+
+ if (apple_smc_key_exists(smc, SMC_KEY(CLKO))) {
+ ret = devm_mfd_add_devices(dev, -1, apple_smc_acpi_rtc,
+ ARRAY_SIZE(apple_smc_acpi_rtc), NULL, 0, NULL);
+ if (ret < 0)
+ return ret;
+ }
+
+ } else
+ ret = devm_mfd_add_devices(dev, -1, apple_smc_rtkit_devs,
+ ARRAY_SIZE(apple_smc_rtkit_devs), NULL, 0, NULL);
+ if (ret < 0)
+ return ret;
+
+ dev_info(dev, "Successfully Initialized (%d keys First key: %p4ch Last key: %p4ch)\n",
+ smc->key_count, &smc->first_key, &smc->last_key);
+ return 0;
+}
+EXPORT_SYMBOL(apple_smc_probe);
+
+MODULE_AUTHOR("Atharva Tiwari <atharvatiwarilinuxdev@gmail.com>");
+MODULE_LICENSE("Dual MIT/GPL");
+MODULE_DESCRIPTION("Apple SMC core");
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index bce996bbe..14d62afc1 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -142,7 +142,7 @@ config POWER_RESET_MCF_RCM
config POWER_RESET_MACSMC
tristate "Apple SMC reset/power-off driver"
- depends on MFD_MACSMC
+ depends on MACSMC_RTKIT
help
This driver supports reset and power-off on Apple Mac machines
that implement this functionality via the SMC.
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index b89ef40df..6e944cc59 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -1193,7 +1193,7 @@ config FUEL_GAUGE_MM8013
config MACSMC_POWER
tristate "Apple SMC Battery and Power Driver"
- depends on MFD_MACSMC
+ depends on MFD_MACSMC_CORE
help
This driver provides support for the battery and AC adapter on
Apple Silicon machines. It exposes battery telemetry (voltage,
diff --git a/drivers/power/supply/macsmc-power.c b/drivers/power/supply/macsmc-power.c
index ef735f863..ced37a701 100644
--- a/drivers/power/supply/macsmc-power.c
+++ b/drivers/power/supply/macsmc-power.c
@@ -859,7 +859,7 @@ static int macsmc_power_probe(struct platform_device *pdev)
return -ENODEV;
power->nb.notifier_call = macsmc_power_event;
- blocking_notifier_chain_register(&smc->event_handlers, &power->nb);
+ blocking_notifier_chain_register(smc->event_handlers, &power->nb);
return 0;
}
@@ -868,7 +868,7 @@ static void macsmc_power_remove(struct platform_device *pdev)
{
struct macsmc_power *power = dev_get_drvdata(&pdev->dev);
- blocking_notifier_chain_unregister(&power->smc->event_handlers, &power->nb);
+ blocking_notifier_chain_unregister(power->smc->event_handlers, &power->nb);
}
static const struct platform_device_id macsmc_power_id[] = {
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 05b9233b9..8cc27891b 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -2096,7 +2096,7 @@ config RTC_DRV_WILCO_EC
config RTC_DRV_MACSMC
tristate "Apple Mac System Management Controller RTC"
- depends on MFD_MACSMC
+ depends on MFD_MACSMC_CORE
help
If you say yes here you get support for RTC functions
inside Apple SPMI PMUs accessed through the SoC's
diff --git a/drivers/soc/apple/Kconfig b/drivers/soc/apple/Kconfig
index db30c0ade..e89bc9cb4 100644
--- a/drivers/soc/apple/Kconfig
+++ b/drivers/soc/apple/Kconfig
@@ -52,6 +52,20 @@ config APPLE_TUNABLE
tristate
depends on ARCH_APPLE || COMPILE_TEST
+config MACSMC_RTKIT
+ tristate "Apple Silicon System Management Controller (SMC) Backend"
+ depends on ARCH_APPLE || COMPILE_TEST
+ depends on OF
+ depends on APPLE_RTKIT
+ depends on MFD_MACSMC_CORE
+ help
+ MACSMC RTKIT allows communicatation with the System Management
+ Controller on M-series Macs. It is required to use GPIO, control fans
+ and to control battery start and end threshold.
+
+ Say 'y' here if you have an Apple Soc
+
+
endmenu
endif
diff --git a/drivers/soc/apple/Makefile b/drivers/soc/apple/Makefile
index 0481f7f43..7227cf69e 100644
--- a/drivers/soc/apple/Makefile
+++ b/drivers/soc/apple/Makefile
@@ -13,3 +13,5 @@ apple-sart-y = sart.o
obj-$(CONFIG_APPLE_TUNABLE) += apple-tunable.o
apple-tunable-y = tunable.o
+
+obj-$(CONFIG_MACSMC_RTKIT) += macsmc-rtkit.o
diff --git a/drivers/mfd/macsmc.c b/drivers/soc/apple/macsmc-rtkit.c
similarity index 70%
rename from drivers/mfd/macsmc.c
rename to drivers/soc/apple/macsmc-rtkit.c
index 514cba7dc..eaebeb1be 100644
--- a/drivers/mfd/macsmc.c
+++ b/drivers/soc/apple/macsmc-rtkit.c
@@ -11,7 +11,6 @@
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/math.h>
-#include <linux/mfd/core.h>
#include <linux/mfd/macsmc.h>
#include <linux/notifier.h>
#include <linux/of.h>
@@ -27,14 +26,6 @@
#define SMC_SHMEM_SIZE 0x1000
#define SMC_MAX_SIZE 255
-#define SMC_MSG_READ_KEY 0x10
-#define SMC_MSG_WRITE_KEY 0x11
-#define SMC_MSG_GET_KEY_BY_INDEX 0x12
-#define SMC_MSG_GET_KEY_INFO 0x13
-#define SMC_MSG_INITIALIZE 0x17
-#define SMC_MSG_NOTIFICATION 0x18
-#define SMC_MSG_RW_KEY 0x20
-
#define SMC_DATA GENMASK_ULL(63, 32)
#define SMC_WSIZE GENMASK_ULL(31, 24)
#define SMC_SIZE GENMASK_ULL(23, 16)
@@ -44,24 +35,35 @@
#define SMC_TIMEOUT_MS 500
-static const struct mfd_cell apple_smc_devs[] = {
- MFD_CELL_NAME("macsmc-input"),
- MFD_CELL_NAME("macsmc-power"),
- 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"),
+struct apple_smc_rtkit {
+ struct device *dev;
+
+ struct blocking_notifier_head event_handlers;
+
+ struct apple_rtkit *rtk;
+
+ struct completion init_done;
+ enum apple_smc_boot_stage boot_stage;
+
+ struct resource *sram;
+ void __iomem *sram_base;
+ struct apple_rtkit_shmem shmem;
+
+ unsigned int msg_id;
+
+ bool atomic_mode;
+ bool atomic_pending;
+ struct completion cmd_done;
+ u64 cmd_ret;
};
-static int apple_smc_cmd_locked(struct apple_smc *smc, u64 cmd, u64 arg,
+static int apple_smc_rtkit_cmd_locked(struct apple_smc_rtkit *smc, u64 cmd, u64 arg,
u64 size, u64 wsize, u32 *ret_data)
{
u8 result;
int ret;
u64 msg;
- lockdep_assert_held(&smc->mutex);
-
if (smc->boot_stage != APPLE_SMC_INITIALIZED)
return -EIO;
if (smc->atomic_mode)
@@ -103,15 +105,7 @@ static int apple_smc_cmd_locked(struct apple_smc *smc, u64 cmd, u64 arg,
return FIELD_GET(SMC_SIZE, smc->cmd_ret);
}
-static int apple_smc_cmd(struct apple_smc *smc, u64 cmd, u64 arg,
- u64 size, u64 wsize, u32 *ret_data)
-{
- guard(mutex)(&smc->mutex);
-
- return apple_smc_cmd_locked(smc, cmd, arg, size, wsize, ret_data);
-}
-
-static int apple_smc_rw_locked(struct apple_smc *smc, smc_key key,
+static int apple_smc_rtkit_rw_locked(struct apple_smc_rtkit *smc, smc_key key,
const void *wbuf, size_t wsize,
void *rbuf, size_t rsize)
{
@@ -120,8 +114,6 @@ static int apple_smc_rw_locked(struct apple_smc *smc, smc_key key,
int ret;
u64 cmd;
- lockdep_assert_held(&smc->mutex);
-
if (rsize > SMC_MAX_SIZE)
return -EINVAL;
if (wsize > SMC_MAX_SIZE)
@@ -149,7 +141,7 @@ static int apple_smc_rw_locked(struct apple_smc *smc, smc_key key,
return -EINVAL;
}
- ret = apple_smc_cmd_locked(smc, cmd, key, smc_size, smc_wsize, &rdata);
+ ret = apple_smc_rtkit_cmd_locked(smc, cmd, key, smc_size, smc_wsize, &rdata);
if (ret < 0)
return ret;
@@ -169,48 +161,42 @@ static int apple_smc_rw_locked(struct apple_smc *smc, smc_key key,
return ret;
}
-int apple_smc_read(struct apple_smc *smc, smc_key key, void *buf, size_t size)
+static int apple_smc_rtkit_read(void *cookie, smc_key key, void *buf, size_t size)
{
- guard(mutex)(&smc->mutex);
+ struct apple_smc_rtkit *smc = cookie;
- return apple_smc_rw_locked(smc, key, NULL, 0, buf, size);
+ return apple_smc_rtkit_rw_locked(smc, key, NULL, 0, buf, size);
}
-EXPORT_SYMBOL(apple_smc_read);
-int apple_smc_write(struct apple_smc *smc, smc_key key, const void *buf, size_t size)
+static int apple_smc_rtkit_write(void *cookie, smc_key key, const void *buf, size_t size)
{
- guard(mutex)(&smc->mutex);
+ struct apple_smc_rtkit *smc = cookie;
- return apple_smc_rw_locked(smc, key, buf, size, NULL, 0);
+ return apple_smc_rtkit_rw_locked(smc, key, buf, size, NULL, 0);
}
-EXPORT_SYMBOL(apple_smc_write);
-int apple_smc_rw(struct apple_smc *smc, smc_key key, const void *wbuf, size_t wsize,
+static int apple_smc_rtkit_rw(void *cookie, smc_key key, const void *wbuf, size_t wsize,
void *rbuf, size_t rsize)
{
- guard(mutex)(&smc->mutex);
+ struct apple_smc_rtkit *smc = cookie;
- return apple_smc_rw_locked(smc, key, wbuf, wsize, rbuf, rsize);
+ return apple_smc_rtkit_rw_locked(smc, key, wbuf, wsize, rbuf, rsize);
}
-EXPORT_SYMBOL(apple_smc_rw);
-int apple_smc_get_key_by_index(struct apple_smc *smc, int index, smc_key *key)
+static int apple_smc_rtkit_get_key_by_index(void *cookie, int index, smc_key *key)
{
- int ret;
+ struct apple_smc_rtkit *smc = cookie;
- ret = apple_smc_cmd(smc, SMC_MSG_GET_KEY_BY_INDEX, index, 0, 0, key);
-
- *key = swab32(*key);
- return ret;
+ return apple_smc_rtkit_cmd_locked(smc, SMC_MSG_GET_KEY_BY_INDEX, index, 0, 0, key);
}
-EXPORT_SYMBOL(apple_smc_get_key_by_index);
-int apple_smc_get_key_info(struct apple_smc *smc, smc_key key, struct apple_smc_key_info *info)
+static int apple_smc_rtkit_get_key_info(void *cookie, smc_key key, struct apple_smc_key_info *info)
{
+ struct apple_smc_rtkit *smc = cookie;
u8 key_info[6];
int ret;
- ret = apple_smc_cmd(smc, SMC_MSG_GET_KEY_INFO, key, 0, 0, NULL);
+ ret = apple_smc_rtkit_cmd_locked(smc, SMC_MSG_GET_KEY_INFO, key, 0, 0, NULL);
if (ret >= 0 && info) {
memcpy_fromio(key_info, smc->shmem.iomem, sizeof(key_info));
info->size = key_info[0];
@@ -219,12 +205,9 @@ int apple_smc_get_key_info(struct apple_smc *smc, smc_key key, struct apple_smc_
}
return ret;
}
-EXPORT_SYMBOL(apple_smc_get_key_info);
-int apple_smc_enter_atomic(struct apple_smc *smc)
+static int apple_smc_rtkit_enter_atomic(void *cookie)
{
- guard(mutex)(&smc->mutex);
-
/*
* Disable notifications since this is called before shutdown and no
* notification handler will be able to handle the notification
@@ -233,19 +216,19 @@ int apple_smc_enter_atomic(struct apple_smc *smc)
* We can't use apple_smc_write_flag here since that would try to lock
* smc->mutex again.
*/
+ struct apple_smc_rtkit *smc = cookie;
const u8 flag = 0;
- apple_smc_rw_locked(smc, SMC_KEY(NTAP), &flag, sizeof(flag), NULL, 0);
+ apple_smc_rtkit_rw_locked(smc, SMC_KEY(NTAP), &flag, sizeof(flag), NULL, 0);
smc->atomic_mode = true;
return 0;
}
-EXPORT_SYMBOL(apple_smc_enter_atomic);
-int apple_smc_write_atomic(struct apple_smc *smc, smc_key key, const void *buf, size_t size)
+static int apple_smc_rtkit_write_atomic(void *cookie, smc_key key, const void *buf, size_t size)
{
- guard(spinlock_irqsave)(&smc->lock);
+ struct apple_smc_rtkit *smc = cookie;
u8 result;
int ret;
u64 msg;
@@ -293,11 +276,28 @@ int apple_smc_write_atomic(struct apple_smc *smc, smc_key key, const void *buf,
return FIELD_GET(SMC_SIZE, smc->cmd_ret);
}
-EXPORT_SYMBOL(apple_smc_write_atomic);
+
+static void apple_smc_rtkit_disable_notifications(void *cookie)
+{
+ const u8 flag = 0;
+
+ apple_smc_rtkit_write(cookie, SMC_KEY(NTAP), &flag, sizeof(flag));
+}
+
+static const struct apple_smc_backend_ops apple_smc_rtkit_backend_ops = {
+ .read = apple_smc_rtkit_read,
+ .write = apple_smc_rtkit_write,
+ .enter_atomic = apple_smc_rtkit_enter_atomic,
+ .write_atomic = apple_smc_rtkit_write_atomic,
+ .rw = apple_smc_rtkit_rw,
+ .get_key_by_index = apple_smc_rtkit_get_key_by_index,
+ .get_key_info = apple_smc_rtkit_get_key_info,
+ .disable_notifications = apple_smc_rtkit_disable_notifications,
+};
static void apple_smc_rtkit_crashed(void *cookie, const void *bfr, size_t bfr_len)
{
- struct apple_smc *smc = cookie;
+ struct apple_smc_rtkit *smc = cookie;
smc->boot_stage = APPLE_SMC_ERROR_CRASHED;
dev_err(smc->dev, "SMC crashed! Your system will reboot in a few seconds...\n");
@@ -305,7 +305,7 @@ static void apple_smc_rtkit_crashed(void *cookie, const void *bfr, size_t bfr_le
static int apple_smc_rtkit_shmem_setup(void *cookie, struct apple_rtkit_shmem *bfr)
{
- struct apple_smc *smc = cookie;
+ struct apple_smc_rtkit *smc = cookie;
size_t bfr_end;
if (!bfr->iova) {
@@ -332,7 +332,7 @@ static int apple_smc_rtkit_shmem_setup(void *cookie, struct apple_rtkit_shmem *b
static bool apple_smc_rtkit_recv_early(void *cookie, u8 endpoint, u64 message)
{
- struct apple_smc *smc = cookie;
+ struct apple_smc_rtkit *smc = cookie;
if (endpoint != SMC_ENDPOINT) {
dev_warn(smc->dev, "Received message for unknown endpoint 0x%x\n", endpoint);
@@ -368,7 +368,7 @@ static bool apple_smc_rtkit_recv_early(void *cookie, u8 endpoint, u64 message)
static void apple_smc_rtkit_recv(void *cookie, u8 endpoint, u64 message)
{
- struct apple_smc *smc = cookie;
+ struct apple_smc_rtkit *smc = cookie;
if (endpoint != SMC_ENDPOINT) {
dev_warn(smc->dev, "Received message for unknown endpoint 0x%x\n", endpoint);
@@ -392,32 +392,24 @@ static const struct apple_rtkit_ops apple_smc_rtkit_ops = {
static void apple_smc_rtkit_shutdown(void *data)
{
- struct apple_smc *smc = data;
+ struct apple_smc_rtkit *smc = data;
/* Shut down SMC firmware, if it's not completely wedged */
if (apple_rtkit_is_running(smc->rtk))
apple_rtkit_quiesce(smc->rtk);
}
-static void apple_smc_disable_notifications(void *data)
-{
- struct apple_smc *smc = data;
-
- apple_smc_write_flag(smc, SMC_KEY(NTAP), false);
-}
-
-static int apple_smc_probe(struct platform_device *pdev)
+static int apple_smc_rtkit_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct apple_smc *smc;
- __be32 count;
+ struct apple_smc_rtkit *smc;
+ const u8 flag = 1;
int ret;
smc = devm_kzalloc(dev, sizeof(*smc), GFP_KERNEL);
if (!smc)
return -ENOMEM;
- mutex_init(&smc->mutex);
smc->dev = &pdev->dev;
smc->sram_base = devm_platform_get_and_ioremap_resource(pdev, 1, &smc->sram);
if (IS_ERR(smc->sram_base))
@@ -458,49 +450,32 @@ static int apple_smc_probe(struct platform_device *pdev)
return -EIO;
}
- dev_set_drvdata(&pdev->dev, smc);
BLOCKING_INIT_NOTIFIER_HEAD(&smc->event_handlers);
- ret = apple_smc_read(smc, SMC_KEY(#KEY), &count, sizeof(count));
- if (ret >= 0 && ret != sizeof(count))
- ret = -EINVAL;
- if (ret < 0)
- return dev_err_probe(smc->dev, ret, "Failed to get key count");
- smc->key_count = be32_to_cpu(count);
-
/* Enable notifications */
- apple_smc_write_flag(smc, SMC_KEY(NTAP), true);
- ret = devm_add_action_or_reset(dev, apple_smc_disable_notifications, smc);
- if (ret)
- return ret;
+ apple_smc_rtkit_rw_locked(smc, SMC_KEY(NTAP), &flag, sizeof(flag), NULL, 0);
- ret = devm_mfd_add_devices(smc->dev, PLATFORM_DEVID_NONE,
- apple_smc_devs, ARRAY_SIZE(apple_smc_devs),
- NULL, 0, NULL);
- if (ret)
- return dev_err_probe(smc->dev, ret, "Failed to register sub-devices");
-
-
- return 0;
+ return apple_smc_probe(dev, &apple_smc_rtkit_backend_ops, smc,
+ &smc->event_handlers, false);
}
-static const struct of_device_id apple_smc_of_match[] = {
+static const struct of_device_id apple_smc_rtkit_of_match[] = {
{ .compatible = "apple,t8103-smc" },
{ .compatible = "apple,smc" },
{},
};
-MODULE_DEVICE_TABLE(of, apple_smc_of_match);
+MODULE_DEVICE_TABLE(of, apple_smc_rtkit_of_match);
-static struct platform_driver apple_smc_driver = {
+static struct platform_driver apple_smc_rtkit_driver = {
.driver = {
- .name = "macsmc",
- .of_match_table = apple_smc_of_match,
+ .name = "macsmc-rtkit",
+ .of_match_table = apple_smc_rtkit_of_match,
},
- .probe = apple_smc_probe,
+ .probe = apple_smc_rtkit_probe,
};
-module_platform_driver(apple_smc_driver);
+module_platform_driver(apple_smc_rtkit_driver);
MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
MODULE_AUTHOR("Sven Peter <sven@kernel.org>");
MODULE_LICENSE("Dual MIT/GPL");
-MODULE_DESCRIPTION("Apple SMC driver");
+MODULE_DESCRIPTION("Apple SMC RTKIT Backend driver");
diff --git a/include/linux/mfd/macsmc.h b/include/linux/mfd/macsmc.h
index cc09ecce0..4b4368b99 100644
--- a/include/linux/mfd/macsmc.h
+++ b/include/linux/mfd/macsmc.h
@@ -47,6 +47,14 @@ typedef u32 smc_key;
#define APPLE_SMC_WRITABLE BIT(6)
#define APPLE_SMC_FUNCTION BIT(4)
+#define SMC_MSG_READ_KEY 0x10
+#define SMC_MSG_WRITE_KEY 0x11
+#define SMC_MSG_GET_KEY_BY_INDEX 0x12
+#define SMC_MSG_GET_KEY_INFO 0x13
+#define SMC_MSG_INITIALIZE 0x17
+#define SMC_MSG_NOTIFICATION 0x18
+#define SMC_MSG_RW_KEY 0x20
+
/**
* struct apple_smc_key_info - Information for a SMC key as returned by SMC
* @type_code: FourCC code indicating the type for this key.
@@ -80,24 +88,41 @@ enum apple_smc_boot_stage {
APPLE_SMC_ERROR_CRASHED
};
+/**
+ * struct apple_smc_backend_ops - SMC backend interface
+ * @read: Read SMC key data
+ * @write: Write SMC key data
+ * @enter_atomic: Enter atomic access mode
+ * @write_atomic: Atomic write to SMC key
+ * @rw: Combined write/read transaction
+ * @get_key_by_index: Resolve key by index
+ * @get_key_info: Get metadata for key
+ * @disable_notifications: Disable notfications on removal
+ */
+struct apple_smc_backend_ops {
+ int (*read)(void *cookie, smc_key key, void *buf, size_t size);
+ int (*write)(void *cookie, smc_key key, const void *buf, size_t size);
+ int (*enter_atomic)(void *cookie);
+ int (*write_atomic)(void *cookie, smc_key key, const void *buf, size_t size);
+ int (*rw)(void *cookie, smc_key key, const void *wbuf, size_t wsize,
+ void *rbuf, size_t rsize);
+ int (*get_key_by_index)(void *cookie, int index, smc_key *key);
+ int (*get_key_info)(void *cookie, smc_key key,
+ struct apple_smc_key_info *info);
+ void (*disable_notifications)(void *cookie);
+};
+
+
/**
* struct apple_smc
* @dev: Underlying device struct for the physical backend device
* @key_count: Number of available SMC keys
* @first_key: First valid SMC key
* @last_key: Last valid SMC key
- * @event_handlers: Notifier call chain for events received from SMC
- * @rtk: Pointer to Apple RTKit instance
- * @init_done: Completion for initialization
- * @boot_stage: Current boot stage of SMC
- * @sram: Pointer to SRAM resource
- * @sram_base: SRAM base address
- * @shmem: RTKit shared memory structure for SRAM
- * @msg_id: Current message id for commands, will be incremented for each command
- * @atomic_mode: Flag set when atomic mode is entered
- * @atomic_pending: Flag indicating pending atomic command
- * @cmd_done: Completion for command execution in non-atomic mode
- * @cmd_ret: Return value from SMC for last command
+ * @event_handlers: Pointer to Notifier call chain from the backend
+ * @be: Backend operations for SMC access
+ * @be_cookie: Backend context passed to ops callbacks
+ * @is_acpi: Is the backend ACPI based
* @mutex: Mutex for non-atomic mode
* @lock: Spinlock for atomic mode
*/
@@ -108,23 +133,11 @@ struct apple_smc {
smc_key first_key;
smc_key last_key;
- struct blocking_notifier_head event_handlers;
-
- struct apple_rtkit *rtk;
+ struct blocking_notifier_head *event_handlers;
+ const struct apple_smc_backend_ops *be;
+ void *be_cookie;
- struct completion init_done;
- enum apple_smc_boot_stage boot_stage;
-
- struct resource *sram;
- void __iomem *sram_base;
- struct apple_rtkit_shmem shmem;
-
- unsigned int msg_id;
-
- bool atomic_mode;
- bool atomic_pending;
- struct completion cmd_done;
- u64 cmd_ret;
+ bool is_acpi;
struct mutex mutex;
spinlock_t lock;
@@ -225,6 +238,18 @@ static inline bool apple_smc_key_exists(struct apple_smc *smc, smc_key key)
return apple_smc_get_key_info(smc, key, NULL) >= 0;
}
+/**
+ * apple_smc_probe - Initialize Apple SMC device
+ * @dev: Device for the SMC instance
+ * @ops: Backend operations for SMC access
+ * @cookie: Opaque backend context
+ * @event_handlers: Pointer to Notifier call chain from backend
+ * @is_acpi: Is the backend ACPI based.
+ * Return: Zero on success, negative errno on error
+ */
+int apple_smc_probe(struct device *dev, const struct apple_smc_backend_ops *ops,
+ void *cookie, struct blocking_notifier_head *event_handlers, bool is_acpi);
+
#define APPLE_SMC_TYPE_OPS(type) \
static inline int apple_smc_read_##type(struct apple_smc *smc, smc_key key, type *p) \
{ \
--
2.55.0
next prev parent reply other threads:[~2026-10-29 8:56 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-29 8:51 [RFC PATCH 00/14] Add macsmc support for Intel Macs, replacing applesmc Atharva Tiwari
2026-10-29 8:51 ` Atharva Tiwari [this message]
2026-10-29 9:20 ` [RFC PATCH 01/14] treewide: Add backend for macsmc sashiko-bot
2026-10-29 8:51 ` [RFC PATCH 02/14] platform/x86: add backend for macsmc in intel macs Atharva Tiwari
2026-10-29 9:23 ` sashiko-bot
2026-10-29 12:59 ` Ilpo Järvinen
2026-10-29 8:52 ` [RFC PATCH 03/14] watchdog: add driver for apple smc Atharva Tiwari
2026-10-29 9:17 ` sashiko-bot
2026-10-29 8:52 ` [RFC PATCH 04/14] iio/light: add new driver for macsmc Atharva Tiwari
2026-10-29 9:17 ` sashiko-bot
2026-10-29 8:52 ` [RFC PATCH 05/14] iio/accel: add driver for apple SMS Atharva Tiwari
2026-10-29 9:20 ` sashiko-bot
2026-10-29 8:52 ` [RFC PATCH 06/14] leds: add support for macsmc kbl Atharva Tiwari
2026-10-29 9:16 ` sashiko-bot
2026-10-29 8:52 ` [RFC PATCH 07/14] rtc: add support for x86 macs in macsmc-rtc Atharva Tiwari
2026-10-29 9:15 ` sashiko-bot
2026-10-29 8:52 ` [RFC PATCH 08/14] treewide: Add a flag to detect the Apple T2 chip Atharva Tiwari
2026-10-29 9:11 ` sashiko-bot
2026-10-29 8:52 ` [RFC PATCH 09/14] treewide: disable other rtc's in t2 macs Atharva Tiwari
2026-10-29 9:16 ` sashiko-bot
2026-10-29 8:52 ` [RFC PATCH 10/14] power/supply: add support for x86 macs in macsmc-power Atharva Tiwari
2026-10-29 9:19 ` sashiko-bot
2026-10-29 8:52 ` [RFC PATCH 11/14] acpi: disable battery and adapter for x86 apple machines Atharva Tiwari
2026-10-29 9:13 ` sashiko-bot
2026-10-29 8:52 ` [RFC PATCH 12/14] hwmon/macsmc: add more types Atharva Tiwari
2026-10-29 9:18 ` sashiko-bot
2026-10-29 8:52 ` [RFC PATCH 13/14] hwmon: add support for x86 macs in macsmc-hwmon Atharva Tiwari
2026-10-29 9:20 ` sashiko-bot
2026-10-29 8:52 ` [RFC PATCH 14/14] mfd/macsmc: add ioctl to access smc keys Atharva Tiwari
2026-10-29 9:22 ` Sasha Finkelstein
2026-10-29 9:26 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261029085504.3547-2-atharvatiwarilinuxdev@gmail.com \
--to=atharvatiwarilinuxdev@gmail.com \
--cc=alexandre.belloni@bootlin.com \
--cc=andy@kernel.org \
--cc=asahi@lists.linux.dev \
--cc=bhelgaas@google.com \
--cc=bp@alien8.de \
--cc=brgl@kernel.org \
--cc=dave.hansen@linux.intel.com \
--cc=dlechner@baylibre.com \
--cc=dmitry.kasatkin@gmail.com \
--cc=eric.snowberg@oracle.com \
--cc=griffin@kroah.com \
--cc=hansg@kernel.org \
--cc=hpa@zytor.com \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=j@jannau.net \
--cc=jarkko@kernel.org \
--cc=jic23@kernel.org \
--cc=jmorris@namei.org \
--cc=keyrings@vger.kernel.org \
--cc=lee@kernel.org \
--cc=lenb@kernel.org \
--cc=linusw@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-hwmon@vger.kernel.org \
--cc=linux-iio@vger.kernel.org \
--cc=linux-integrity@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-leds@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=linux-rtc@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=linux-watchdog@vger.kernel.org \
--cc=linux@roeck-us.net \
--cc=mfd@lists.linux.dev \
--cc=mingo@redhat.com \
--cc=neal@gompa.dev \
--cc=nuno.sa@analog.com \
--cc=paul@paul-moore.com \
--cc=pavel@kernel.org \
--cc=platform-driver-x86@vger.kernel.org \
--cc=rafael@kernel.org \
--cc=roberto.sassu@huawei.com \
--cc=serge@hallyn.com \
--cc=sre@kernel.org \
--cc=sven@kernel.org \
--cc=tglx@kernel.org \
--cc=wim@linux-watchdog.org \
--cc=x86@kernel.org \
--cc=zohar@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.