xref: /openbmc/linux/arch/arm/mach-sunxi/sunxi.c (revision bc34b5f2)
13b52634fSMaxime Ripard /*
23b52634fSMaxime Ripard  * Device Tree support for Allwinner A1X SoCs
33b52634fSMaxime Ripard  *
43b52634fSMaxime Ripard  * Copyright (C) 2012 Maxime Ripard
53b52634fSMaxime Ripard  *
63b52634fSMaxime Ripard  * Maxime Ripard <maxime.ripard@free-electrons.com>
73b52634fSMaxime Ripard  *
83b52634fSMaxime Ripard  * This file is licensed under the terms of the GNU General Public
93b52634fSMaxime Ripard  * License version 2.  This program is licensed "as is" without any
103b52634fSMaxime Ripard  * warranty of any kind, whether express or implied.
113b52634fSMaxime Ripard  */
123b52634fSMaxime Ripard 
13ea71d9a6SMaxime Ripard #include <linux/clocksource.h>
145e51651dSJosh Cartwright #include <linux/delay.h>
153b52634fSMaxime Ripard #include <linux/kernel.h>
163b52634fSMaxime Ripard #include <linux/init.h>
17f1dc6c4fSMaxime Ripard #include <linux/irqchip.h>
1867bea88dSMaxime Ripard #include <linux/of_address.h>
193b52634fSMaxime Ripard #include <linux/of_irq.h>
203b52634fSMaxime Ripard #include <linux/of_platform.h>
213b52634fSMaxime Ripard #include <linux/io.h>
223b52634fSMaxime Ripard 
23ea71d9a6SMaxime Ripard #include <linux/clk/sunxi.h>
243b52634fSMaxime Ripard 
253b52634fSMaxime Ripard #include <asm/mach/arch.h>
263b52634fSMaxime Ripard #include <asm/mach/map.h>
27bc34b5f2SMaxime Ripard #include <asm/system_misc.h>
283b52634fSMaxime Ripard 
293b52634fSMaxime Ripard #include "sunxi.h"
303b52634fSMaxime Ripard 
31bc34b5f2SMaxime Ripard #define SUN4I_WATCHDOG_CTRL_REG		0x00
32bc34b5f2SMaxime Ripard #define SUN4I_WATCHDOG_CTRL_RESTART		(1 << 0)
33bc34b5f2SMaxime Ripard #define SUN4I_WATCHDOG_MODE_REG		0x04
34bc34b5f2SMaxime Ripard #define SUN4I_WATCHDOG_MODE_ENABLE		(1 << 0)
35bc34b5f2SMaxime Ripard #define SUN4I_WATCHDOG_MODE_RESET_ENABLE	(1 << 1)
3667bea88dSMaxime Ripard 
3767bea88dSMaxime Ripard static void __iomem *wdt_base;
3867bea88dSMaxime Ripard 
39bc34b5f2SMaxime Ripard static void sun4i_restart(char mode, const char *cmd)
4067bea88dSMaxime Ripard {
4167bea88dSMaxime Ripard 	if (!wdt_base)
4267bea88dSMaxime Ripard 		return;
4367bea88dSMaxime Ripard 
4467bea88dSMaxime Ripard 	/* Enable timer and set reset bit in the watchdog */
45bc34b5f2SMaxime Ripard 	writel(SUN4I_WATCHDOG_MODE_ENABLE | SUN4I_WATCHDOG_MODE_RESET_ENABLE,
46bc34b5f2SMaxime Ripard 	       wdt_base + SUN4I_WATCHDOG_MODE_REG);
47b60decadSMaxime Ripard 
48b60decadSMaxime Ripard 	/*
49b60decadSMaxime Ripard 	 * Restart the watchdog. The default (and lowest) interval
50b60decadSMaxime Ripard 	 * value for the watchdog is 0.5s.
51b60decadSMaxime Ripard 	 */
52bc34b5f2SMaxime Ripard 	writel(SUN4I_WATCHDOG_CTRL_RESTART, wdt_base + SUN4I_WATCHDOG_CTRL_REG);
53b60decadSMaxime Ripard 
5467bea88dSMaxime Ripard 	while (1) {
5567bea88dSMaxime Ripard 		mdelay(5);
56bc34b5f2SMaxime Ripard 		writel(SUN4I_WATCHDOG_MODE_ENABLE | SUN4I_WATCHDOG_MODE_RESET_ENABLE,
57bc34b5f2SMaxime Ripard 		       wdt_base + SUN4I_WATCHDOG_MODE_REG);
5867bea88dSMaxime Ripard 	}
5967bea88dSMaxime Ripard }
6067bea88dSMaxime Ripard 
61bc34b5f2SMaxime Ripard static struct of_device_id sunxi_restart_ids[] = {
62bc34b5f2SMaxime Ripard 	{ .compatible = "allwinner,sun4i-wdt", .data = sun4i_restart },
63bc34b5f2SMaxime Ripard 	{ /*sentinel*/ }
64bc34b5f2SMaxime Ripard };
65bc34b5f2SMaxime Ripard 
66bc34b5f2SMaxime Ripard static void sunxi_setup_restart(void)
67bc34b5f2SMaxime Ripard {
68bc34b5f2SMaxime Ripard 	const struct of_device_id *of_id;
69bc34b5f2SMaxime Ripard 	struct device_node *np;
70bc34b5f2SMaxime Ripard 
71bc34b5f2SMaxime Ripard 	np = of_find_matching_node(NULL, sunxi_restart_ids);
72bc34b5f2SMaxime Ripard 	if (WARN(!np, "unable to setup watchdog restart"))
73bc34b5f2SMaxime Ripard 		return;
74bc34b5f2SMaxime Ripard 
75bc34b5f2SMaxime Ripard 	wdt_base = of_iomap(np, 0);
76bc34b5f2SMaxime Ripard 	WARN(!wdt_base, "failed to map watchdog base address");
77bc34b5f2SMaxime Ripard 
78bc34b5f2SMaxime Ripard 	of_id = of_match_node(sunxi_restart_ids, np);
79bc34b5f2SMaxime Ripard 	WARN(!of_id, "restart function not available");
80bc34b5f2SMaxime Ripard 
81bc34b5f2SMaxime Ripard 	arm_pm_restart = of_id->data;
82bc34b5f2SMaxime Ripard }
83bc34b5f2SMaxime Ripard 
843b52634fSMaxime Ripard static struct map_desc sunxi_io_desc[] __initdata = {
853b52634fSMaxime Ripard 	{
863b52634fSMaxime Ripard 		.virtual	= (unsigned long) SUNXI_REGS_VIRT_BASE,
873b52634fSMaxime Ripard 		.pfn		= __phys_to_pfn(SUNXI_REGS_PHYS_BASE),
883b52634fSMaxime Ripard 		.length		= SUNXI_REGS_SIZE,
893b52634fSMaxime Ripard 		.type		= MT_DEVICE,
903b52634fSMaxime Ripard 	},
913b52634fSMaxime Ripard };
923b52634fSMaxime Ripard 
933b52634fSMaxime Ripard void __init sunxi_map_io(void)
943b52634fSMaxime Ripard {
953b52634fSMaxime Ripard 	iotable_init(sunxi_io_desc, ARRAY_SIZE(sunxi_io_desc));
963b52634fSMaxime Ripard }
973b52634fSMaxime Ripard 
98ea71d9a6SMaxime Ripard static void __init sunxi_timer_init(void)
99ea71d9a6SMaxime Ripard {
100ea71d9a6SMaxime Ripard 	sunxi_init_clocks();
101ea71d9a6SMaxime Ripard 	clocksource_of_init();
102ea71d9a6SMaxime Ripard }
103ea71d9a6SMaxime Ripard 
1043b52634fSMaxime Ripard static void __init sunxi_dt_init(void)
1053b52634fSMaxime Ripard {
10667bea88dSMaxime Ripard 	sunxi_setup_restart();
10767bea88dSMaxime Ripard 
1083b52634fSMaxime Ripard 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
1093b52634fSMaxime Ripard }
1103b52634fSMaxime Ripard 
1113b52634fSMaxime Ripard static const char * const sunxi_board_dt_compat[] = {
11243880f70SMaxime Ripard 	"allwinner,sun4i-a10",
11343880f70SMaxime Ripard 	"allwinner,sun5i-a13",
1143b52634fSMaxime Ripard 	NULL,
1153b52634fSMaxime Ripard };
1163b52634fSMaxime Ripard 
1173b52634fSMaxime Ripard DT_MACHINE_START(SUNXI_DT, "Allwinner A1X (Device Tree)")
1183b52634fSMaxime Ripard 	.init_machine	= sunxi_dt_init,
1193b52634fSMaxime Ripard 	.map_io		= sunxi_map_io,
120f1dc6c4fSMaxime Ripard 	.init_irq	= irqchip_init,
121ea71d9a6SMaxime Ripard 	.init_time	= sunxi_timer_init,
1223b52634fSMaxime Ripard 	.dt_compat	= sunxi_board_dt_compat,
1233b52634fSMaxime Ripard MACHINE_END
124