1 /* 2 * OMAP4 specific common source file. 3 * 4 * Copyright (C) 2010 Texas Instruments, Inc. 5 * Author: 6 * Santosh Shilimkar <santosh.shilimkar@ti.com> 7 * 8 * 9 * This program is free software,you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14 #include <linux/kernel.h> 15 #include <linux/init.h> 16 #include <linux/io.h> 17 #include <linux/irq.h> 18 #include <linux/irqchip.h> 19 #include <linux/platform_device.h> 20 #include <linux/memblock.h> 21 #include <linux/of_irq.h> 22 #include <linux/of_platform.h> 23 #include <linux/export.h> 24 #include <linux/irqchip/arm-gic.h> 25 #include <linux/irqchip/irq-crossbar.h> 26 #include <linux/of_address.h> 27 #include <linux/reboot.h> 28 #include <linux/genalloc.h> 29 30 #include <asm/hardware/cache-l2x0.h> 31 #include <asm/mach/map.h> 32 #include <asm/memblock.h> 33 #include <asm/smp_twd.h> 34 35 #include "omap-wakeupgen.h" 36 #include "soc.h" 37 #include "iomap.h" 38 #include "common.h" 39 #include "prminst44xx.h" 40 #include "prcm_mpu44xx.h" 41 #include "omap4-sar-layout.h" 42 #include "omap-secure.h" 43 #include "sram.h" 44 45 #ifdef CONFIG_CACHE_L2X0 46 static void __iomem *l2cache_base; 47 #endif 48 49 static void __iomem *sar_ram_base; 50 static void __iomem *gic_dist_base_addr; 51 static void __iomem *twd_base; 52 53 #define IRQ_LOCALTIMER 29 54 55 #ifdef CONFIG_OMAP4_ERRATA_I688 56 /* Used to implement memory barrier on DRAM path */ 57 #define OMAP4_DRAM_BARRIER_VA 0xfe600000 58 59 void __iomem *dram_sync, *sram_sync; 60 61 static phys_addr_t paddr; 62 static u32 size; 63 64 void omap_bus_sync(void) 65 { 66 if (dram_sync && sram_sync) { 67 writel_relaxed(readl_relaxed(dram_sync), dram_sync); 68 writel_relaxed(readl_relaxed(sram_sync), sram_sync); 69 isb(); 70 } 71 } 72 EXPORT_SYMBOL(omap_bus_sync); 73 74 static int __init omap4_sram_init(void) 75 { 76 struct device_node *np; 77 struct gen_pool *sram_pool; 78 79 np = of_find_compatible_node(NULL, NULL, "ti,omap4-mpu"); 80 if (!np) 81 pr_warn("%s:Unable to allocate sram needed to handle errata I688\n", 82 __func__); 83 sram_pool = of_get_named_gen_pool(np, "sram", 0); 84 if (!sram_pool) 85 pr_warn("%s:Unable to get sram pool needed to handle errata I688\n", 86 __func__); 87 else 88 sram_sync = (void *)gen_pool_alloc(sram_pool, PAGE_SIZE); 89 90 return 0; 91 } 92 omap_arch_initcall(omap4_sram_init); 93 94 /* Steal one page physical memory for barrier implementation */ 95 int __init omap_barrier_reserve_memblock(void) 96 { 97 98 size = ALIGN(PAGE_SIZE, SZ_1M); 99 paddr = arm_memblock_steal(size, SZ_1M); 100 101 return 0; 102 } 103 104 void __init omap_barriers_init(void) 105 { 106 struct map_desc dram_io_desc[1]; 107 108 dram_io_desc[0].virtual = OMAP4_DRAM_BARRIER_VA; 109 dram_io_desc[0].pfn = __phys_to_pfn(paddr); 110 dram_io_desc[0].length = size; 111 dram_io_desc[0].type = MT_MEMORY_RW_SO; 112 iotable_init(dram_io_desc, ARRAY_SIZE(dram_io_desc)); 113 dram_sync = (void __iomem *) dram_io_desc[0].virtual; 114 115 pr_info("OMAP4: Map 0x%08llx to 0x%08lx for dram barrier\n", 116 (long long) paddr, dram_io_desc[0].virtual); 117 118 } 119 #else 120 void __init omap_barriers_init(void) 121 {} 122 #endif 123 124 void gic_dist_disable(void) 125 { 126 if (gic_dist_base_addr) 127 writel_relaxed(0x0, gic_dist_base_addr + GIC_DIST_CTRL); 128 } 129 130 void gic_dist_enable(void) 131 { 132 if (gic_dist_base_addr) 133 writel_relaxed(0x1, gic_dist_base_addr + GIC_DIST_CTRL); 134 } 135 136 bool gic_dist_disabled(void) 137 { 138 return !(readl_relaxed(gic_dist_base_addr + GIC_DIST_CTRL) & 0x1); 139 } 140 141 void gic_timer_retrigger(void) 142 { 143 u32 twd_int = readl_relaxed(twd_base + TWD_TIMER_INTSTAT); 144 u32 gic_int = readl_relaxed(gic_dist_base_addr + GIC_DIST_PENDING_SET); 145 u32 twd_ctrl = readl_relaxed(twd_base + TWD_TIMER_CONTROL); 146 147 if (twd_int && !(gic_int & BIT(IRQ_LOCALTIMER))) { 148 /* 149 * The local timer interrupt got lost while the distributor was 150 * disabled. Ack the pending interrupt, and retrigger it. 151 */ 152 pr_warn("%s: lost localtimer interrupt\n", __func__); 153 writel_relaxed(1, twd_base + TWD_TIMER_INTSTAT); 154 if (!(twd_ctrl & TWD_TIMER_CONTROL_PERIODIC)) { 155 writel_relaxed(1, twd_base + TWD_TIMER_COUNTER); 156 twd_ctrl |= TWD_TIMER_CONTROL_ENABLE; 157 writel_relaxed(twd_ctrl, twd_base + TWD_TIMER_CONTROL); 158 } 159 } 160 } 161 162 #ifdef CONFIG_CACHE_L2X0 163 164 void __iomem *omap4_get_l2cache_base(void) 165 { 166 return l2cache_base; 167 } 168 169 static void omap4_l2c310_write_sec(unsigned long val, unsigned reg) 170 { 171 unsigned smc_op; 172 173 switch (reg) { 174 case L2X0_CTRL: 175 smc_op = OMAP4_MON_L2X0_CTRL_INDEX; 176 break; 177 178 case L2X0_AUX_CTRL: 179 smc_op = OMAP4_MON_L2X0_AUXCTRL_INDEX; 180 break; 181 182 case L2X0_DEBUG_CTRL: 183 smc_op = OMAP4_MON_L2X0_DBG_CTRL_INDEX; 184 break; 185 186 case L310_PREFETCH_CTRL: 187 smc_op = OMAP4_MON_L2X0_PREFETCH_INDEX; 188 break; 189 190 case L310_POWER_CTRL: 191 pr_info_once("OMAP L2C310: ROM does not support power control setting\n"); 192 return; 193 194 default: 195 WARN_ONCE(1, "OMAP L2C310: ignoring write to reg 0x%x\n", reg); 196 return; 197 } 198 199 omap_smc1(smc_op, val); 200 } 201 202 int __init omap_l2_cache_init(void) 203 { 204 u32 aux_ctrl; 205 206 /* Static mapping, never released */ 207 l2cache_base = ioremap(OMAP44XX_L2CACHE_BASE, SZ_4K); 208 if (WARN_ON(!l2cache_base)) 209 return -ENOMEM; 210 211 /* 16-way associativity, parity disabled, way size - 64KB (es2.0 +) */ 212 aux_ctrl = L2C_AUX_CTRL_SHARED_OVERRIDE | 213 L310_AUX_CTRL_DATA_PREFETCH | 214 L310_AUX_CTRL_INSTR_PREFETCH; 215 216 outer_cache.write_sec = omap4_l2c310_write_sec; 217 if (of_have_populated_dt()) 218 l2x0_of_init(aux_ctrl, 0xcf9fffff); 219 else 220 l2x0_init(l2cache_base, aux_ctrl, 0xcf9fffff); 221 222 return 0; 223 } 224 #endif 225 226 void __iomem *omap4_get_sar_ram_base(void) 227 { 228 return sar_ram_base; 229 } 230 231 /* 232 * SAR RAM used to save and restore the HW 233 * context in low power modes 234 */ 235 static int __init omap4_sar_ram_init(void) 236 { 237 unsigned long sar_base; 238 239 /* 240 * To avoid code running on other OMAPs in 241 * multi-omap builds 242 */ 243 if (cpu_is_omap44xx()) 244 sar_base = OMAP44XX_SAR_RAM_BASE; 245 else if (soc_is_omap54xx()) 246 sar_base = OMAP54XX_SAR_RAM_BASE; 247 else 248 return -ENOMEM; 249 250 /* Static mapping, never released */ 251 sar_ram_base = ioremap(sar_base, SZ_16K); 252 if (WARN_ON(!sar_ram_base)) 253 return -ENOMEM; 254 255 return 0; 256 } 257 omap_early_initcall(omap4_sar_ram_init); 258 259 static struct of_device_id gic_match[] = { 260 { .compatible = "arm,cortex-a9-gic", }, 261 { .compatible = "arm,cortex-a15-gic", }, 262 { }, 263 }; 264 265 static struct device_node *gic_node; 266 267 unsigned int omap4_xlate_irq(unsigned int hwirq) 268 { 269 struct of_phandle_args irq_data; 270 unsigned int irq; 271 272 if (!gic_node) 273 gic_node = of_find_matching_node(NULL, gic_match); 274 275 if (WARN_ON(!gic_node)) 276 return hwirq; 277 278 irq_data.np = gic_node; 279 irq_data.args_count = 3; 280 irq_data.args[0] = 0; 281 irq_data.args[1] = hwirq - OMAP44XX_IRQ_GIC_START; 282 irq_data.args[2] = IRQ_TYPE_LEVEL_HIGH; 283 284 irq = irq_create_of_mapping(&irq_data); 285 if (WARN_ON(!irq)) 286 irq = hwirq; 287 288 return irq; 289 } 290 291 void __init omap_gic_of_init(void) 292 { 293 struct device_node *np; 294 295 /* Extract GIC distributor and TWD bases for OMAP4460 ROM Errata WA */ 296 if (!cpu_is_omap446x()) 297 goto skip_errata_init; 298 299 np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-gic"); 300 gic_dist_base_addr = of_iomap(np, 0); 301 WARN_ON(!gic_dist_base_addr); 302 303 np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-twd-timer"); 304 twd_base = of_iomap(np, 0); 305 WARN_ON(!twd_base); 306 307 skip_errata_init: 308 omap_wakeupgen_init(); 309 #ifdef CONFIG_IRQ_CROSSBAR 310 irqcrossbar_init(); 311 #endif 312 irqchip_init(); 313 } 314