18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2011 Picochip Ltd., Jamie Iles 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * All enquiries to support@picochip.com 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci#include <linux/delay.h> 88c2ecf20Sopenharmony_ci#include <linux/of.h> 98c2ecf20Sopenharmony_ci#include <linux/of_address.h> 108c2ecf20Sopenharmony_ci#include <linux/reboot.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <asm/mach/arch.h> 138c2ecf20Sopenharmony_ci#include <asm/mach/map.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define PHYS_TO_IO(x) (((x) & 0x00ffffff) | 0xfe000000) 168c2ecf20Sopenharmony_ci#define PICOXCELL_PERIPH_BASE 0x80000000 178c2ecf20Sopenharmony_ci#define PICOXCELL_PERIPH_LENGTH SZ_4M 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define WDT_CTRL_REG_EN_MASK (1 << 0) 208c2ecf20Sopenharmony_ci#define WDT_CTRL_REG_OFFS (0x00) 218c2ecf20Sopenharmony_ci#define WDT_TIMEOUT_REG_OFFS (0x04) 228c2ecf20Sopenharmony_cistatic void __iomem *wdt_regs; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci/* 258c2ecf20Sopenharmony_ci * The machine restart method can be called from an atomic context so we won't 268c2ecf20Sopenharmony_ci * be able to ioremap the regs then. 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_cistatic void picoxcell_setup_restart(void) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci struct device_node *np = of_find_compatible_node(NULL, NULL, 318c2ecf20Sopenharmony_ci "snps,dw-apb-wdg"); 328c2ecf20Sopenharmony_ci if (WARN(!np, "unable to setup watchdog restart")) 338c2ecf20Sopenharmony_ci return; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci wdt_regs = of_iomap(np, 0); 368c2ecf20Sopenharmony_ci WARN(!wdt_regs, "failed to remap watchdog regs"); 378c2ecf20Sopenharmony_ci} 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic struct map_desc io_map __initdata = { 408c2ecf20Sopenharmony_ci .virtual = PHYS_TO_IO(PICOXCELL_PERIPH_BASE), 418c2ecf20Sopenharmony_ci .pfn = __phys_to_pfn(PICOXCELL_PERIPH_BASE), 428c2ecf20Sopenharmony_ci .length = PICOXCELL_PERIPH_LENGTH, 438c2ecf20Sopenharmony_ci .type = MT_DEVICE, 448c2ecf20Sopenharmony_ci}; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic void __init picoxcell_map_io(void) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci iotable_init(&io_map, 1); 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistatic void __init picoxcell_init_machine(void) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci picoxcell_setup_restart(); 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic const char *picoxcell_dt_match[] = { 578c2ecf20Sopenharmony_ci "picochip,pc3x2", 588c2ecf20Sopenharmony_ci "picochip,pc3x3", 598c2ecf20Sopenharmony_ci NULL 608c2ecf20Sopenharmony_ci}; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic void picoxcell_wdt_restart(enum reboot_mode mode, const char *cmd) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci /* 658c2ecf20Sopenharmony_ci * Configure the watchdog to reset with the shortest possible timeout 668c2ecf20Sopenharmony_ci * and give it chance to do the reset. 678c2ecf20Sopenharmony_ci */ 688c2ecf20Sopenharmony_ci if (wdt_regs) { 698c2ecf20Sopenharmony_ci writel_relaxed(WDT_CTRL_REG_EN_MASK, wdt_regs + WDT_CTRL_REG_OFFS); 708c2ecf20Sopenharmony_ci writel_relaxed(0, wdt_regs + WDT_TIMEOUT_REG_OFFS); 718c2ecf20Sopenharmony_ci /* No sleeping, possibly atomic. */ 728c2ecf20Sopenharmony_ci mdelay(500); 738c2ecf20Sopenharmony_ci } 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ciDT_MACHINE_START(PICOXCELL, "Picochip picoXcell") 778c2ecf20Sopenharmony_ci .map_io = picoxcell_map_io, 788c2ecf20Sopenharmony_ci .init_machine = picoxcell_init_machine, 798c2ecf20Sopenharmony_ci .dt_compat = picoxcell_dt_match, 808c2ecf20Sopenharmony_ci .restart = picoxcell_wdt_restart, 818c2ecf20Sopenharmony_ciMACHINE_END 82