1 /* 2 * linux/arch/arm/mach-omap2/io.c 3 * 4 * OMAP2 I/O mapping code 5 * 6 * Copyright (C) 2005 Nokia Corporation 7 * Copyright (C) 2007-2009 Texas Instruments 8 * 9 * Author: 10 * Juha Yrjola <juha.yrjola@nokia.com> 11 * Syed Khasim <x0khasim@ti.com> 12 * 13 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> 14 * 15 * This program is free software; you can redistribute it and/or modify 16 * it under the terms of the GNU General Public License version 2 as 17 * published by the Free Software Foundation. 18 */ 19 20 #include <linux/module.h> 21 #include <linux/kernel.h> 22 #include <linux/init.h> 23 #include <linux/io.h> 24 #include <linux/clk.h> 25 26 #include <asm/tlb.h> 27 28 #include <asm/mach/map.h> 29 30 #include <mach/mux.h> 31 #include <mach/omapfb.h> 32 #include <mach/sram.h> 33 #include <mach/sdrc.h> 34 #include <mach/gpmc.h> 35 #include <mach/serial.h> 36 37 #ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdev is ready */ 38 #include "clock.h" 39 40 #include <mach/omap-pm.h> 41 #include <mach/powerdomain.h> 42 #include "powerdomains.h" 43 44 #include <mach/clockdomain.h> 45 #include "clockdomains.h" 46 #endif 47 #include <mach/omap_hwmod.h> 48 #include "omap_hwmod_2420.h" 49 #include "omap_hwmod_2430.h" 50 #include "omap_hwmod_34xx.h" 51 52 /* 53 * The machine specific code may provide the extra mapping besides the 54 * default mapping provided here. 55 */ 56 57 #ifdef CONFIG_ARCH_OMAP24XX 58 static struct map_desc omap24xx_io_desc[] __initdata = { 59 { 60 .virtual = L3_24XX_VIRT, 61 .pfn = __phys_to_pfn(L3_24XX_PHYS), 62 .length = L3_24XX_SIZE, 63 .type = MT_DEVICE 64 }, 65 { 66 .virtual = L4_24XX_VIRT, 67 .pfn = __phys_to_pfn(L4_24XX_PHYS), 68 .length = L4_24XX_SIZE, 69 .type = MT_DEVICE 70 }, 71 }; 72 73 #ifdef CONFIG_ARCH_OMAP2420 74 static struct map_desc omap242x_io_desc[] __initdata = { 75 { 76 .virtual = DSP_MEM_24XX_VIRT, 77 .pfn = __phys_to_pfn(DSP_MEM_24XX_PHYS), 78 .length = DSP_MEM_24XX_SIZE, 79 .type = MT_DEVICE 80 }, 81 { 82 .virtual = DSP_IPI_24XX_VIRT, 83 .pfn = __phys_to_pfn(DSP_IPI_24XX_PHYS), 84 .length = DSP_IPI_24XX_SIZE, 85 .type = MT_DEVICE 86 }, 87 { 88 .virtual = DSP_MMU_24XX_VIRT, 89 .pfn = __phys_to_pfn(DSP_MMU_24XX_PHYS), 90 .length = DSP_MMU_24XX_SIZE, 91 .type = MT_DEVICE 92 }, 93 }; 94 95 #endif 96 97 #ifdef CONFIG_ARCH_OMAP2430 98 static struct map_desc omap243x_io_desc[] __initdata = { 99 { 100 .virtual = L4_WK_243X_VIRT, 101 .pfn = __phys_to_pfn(L4_WK_243X_PHYS), 102 .length = L4_WK_243X_SIZE, 103 .type = MT_DEVICE 104 }, 105 { 106 .virtual = OMAP243X_GPMC_VIRT, 107 .pfn = __phys_to_pfn(OMAP243X_GPMC_PHYS), 108 .length = OMAP243X_GPMC_SIZE, 109 .type = MT_DEVICE 110 }, 111 { 112 .virtual = OMAP243X_SDRC_VIRT, 113 .pfn = __phys_to_pfn(OMAP243X_SDRC_PHYS), 114 .length = OMAP243X_SDRC_SIZE, 115 .type = MT_DEVICE 116 }, 117 { 118 .virtual = OMAP243X_SMS_VIRT, 119 .pfn = __phys_to_pfn(OMAP243X_SMS_PHYS), 120 .length = OMAP243X_SMS_SIZE, 121 .type = MT_DEVICE 122 }, 123 }; 124 #endif 125 #endif 126 127 #ifdef CONFIG_ARCH_OMAP34XX 128 static struct map_desc omap34xx_io_desc[] __initdata = { 129 { 130 .virtual = L3_34XX_VIRT, 131 .pfn = __phys_to_pfn(L3_34XX_PHYS), 132 .length = L3_34XX_SIZE, 133 .type = MT_DEVICE 134 }, 135 { 136 .virtual = L4_34XX_VIRT, 137 .pfn = __phys_to_pfn(L4_34XX_PHYS), 138 .length = L4_34XX_SIZE, 139 .type = MT_DEVICE 140 }, 141 { 142 .virtual = L4_WK_34XX_VIRT, 143 .pfn = __phys_to_pfn(L4_WK_34XX_PHYS), 144 .length = L4_WK_34XX_SIZE, 145 .type = MT_DEVICE 146 }, 147 { 148 .virtual = OMAP34XX_GPMC_VIRT, 149 .pfn = __phys_to_pfn(OMAP34XX_GPMC_PHYS), 150 .length = OMAP34XX_GPMC_SIZE, 151 .type = MT_DEVICE 152 }, 153 { 154 .virtual = OMAP343X_SMS_VIRT, 155 .pfn = __phys_to_pfn(OMAP343X_SMS_PHYS), 156 .length = OMAP343X_SMS_SIZE, 157 .type = MT_DEVICE 158 }, 159 { 160 .virtual = OMAP343X_SDRC_VIRT, 161 .pfn = __phys_to_pfn(OMAP343X_SDRC_PHYS), 162 .length = OMAP343X_SDRC_SIZE, 163 .type = MT_DEVICE 164 }, 165 { 166 .virtual = L4_PER_34XX_VIRT, 167 .pfn = __phys_to_pfn(L4_PER_34XX_PHYS), 168 .length = L4_PER_34XX_SIZE, 169 .type = MT_DEVICE 170 }, 171 { 172 .virtual = L4_EMU_34XX_VIRT, 173 .pfn = __phys_to_pfn(L4_EMU_34XX_PHYS), 174 .length = L4_EMU_34XX_SIZE, 175 .type = MT_DEVICE 176 }, 177 }; 178 #endif 179 #ifdef CONFIG_ARCH_OMAP4 180 static struct map_desc omap44xx_io_desc[] __initdata = { 181 { 182 .virtual = L3_44XX_VIRT, 183 .pfn = __phys_to_pfn(L3_44XX_PHYS), 184 .length = L3_44XX_SIZE, 185 .type = MT_DEVICE, 186 }, 187 { 188 .virtual = L4_44XX_VIRT, 189 .pfn = __phys_to_pfn(L4_44XX_PHYS), 190 .length = L4_44XX_SIZE, 191 .type = MT_DEVICE, 192 }, 193 { 194 .virtual = L4_WK_44XX_VIRT, 195 .pfn = __phys_to_pfn(L4_WK_44XX_PHYS), 196 .length = L4_WK_44XX_SIZE, 197 .type = MT_DEVICE, 198 }, 199 { 200 .virtual = OMAP44XX_GPMC_VIRT, 201 .pfn = __phys_to_pfn(OMAP44XX_GPMC_PHYS), 202 .length = OMAP44XX_GPMC_SIZE, 203 .type = MT_DEVICE, 204 }, 205 { 206 .virtual = L4_PER_44XX_VIRT, 207 .pfn = __phys_to_pfn(L4_PER_44XX_PHYS), 208 .length = L4_PER_44XX_SIZE, 209 .type = MT_DEVICE, 210 }, 211 { 212 .virtual = L4_EMU_44XX_VIRT, 213 .pfn = __phys_to_pfn(L4_EMU_44XX_PHYS), 214 .length = L4_EMU_44XX_SIZE, 215 .type = MT_DEVICE, 216 }, 217 }; 218 #endif 219 220 void __init omap2_map_common_io(void) 221 { 222 #if defined(CONFIG_ARCH_OMAP2420) 223 iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc)); 224 iotable_init(omap242x_io_desc, ARRAY_SIZE(omap242x_io_desc)); 225 #endif 226 227 #if defined(CONFIG_ARCH_OMAP2430) 228 iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc)); 229 iotable_init(omap243x_io_desc, ARRAY_SIZE(omap243x_io_desc)); 230 #endif 231 232 #if defined(CONFIG_ARCH_OMAP34XX) 233 iotable_init(omap34xx_io_desc, ARRAY_SIZE(omap34xx_io_desc)); 234 #endif 235 236 #if defined(CONFIG_ARCH_OMAP4) 237 iotable_init(omap44xx_io_desc, ARRAY_SIZE(omap44xx_io_desc)); 238 #endif 239 /* Normally devicemaps_init() would flush caches and tlb after 240 * mdesc->map_io(), but we must also do it here because of the CPU 241 * revision check below. 242 */ 243 local_flush_tlb_all(); 244 flush_cache_all(); 245 246 omap2_check_revision(); 247 omap_sram_init(); 248 omapfb_reserve_sdram(); 249 } 250 251 /* 252 * omap2_init_reprogram_sdrc - reprogram SDRC timing parameters 253 * 254 * Sets the CORE DPLL3 M2 divider to the same value that it's at 255 * currently. This has the effect of setting the SDRC SDRAM AC timing 256 * registers to the values currently defined by the kernel. Currently 257 * only defined for OMAP3; will return 0 if called on OMAP2. Returns 258 * -EINVAL if the dpll3_m2_ck cannot be found, 0 if called on OMAP2, 259 * or passes along the return value of clk_set_rate(). 260 */ 261 static int __init _omap2_init_reprogram_sdrc(void) 262 { 263 struct clk *dpll3_m2_ck; 264 int v = -EINVAL; 265 long rate; 266 267 if (!cpu_is_omap34xx()) 268 return 0; 269 270 dpll3_m2_ck = clk_get(NULL, "dpll3_m2_ck"); 271 if (!dpll3_m2_ck) 272 return -EINVAL; 273 274 rate = clk_get_rate(dpll3_m2_ck); 275 pr_info("Reprogramming SDRC clock to %ld Hz\n", rate); 276 v = clk_set_rate(dpll3_m2_ck, rate); 277 if (v) 278 pr_err("dpll3_m2_clk rate change failed: %d\n", v); 279 280 clk_put(dpll3_m2_ck); 281 282 return v; 283 } 284 285 void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0, 286 struct omap_sdrc_params *sdrc_cs1) 287 { 288 struct omap_hwmod **hwmods = NULL; 289 290 if (cpu_is_omap2420()) 291 hwmods = omap2420_hwmods; 292 else if (cpu_is_omap2430()) 293 hwmods = omap2430_hwmods; 294 else if (cpu_is_omap34xx()) 295 hwmods = omap34xx_hwmods; 296 297 omap_hwmod_init(hwmods); 298 omap2_mux_init(); 299 #ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once the clkdev is ready */ 300 /* The OPP tables have to be registered before a clk init */ 301 omap_pm_if_early_init(mpu_opps, dsp_opps, l3_opps); 302 pwrdm_init(powerdomains_omap); 303 clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps); 304 omap2_clk_init(); 305 omap_serial_early_init(); 306 omap_hwmod_late_init(); 307 omap_pm_if_init(); 308 omap2_sdrc_init(sdrc_cs0, sdrc_cs1); 309 _omap2_init_reprogram_sdrc(); 310 #endif 311 gpmc_init(); 312 } 313