1/* 2 * linux/arch/arm/plat-omap/common.c 3 * 4 * Code common to all OMAP machines. 5 * The file is created by Tony Lindgren <tony@atomide.com> 6 * 7 * Copyright (C) 2009 Texas Instruments 8 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14#include <linux/module.h> 15#include <linux/kernel.h> 16#include <linux/init.h> 17#include <linux/delay.h> 18#include <linux/console.h> 19#include <linux/serial.h> 20#include <linux/tty.h> 21#include <linux/serial_8250.h> 22#include <linux/serial_reg.h> 23#include <linux/clk.h> 24#include <linux/io.h> 25#include <linux/omapfb.h> 26 27#include <mach/hardware.h> 28#include <asm/system.h> 29#include <asm/pgtable.h> 30#include <asm/mach/map.h> 31#include <asm/setup.h> 32 33#include <plat/common.h> 34#include <plat/board.h> 35#include <plat/control.h> 36#include <plat/mux.h> 37#include <plat/fpga.h> 38#include <plat/serial.h> 39#include <plat/vram.h> 40 41#include <plat/clock.h> 42 43#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) 44# include "../mach-omap2/sdrc.h" 45#endif 46 47#define NO_LENGTH_CHECK 0xffffffff 48 49struct omap_board_config_kernel *omap_board_config; 50int omap_board_config_size; 51 52static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out) 53{ 54 struct omap_board_config_kernel *kinfo = NULL; 55 int i; 56 57 /* Try to find the config from the board-specific structures 58 * in the kernel. */ 59 for (i = 0; i < omap_board_config_size; i++) { 60 if (omap_board_config[i].tag == tag) { 61 if (skip == 0) { 62 kinfo = &omap_board_config[i]; 63 break; 64 } else { 65 skip--; 66 } 67 } 68 } 69 if (kinfo == NULL) 70 return NULL; 71 return kinfo->data; 72} 73 74const void *__omap_get_config(u16 tag, size_t len, int nr) 75{ 76 return get_config(tag, len, nr, NULL); 77} 78EXPORT_SYMBOL(__omap_get_config); 79 80const void *omap_get_var_config(u16 tag, size_t *len) 81{ 82 return get_config(tag, NO_LENGTH_CHECK, 0, len); 83} 84EXPORT_SYMBOL(omap_get_var_config); 85 86void __init omap_reserve(void) 87{ 88 omapfb_reserve_sdram_memblock(); 89 omap_vram_reserve_sdram_memblock(); 90} 91 92/* 93 * 32KHz clocksource ... always available, on pretty most chips except 94 * OMAP 730 and 1510. Other timers could be used as clocksources, with 95 * higher resolution in free-running counter modes (e.g. 12 MHz xtal), 96 * but systems won't necessarily want to spend resources that way. 97 */ 98 99#define OMAP16XX_TIMER_32K_SYNCHRONIZED 0xfffbc410 100 101#if !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) 102 103#include <linux/clocksource.h> 104 105/* 106 * offset_32k holds the init time counter value. It is then subtracted 107 * from every counter read to achieve a counter that counts time from the 108 * kernel boot (needed for sched_clock()). 109 */ 110static u32 offset_32k __read_mostly; 111 112#ifdef CONFIG_ARCH_OMAP16XX 113static cycle_t omap16xx_32k_read(struct clocksource *cs) 114{ 115 return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k; 116} 117#else 118#define omap16xx_32k_read NULL 119#endif 120 121#ifdef CONFIG_ARCH_OMAP2420 122static cycle_t omap2420_32k_read(struct clocksource *cs) 123{ 124 return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k; 125} 126#else 127#define omap2420_32k_read NULL 128#endif 129 130#ifdef CONFIG_ARCH_OMAP2430 131static cycle_t omap2430_32k_read(struct clocksource *cs) 132{ 133 return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k; 134} 135#else 136#define omap2430_32k_read NULL 137#endif 138 139#ifdef CONFIG_ARCH_OMAP3 140static cycle_t omap34xx_32k_read(struct clocksource *cs) 141{ 142 return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k; 143} 144#else 145#define omap34xx_32k_read NULL 146#endif 147 148#ifdef CONFIG_ARCH_OMAP4 149static cycle_t omap44xx_32k_read(struct clocksource *cs) 150{ 151 return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k; 152} 153#else 154#define omap44xx_32k_read NULL 155#endif 156 157/* 158 * Kernel assumes that sched_clock can be called early but may not have 159 * things ready yet. 160 */ 161static cycle_t omap_32k_read_dummy(struct clocksource *cs) 162{ 163 return 0; 164} 165 166static struct clocksource clocksource_32k = { 167 .name = "32k_counter", 168 .rating = 250, 169 .read = omap_32k_read_dummy, 170 .mask = CLOCKSOURCE_MASK(32), 171 .shift = 10, 172 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 173}; 174 175/* 176 * Returns current time from boot in nsecs. It's OK for this to wrap 177 * around for now, as it's just a relative time stamp. 178 */ 179unsigned long long sched_clock(void) 180{ 181 return clocksource_cyc2ns(clocksource_32k.read(&clocksource_32k), 182 clocksource_32k.mult, clocksource_32k.shift); 183} 184 185/** 186 * read_persistent_clock - Return time from a persistent clock. 187 * 188 * Reads the time from a source which isn't disabled during PM, the 189 * 32k sync timer. Convert the cycles elapsed since last read into 190 * nsecs and adds to a monotonically increasing timespec. 191 */ 192static struct timespec persistent_ts; 193static cycles_t cycles, last_cycles; 194void read_persistent_clock(struct timespec *ts) 195{ 196 unsigned long long nsecs; 197 cycles_t delta; 198 struct timespec *tsp = &persistent_ts; 199 200 last_cycles = cycles; 201 cycles = clocksource_32k.read(&clocksource_32k); 202 delta = cycles - last_cycles; 203 204 nsecs = clocksource_cyc2ns(delta, 205 clocksource_32k.mult, clocksource_32k.shift); 206 207 timespec_add_ns(tsp, nsecs); 208 *ts = *tsp; 209} 210 211static int __init omap_init_clocksource_32k(void) 212{ 213 static char err[] __initdata = KERN_ERR 214 "%s: can't register clocksource!\n"; 215 216 if (cpu_is_omap16xx() || cpu_class_is_omap2()) { 217 struct clk *sync_32k_ick; 218 219 if (cpu_is_omap16xx()) 220 clocksource_32k.read = omap16xx_32k_read; 221 else if (cpu_is_omap2420()) 222 clocksource_32k.read = omap2420_32k_read; 223 else if (cpu_is_omap2430()) 224 clocksource_32k.read = omap2430_32k_read; 225 else if (cpu_is_omap34xx()) 226 clocksource_32k.read = omap34xx_32k_read; 227 else if (cpu_is_omap44xx()) 228 clocksource_32k.read = omap44xx_32k_read; 229 else 230 return -ENODEV; 231 232 sync_32k_ick = clk_get(NULL, "omap_32ksync_ick"); 233 if (sync_32k_ick) 234 clk_enable(sync_32k_ick); 235 236 clocksource_32k.mult = clocksource_hz2mult(32768, 237 clocksource_32k.shift); 238 239 offset_32k = clocksource_32k.read(&clocksource_32k); 240 241 if (clocksource_register(&clocksource_32k)) 242 printk(err, clocksource_32k.name); 243 } 244 return 0; 245} 246arch_initcall(omap_init_clocksource_32k); 247 248#endif /* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */ 249 250/* Global address base setup code */ 251 252#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) 253 254static void __init __omap2_set_globals(struct omap_globals *omap2_globals) 255{ 256 omap2_set_globals_tap(omap2_globals); 257 omap2_set_globals_sdrc(omap2_globals); 258 omap2_set_globals_control(omap2_globals); 259 omap2_set_globals_prcm(omap2_globals); 260 omap2_set_globals_uart(omap2_globals); 261} 262 263#endif 264 265#if defined(CONFIG_ARCH_OMAP2420) 266 267static struct omap_globals omap242x_globals = { 268 .class = OMAP242X_CLASS, 269 .tap = OMAP2_L4_IO_ADDRESS(0x48014000), 270 .sdrc = OMAP2420_SDRC_BASE, 271 .sms = OMAP2420_SMS_BASE, 272 .ctrl = OMAP2420_CTRL_BASE, 273 .prm = OMAP2420_PRM_BASE, 274 .cm = OMAP2420_CM_BASE, 275 .uart1_phys = OMAP2_UART1_BASE, 276 .uart2_phys = OMAP2_UART2_BASE, 277 .uart3_phys = OMAP2_UART3_BASE, 278}; 279 280void __init omap2_set_globals_242x(void) 281{ 282 __omap2_set_globals(&omap242x_globals); 283} 284#endif 285 286#if defined(CONFIG_ARCH_OMAP2430) 287 288static struct omap_globals omap243x_globals = { 289 .class = OMAP243X_CLASS, 290 .tap = OMAP2_L4_IO_ADDRESS(0x4900a000), 291 .sdrc = OMAP243X_SDRC_BASE, 292 .sms = OMAP243X_SMS_BASE, 293 .ctrl = OMAP243X_CTRL_BASE, 294 .prm = OMAP2430_PRM_BASE, 295 .cm = OMAP2430_CM_BASE, 296 .uart1_phys = OMAP2_UART1_BASE, 297 .uart2_phys = OMAP2_UART2_BASE, 298 .uart3_phys = OMAP2_UART3_BASE, 299}; 300 301void __init omap2_set_globals_243x(void) 302{ 303 __omap2_set_globals(&omap243x_globals); 304} 305#endif 306 307#if defined(CONFIG_ARCH_OMAP3) 308 309static struct omap_globals omap3_globals = { 310 .class = OMAP343X_CLASS, 311 .tap = OMAP2_L4_IO_ADDRESS(0x4830A000), 312 .sdrc = OMAP343X_SDRC_BASE, 313 .sms = OMAP343X_SMS_BASE, 314 .ctrl = OMAP343X_CTRL_BASE, 315 .prm = OMAP3430_PRM_BASE, 316 .cm = OMAP3430_CM_BASE, 317 .uart1_phys = OMAP3_UART1_BASE, 318 .uart2_phys = OMAP3_UART2_BASE, 319 .uart3_phys = OMAP3_UART3_BASE, 320 .uart4_phys = OMAP3_UART4_BASE, /* Only on 3630 */ 321}; 322 323void __init omap2_set_globals_3xxx(void) 324{ 325 __omap2_set_globals(&omap3_globals); 326} 327 328void __init omap3_map_io(void) 329{ 330 omap2_set_globals_3xxx(); 331 omap34xx_map_common_io(); 332} 333#endif 334 335#if defined(CONFIG_ARCH_OMAP4) 336static struct omap_globals omap4_globals = { 337 .class = OMAP443X_CLASS, 338 .tap = OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE), 339 .ctrl = OMAP443X_CTRL_BASE, 340 .prm = OMAP4430_PRM_BASE, 341 .cm = OMAP4430_CM_BASE, 342 .cm2 = OMAP4430_CM2_BASE, 343 .uart1_phys = OMAP4_UART1_BASE, 344 .uart2_phys = OMAP4_UART2_BASE, 345 .uart3_phys = OMAP4_UART3_BASE, 346 .uart4_phys = OMAP4_UART4_BASE, 347}; 348 349void __init omap2_set_globals_443x(void) 350{ 351 omap2_set_globals_tap(&omap4_globals); 352 omap2_set_globals_control(&omap4_globals); 353 omap2_set_globals_prcm(&omap4_globals); 354 omap2_set_globals_uart(&omap4_globals); 355} 356#endif 357