xref: /OK3568_Linux_fs/kernel/drivers/power/reset/msm-poweroff.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /* Copyright (c) 2013, The Linux Foundation. All rights reserved.
3*4882a593Smuzhiyun  */
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun #include <linux/delay.h>
6*4882a593Smuzhiyun #include <linux/err.h>
7*4882a593Smuzhiyun #include <linux/init.h>
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include <linux/io.h>
10*4882a593Smuzhiyun #include <linux/of.h>
11*4882a593Smuzhiyun #include <linux/platform_device.h>
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/reboot.h>
14*4882a593Smuzhiyun #include <linux/pm.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun static void __iomem *msm_ps_hold;
deassert_pshold(struct notifier_block * nb,unsigned long action,void * data)17*4882a593Smuzhiyun static int deassert_pshold(struct notifier_block *nb, unsigned long action,
18*4882a593Smuzhiyun 			   void *data)
19*4882a593Smuzhiyun {
20*4882a593Smuzhiyun 	writel(0, msm_ps_hold);
21*4882a593Smuzhiyun 	mdelay(10000);
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun 	return NOTIFY_DONE;
24*4882a593Smuzhiyun }
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun static struct notifier_block restart_nb = {
27*4882a593Smuzhiyun 	.notifier_call = deassert_pshold,
28*4882a593Smuzhiyun 	.priority = 128,
29*4882a593Smuzhiyun };
30*4882a593Smuzhiyun 
do_msm_poweroff(void)31*4882a593Smuzhiyun static void do_msm_poweroff(void)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun 	deassert_pshold(&restart_nb, 0, NULL);
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun 
msm_restart_probe(struct platform_device * pdev)36*4882a593Smuzhiyun static int msm_restart_probe(struct platform_device *pdev)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
39*4882a593Smuzhiyun 	struct resource *mem;
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
42*4882a593Smuzhiyun 	msm_ps_hold = devm_ioremap_resource(dev, mem);
43*4882a593Smuzhiyun 	if (IS_ERR(msm_ps_hold))
44*4882a593Smuzhiyun 		return PTR_ERR(msm_ps_hold);
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	register_restart_handler(&restart_nb);
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	pm_power_off = do_msm_poweroff;
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	return 0;
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun static const struct of_device_id of_msm_restart_match[] = {
54*4882a593Smuzhiyun 	{ .compatible = "qcom,pshold", },
55*4882a593Smuzhiyun 	{},
56*4882a593Smuzhiyun };
57*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, of_msm_restart_match);
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun static struct platform_driver msm_restart_driver = {
60*4882a593Smuzhiyun 	.probe = msm_restart_probe,
61*4882a593Smuzhiyun 	.driver = {
62*4882a593Smuzhiyun 		.name = "msm-restart",
63*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(of_msm_restart_match),
64*4882a593Smuzhiyun 	},
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun 
msm_restart_init(void)67*4882a593Smuzhiyun static int __init msm_restart_init(void)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun 	return platform_driver_register(&msm_restart_driver);
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun device_initcall(msm_restart_init);
72