162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * arch/arm/mach-vt8500/vt8500.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/io.h> 962306a36Sopenharmony_ci#include <linux/pm.h> 1062306a36Sopenharmony_ci#include <linux/reboot.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <asm/mach-types.h> 1362306a36Sopenharmony_ci#include <asm/mach/arch.h> 1462306a36Sopenharmony_ci#include <asm/mach/time.h> 1562306a36Sopenharmony_ci#include <asm/mach/map.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <linux/of.h> 1862306a36Sopenharmony_ci#include <linux/of_address.h> 1962306a36Sopenharmony_ci#include <linux/of_irq.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define LEGACY_GPIO_BASE 0xD8110000 2262306a36Sopenharmony_ci#define LEGACY_PMC_BASE 0xD8130000 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* Registers in GPIO Controller */ 2562306a36Sopenharmony_ci#define VT8500_GPIO_MUX_REG 0x200 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* Registers in Power Management Controller */ 2862306a36Sopenharmony_ci#define VT8500_HCR_REG 0x12 2962306a36Sopenharmony_ci#define VT8500_PMSR_REG 0x60 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic void __iomem *pmc_base; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic void vt8500_restart(enum reboot_mode mode, const char *cmd) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci if (pmc_base) 3662306a36Sopenharmony_ci writel(1, pmc_base + VT8500_PMSR_REG); 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic struct map_desc vt8500_io_desc[] __initdata = { 4062306a36Sopenharmony_ci /* SoC MMIO registers */ 4162306a36Sopenharmony_ci [0] = { 4262306a36Sopenharmony_ci .virtual = 0xf8000000, 4362306a36Sopenharmony_ci .pfn = __phys_to_pfn(0xd8000000), 4462306a36Sopenharmony_ci .length = 0x00390000, /* max of all chip variants */ 4562306a36Sopenharmony_ci .type = MT_DEVICE 4662306a36Sopenharmony_ci }, 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic void __init vt8500_map_io(void) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci iotable_init(vt8500_io_desc, ARRAY_SIZE(vt8500_io_desc)); 5262306a36Sopenharmony_ci} 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic void vt8500_power_off(void) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci local_irq_disable(); 5762306a36Sopenharmony_ci writew(5, pmc_base + VT8500_HCR_REG); 5862306a36Sopenharmony_ci asm("mcr p15, 0, %0, c7, c0, 4" : : "r" (0)); 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic void __init vt8500_init(void) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci struct device_node *np; 6462306a36Sopenharmony_ci#if defined(CONFIG_FB_VT8500) || defined(CONFIG_FB_WM8505) 6562306a36Sopenharmony_ci struct device_node *fb; 6662306a36Sopenharmony_ci void __iomem *gpio_base; 6762306a36Sopenharmony_ci#endif 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci#ifdef CONFIG_FB_VT8500 7062306a36Sopenharmony_ci fb = of_find_compatible_node(NULL, NULL, "via,vt8500-fb"); 7162306a36Sopenharmony_ci if (fb) { 7262306a36Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "via,vt8500-gpio"); 7362306a36Sopenharmony_ci if (np) { 7462306a36Sopenharmony_ci gpio_base = of_iomap(np, 0); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if (!gpio_base) 7762306a36Sopenharmony_ci pr_err("%s: of_iomap(gpio_mux) failed\n", 7862306a36Sopenharmony_ci __func__); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci of_node_put(np); 8162306a36Sopenharmony_ci } else { 8262306a36Sopenharmony_ci gpio_base = ioremap(LEGACY_GPIO_BASE, 0x1000); 8362306a36Sopenharmony_ci if (!gpio_base) 8462306a36Sopenharmony_ci pr_err("%s: ioremap(legacy_gpio_mux) failed\n", 8562306a36Sopenharmony_ci __func__); 8662306a36Sopenharmony_ci } 8762306a36Sopenharmony_ci if (gpio_base) { 8862306a36Sopenharmony_ci writel(readl(gpio_base + VT8500_GPIO_MUX_REG) | 1, 8962306a36Sopenharmony_ci gpio_base + VT8500_GPIO_MUX_REG); 9062306a36Sopenharmony_ci iounmap(gpio_base); 9162306a36Sopenharmony_ci } else 9262306a36Sopenharmony_ci pr_err("%s: Could not remap GPIO mux\n", __func__); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci of_node_put(fb); 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci#endif 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci#ifdef CONFIG_FB_WM8505 9962306a36Sopenharmony_ci fb = of_find_compatible_node(NULL, NULL, "wm,wm8505-fb"); 10062306a36Sopenharmony_ci if (fb) { 10162306a36Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "wm,wm8505-gpio"); 10262306a36Sopenharmony_ci if (!np) 10362306a36Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, 10462306a36Sopenharmony_ci "wm,wm8650-gpio"); 10562306a36Sopenharmony_ci if (np) { 10662306a36Sopenharmony_ci gpio_base = of_iomap(np, 0); 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci if (!gpio_base) 10962306a36Sopenharmony_ci pr_err("%s: of_iomap(gpio_mux) failed\n", 11062306a36Sopenharmony_ci __func__); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci of_node_put(np); 11362306a36Sopenharmony_ci } else { 11462306a36Sopenharmony_ci gpio_base = ioremap(LEGACY_GPIO_BASE, 0x1000); 11562306a36Sopenharmony_ci if (!gpio_base) 11662306a36Sopenharmony_ci pr_err("%s: ioremap(legacy_gpio_mux) failed\n", 11762306a36Sopenharmony_ci __func__); 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci if (gpio_base) { 12062306a36Sopenharmony_ci writel(readl(gpio_base + VT8500_GPIO_MUX_REG) | 12162306a36Sopenharmony_ci 0x80000000, gpio_base + VT8500_GPIO_MUX_REG); 12262306a36Sopenharmony_ci iounmap(gpio_base); 12362306a36Sopenharmony_ci } else 12462306a36Sopenharmony_ci pr_err("%s: Could not remap GPIO mux\n", __func__); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci of_node_put(fb); 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci#endif 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "via,vt8500-pmc"); 13162306a36Sopenharmony_ci if (np) { 13262306a36Sopenharmony_ci pmc_base = of_iomap(np, 0); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci if (!pmc_base) 13562306a36Sopenharmony_ci pr_err("%s:of_iomap(pmc) failed\n", __func__); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci of_node_put(np); 13862306a36Sopenharmony_ci } else { 13962306a36Sopenharmony_ci pmc_base = ioremap(LEGACY_PMC_BASE, 0x1000); 14062306a36Sopenharmony_ci if (!pmc_base) 14162306a36Sopenharmony_ci pr_err("%s:ioremap(power_off) failed\n", __func__); 14262306a36Sopenharmony_ci } 14362306a36Sopenharmony_ci if (pmc_base) 14462306a36Sopenharmony_ci pm_power_off = &vt8500_power_off; 14562306a36Sopenharmony_ci else 14662306a36Sopenharmony_ci pr_err("%s: PMC Hibernation register could not be remapped, not enabling power off!\n", __func__); 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic const char * const vt8500_dt_compat[] = { 15062306a36Sopenharmony_ci "via,vt8500", 15162306a36Sopenharmony_ci "wm,wm8650", 15262306a36Sopenharmony_ci "wm,wm8505", 15362306a36Sopenharmony_ci "wm,wm8750", 15462306a36Sopenharmony_ci "wm,wm8850", 15562306a36Sopenharmony_ci NULL 15662306a36Sopenharmony_ci}; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ciDT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)") 15962306a36Sopenharmony_ci .dt_compat = vt8500_dt_compat, 16062306a36Sopenharmony_ci .map_io = vt8500_map_io, 16162306a36Sopenharmony_ci .init_machine = vt8500_init, 16262306a36Sopenharmony_ci .restart = vt8500_restart, 16362306a36Sopenharmony_ciMACHINE_END 16462306a36Sopenharmony_ci 165