Thread (24 messages) 24 messages, 7 authors, 2025-05-14

Re: [PATCH v5 07/10] power: reset: macsmc-reboot: Add driver for rebooting via Apple SMC

From: Stefan Wahren <wahrenst@gmx.net>
Date: 2025-05-11 10:07:31
Also in: asahi, linux-devicetree, linux-gpio, linux-pm, lkml

Hi Sven,

Am 11.05.25 um 10:18 schrieb Sven Peter via B4 Relay:
quoted hunk ↗ jump to hunk
From: Hector Martin <redacted>

This driver implements the reboot/shutdown support exposed by the SMC
on Apple Silicon machines, such as Apple M1 Macs.

Signed-off-by: Hector Martin <redacted>
Signed-off-by: Sven Peter <redacted>
---
  MAINTAINERS                         |   1 +
  drivers/power/reset/Kconfig         |  11 ++
  drivers/power/reset/Makefile        |   1 +
  drivers/power/reset/macsmc-reboot.c | 363 ++++++++++++++++++++++++++++++++++++
  4 files changed, 376 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index fa3a5f9ee40446bcc725c9eac2a36651e6bc7553..84f7a730eb2260b7c1e0487d18c8eb3de82f5206 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2303,6 +2303,7 @@ F:	drivers/mfd/macsmc.c
  F:	drivers/nvme/host/apple.c
  F:	drivers/nvmem/apple-efuses.c
  F:	drivers/pinctrl/pinctrl-apple-gpio.c
+F:	drivers/power/reset/macsmc-reboot.c
  F:	drivers/pwm/pwm-apple.c
  F:	drivers/soc/apple/*
  F:	drivers/spi/spi-apple.c
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 60bf0ca64cf395cd18238fc626611c74d29844ee..6e8dfff64fdc001d09b6c00630cd8b7e2fafdd8e 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -128,6 +128,17 @@ config POWER_RESET_LINKSTATION
  
  	  Say Y here if you have a Buffalo LinkStation LS421D/E.
  
+config POWER_RESET_MACSMC
+	tristate "Apple SMC reset/power-off driver"
+	depends on ARCH_APPLE || COMPILE_TEST
+	depends on MFD_MACSMC
+	depends on OF
+	help
+	  This driver supports reset and power-off on Apple Mac machines
+	  that implement this functionality via the SMC.
+
+	  Say Y here if you have an Apple Silicon Mac.
+
  config POWER_RESET_MSM
  	bool "Qualcomm MSM power-off driver"
  	depends on ARCH_QCOM
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 10782d32e1da39f4b8b4566e8a885f2e13f65130..887dd9e49b7293b69b9429ddc0c1571194a153cf 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
  obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
  obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
  obj-$(CONFIG_POWER_RESET_LINKSTATION) += linkstation-poweroff.o
+obj-$(CONFIG_POWER_RESET_MACSMC) += macsmc-reboot.o
  obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
  obj-$(CONFIG_POWER_RESET_MT6323) += mt6323-poweroff.o
  obj-$(CONFIG_POWER_RESET_QCOM_PON) += qcom-pon.o
diff --git a/drivers/power/reset/macsmc-reboot.c b/drivers/power/reset/macsmc-reboot.c
new file mode 100644
index 0000000000000000000000000000000000000000..d82339e427886667be4ad2de0d1d5c04d2383059
--- /dev/null
+++ b/drivers/power/reset/macsmc-reboot.c
@@ -0,0 +1,363 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+/*
+ * Apple SMC Reboot/Poweroff Handler
+ * Copyright The Asahi Linux Contributors
+ */
+
+#include <linux/delay.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/reboot.h>
+#include <linux/slab.h>
+
+struct macsmc_reboot_nvmem {
+	struct nvmem_cell *shutdown_flag;
+	struct nvmem_cell *pm_setting;
+	struct nvmem_cell *boot_stage;
+	struct nvmem_cell *boot_error_count;
+	struct nvmem_cell *panic_count;
+};
+
+static const char * const nvmem_names[] = {
+	"shutdown_flag",
+	"pm_setting",
+	"boot_stage",
+	"boot_error_count",
+	"panic_count",
+};
+
+enum boot_stage {
+	BOOT_STAGE_SHUTDOWN		= 0x00, /* Clean shutdown */
+	BOOT_STAGE_IBOOT_DONE		= 0x2f, /* Last stage of bootloader */
+	BOOT_STAGE_KERNEL_STARTED	= 0x30, /* Normal OS booting */
+};
+
+enum pm_setting {
+	PM_SETTING_AC_POWER_RESTORE	= 0x02,
+	PM_SETTING_AC_POWER_OFF		= 0x03,
+};
+
+static const char * const ac_power_modes[] = { "off", "restore" };
+
+static int ac_power_mode_map[] = {
+	PM_SETTING_AC_POWER_OFF,
+	PM_SETTING_AC_POWER_RESTORE,
+};
+
+struct macsmc_reboot {
+	struct device *dev;
+	struct apple_smc *smc;
+	struct notifier_block reboot_notify;
+
+	union {
+		struct macsmc_reboot_nvmem nvm;
+		struct nvmem_cell *nvm_cells[ARRAY_SIZE(nvmem_names)];
+	};
+};
+
+/* Helpers to read/write a u8 given a struct nvmem_cell */
+static int nvmem_cell_get_u8(struct nvmem_cell *cell)
+{
+	size_t len;
+	u8 val;
+	void *ret = nvmem_cell_read(cell, &len);
in case this series needs a respin, please rename the pointer (e.g. 
buf). This is very unusual, because ret is usually of type int.

Regards
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help