aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/reset/sun6i-reboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/reset/sun6i-reboot.c')
-rw-r--r--drivers/power/reset/sun6i-reboot.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/drivers/power/reset/sun6i-reboot.c b/drivers/power/reset/sun6i-reboot.c
new file mode 100644
index 000000000000..af2cd7ff2fe8
--- /dev/null
+++ b/drivers/power/reset/sun6i-reboot.c
@@ -0,0 +1,85 @@
1/*
2 * Allwinner A31 SoCs reset code
3 *
4 * Copyright (C) 2012-2014 Maxime Ripard
5 *
6 * Maxime Ripard <maxime.ripard@free-electrons.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/delay.h>
14#include <linux/io.h>
15#include <linux/module.h>
16#include <linux/of_address.h>
17#include <linux/platform_device.h>
18#include <linux/reboot.h>
19
20#include <asm/system_misc.h>
21
22#define SUN6I_WATCHDOG1_IRQ_REG 0x00
23#define SUN6I_WATCHDOG1_CTRL_REG 0x10
24#define SUN6I_WATCHDOG1_CTRL_RESTART BIT(0)
25#define SUN6I_WATCHDOG1_CONFIG_REG 0x14
26#define SUN6I_WATCHDOG1_CONFIG_RESTART BIT(0)
27#define SUN6I_WATCHDOG1_CONFIG_IRQ BIT(1)
28#define SUN6I_WATCHDOG1_MODE_REG 0x18
29#define SUN6I_WATCHDOG1_MODE_ENABLE BIT(0)
30
31static void __iomem *wdt_base;
32
33static void sun6i_wdt_restart(enum reboot_mode mode, const char *cmd)
34{
35 if (!wdt_base)
36 return;
37
38 /* Disable interrupts */
39 writel(0, wdt_base + SUN6I_WATCHDOG1_IRQ_REG);
40
41 /* We want to disable the IRQ and just reset the whole system */
42 writel(SUN6I_WATCHDOG1_CONFIG_RESTART,
43 wdt_base + SUN6I_WATCHDOG1_CONFIG_REG);
44
45 /* Enable timer. The default and lowest interval value is 0.5s */
46 writel(SUN6I_WATCHDOG1_MODE_ENABLE,
47 wdt_base + SUN6I_WATCHDOG1_MODE_REG);
48
49 /* Restart the watchdog. */
50 writel(SUN6I_WATCHDOG1_CTRL_RESTART,
51 wdt_base + SUN6I_WATCHDOG1_CTRL_REG);
52
53 while (1) {
54 mdelay(5);
55 writel(SUN6I_WATCHDOG1_MODE_ENABLE,
56 wdt_base + SUN6I_WATCHDOG1_MODE_REG);
57 }
58}
59
60static int sun6i_reboot_probe(struct platform_device *pdev)
61{
62 wdt_base = of_iomap(pdev->dev.of_node, 0);
63 if (!wdt_base) {
64 WARN(1, "failed to map watchdog base address");
65 return -ENODEV;
66 }
67
68 arm_pm_restart = sun6i_wdt_restart;
69
70 return 0;
71}
72
73static struct of_device_id sun6i_reboot_of_match[] = {
74 { .compatible = "allwinner,sun6i-a31-wdt" },
75 {}
76};
77
78static struct platform_driver sun6i_reboot_driver = {
79 .probe = sun6i_reboot_probe,
80 .driver = {
81 .name = "sun6i-reboot",
82 .of_match_table = sun6i_reboot_of_match,
83 },
84};
85module_platform_driver(sun6i_reboot_driver);