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