162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Power off by restarting and let u-boot keep hold of the machine 462306a36Sopenharmony_ci * until the user presses a button for example. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Andrew Lunn <andrew@lunn.ch> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Copyright (C) 2012 Andrew Lunn 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/init.h> 1262306a36Sopenharmony_ci#include <linux/platform_device.h> 1362306a36Sopenharmony_ci#include <linux/of_platform.h> 1462306a36Sopenharmony_ci#include <linux/module.h> 1562306a36Sopenharmony_ci#include <linux/reboot.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistatic void restart_poweroff_do_poweroff(void) 1862306a36Sopenharmony_ci{ 1962306a36Sopenharmony_ci reboot_mode = REBOOT_HARD; 2062306a36Sopenharmony_ci machine_restart(NULL); 2162306a36Sopenharmony_ci} 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic int restart_poweroff_probe(struct platform_device *pdev) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci /* If a pm_power_off function has already been added, leave it alone */ 2662306a36Sopenharmony_ci if (pm_power_off != NULL) { 2762306a36Sopenharmony_ci dev_err(&pdev->dev, 2862306a36Sopenharmony_ci "pm_power_off function already registered"); 2962306a36Sopenharmony_ci return -EBUSY; 3062306a36Sopenharmony_ci } 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci pm_power_off = &restart_poweroff_do_poweroff; 3362306a36Sopenharmony_ci return 0; 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic int restart_poweroff_remove(struct platform_device *pdev) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci if (pm_power_off == &restart_poweroff_do_poweroff) 3962306a36Sopenharmony_ci pm_power_off = NULL; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci return 0; 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic const struct of_device_id of_restart_poweroff_match[] = { 4562306a36Sopenharmony_ci { .compatible = "restart-poweroff", }, 4662306a36Sopenharmony_ci {}, 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, of_restart_poweroff_match); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic struct platform_driver restart_poweroff_driver = { 5162306a36Sopenharmony_ci .probe = restart_poweroff_probe, 5262306a36Sopenharmony_ci .remove = restart_poweroff_remove, 5362306a36Sopenharmony_ci .driver = { 5462306a36Sopenharmony_ci .name = "poweroff-restart", 5562306a36Sopenharmony_ci .of_match_table = of_restart_poweroff_match, 5662306a36Sopenharmony_ci }, 5762306a36Sopenharmony_ci}; 5862306a36Sopenharmony_cimodule_platform_driver(restart_poweroff_driver); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ciMODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch"); 6162306a36Sopenharmony_ciMODULE_DESCRIPTION("restart poweroff driver"); 6262306a36Sopenharmony_ciMODULE_ALIAS("platform:poweroff-restart"); 63