1 /* 2 * arch/arm/mach-vt8500/vt8500.c 3 * 4 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 #include <linux/io.h> 22 #include <linux/pm.h> 23 #include <linux/reboot.h> 24 25 #include <asm/mach-types.h> 26 #include <asm/mach/arch.h> 27 #include <asm/mach/time.h> 28 #include <asm/mach/map.h> 29 30 #include <linux/of.h> 31 #include <linux/of_address.h> 32 #include <linux/of_irq.h> 33 34 #define LEGACY_GPIO_BASE 0xD8110000 35 #define LEGACY_PMC_BASE 0xD8130000 36 37 /* Registers in GPIO Controller */ 38 #define VT8500_GPIO_MUX_REG 0x200 39 40 /* Registers in Power Management Controller */ 41 #define VT8500_HCR_REG 0x12 42 #define VT8500_PMSR_REG 0x60 43 44 static void __iomem *pmc_base; 45 46 static void vt8500_restart(enum reboot_mode mode, const char *cmd) 47 { 48 if (pmc_base) 49 writel(1, pmc_base + VT8500_PMSR_REG); 50 } 51 52 static struct map_desc vt8500_io_desc[] __initdata = { 53 /* SoC MMIO registers */ 54 [0] = { 55 .virtual = 0xf8000000, 56 .pfn = __phys_to_pfn(0xd8000000), 57 .length = 0x00390000, /* max of all chip variants */ 58 .type = MT_DEVICE 59 }, 60 }; 61 62 static void __init vt8500_map_io(void) 63 { 64 iotable_init(vt8500_io_desc, ARRAY_SIZE(vt8500_io_desc)); 65 } 66 67 static void vt8500_power_off(void) 68 { 69 local_irq_disable(); 70 writew(5, pmc_base + VT8500_HCR_REG); 71 asm("mcr p15, 0, %0, c7, c0, 4" : : "r" (0)); 72 } 73 74 static void __init vt8500_init(void) 75 { 76 struct device_node *np; 77 #if defined(CONFIG_FB_VT8500) || defined(CONFIG_FB_WM8505) 78 struct device_node *fb; 79 void __iomem *gpio_base; 80 #endif 81 82 #ifdef CONFIG_FB_VT8500 83 fb = of_find_compatible_node(NULL, NULL, "via,vt8500-fb"); 84 if (fb) { 85 np = of_find_compatible_node(NULL, NULL, "via,vt8500-gpio"); 86 if (np) { 87 gpio_base = of_iomap(np, 0); 88 89 if (!gpio_base) 90 pr_err("%s: of_iomap(gpio_mux) failed\n", 91 __func__); 92 93 of_node_put(np); 94 } else { 95 gpio_base = ioremap(LEGACY_GPIO_BASE, 0x1000); 96 if (!gpio_base) 97 pr_err("%s: ioremap(legacy_gpio_mux) failed\n", 98 __func__); 99 } 100 if (gpio_base) { 101 writel(readl(gpio_base + VT8500_GPIO_MUX_REG) | 1, 102 gpio_base + VT8500_GPIO_MUX_REG); 103 iounmap(gpio_base); 104 } else 105 pr_err("%s: Could not remap GPIO mux\n", __func__); 106 107 of_node_put(fb); 108 } 109 #endif 110 111 #ifdef CONFIG_FB_WM8505 112 fb = of_find_compatible_node(NULL, NULL, "wm,wm8505-fb"); 113 if (fb) { 114 np = of_find_compatible_node(NULL, NULL, "wm,wm8505-gpio"); 115 if (!np) 116 np = of_find_compatible_node(NULL, NULL, 117 "wm,wm8650-gpio"); 118 if (np) { 119 gpio_base = of_iomap(np, 0); 120 121 if (!gpio_base) 122 pr_err("%s: of_iomap(gpio_mux) failed\n", 123 __func__); 124 125 of_node_put(np); 126 } else { 127 gpio_base = ioremap(LEGACY_GPIO_BASE, 0x1000); 128 if (!gpio_base) 129 pr_err("%s: ioremap(legacy_gpio_mux) failed\n", 130 __func__); 131 } 132 if (gpio_base) { 133 writel(readl(gpio_base + VT8500_GPIO_MUX_REG) | 134 0x80000000, gpio_base + VT8500_GPIO_MUX_REG); 135 iounmap(gpio_base); 136 } else 137 pr_err("%s: Could not remap GPIO mux\n", __func__); 138 139 of_node_put(fb); 140 } 141 #endif 142 143 np = of_find_compatible_node(NULL, NULL, "via,vt8500-pmc"); 144 if (np) { 145 pmc_base = of_iomap(np, 0); 146 147 if (!pmc_base) 148 pr_err("%s:of_iomap(pmc) failed\n", __func__); 149 150 of_node_put(np); 151 } else { 152 pmc_base = ioremap(LEGACY_PMC_BASE, 0x1000); 153 if (!pmc_base) 154 pr_err("%s:ioremap(power_off) failed\n", __func__); 155 } 156 if (pmc_base) 157 pm_power_off = &vt8500_power_off; 158 else 159 pr_err("%s: PMC Hibernation register could not be remapped, not enabling power off!\n", __func__); 160 } 161 162 static const char * const vt8500_dt_compat[] = { 163 "via,vt8500", 164 "wm,wm8650", 165 "wm,wm8505", 166 "wm,wm8750", 167 "wm,wm8850", 168 NULL 169 }; 170 171 DT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)") 172 .dt_compat = vt8500_dt_compat, 173 .map_io = vt8500_map_io, 174 .init_machine = vt8500_init, 175 .restart = vt8500_restart, 176 MACHINE_END 177 178