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"); 89