162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* Copyright (c) 2013, The Linux Foundation. All rights reserved. 362306a36Sopenharmony_ci */ 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/delay.h> 662306a36Sopenharmony_ci#include <linux/err.h> 762306a36Sopenharmony_ci#include <linux/init.h> 862306a36Sopenharmony_ci#include <linux/kernel.h> 962306a36Sopenharmony_ci#include <linux/io.h> 1062306a36Sopenharmony_ci#include <linux/of.h> 1162306a36Sopenharmony_ci#include <linux/platform_device.h> 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci#include <linux/reboot.h> 1462306a36Sopenharmony_ci#include <linux/pm.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistatic void __iomem *msm_ps_hold; 1762306a36Sopenharmony_cistatic int deassert_pshold(struct notifier_block *nb, unsigned long action, 1862306a36Sopenharmony_ci void *data) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci writel(0, msm_ps_hold); 2162306a36Sopenharmony_ci mdelay(10000); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci return NOTIFY_DONE; 2462306a36Sopenharmony_ci} 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic struct notifier_block restart_nb = { 2762306a36Sopenharmony_ci .notifier_call = deassert_pshold, 2862306a36Sopenharmony_ci .priority = 128, 2962306a36Sopenharmony_ci}; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic void do_msm_poweroff(void) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci deassert_pshold(&restart_nb, 0, NULL); 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic int msm_restart_probe(struct platform_device *pdev) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci msm_ps_hold = devm_platform_ioremap_resource(pdev, 0); 3962306a36Sopenharmony_ci if (IS_ERR(msm_ps_hold)) 4062306a36Sopenharmony_ci return PTR_ERR(msm_ps_hold); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci register_restart_handler(&restart_nb); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci pm_power_off = do_msm_poweroff; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci return 0; 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic const struct of_device_id of_msm_restart_match[] = { 5062306a36Sopenharmony_ci { .compatible = "qcom,pshold", }, 5162306a36Sopenharmony_ci {}, 5262306a36Sopenharmony_ci}; 5362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, of_msm_restart_match); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic struct platform_driver msm_restart_driver = { 5662306a36Sopenharmony_ci .probe = msm_restart_probe, 5762306a36Sopenharmony_ci .driver = { 5862306a36Sopenharmony_ci .name = "msm-restart", 5962306a36Sopenharmony_ci .of_match_table = of_match_ptr(of_msm_restart_match), 6062306a36Sopenharmony_ci }, 6162306a36Sopenharmony_ci}; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistatic int __init msm_restart_init(void) 6462306a36Sopenharmony_ci{ 6562306a36Sopenharmony_ci return platform_driver_register(&msm_restart_driver); 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_cidevice_initcall(msm_restart_init); 68