| /* | 
 |  * Copyright (c) 2011 Picochip Ltd., Jamie Iles | 
 |  * | 
 |  * This program is free software; you can redistribute it and/or modify | 
 |  * it under the terms of the GNU General Public License version 2 as | 
 |  * published by the Free Software Foundation. | 
 |  * | 
 |  * All enquiries to support@picochip.com | 
 |  */ | 
 | #include <linux/delay.h> | 
 | #include <linux/of.h> | 
 | #include <linux/of_address.h> | 
 | #include <linux/reboot.h> | 
 |  | 
 | #include <asm/mach/arch.h> | 
 | #include <asm/mach/map.h> | 
 |  | 
 | #define PHYS_TO_IO(x)			(((x) & 0x00ffffff) | 0xfe000000) | 
 | #define PICOXCELL_PERIPH_BASE		0x80000000 | 
 | #define PICOXCELL_PERIPH_LENGTH		SZ_4M | 
 |  | 
 | #define WDT_CTRL_REG_EN_MASK		(1 << 0) | 
 | #define WDT_CTRL_REG_OFFS		(0x00) | 
 | #define WDT_TIMEOUT_REG_OFFS		(0x04) | 
 | static void __iomem *wdt_regs; | 
 |  | 
 | /* | 
 |  * The machine restart method can be called from an atomic context so we won't | 
 |  * be able to ioremap the regs then. | 
 |  */ | 
 | static void picoxcell_setup_restart(void) | 
 | { | 
 | 	struct device_node *np = of_find_compatible_node(NULL, NULL, | 
 | 							 "snps,dw-apb-wdg"); | 
 | 	if (WARN(!np, "unable to setup watchdog restart")) | 
 | 		return; | 
 |  | 
 | 	wdt_regs = of_iomap(np, 0); | 
 | 	WARN(!wdt_regs, "failed to remap watchdog regs"); | 
 | } | 
 |  | 
 | static struct map_desc io_map __initdata = { | 
 | 	.virtual	= PHYS_TO_IO(PICOXCELL_PERIPH_BASE), | 
 | 	.pfn		= __phys_to_pfn(PICOXCELL_PERIPH_BASE), | 
 | 	.length		= PICOXCELL_PERIPH_LENGTH, | 
 | 	.type		= MT_DEVICE, | 
 | }; | 
 |  | 
 | static void __init picoxcell_map_io(void) | 
 | { | 
 | 	iotable_init(&io_map, 1); | 
 | } | 
 |  | 
 | static void __init picoxcell_init_machine(void) | 
 | { | 
 | 	picoxcell_setup_restart(); | 
 | } | 
 |  | 
 | static const char *picoxcell_dt_match[] = { | 
 | 	"picochip,pc3x2", | 
 | 	"picochip,pc3x3", | 
 | 	NULL | 
 | }; | 
 |  | 
 | static void picoxcell_wdt_restart(enum reboot_mode mode, const char *cmd) | 
 | { | 
 | 	/* | 
 | 	 * Configure the watchdog to reset with the shortest possible timeout | 
 | 	 * and give it chance to do the reset. | 
 | 	 */ | 
 | 	if (wdt_regs) { | 
 | 		writel_relaxed(WDT_CTRL_REG_EN_MASK, wdt_regs + WDT_CTRL_REG_OFFS); | 
 | 		writel_relaxed(0, wdt_regs + WDT_TIMEOUT_REG_OFFS); | 
 | 		/* No sleeping, possibly atomic. */ | 
 | 		mdelay(500); | 
 | 	} | 
 | } | 
 |  | 
 | DT_MACHINE_START(PICOXCELL, "Picochip picoXcell") | 
 | 	.map_io		= picoxcell_map_io, | 
 | 	.init_machine	= picoxcell_init_machine, | 
 | 	.dt_compat	= picoxcell_dt_match, | 
 | 	.restart	= picoxcell_wdt_restart, | 
 | MACHINE_END |