1af75655c066621352c419646ec0775e9523dc720Jamie Iles/*
2af75655c066621352c419646ec0775e9523dc720Jamie Iles * Copyright (c) 2011 Picochip Ltd., Jamie Iles
3af75655c066621352c419646ec0775e9523dc720Jamie Iles *
4af75655c066621352c419646ec0775e9523dc720Jamie Iles * This program is free software; you can redistribute it and/or modify
5af75655c066621352c419646ec0775e9523dc720Jamie Iles * it under the terms of the GNU General Public License version 2 as
6af75655c066621352c419646ec0775e9523dc720Jamie Iles * published by the Free Software Foundation.
7af75655c066621352c419646ec0775e9523dc720Jamie Iles *
8af75655c066621352c419646ec0775e9523dc720Jamie Iles * All enquiries to support@picochip.com
9af75655c066621352c419646ec0775e9523dc720Jamie Iles */
101b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles#include <linux/delay.h>
11af75655c066621352c419646ec0775e9523dc720Jamie Iles#include <linux/irq.h>
12af75655c066621352c419646ec0775e9523dc720Jamie Iles#include <linux/irqdomain.h>
13af75655c066621352c419646ec0775e9523dc720Jamie Iles#include <linux/of.h>
14af75655c066621352c419646ec0775e9523dc720Jamie Iles#include <linux/of_address.h>
15c05012ce9a70100dd547042865df751498244ec3Jamie Iles#include <linux/of_irq.h>
16af75655c066621352c419646ec0775e9523dc720Jamie Iles#include <linux/of_platform.h>
17af75655c066621352c419646ec0775e9523dc720Jamie Iles
18af75655c066621352c419646ec0775e9523dc720Jamie Iles#include <asm/mach/arch.h>
19af75655c066621352c419646ec0775e9523dc720Jamie Iles#include <asm/hardware/vic.h>
208f37a0b49656ed961598351da3ebdd89f2d2e5b4Jamie Iles#include <asm/mach/map.h>
21af75655c066621352c419646ec0775e9523dc720Jamie Iles
22af75655c066621352c419646ec0775e9523dc720Jamie Iles#include <mach/map.h>
23af75655c066621352c419646ec0775e9523dc720Jamie Iles#include <mach/picoxcell_soc.h>
24af75655c066621352c419646ec0775e9523dc720Jamie Iles
25af75655c066621352c419646ec0775e9523dc720Jamie Iles#include "common.h"
26af75655c066621352c419646ec0775e9523dc720Jamie Iles
271b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles#define WDT_CTRL_REG_EN_MASK	(1 << 0)
281b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles#define WDT_CTRL_REG_OFFS	(0x00)
291b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles#define WDT_TIMEOUT_REG_OFFS	(0x04)
301b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Ilesstatic void __iomem *wdt_regs;
311b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles
321b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles/*
331b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles * The machine restart method can be called from an atomic context so we won't
341b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles * be able to ioremap the regs then.
351b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles */
361b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Ilesstatic void picoxcell_setup_restart(void)
371b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles{
381b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles	struct device_node *np = of_find_compatible_node(NULL, NULL,
391b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles							 "snps,dw-apb-wdg");
401b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles	if (WARN(!np, "unable to setup watchdog restart"))
411b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles		return;
421b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles
431b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles	wdt_regs = of_iomap(np, 0);
441b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles	WARN(!wdt_regs, "failed to remap watchdog regs");
451b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles}
461b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles
478f37a0b49656ed961598351da3ebdd89f2d2e5b4Jamie Ilesstatic struct map_desc io_map __initdata = {
488f37a0b49656ed961598351da3ebdd89f2d2e5b4Jamie Iles	.virtual	= PHYS_TO_IO(PICOXCELL_PERIPH_BASE),
498f37a0b49656ed961598351da3ebdd89f2d2e5b4Jamie Iles	.pfn		= __phys_to_pfn(PICOXCELL_PERIPH_BASE),
508f37a0b49656ed961598351da3ebdd89f2d2e5b4Jamie Iles	.length		= PICOXCELL_PERIPH_LENGTH,
518f37a0b49656ed961598351da3ebdd89f2d2e5b4Jamie Iles	.type		= MT_DEVICE,
528f37a0b49656ed961598351da3ebdd89f2d2e5b4Jamie Iles};
538f37a0b49656ed961598351da3ebdd89f2d2e5b4Jamie Iles
548f37a0b49656ed961598351da3ebdd89f2d2e5b4Jamie Ilesstatic void __init picoxcell_map_io(void)
558f37a0b49656ed961598351da3ebdd89f2d2e5b4Jamie Iles{
568f37a0b49656ed961598351da3ebdd89f2d2e5b4Jamie Iles	iotable_init(&io_map, 1);
578f37a0b49656ed961598351da3ebdd89f2d2e5b4Jamie Iles}
588f37a0b49656ed961598351da3ebdd89f2d2e5b4Jamie Iles
59af75655c066621352c419646ec0775e9523dc720Jamie Ilesstatic void __init picoxcell_init_machine(void)
60af75655c066621352c419646ec0775e9523dc720Jamie Iles{
61af75655c066621352c419646ec0775e9523dc720Jamie Iles	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
621b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles	picoxcell_setup_restart();
63af75655c066621352c419646ec0775e9523dc720Jamie Iles}
64af75655c066621352c419646ec0775e9523dc720Jamie Iles
65af75655c066621352c419646ec0775e9523dc720Jamie Ilesstatic const char *picoxcell_dt_match[] = {
66af75655c066621352c419646ec0775e9523dc720Jamie Iles	"picochip,pc3x2",
67af75655c066621352c419646ec0775e9523dc720Jamie Iles	"picochip,pc3x3",
68af75655c066621352c419646ec0775e9523dc720Jamie Iles	NULL
69af75655c066621352c419646ec0775e9523dc720Jamie Iles};
70af75655c066621352c419646ec0775e9523dc720Jamie Iles
71af75655c066621352c419646ec0775e9523dc720Jamie Ilesstatic const struct of_device_id vic_of_match[] __initconst = {
72c05012ce9a70100dd547042865df751498244ec3Jamie Iles	{ .compatible = "arm,pl192-vic", .data = vic_of_init, },
73af75655c066621352c419646ec0775e9523dc720Jamie Iles	{ /* Sentinel */ }
74af75655c066621352c419646ec0775e9523dc720Jamie Iles};
75af75655c066621352c419646ec0775e9523dc720Jamie Iles
76af75655c066621352c419646ec0775e9523dc720Jamie Ilesstatic void __init picoxcell_init_irq(void)
77af75655c066621352c419646ec0775e9523dc720Jamie Iles{
78c05012ce9a70100dd547042865df751498244ec3Jamie Iles	of_irq_init(vic_of_match);
79af75655c066621352c419646ec0775e9523dc720Jamie Iles}
80af75655c066621352c419646ec0775e9523dc720Jamie Iles
811b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Ilesstatic void picoxcell_wdt_restart(char mode, const char *cmd)
821b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles{
831b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles	/*
841b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles	 * Configure the watchdog to reset with the shortest possible timeout
851b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles	 * and give it chance to do the reset.
861b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles	 */
871b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles	if (wdt_regs) {
881b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles		writel_relaxed(WDT_CTRL_REG_EN_MASK, wdt_regs + WDT_CTRL_REG_OFFS);
891b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles		writel_relaxed(0, wdt_regs + WDT_TIMEOUT_REG_OFFS);
901b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles		/* No sleeping, possibly atomic. */
911b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles		mdelay(500);
921b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles	}
931b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles}
941b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles
95af75655c066621352c419646ec0775e9523dc720Jamie IlesDT_MACHINE_START(PICOXCELL, "Picochip picoXcell")
96af75655c066621352c419646ec0775e9523dc720Jamie Iles	.map_io		= picoxcell_map_io,
9798e27a5c13badb5c56d9d1d6c8ec210753ac1195Jamie Iles	.nr_irqs	= NR_IRQS_LEGACY,
98af75655c066621352c419646ec0775e9523dc720Jamie Iles	.init_irq	= picoxcell_init_irq,
99c05012ce9a70100dd547042865df751498244ec3Jamie Iles	.handle_irq	= vic_handle_irq,
100af75655c066621352c419646ec0775e9523dc720Jamie Iles	.timer		= &picoxcell_timer,
101af75655c066621352c419646ec0775e9523dc720Jamie Iles	.init_machine	= picoxcell_init_machine,
102af75655c066621352c419646ec0775e9523dc720Jamie Iles	.dt_compat	= picoxcell_dt_match,
1031b46f8782c2607afa1298b0c7f7fe307fc0f7a5bJamie Iles	.restart	= picoxcell_wdt_restart,
104af75655c066621352c419646ec0775e9523dc720Jamie IlesMACHINE_END
105