1b3e1b276SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0
2fa0f8d67SGeert Uytterhoeven /*
3fa0f8d67SGeert Uytterhoeven  * Renesas R-Mobile Reset Driver
4fa0f8d67SGeert Uytterhoeven  *
5fa0f8d67SGeert Uytterhoeven  * Copyright (C) 2014 Glider bvba
6fa0f8d67SGeert Uytterhoeven  */
7fa0f8d67SGeert Uytterhoeven 
8fa0f8d67SGeert Uytterhoeven #include <linux/io.h>
9fa0f8d67SGeert Uytterhoeven #include <linux/module.h>
10fa0f8d67SGeert Uytterhoeven #include <linux/notifier.h>
11fa0f8d67SGeert Uytterhoeven #include <linux/of_address.h>
12fa0f8d67SGeert Uytterhoeven #include <linux/platform_device.h>
13fa0f8d67SGeert Uytterhoeven #include <linux/printk.h>
14fa0f8d67SGeert Uytterhoeven #include <linux/reboot.h>
15fa0f8d67SGeert Uytterhoeven 
16fa0f8d67SGeert Uytterhoeven /* SYSC Register Bank 2 */
17fa0f8d67SGeert Uytterhoeven #define RESCNT2		0x20		/* Reset Control Register 2 */
18fa0f8d67SGeert Uytterhoeven 
19fa0f8d67SGeert Uytterhoeven /* Reset Control Register 2 */
20fa0f8d67SGeert Uytterhoeven #define RESCNT2_PRES	0x80000000	/* Soft power-on reset */
21fa0f8d67SGeert Uytterhoeven 
22fa0f8d67SGeert Uytterhoeven static void __iomem *sysc_base2;
23fa0f8d67SGeert Uytterhoeven 
rmobile_reset_handler(struct notifier_block * this,unsigned long mode,void * cmd)24fa0f8d67SGeert Uytterhoeven static int rmobile_reset_handler(struct notifier_block *this,
25fa0f8d67SGeert Uytterhoeven 				 unsigned long mode, void *cmd)
26fa0f8d67SGeert Uytterhoeven {
27fa0f8d67SGeert Uytterhoeven 	pr_debug("%s %lu\n", __func__, mode);
28fa0f8d67SGeert Uytterhoeven 
29fa0f8d67SGeert Uytterhoeven 	/* Let's assume we have acquired the HPB semaphore */
30fa0f8d67SGeert Uytterhoeven 	writel(RESCNT2_PRES, sysc_base2 + RESCNT2);
31fa0f8d67SGeert Uytterhoeven 
32fa0f8d67SGeert Uytterhoeven 	return NOTIFY_DONE;
33fa0f8d67SGeert Uytterhoeven }
34fa0f8d67SGeert Uytterhoeven 
35fa0f8d67SGeert Uytterhoeven static struct notifier_block rmobile_reset_nb = {
36fa0f8d67SGeert Uytterhoeven 	.notifier_call = rmobile_reset_handler,
37fa0f8d67SGeert Uytterhoeven 	.priority = 192,
38fa0f8d67SGeert Uytterhoeven };
39fa0f8d67SGeert Uytterhoeven 
rmobile_reset_probe(struct platform_device * pdev)40fa0f8d67SGeert Uytterhoeven static int rmobile_reset_probe(struct platform_device *pdev)
41fa0f8d67SGeert Uytterhoeven {
42fa0f8d67SGeert Uytterhoeven 	int error;
43fa0f8d67SGeert Uytterhoeven 
44fa0f8d67SGeert Uytterhoeven 	sysc_base2 = of_iomap(pdev->dev.of_node, 1);
45fa0f8d67SGeert Uytterhoeven 	if (!sysc_base2)
46fa0f8d67SGeert Uytterhoeven 		return -ENODEV;
47fa0f8d67SGeert Uytterhoeven 
48fa0f8d67SGeert Uytterhoeven 	error = register_restart_handler(&rmobile_reset_nb);
49fa0f8d67SGeert Uytterhoeven 	if (error) {
50fa0f8d67SGeert Uytterhoeven 		dev_err(&pdev->dev,
51fa0f8d67SGeert Uytterhoeven 			"cannot register restart handler (err=%d)\n", error);
52fa0f8d67SGeert Uytterhoeven 		goto fail_unmap;
53fa0f8d67SGeert Uytterhoeven 	}
54fa0f8d67SGeert Uytterhoeven 
55fa0f8d67SGeert Uytterhoeven 	return 0;
56fa0f8d67SGeert Uytterhoeven 
57fa0f8d67SGeert Uytterhoeven fail_unmap:
58fa0f8d67SGeert Uytterhoeven 	iounmap(sysc_base2);
59fa0f8d67SGeert Uytterhoeven 	return error;
60fa0f8d67SGeert Uytterhoeven }
61fa0f8d67SGeert Uytterhoeven 
rmobile_reset_remove(struct platform_device * pdev)62fa0f8d67SGeert Uytterhoeven static int rmobile_reset_remove(struct platform_device *pdev)
63fa0f8d67SGeert Uytterhoeven {
64fa0f8d67SGeert Uytterhoeven 	unregister_restart_handler(&rmobile_reset_nb);
65fa0f8d67SGeert Uytterhoeven 	iounmap(sysc_base2);
66fa0f8d67SGeert Uytterhoeven 	return 0;
67fa0f8d67SGeert Uytterhoeven }
68fa0f8d67SGeert Uytterhoeven 
69fa0f8d67SGeert Uytterhoeven static const struct of_device_id rmobile_reset_of_match[] = {
70fa0f8d67SGeert Uytterhoeven 	{ .compatible = "renesas,sysc-rmobile", },
71fa0f8d67SGeert Uytterhoeven 	{ /* sentinel */ }
72fa0f8d67SGeert Uytterhoeven };
73fa0f8d67SGeert Uytterhoeven MODULE_DEVICE_TABLE(of, rmobile_reset_of_match);
74fa0f8d67SGeert Uytterhoeven 
75fa0f8d67SGeert Uytterhoeven static struct platform_driver rmobile_reset_driver = {
76fa0f8d67SGeert Uytterhoeven 	.probe = rmobile_reset_probe,
77fa0f8d67SGeert Uytterhoeven 	.remove = rmobile_reset_remove,
78fa0f8d67SGeert Uytterhoeven 	.driver = {
79fa0f8d67SGeert Uytterhoeven 		.name = "rmobile_reset",
80fa0f8d67SGeert Uytterhoeven 		.of_match_table = rmobile_reset_of_match,
81fa0f8d67SGeert Uytterhoeven 	},
82fa0f8d67SGeert Uytterhoeven };
83fa0f8d67SGeert Uytterhoeven 
84fa0f8d67SGeert Uytterhoeven module_platform_driver(rmobile_reset_driver);
85fa0f8d67SGeert Uytterhoeven 
86fa0f8d67SGeert Uytterhoeven MODULE_DESCRIPTION("Renesas R-Mobile Reset Driver");
87fa0f8d67SGeert Uytterhoeven MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>");
88fa0f8d67SGeert Uytterhoeven MODULE_LICENSE("GPL v2");
89