71 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Force-disables a regulator to power down a device4 *5 * Michael Klein <michael@fossekall.de>6 *7 * Copyright (C) 2020 Michael Klein8 *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/reboot.h>17#include <linux/regulator/consumer.h>18 19#define TIMEOUT_MS 300020 21static int regulator_poweroff_do_poweroff(struct sys_off_data *data)22{23 struct regulator *cpu_regulator = data->cb_data;24 25 if (cpu_regulator && regulator_is_enabled(cpu_regulator))26 regulator_force_disable(cpu_regulator);27 28 /* give it some time */29 mdelay(TIMEOUT_MS);30 31 WARN_ON(1);32 33 return NOTIFY_DONE;34}35 36static int regulator_poweroff_probe(struct platform_device *pdev)37{38 struct regulator *cpu_regulator;39 40 cpu_regulator = devm_regulator_get(&pdev->dev, "cpu");41 if (IS_ERR(cpu_regulator))42 return PTR_ERR(cpu_regulator);43 44 /* Set this handler to low priority to not override an existing handler */45 return devm_register_sys_off_handler(&pdev->dev,46 SYS_OFF_MODE_POWER_OFF,47 SYS_OFF_PRIO_LOW,48 regulator_poweroff_do_poweroff,49 cpu_regulator);50}51 52static const struct of_device_id of_regulator_poweroff_match[] = {53 { .compatible = "regulator-poweroff", },54 {},55};56MODULE_DEVICE_TABLE(of, of_regulator_poweroff_match);57 58static struct platform_driver regulator_poweroff_driver = {59 .probe = regulator_poweroff_probe,60 .driver = {61 .name = "poweroff-regulator",62 .of_match_table = of_regulator_poweroff_match,63 },64};65 66module_platform_driver(regulator_poweroff_driver);67 68MODULE_AUTHOR("Michael Klein <michael@fossekall.de>");69MODULE_DESCRIPTION("Regulator poweroff driver");70MODULE_ALIAS("platform:poweroff-regulator");71