178be3176SAbhimanyu Kapur /* Copyright (c) 2013, The Linux Foundation. All rights reserved. 278be3176SAbhimanyu Kapur * 378be3176SAbhimanyu Kapur * This program is free software; you can redistribute it and/or modify 478be3176SAbhimanyu Kapur * it under the terms of the GNU General Public License version 2 and 578be3176SAbhimanyu Kapur * only version 2 as published by the Free Software Foundation. 678be3176SAbhimanyu Kapur * 778be3176SAbhimanyu Kapur * This program is distributed in the hope that it will be useful, 878be3176SAbhimanyu Kapur * but WITHOUT ANY WARRANTY; without even the implied warranty of 978be3176SAbhimanyu Kapur * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1078be3176SAbhimanyu Kapur * GNU General Public License for more details. 1178be3176SAbhimanyu Kapur * 1278be3176SAbhimanyu Kapur */ 1378be3176SAbhimanyu Kapur 1478be3176SAbhimanyu Kapur #include <linux/delay.h> 1578be3176SAbhimanyu Kapur #include <linux/err.h> 1678be3176SAbhimanyu Kapur #include <linux/init.h> 1778be3176SAbhimanyu Kapur #include <linux/kernel.h> 1878be3176SAbhimanyu Kapur #include <linux/io.h> 1978be3176SAbhimanyu Kapur #include <linux/of.h> 2078be3176SAbhimanyu Kapur #include <linux/platform_device.h> 2178be3176SAbhimanyu Kapur #include <linux/module.h> 2278be3176SAbhimanyu Kapur #include <linux/reboot.h> 2318a702e0SPramod Gurav #include <linux/pm.h> 2478be3176SAbhimanyu Kapur 2578be3176SAbhimanyu Kapur static void __iomem *msm_ps_hold; 26fd8b8f17SBjorn Andersson static int deassert_pshold(struct notifier_block *nb, unsigned long action, 2718a702e0SPramod Gurav void *data) 2878be3176SAbhimanyu Kapur { 2978be3176SAbhimanyu Kapur writel(0, msm_ps_hold); 3078be3176SAbhimanyu Kapur mdelay(10000); 3118a702e0SPramod Gurav 3218a702e0SPramod Gurav return NOTIFY_DONE; 3378be3176SAbhimanyu Kapur } 3478be3176SAbhimanyu Kapur 3518a702e0SPramod Gurav static struct notifier_block restart_nb = { 36fd8b8f17SBjorn Andersson .notifier_call = deassert_pshold, 3718a702e0SPramod Gurav .priority = 128, 3818a702e0SPramod Gurav }; 3918a702e0SPramod Gurav 4078be3176SAbhimanyu Kapur static void do_msm_poweroff(void) 4178be3176SAbhimanyu Kapur { 42fd8b8f17SBjorn Andersson deassert_pshold(&restart_nb, 0, NULL); 4378be3176SAbhimanyu Kapur } 4478be3176SAbhimanyu Kapur 4578be3176SAbhimanyu Kapur static int msm_restart_probe(struct platform_device *pdev) 4678be3176SAbhimanyu Kapur { 4778be3176SAbhimanyu Kapur struct device *dev = &pdev->dev; 4878be3176SAbhimanyu Kapur struct resource *mem; 4978be3176SAbhimanyu Kapur 5078be3176SAbhimanyu Kapur mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 5178be3176SAbhimanyu Kapur msm_ps_hold = devm_ioremap_resource(dev, mem); 5278be3176SAbhimanyu Kapur if (IS_ERR(msm_ps_hold)) 5378be3176SAbhimanyu Kapur return PTR_ERR(msm_ps_hold); 5478be3176SAbhimanyu Kapur 5518a702e0SPramod Gurav register_restart_handler(&restart_nb); 5618a702e0SPramod Gurav 5778be3176SAbhimanyu Kapur pm_power_off = do_msm_poweroff; 5818a702e0SPramod Gurav 5978be3176SAbhimanyu Kapur return 0; 6078be3176SAbhimanyu Kapur } 6178be3176SAbhimanyu Kapur 6278be3176SAbhimanyu Kapur static const struct of_device_id of_msm_restart_match[] = { 6378be3176SAbhimanyu Kapur { .compatible = "qcom,pshold", }, 6478be3176SAbhimanyu Kapur {}, 6578be3176SAbhimanyu Kapur }; 6678be3176SAbhimanyu Kapur MODULE_DEVICE_TABLE(of, of_msm_restart_match); 6778be3176SAbhimanyu Kapur 6878be3176SAbhimanyu Kapur static struct platform_driver msm_restart_driver = { 6978be3176SAbhimanyu Kapur .probe = msm_restart_probe, 7078be3176SAbhimanyu Kapur .driver = { 7178be3176SAbhimanyu Kapur .name = "msm-restart", 7278be3176SAbhimanyu Kapur .of_match_table = of_match_ptr(of_msm_restart_match), 7378be3176SAbhimanyu Kapur }, 7478be3176SAbhimanyu Kapur }; 7578be3176SAbhimanyu Kapur 7678be3176SAbhimanyu Kapur static int __init msm_restart_init(void) 7778be3176SAbhimanyu Kapur { 7878be3176SAbhimanyu Kapur return platform_driver_register(&msm_restart_driver); 7978be3176SAbhimanyu Kapur } 8078be3176SAbhimanyu Kapur device_initcall(msm_restart_init); 81