1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2011 Picochip Ltd., Jamie Iles 4 * 5 * All enquiries to support@picochip.com 6 */ 7 #include <linux/delay.h> 8 #include <linux/of.h> 9 #include <linux/of_address.h> 10 #include <linux/reboot.h> 11 12 #include <asm/mach/arch.h> 13 #include <asm/mach/map.h> 14 15 #define PHYS_TO_IO(x) (((x) & 0x00ffffff) | 0xfe000000) 16 #define PICOXCELL_PERIPH_BASE 0x80000000 17 #define PICOXCELL_PERIPH_LENGTH SZ_4M 18 19 #define WDT_CTRL_REG_EN_MASK (1 << 0) 20 #define WDT_CTRL_REG_OFFS (0x00) 21 #define WDT_TIMEOUT_REG_OFFS (0x04) 22 static void __iomem *wdt_regs; 23 24 /* 25 * The machine restart method can be called from an atomic context so we won't 26 * be able to ioremap the regs then. 27 */ picoxcell_setup_restart(void)28 static void picoxcell_setup_restart(void) 29 { 30 struct device_node *np = of_find_compatible_node(NULL, NULL, 31 "snps,dw-apb-wdg"); 32 if (WARN(!np, "unable to setup watchdog restart")) 33 return; 34 35 wdt_regs = of_iomap(np, 0); 36 WARN(!wdt_regs, "failed to remap watchdog regs"); 37 } 38 39 static struct map_desc io_map __initdata = { 40 .virtual = PHYS_TO_IO(PICOXCELL_PERIPH_BASE), 41 .pfn = __phys_to_pfn(PICOXCELL_PERIPH_BASE), 42 .length = PICOXCELL_PERIPH_LENGTH, 43 .type = MT_DEVICE, 44 }; 45 picoxcell_map_io(void)46 static void __init picoxcell_map_io(void) 47 { 48 iotable_init(&io_map, 1); 49 } 50 picoxcell_init_machine(void)51 static void __init picoxcell_init_machine(void) 52 { 53 picoxcell_setup_restart(); 54 } 55 56 static const char *picoxcell_dt_match[] = { 57 "picochip,pc3x2", 58 "picochip,pc3x3", 59 NULL 60 }; 61 picoxcell_wdt_restart(enum reboot_mode mode,const char * cmd)62 static void picoxcell_wdt_restart(enum reboot_mode mode, const char *cmd) 63 { 64 /* 65 * Configure the watchdog to reset with the shortest possible timeout 66 * and give it chance to do the reset. 67 */ 68 if (wdt_regs) { 69 writel_relaxed(WDT_CTRL_REG_EN_MASK, wdt_regs + WDT_CTRL_REG_OFFS); 70 writel_relaxed(0, wdt_regs + WDT_TIMEOUT_REG_OFFS); 71 /* No sleeping, possibly atomic. */ 72 mdelay(500); 73 } 74 } 75 76 DT_MACHINE_START(PICOXCELL, "Picochip picoXcell") 77 .map_io = picoxcell_map_io, 78 .init_machine = picoxcell_init_machine, 79 .dt_compat = picoxcell_dt_match, 80 .restart = picoxcell_wdt_restart, 81 MACHINE_END 82