regulator-poweroff.c (2069B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Force-disables a regulator to power down a device 4 * 5 * Michael Klein <michael@fossekall.de> 6 * 7 * Copyright (C) 2020 Michael Klein 8 * 9 * Based on the gpio-poweroff driver. 10 */ 11#include <linux/delay.h> 12#include <linux/module.h> 13#include <linux/of.h> 14#include <linux/platform_device.h> 15#include <linux/pm.h> 16#include <linux/regulator/consumer.h> 17 18#define TIMEOUT_MS 3000 19 20/* 21 * Hold configuration here, cannot be more than one instance of the driver 22 * since pm_power_off itself is global. 23 */ 24static struct regulator *cpu_regulator; 25 26static void regulator_poweroff_do_poweroff(void) 27{ 28 if (cpu_regulator && regulator_is_enabled(cpu_regulator)) 29 regulator_force_disable(cpu_regulator); 30 31 /* give it some time */ 32 mdelay(TIMEOUT_MS); 33 34 WARN_ON(1); 35} 36 37static int regulator_poweroff_probe(struct platform_device *pdev) 38{ 39 /* If a pm_power_off function has already been added, leave it alone */ 40 if (pm_power_off != NULL) { 41 dev_err(&pdev->dev, 42 "%s: pm_power_off function already registered\n", 43 __func__); 44 return -EBUSY; 45 } 46 47 cpu_regulator = devm_regulator_get(&pdev->dev, "cpu"); 48 if (IS_ERR(cpu_regulator)) 49 return PTR_ERR(cpu_regulator); 50 51 pm_power_off = ®ulator_poweroff_do_poweroff; 52 return 0; 53} 54 55static int regulator_poweroff_remove(__maybe_unused struct platform_device *pdev) 56{ 57 if (pm_power_off == ®ulator_poweroff_do_poweroff) 58 pm_power_off = NULL; 59 60 return 0; 61} 62 63static const struct of_device_id of_regulator_poweroff_match[] = { 64 { .compatible = "regulator-poweroff", }, 65 {}, 66}; 67MODULE_DEVICE_TABLE(of, of_regulator_poweroff_match); 68 69static struct platform_driver regulator_poweroff_driver = { 70 .probe = regulator_poweroff_probe, 71 .remove = regulator_poweroff_remove, 72 .driver = { 73 .name = "poweroff-regulator", 74 .of_match_table = of_regulator_poweroff_match, 75 }, 76}; 77 78module_platform_driver(regulator_poweroff_driver); 79 80MODULE_AUTHOR("Michael Klein <michael@fossekall.de>"); 81MODULE_DESCRIPTION("Regulator poweroff driver"); 82MODULE_LICENSE("GPL v2"); 83MODULE_ALIAS("platform:poweroff-regulator");