aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2014-05-23 18:46:39 -0400
committerArnd Bergmann <arnd@arndb.de>2014-05-23 18:46:55 -0400
commitb3d491e85dcd65d0ffdb60f56652e314cc278b55 (patch)
treee1b9bfb099d70788ae2cd50d8c5dbb570e2ace05
parent34b16f74ebfb586d97e90bdb72f369aa5d8f16a1 (diff)
parent1be7f5520a3885747174008d2905ae551f74ea78 (diff)
Merge tag 'sunxi-drivers-for-3.16-2' of https://github.com/mripard/linux into next/drivers
Allwinner drivers changes for 3.16, take 2 Add reset driver for the A31 * tag 'sunxi-drivers-for-3.16-2' of https://github.com/mripard/linux: power: reset: Add Allwinner A31 reset code Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--drivers/power/reset/Kconfig7
-rw-r--r--drivers/power/reset/Makefile1
-rw-r--r--drivers/power/reset/sun6i-reboot.c85
3 files changed, 93 insertions, 0 deletions
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index fa0e4e057b99..67aeb6ec08f9 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -43,6 +43,13 @@ config POWER_RESET_RESTART
43 Instead they restart, and u-boot holds the SoC until the 43 Instead they restart, and u-boot holds the SoC until the
44 user presses a key. u-boot then boots into Linux. 44 user presses a key. u-boot then boots into Linux.
45 45
46config POWER_RESET_SUN6I
47 bool "Allwinner A31 SoC reset driver"
48 depends on ARCH_SUNXI
49 depends on POWER_RESET
50 help
51 Reboot support for the Allwinner A31 SoCs.
52
46config POWER_RESET_VEXPRESS 53config POWER_RESET_VEXPRESS
47 bool "ARM Versatile Express power-off and reset driver" 54 bool "ARM Versatile Express power-off and reset driver"
48 depends on ARM || ARM64 55 depends on ARM || ARM64
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index a5b4a77d1a41..950fdc011c7a 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -3,5 +3,6 @@ obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
3obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o 3obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
4obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o 4obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
5obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o 5obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
6obj-$(CONFIG_POWER_RESET_SUN6I) += sun6i-reboot.o
6obj-$(CONFIG_POWER_RESET_VEXPRESS) += vexpress-poweroff.o 7obj-$(CONFIG_POWER_RESET_VEXPRESS) += vexpress-poweroff.o
7obj-$(CONFIG_POWER_RESET_XGENE) += xgene-reboot.o 8obj-$(CONFIG_POWER_RESET_XGENE) += xgene-reboot.o
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);