197fb5e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
278be3176SAbhimanyu Kapur /* Copyright (c) 2013, The Linux Foundation. All rights reserved.
378be3176SAbhimanyu Kapur  */
478be3176SAbhimanyu Kapur 
578be3176SAbhimanyu Kapur #include <linux/delay.h>
678be3176SAbhimanyu Kapur #include <linux/err.h>
778be3176SAbhimanyu Kapur #include <linux/init.h>
878be3176SAbhimanyu Kapur #include <linux/kernel.h>
978be3176SAbhimanyu Kapur #include <linux/io.h>
1078be3176SAbhimanyu Kapur #include <linux/of.h>
1178be3176SAbhimanyu Kapur #include <linux/platform_device.h>
1278be3176SAbhimanyu Kapur #include <linux/module.h>
1378be3176SAbhimanyu Kapur #include <linux/reboot.h>
1418a702e0SPramod Gurav #include <linux/pm.h>
1578be3176SAbhimanyu Kapur 
1678be3176SAbhimanyu Kapur static void __iomem *msm_ps_hold;
deassert_pshold(struct notifier_block * nb,unsigned long action,void * data)17fd8b8f17SBjorn Andersson static int deassert_pshold(struct notifier_block *nb, unsigned long action,
1818a702e0SPramod Gurav 			   void *data)
1978be3176SAbhimanyu Kapur {
2078be3176SAbhimanyu Kapur 	writel(0, msm_ps_hold);
2178be3176SAbhimanyu Kapur 	mdelay(10000);
2218a702e0SPramod Gurav 
2318a702e0SPramod Gurav 	return NOTIFY_DONE;
2478be3176SAbhimanyu Kapur }
2578be3176SAbhimanyu Kapur 
2618a702e0SPramod Gurav static struct notifier_block restart_nb = {
27fd8b8f17SBjorn Andersson 	.notifier_call = deassert_pshold,
2818a702e0SPramod Gurav 	.priority = 128,
2918a702e0SPramod Gurav };
3018a702e0SPramod Gurav 
do_msm_poweroff(void)3178be3176SAbhimanyu Kapur static void do_msm_poweroff(void)
3278be3176SAbhimanyu Kapur {
33fd8b8f17SBjorn Andersson 	deassert_pshold(&restart_nb, 0, NULL);
3478be3176SAbhimanyu Kapur }
3578be3176SAbhimanyu Kapur 
msm_restart_probe(struct platform_device * pdev)3678be3176SAbhimanyu Kapur static int msm_restart_probe(struct platform_device *pdev)
3778be3176SAbhimanyu Kapur {
38*19223ffaSYangtao Li 	msm_ps_hold = devm_platform_ioremap_resource(pdev, 0);
3978be3176SAbhimanyu Kapur 	if (IS_ERR(msm_ps_hold))
4078be3176SAbhimanyu Kapur 		return PTR_ERR(msm_ps_hold);
4178be3176SAbhimanyu Kapur 
4218a702e0SPramod Gurav 	register_restart_handler(&restart_nb);
4318a702e0SPramod Gurav 
4478be3176SAbhimanyu Kapur 	pm_power_off = do_msm_poweroff;
4518a702e0SPramod Gurav 
4678be3176SAbhimanyu Kapur 	return 0;
4778be3176SAbhimanyu Kapur }
4878be3176SAbhimanyu Kapur 
4978be3176SAbhimanyu Kapur static const struct of_device_id of_msm_restart_match[] = {
5078be3176SAbhimanyu Kapur 	{ .compatible = "qcom,pshold", },
5178be3176SAbhimanyu Kapur 	{},
5278be3176SAbhimanyu Kapur };
5378be3176SAbhimanyu Kapur MODULE_DEVICE_TABLE(of, of_msm_restart_match);
5478be3176SAbhimanyu Kapur 
5578be3176SAbhimanyu Kapur static struct platform_driver msm_restart_driver = {
5678be3176SAbhimanyu Kapur 	.probe = msm_restart_probe,
5778be3176SAbhimanyu Kapur 	.driver = {
5878be3176SAbhimanyu Kapur 		.name = "msm-restart",
5978be3176SAbhimanyu Kapur 		.of_match_table = of_match_ptr(of_msm_restart_match),
6078be3176SAbhimanyu Kapur 	},
6178be3176SAbhimanyu Kapur };
6278be3176SAbhimanyu Kapur 
msm_restart_init(void)6378be3176SAbhimanyu Kapur static int __init msm_restart_init(void)
6478be3176SAbhimanyu Kapur {
6578be3176SAbhimanyu Kapur 	return platform_driver_register(&msm_restart_driver);
6678be3176SAbhimanyu Kapur }
6778be3176SAbhimanyu Kapur device_initcall(msm_restart_init);
68