summaryrefslogtreecommitdiffstats
path: root/drivers/power/reset/sun6i-reboot.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-03 01:35:49 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-03 01:35:49 +0200
commita727eaf64ff084a50b983fc506810c7a576b7ce3 (patch)
treecb82642227ed590ebc43b12cfad285a2d7681d5d /drivers/power/reset/sun6i-reboot.c
parentMerge tag 'dt-for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/... (diff)
parentMerge tag 'samsung-drivers-2' of git://git.kernel.org/pub/scm/linux/kernel/gi... (diff)
downloadlinux-a727eaf64ff084a50b983fc506810c7a576b7ce3.tar.xz
linux-a727eaf64ff084a50b983fc506810c7a576b7ce3.zip
Merge tag 'drivers-for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc into next
Pull ARM SoC driver changes from Olof Johansson: "SoC-near driver changes that we're merging through our tree. Mostly because they depend on other changes we have staged, but in some cases because the driver maintainers preferred that we did it this way. This contains a largeish cleanup series of the omap_l3_noc bus driver, cpuidle rework for Exynos, some reset driver conversions and a long branch of TI EDMA fixes and cleanups, with more to come next release. The TI EDMA cleanups is a shared branch with the dmaengine tree, with a handful of Davinci-specific fixes on top. After discussion at last year's KS (and some more on the mailing lists), we are here adding a drivers/soc directory. The purpose of this is to keep per-vendor shared code that's needed by different drivers but that doesn't fit into the MFD (nor drivers/platform) model. We expect to keep merging contents for this hierarchy through arm-soc so we can keep an eye on what the vendors keep adding here and not making it a free-for-all to shove in crazy stuff" * tag 'drivers-for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (101 commits) cpufreq: exynos: Fix driver compilation with ARCH_MULTIPLATFORM tty: serial: msm: Remove direct access to GSBI power: reset: keystone-reset: introduce keystone reset driver Documentation: dt: add bindings for keystone pll control controller Documentation: dt: add bindings for keystone reset driver soc: qcom: fix of_device_id table ARM: EXYNOS: Fix kernel panic when unplugging CPU1 on exynos ARM: EXYNOS: Move the driver to drivers/cpuidle directory ARM: EXYNOS: Cleanup all unneeded headers from cpuidle.c ARM: EXYNOS: Pass the AFTR callback to the platform_data ARM: EXYNOS: Move S5P_CHECK_SLEEP into pm.c ARM: EXYNOS: Move the power sequence call in the cpu_pm notifier ARM: EXYNOS: Move the AFTR state function into pm.c ARM: EXYNOS: Encapsulate the AFTR code into a function ARM: EXYNOS: Disable cpuidle for exynos5440 ARM: EXYNOS: Encapsulate boot vector code into a function for cpuidle ARM: EXYNOS: Pass wakeup mask parameter to function for cpuidle ARM: EXYNOS: Remove ifdef for scu_enable in pm ARM: EXYNOS: Move scu_enable in the cpu_pm notifier ARM: EXYNOS: Use the cpu_pm notifier for pm ...
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 @@
+/*
+ * Allwinner A31 SoCs reset code
+ *
+ * Copyright (C) 2012-2014 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+
+#include <asm/system_misc.h>
+
+#define SUN6I_WATCHDOG1_IRQ_REG 0x00
+#define SUN6I_WATCHDOG1_CTRL_REG 0x10
+#define SUN6I_WATCHDOG1_CTRL_RESTART BIT(0)
+#define SUN6I_WATCHDOG1_CONFIG_REG 0x14
+#define SUN6I_WATCHDOG1_CONFIG_RESTART BIT(0)
+#define SUN6I_WATCHDOG1_CONFIG_IRQ BIT(1)
+#define SUN6I_WATCHDOG1_MODE_REG 0x18
+#define SUN6I_WATCHDOG1_MODE_ENABLE BIT(0)
+
+static void __iomem *wdt_base;
+
+static void sun6i_wdt_restart(enum reboot_mode mode, const char *cmd)
+{
+ if (!wdt_base)
+ return;
+
+ /* Disable interrupts */
+ writel(0, wdt_base + SUN6I_WATCHDOG1_IRQ_REG);
+
+ /* We want to disable the IRQ and just reset the whole system */
+ writel(SUN6I_WATCHDOG1_CONFIG_RESTART,
+ wdt_base + SUN6I_WATCHDOG1_CONFIG_REG);
+
+ /* Enable timer. The default and lowest interval value is 0.5s */
+ writel(SUN6I_WATCHDOG1_MODE_ENABLE,
+ wdt_base + SUN6I_WATCHDOG1_MODE_REG);
+
+ /* Restart the watchdog. */
+ writel(SUN6I_WATCHDOG1_CTRL_RESTART,
+ wdt_base + SUN6I_WATCHDOG1_CTRL_REG);
+
+ while (1) {
+ mdelay(5);
+ writel(SUN6I_WATCHDOG1_MODE_ENABLE,
+ wdt_base + SUN6I_WATCHDOG1_MODE_REG);
+ }
+}
+
+static int sun6i_reboot_probe(struct platform_device *pdev)
+{
+ wdt_base = of_iomap(pdev->dev.of_node, 0);
+ if (!wdt_base) {
+ WARN(1, "failed to map watchdog base address");
+ return -ENODEV;
+ }
+
+ arm_pm_restart = sun6i_wdt_restart;
+
+ return 0;
+}
+
+static struct of_device_id sun6i_reboot_of_match[] = {
+ { .compatible = "allwinner,sun6i-a31-wdt" },
+ {}
+};
+
+static struct platform_driver sun6i_reboot_driver = {
+ .probe = sun6i_reboot_probe,
+ .driver = {
+ .name = "sun6i-reboot",
+ .of_match_table = sun6i_reboot_of_match,
+ },
+};
+module_platform_driver(sun6i_reboot_driver);