18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* Copyright (c) 2013, The Linux Foundation. All rights reserved. 38c2ecf20Sopenharmony_ci */ 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <linux/delay.h> 68c2ecf20Sopenharmony_ci#include <linux/err.h> 78c2ecf20Sopenharmony_ci#include <linux/init.h> 88c2ecf20Sopenharmony_ci#include <linux/kernel.h> 98c2ecf20Sopenharmony_ci#include <linux/io.h> 108c2ecf20Sopenharmony_ci#include <linux/of.h> 118c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/reboot.h> 148c2ecf20Sopenharmony_ci#include <linux/pm.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistatic void __iomem *msm_ps_hold; 178c2ecf20Sopenharmony_cistatic int deassert_pshold(struct notifier_block *nb, unsigned long action, 188c2ecf20Sopenharmony_ci void *data) 198c2ecf20Sopenharmony_ci{ 208c2ecf20Sopenharmony_ci writel(0, msm_ps_hold); 218c2ecf20Sopenharmony_ci mdelay(10000); 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci return NOTIFY_DONE; 248c2ecf20Sopenharmony_ci} 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic struct notifier_block restart_nb = { 278c2ecf20Sopenharmony_ci .notifier_call = deassert_pshold, 288c2ecf20Sopenharmony_ci .priority = 128, 298c2ecf20Sopenharmony_ci}; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic void do_msm_poweroff(void) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci deassert_pshold(&restart_nb, 0, NULL); 348c2ecf20Sopenharmony_ci} 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic int msm_restart_probe(struct platform_device *pdev) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 398c2ecf20Sopenharmony_ci struct resource *mem; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 428c2ecf20Sopenharmony_ci msm_ps_hold = devm_ioremap_resource(dev, mem); 438c2ecf20Sopenharmony_ci if (IS_ERR(msm_ps_hold)) 448c2ecf20Sopenharmony_ci return PTR_ERR(msm_ps_hold); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci register_restart_handler(&restart_nb); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci pm_power_off = do_msm_poweroff; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci return 0; 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic const struct of_device_id of_msm_restart_match[] = { 548c2ecf20Sopenharmony_ci { .compatible = "qcom,pshold", }, 558c2ecf20Sopenharmony_ci {}, 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, of_msm_restart_match); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic struct platform_driver msm_restart_driver = { 608c2ecf20Sopenharmony_ci .probe = msm_restart_probe, 618c2ecf20Sopenharmony_ci .driver = { 628c2ecf20Sopenharmony_ci .name = "msm-restart", 638c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(of_msm_restart_match), 648c2ecf20Sopenharmony_ci }, 658c2ecf20Sopenharmony_ci}; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic int __init msm_restart_init(void) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci return platform_driver_register(&msm_restart_driver); 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_cidevice_initcall(msm_restart_init); 72