Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+93
+7
drivers/power/reset/Kconfig
··· 43 43 Instead they restart, and u-boot holds the SoC until the 44 44 user presses a key. u-boot then boots into Linux. 45 45 46 + config 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 + 46 53 config POWER_RESET_VEXPRESS 47 54 bool "ARM Versatile Express power-off and reset driver" 48 55 depends on ARM || ARM64
+1
drivers/power/reset/Makefile
··· 3 3 obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o 4 4 obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o 5 5 obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o 6 + obj-$(CONFIG_POWER_RESET_SUN6I) += sun6i-reboot.o 6 7 obj-$(CONFIG_POWER_RESET_VEXPRESS) += vexpress-poweroff.o 7 8 obj-$(CONFIG_POWER_RESET_XGENE) += xgene-reboot.o
+85
drivers/power/reset/sun6i-reboot.c
··· 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 + 31 + static void __iomem *wdt_base; 32 + 33 + static 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 + 60 + static 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 + 73 + static struct of_device_id sun6i_reboot_of_match[] = { 74 + { .compatible = "allwinner,sun6i-a31-wdt" }, 75 + {} 76 + }; 77 + 78 + static 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 + }; 85 + module_platform_driver(sun6i_reboot_driver);