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