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 24 #include <asm/mach-types.h> 25 #include <asm/mach/arch.h> 26 #include <asm/mach/time.h> 27 #include <asm/mach/map.h> 28 29 #include <linux/of.h> 30 #include <linux/of_address.h> 31 #include <linux/of_irq.h> 32 #include <linux/of_platform.h> 33 34 #include "common.h" 35 36 #define LEGACY_GPIO_BASE 0xD8110000 37 #define LEGACY_PMC_BASE 0xD8130000 38 39 /* Registers in GPIO Controller */ 40 #define VT8500_GPIO_MUX_REG 0x200 41 42 /* Registers in Power Management Controller */ 43 #define VT8500_HCR_REG 0x12 44 #define VT8500_PMSR_REG 0x60 45 46 static void __iomem *pmc_base; 47 48 void vt8500_restart(char mode, const char *cmd) 49 { 50 if (pmc_base) 51 writel(1, pmc_base + VT8500_PMSR_REG); 52 } 53 54 static struct map_desc vt8500_io_desc[] __initdata = { 55 /* SoC MMIO registers */ 56 [0] = { 57 .virtual = 0xf8000000, 58 .pfn = __phys_to_pfn(0xd8000000), 59 .length = 0x00390000, /* max of all chip variants */ 60 .type = MT_DEVICE 61 }, 62 }; 63 64 void __init vt8500_map_io(void) 65 { 66 iotable_init(vt8500_io_desc, ARRAY_SIZE(vt8500_io_desc)); 67 } 68 69 static void vt8500_power_off(void) 70 { 71 local_irq_disable(); 72 writew(5, pmc_base + VT8500_HCR_REG); 73 asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0)); 74 } 75 76 void __init vt8500_init(void) 77 { 78 struct device_node *np; 79 #if defined(CONFIG_FB_VT8500) || defined(CONFIG_FB_WM8505) 80 struct device_node *fb; 81 void __iomem *gpio_base; 82 #endif 83 84 #ifdef CONFIG_FB_VT8500 85 fb = of_find_compatible_node(NULL, NULL, "via,vt8500-fb"); 86 if (fb) { 87 np = of_find_compatible_node(NULL, NULL, "via,vt8500-gpio"); 88 if (np) { 89 gpio_base = of_iomap(np, 0); 90 91 if (!gpio_base) 92 pr_err("%s: of_iomap(gpio_mux) failed\n", 93 __func__); 94 95 of_node_put(np); 96 } else { 97 gpio_base = ioremap(LEGACY_GPIO_BASE, 0x1000); 98 if (!gpio_base) 99 pr_err("%s: ioremap(legacy_gpio_mux) failed\n", 100 __func__); 101 } 102 if (gpio_base) { 103 writel(readl(gpio_base + VT8500_GPIO_MUX_REG) | 1, 104 gpio_base + VT8500_GPIO_MUX_REG); 105 iounmap(gpio_base); 106 } else 107 pr_err("%s: Could not remap GPIO mux\n", __func__); 108 109 of_node_put(fb); 110 } 111 #endif 112 113 #ifdef CONFIG_FB_WM8505 114 fb = of_find_compatible_node(NULL, NULL, "wm,wm8505-fb"); 115 if (fb) { 116 np = of_find_compatible_node(NULL, NULL, "wm,wm8505-gpio"); 117 if (!np) 118 np = of_find_compatible_node(NULL, NULL, 119 "wm,wm8650-gpio"); 120 if (np) { 121 gpio_base = of_iomap(np, 0); 122 123 if (!gpio_base) 124 pr_err("%s: of_iomap(gpio_mux) failed\n", 125 __func__); 126 127 of_node_put(np); 128 } else { 129 gpio_base = ioremap(LEGACY_GPIO_BASE, 0x1000); 130 if (!gpio_base) 131 pr_err("%s: ioremap(legacy_gpio_mux) failed\n", 132 __func__); 133 } 134 if (gpio_base) { 135 writel(readl(gpio_base + VT8500_GPIO_MUX_REG) | 136 0x80000000, gpio_base + VT8500_GPIO_MUX_REG); 137 iounmap(gpio_base); 138 } else 139 pr_err("%s: Could not remap GPIO mux\n", __func__); 140 141 of_node_put(fb); 142 } 143 #endif 144 145 np = of_find_compatible_node(NULL, NULL, "via,vt8500-pmc"); 146 if (np) { 147 pmc_base = of_iomap(np, 0); 148 149 if (!pmc_base) 150 pr_err("%s:of_iomap(pmc) failed\n", __func__); 151 152 of_node_put(np); 153 } else { 154 pmc_base = ioremap(LEGACY_PMC_BASE, 0x1000); 155 if (!pmc_base) 156 pr_err("%s:ioremap(power_off) failed\n", __func__); 157 } 158 if (pmc_base) 159 pm_power_off = &vt8500_power_off; 160 else 161 pr_err("%s: PMC Hibernation register could not be remapped, not enabling power off!\n", __func__); 162 163 vtwm_clk_init(pmc_base); 164 165 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); 166 } 167 168 static const struct of_device_id vt8500_irq_match[] __initconst = { 169 { .compatible = "via,vt8500-intc", .data = vt8500_irq_init, }, 170 { /* sentinel */ }, 171 }; 172 173 static void __init vt8500_init_irq(void) 174 { 175 of_irq_init(vt8500_irq_match); 176 }; 177 178 static struct sys_timer vt8500_timer = { 179 .init = vt8500_timer_init, 180 }; 181 182 static const char * const vt8500_dt_compat[] = { 183 "via,vt8500", 184 "wm,wm8650", 185 "wm,wm8505", 186 }; 187 188 DT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)") 189 .dt_compat = vt8500_dt_compat, 190 .map_io = vt8500_map_io, 191 .init_irq = vt8500_init_irq, 192 .timer = &vt8500_timer, 193 .init_machine = vt8500_init, 194 .restart = vt8500_restart, 195 .handle_irq = vt8500_handle_irq, 196 MACHINE_END 197 198