18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * arch/arm/mach-vt8500/vt8500.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/io.h> 98c2ecf20Sopenharmony_ci#include <linux/pm.h> 108c2ecf20Sopenharmony_ci#include <linux/reboot.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <asm/mach-types.h> 138c2ecf20Sopenharmony_ci#include <asm/mach/arch.h> 148c2ecf20Sopenharmony_ci#include <asm/mach/time.h> 158c2ecf20Sopenharmony_ci#include <asm/mach/map.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <linux/of.h> 188c2ecf20Sopenharmony_ci#include <linux/of_address.h> 198c2ecf20Sopenharmony_ci#include <linux/of_irq.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define LEGACY_GPIO_BASE 0xD8110000 228c2ecf20Sopenharmony_ci#define LEGACY_PMC_BASE 0xD8130000 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci/* Registers in GPIO Controller */ 258c2ecf20Sopenharmony_ci#define VT8500_GPIO_MUX_REG 0x200 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* Registers in Power Management Controller */ 288c2ecf20Sopenharmony_ci#define VT8500_HCR_REG 0x12 298c2ecf20Sopenharmony_ci#define VT8500_PMSR_REG 0x60 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic void __iomem *pmc_base; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic void vt8500_restart(enum reboot_mode mode, const char *cmd) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci if (pmc_base) 368c2ecf20Sopenharmony_ci writel(1, pmc_base + VT8500_PMSR_REG); 378c2ecf20Sopenharmony_ci} 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic struct map_desc vt8500_io_desc[] __initdata = { 408c2ecf20Sopenharmony_ci /* SoC MMIO registers */ 418c2ecf20Sopenharmony_ci [0] = { 428c2ecf20Sopenharmony_ci .virtual = 0xf8000000, 438c2ecf20Sopenharmony_ci .pfn = __phys_to_pfn(0xd8000000), 448c2ecf20Sopenharmony_ci .length = 0x00390000, /* max of all chip variants */ 458c2ecf20Sopenharmony_ci .type = MT_DEVICE 468c2ecf20Sopenharmony_ci }, 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic void __init vt8500_map_io(void) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci iotable_init(vt8500_io_desc, ARRAY_SIZE(vt8500_io_desc)); 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic void vt8500_power_off(void) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci local_irq_disable(); 578c2ecf20Sopenharmony_ci writew(5, pmc_base + VT8500_HCR_REG); 588c2ecf20Sopenharmony_ci asm("mcr p15, 0, %0, c7, c0, 4" : : "r" (0)); 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic void __init vt8500_init(void) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci struct device_node *np; 648c2ecf20Sopenharmony_ci#if defined(CONFIG_FB_VT8500) || defined(CONFIG_FB_WM8505) 658c2ecf20Sopenharmony_ci struct device_node *fb; 668c2ecf20Sopenharmony_ci void __iomem *gpio_base; 678c2ecf20Sopenharmony_ci#endif 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_VT8500 708c2ecf20Sopenharmony_ci fb = of_find_compatible_node(NULL, NULL, "via,vt8500-fb"); 718c2ecf20Sopenharmony_ci if (fb) { 728c2ecf20Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "via,vt8500-gpio"); 738c2ecf20Sopenharmony_ci if (np) { 748c2ecf20Sopenharmony_ci gpio_base = of_iomap(np, 0); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci if (!gpio_base) 778c2ecf20Sopenharmony_ci pr_err("%s: of_iomap(gpio_mux) failed\n", 788c2ecf20Sopenharmony_ci __func__); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci of_node_put(np); 818c2ecf20Sopenharmony_ci } else { 828c2ecf20Sopenharmony_ci gpio_base = ioremap(LEGACY_GPIO_BASE, 0x1000); 838c2ecf20Sopenharmony_ci if (!gpio_base) 848c2ecf20Sopenharmony_ci pr_err("%s: ioremap(legacy_gpio_mux) failed\n", 858c2ecf20Sopenharmony_ci __func__); 868c2ecf20Sopenharmony_ci } 878c2ecf20Sopenharmony_ci if (gpio_base) { 888c2ecf20Sopenharmony_ci writel(readl(gpio_base + VT8500_GPIO_MUX_REG) | 1, 898c2ecf20Sopenharmony_ci gpio_base + VT8500_GPIO_MUX_REG); 908c2ecf20Sopenharmony_ci iounmap(gpio_base); 918c2ecf20Sopenharmony_ci } else 928c2ecf20Sopenharmony_ci pr_err("%s: Could not remap GPIO mux\n", __func__); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci of_node_put(fb); 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci#endif 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci#ifdef CONFIG_FB_WM8505 998c2ecf20Sopenharmony_ci fb = of_find_compatible_node(NULL, NULL, "wm,wm8505-fb"); 1008c2ecf20Sopenharmony_ci if (fb) { 1018c2ecf20Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "wm,wm8505-gpio"); 1028c2ecf20Sopenharmony_ci if (!np) 1038c2ecf20Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, 1048c2ecf20Sopenharmony_ci "wm,wm8650-gpio"); 1058c2ecf20Sopenharmony_ci if (np) { 1068c2ecf20Sopenharmony_ci gpio_base = of_iomap(np, 0); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci if (!gpio_base) 1098c2ecf20Sopenharmony_ci pr_err("%s: of_iomap(gpio_mux) failed\n", 1108c2ecf20Sopenharmony_ci __func__); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci of_node_put(np); 1138c2ecf20Sopenharmony_ci } else { 1148c2ecf20Sopenharmony_ci gpio_base = ioremap(LEGACY_GPIO_BASE, 0x1000); 1158c2ecf20Sopenharmony_ci if (!gpio_base) 1168c2ecf20Sopenharmony_ci pr_err("%s: ioremap(legacy_gpio_mux) failed\n", 1178c2ecf20Sopenharmony_ci __func__); 1188c2ecf20Sopenharmony_ci } 1198c2ecf20Sopenharmony_ci if (gpio_base) { 1208c2ecf20Sopenharmony_ci writel(readl(gpio_base + VT8500_GPIO_MUX_REG) | 1218c2ecf20Sopenharmony_ci 0x80000000, gpio_base + VT8500_GPIO_MUX_REG); 1228c2ecf20Sopenharmony_ci iounmap(gpio_base); 1238c2ecf20Sopenharmony_ci } else 1248c2ecf20Sopenharmony_ci pr_err("%s: Could not remap GPIO mux\n", __func__); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci of_node_put(fb); 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci#endif 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "via,vt8500-pmc"); 1318c2ecf20Sopenharmony_ci if (np) { 1328c2ecf20Sopenharmony_ci pmc_base = of_iomap(np, 0); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci if (!pmc_base) 1358c2ecf20Sopenharmony_ci pr_err("%s:of_iomap(pmc) failed\n", __func__); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci of_node_put(np); 1388c2ecf20Sopenharmony_ci } else { 1398c2ecf20Sopenharmony_ci pmc_base = ioremap(LEGACY_PMC_BASE, 0x1000); 1408c2ecf20Sopenharmony_ci if (!pmc_base) 1418c2ecf20Sopenharmony_ci pr_err("%s:ioremap(power_off) failed\n", __func__); 1428c2ecf20Sopenharmony_ci } 1438c2ecf20Sopenharmony_ci if (pmc_base) 1448c2ecf20Sopenharmony_ci pm_power_off = &vt8500_power_off; 1458c2ecf20Sopenharmony_ci else 1468c2ecf20Sopenharmony_ci pr_err("%s: PMC Hibernation register could not be remapped, not enabling power off!\n", __func__); 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic const char * const vt8500_dt_compat[] = { 1508c2ecf20Sopenharmony_ci "via,vt8500", 1518c2ecf20Sopenharmony_ci "wm,wm8650", 1528c2ecf20Sopenharmony_ci "wm,wm8505", 1538c2ecf20Sopenharmony_ci "wm,wm8750", 1548c2ecf20Sopenharmony_ci "wm,wm8850", 1558c2ecf20Sopenharmony_ci NULL 1568c2ecf20Sopenharmony_ci}; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ciDT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)") 1598c2ecf20Sopenharmony_ci .dt_compat = vt8500_dt_compat, 1608c2ecf20Sopenharmony_ci .map_io = vt8500_map_io, 1618c2ecf20Sopenharmony_ci .init_machine = vt8500_init, 1628c2ecf20Sopenharmony_ci .restart = vt8500_restart, 1638c2ecf20Sopenharmony_ciMACHINE_END 1648c2ecf20Sopenharmony_ci 165