Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

driver: reset: spacemit-p1: add driver for poweroff/reboot

This driver implements poweroff/reboot support for the SpacemiT P1 PMIC
chip, which is commonly paired with the SpacemiT K1 SoC.

The SpacemiT P1 support is implemented as a MFD driver, so the access is
done directly through the regmap interface. Reboot or poweroff is
triggered by setting a specific bit in a control register, which is
automatically cleared by the hardware afterwards.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Link: https://patch.msgid.link/20251102230352.914421-2-aurelien@aurel32.net
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>

authored by

Aurelien Jarno and committed by
Sebastian Reichel
28124cc0 bd44ea12

+98
+9
drivers/power/reset/Kconfig
··· 283 283 help 284 284 Reboot support for the KEYSTONE SoCs. 285 285 286 + config POWER_RESET_SPACEMIT_P1 287 + tristate "SpacemiT P1 poweroff and reset driver" 288 + depends on ARCH_SPACEMIT || COMPILE_TEST 289 + depends on MFD_SPACEMIT_P1 290 + default MFD_SPACEMIT_P1 291 + help 292 + This driver supports power-off and reset operations for the SpacemiT 293 + P1 PMIC. 294 + 286 295 config POWER_RESET_SYSCON 287 296 bool "Generic SYSCON regmap reset driver" 288 297 depends on OF
+1
drivers/power/reset/Makefile
··· 24 24 obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o 25 25 obj-$(CONFIG_POWER_RESET_REGULATOR) += regulator-poweroff.o 26 26 obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o 27 + obj-$(CONFIG_POWER_RESET_SPACEMIT_P1) += spacemit-p1-reboot.o 27 28 obj-$(CONFIG_POWER_RESET_ST) += st-poweroff.o 28 29 obj-$(CONFIG_POWER_RESET_TH1520_AON) += th1520-aon-reboot.o 29 30 obj-$(CONFIG_POWER_RESET_TORADEX_EC) += tdx-ec-poweroff.o
+88
drivers/power/reset/spacemit-p1-reboot.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2025 by Aurelien Jarno 4 + */ 5 + 6 + #include <linux/bits.h> 7 + #include <linux/mod_devicetable.h> 8 + #include <linux/platform_device.h> 9 + #include <linux/regmap.h> 10 + #include <linux/reboot.h> 11 + 12 + /* Power Control Register 2 */ 13 + #define PWR_CTRL2 0x7e 14 + #define PWR_CTRL2_SHUTDOWN BIT(2) /* Shutdown request */ 15 + #define PWR_CTRL2_RST BIT(1) /* Reset request */ 16 + 17 + static int spacemit_p1_pwroff_handler(struct sys_off_data *data) 18 + { 19 + struct regmap *regmap = data->cb_data; 20 + int ret; 21 + 22 + /* Put the PMIC into shutdown state */ 23 + ret = regmap_set_bits(regmap, PWR_CTRL2, PWR_CTRL2_SHUTDOWN); 24 + if (ret) { 25 + dev_err(data->dev, "shutdown failed: %d\n", ret); 26 + return notifier_from_errno(ret); 27 + } 28 + 29 + return NOTIFY_DONE; 30 + } 31 + 32 + static int spacemit_p1_restart_handler(struct sys_off_data *data) 33 + { 34 + struct regmap *regmap = data->cb_data; 35 + int ret; 36 + 37 + /* Put the PMIC into reset state */ 38 + ret = regmap_set_bits(regmap, PWR_CTRL2, PWR_CTRL2_RST); 39 + if (ret) { 40 + dev_err(data->dev, "restart failed: %d\n", ret); 41 + return notifier_from_errno(ret); 42 + } 43 + 44 + return NOTIFY_DONE; 45 + } 46 + 47 + static int spacemit_p1_reboot_probe(struct platform_device *pdev) 48 + { 49 + struct device *dev = &pdev->dev; 50 + struct regmap *regmap; 51 + int ret; 52 + 53 + regmap = dev_get_regmap(dev->parent, NULL); 54 + if (!regmap) 55 + return -ENODEV; 56 + 57 + ret = devm_register_power_off_handler(dev, &spacemit_p1_pwroff_handler, 58 + regmap); 59 + if (ret) 60 + return dev_err_probe(dev, ret, 61 + "Failed to register power off handler\n"); 62 + 63 + ret = devm_register_restart_handler(dev, spacemit_p1_restart_handler, 64 + regmap); 65 + if (ret) 66 + return dev_err_probe(dev, ret, 67 + "Failed to register restart handler\n"); 68 + 69 + return 0; 70 + } 71 + 72 + static const struct platform_device_id spacemit_p1_reboot_id_table[] = { 73 + { "spacemit-p1-reboot", }, 74 + { /* sentinel */ }, 75 + }; 76 + MODULE_DEVICE_TABLE(platform, spacemit_p1_reboot_id_table); 77 + 78 + static struct platform_driver spacemit_p1_reboot_driver = { 79 + .driver = { 80 + .name = "spacemit-p1-reboot", 81 + }, 82 + .probe = spacemit_p1_reboot_probe, 83 + .id_table = spacemit_p1_reboot_id_table, 84 + }; 85 + module_platform_driver(spacemit_p1_reboot_driver); 86 + 87 + MODULE_DESCRIPTION("SpacemiT P1 reboot/poweroff driver"); 88 + MODULE_LICENSE("GPL");