linux/arch/arm/plat-omap/common.c
<<
>>
Prefs
   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
  26#include <mach/hardware.h>
  27#include <asm/system.h>
  28#include <asm/pgtable.h>
  29#include <asm/mach/map.h>
  30#include <asm/setup.h>
  31
  32#include <mach/common.h>
  33#include <mach/board.h>
  34#include <mach/control.h>
  35#include <mach/mux.h>
  36#include <mach/fpga.h>
  37
  38#include <mach/clock.h>
  39
  40#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
  41# include "../mach-omap2/sdrc.h"
  42#endif
  43
  44#define NO_LENGTH_CHECK 0xffffffff
  45
  46unsigned char omap_bootloader_tag[512];
  47int omap_bootloader_tag_len;
  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
  86/*
  87 * 32KHz clocksource ... always available, on pretty most chips except
  88 * OMAP 730 and 1510.  Other timers could be used as clocksources, with
  89 * higher resolution in free-running counter modes (e.g. 12 MHz xtal),
  90 * but systems won't necessarily want to spend resources that way.
  91 */
  92
  93#define OMAP16XX_TIMER_32K_SYNCHRONIZED         0xfffbc410
  94
  95#if !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX))
  96
  97#include <linux/clocksource.h>
  98
  99#ifdef CONFIG_ARCH_OMAP16XX
 100static cycle_t omap16xx_32k_read(struct clocksource *cs)
 101{
 102        return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED);
 103}
 104#else
 105#define omap16xx_32k_read       NULL
 106#endif
 107
 108#ifdef CONFIG_ARCH_OMAP2420
 109static cycle_t omap2420_32k_read(struct clocksource *cs)
 110{
 111        return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10);
 112}
 113#else
 114#define omap2420_32k_read       NULL
 115#endif
 116
 117#ifdef CONFIG_ARCH_OMAP2430
 118static cycle_t omap2430_32k_read(struct clocksource *cs)
 119{
 120        return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10);
 121}
 122#else
 123#define omap2430_32k_read       NULL
 124#endif
 125
 126#ifdef CONFIG_ARCH_OMAP34XX
 127static cycle_t omap34xx_32k_read(struct clocksource *cs)
 128{
 129        return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10);
 130}
 131#else
 132#define omap34xx_32k_read       NULL
 133#endif
 134
 135#ifdef CONFIG_ARCH_OMAP4
 136static cycle_t omap44xx_32k_read(struct clocksource *cs)
 137{
 138        return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10);
 139}
 140#else
 141#define omap44xx_32k_read       NULL
 142#endif
 143
 144/*
 145 * Kernel assumes that sched_clock can be called early but may not have
 146 * things ready yet.
 147 */
 148static cycle_t omap_32k_read_dummy(struct clocksource *cs)
 149{
 150        return 0;
 151}
 152
 153static struct clocksource clocksource_32k = {
 154        .name           = "32k_counter",
 155        .rating         = 250,
 156        .read           = omap_32k_read_dummy,
 157        .mask           = CLOCKSOURCE_MASK(32),
 158        .shift          = 10,
 159        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 160};
 161
 162/*
 163 * Returns current time from boot in nsecs. It's OK for this to wrap
 164 * around for now, as it's just a relative time stamp.
 165 */
 166unsigned long long sched_clock(void)
 167{
 168        return clocksource_cyc2ns(clocksource_32k.read(&clocksource_32k),
 169                                  clocksource_32k.mult, clocksource_32k.shift);
 170}
 171
 172static int __init omap_init_clocksource_32k(void)
 173{
 174        static char err[] __initdata = KERN_ERR
 175                        "%s: can't register clocksource!\n";
 176
 177        if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
 178                struct clk *sync_32k_ick;
 179
 180                if (cpu_is_omap16xx())
 181                        clocksource_32k.read = omap16xx_32k_read;
 182                else if (cpu_is_omap2420())
 183                        clocksource_32k.read = omap2420_32k_read;
 184                else if (cpu_is_omap2430())
 185                        clocksource_32k.read = omap2430_32k_read;
 186                else if (cpu_is_omap34xx())
 187                        clocksource_32k.read = omap34xx_32k_read;
 188                else if (cpu_is_omap44xx())
 189                        clocksource_32k.read = omap44xx_32k_read;
 190                else
 191                        return -ENODEV;
 192
 193                sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
 194                if (sync_32k_ick)
 195                        clk_enable(sync_32k_ick);
 196
 197                clocksource_32k.mult = clocksource_hz2mult(32768,
 198                                            clocksource_32k.shift);
 199
 200                if (clocksource_register(&clocksource_32k))
 201                        printk(err, clocksource_32k.name);
 202        }
 203        return 0;
 204}
 205arch_initcall(omap_init_clocksource_32k);
 206
 207#endif  /* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */
 208
 209/* Global address base setup code */
 210
 211#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 212
 213static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
 214{
 215        omap2_set_globals_tap(omap2_globals);
 216        omap2_set_globals_sdrc(omap2_globals);
 217        omap2_set_globals_control(omap2_globals);
 218        omap2_set_globals_prcm(omap2_globals);
 219}
 220
 221#endif
 222
 223#if defined(CONFIG_ARCH_OMAP2420)
 224
 225static struct omap_globals omap242x_globals = {
 226        .class  = OMAP242X_CLASS,
 227        .tap    = OMAP2_IO_ADDRESS(0x48014000),
 228        .sdrc   = OMAP2_IO_ADDRESS(OMAP2420_SDRC_BASE),
 229        .sms    = OMAP2_IO_ADDRESS(OMAP2420_SMS_BASE),
 230        .ctrl   = OMAP2_IO_ADDRESS(OMAP2420_CTRL_BASE),
 231        .prm    = OMAP2_IO_ADDRESS(OMAP2420_PRM_BASE),
 232        .cm     = OMAP2_IO_ADDRESS(OMAP2420_CM_BASE),
 233};
 234
 235void __init omap2_set_globals_242x(void)
 236{
 237        __omap2_set_globals(&omap242x_globals);
 238}
 239#endif
 240
 241#if defined(CONFIG_ARCH_OMAP2430)
 242
 243static struct omap_globals omap243x_globals = {
 244        .class  = OMAP243X_CLASS,
 245        .tap    = OMAP2_IO_ADDRESS(0x4900a000),
 246        .sdrc   = OMAP2_IO_ADDRESS(OMAP243X_SDRC_BASE),
 247        .sms    = OMAP2_IO_ADDRESS(OMAP243X_SMS_BASE),
 248        .ctrl   = OMAP2_IO_ADDRESS(OMAP243X_CTRL_BASE),
 249        .prm    = OMAP2_IO_ADDRESS(OMAP2430_PRM_BASE),
 250        .cm     = OMAP2_IO_ADDRESS(OMAP2430_CM_BASE),
 251};
 252
 253void __init omap2_set_globals_243x(void)
 254{
 255        __omap2_set_globals(&omap243x_globals);
 256}
 257#endif
 258
 259#if defined(CONFIG_ARCH_OMAP3430)
 260
 261static struct omap_globals omap343x_globals = {
 262        .class  = OMAP343X_CLASS,
 263        .tap    = OMAP2_IO_ADDRESS(0x4830A000),
 264        .sdrc   = OMAP2_IO_ADDRESS(OMAP343X_SDRC_BASE),
 265        .sms    = OMAP2_IO_ADDRESS(OMAP343X_SMS_BASE),
 266        .ctrl   = OMAP2_IO_ADDRESS(OMAP343X_CTRL_BASE),
 267        .prm    = OMAP2_IO_ADDRESS(OMAP3430_PRM_BASE),
 268        .cm     = OMAP2_IO_ADDRESS(OMAP3430_CM_BASE),
 269};
 270
 271void __init omap2_set_globals_343x(void)
 272{
 273        __omap2_set_globals(&omap343x_globals);
 274}
 275#endif
 276
 277#if defined(CONFIG_ARCH_OMAP4)
 278static struct omap_globals omap4_globals = {
 279        .class  = OMAP443X_CLASS,
 280        .tap    = OMAP2_IO_ADDRESS(0x4830a000),
 281        .ctrl   = OMAP2_IO_ADDRESS(OMAP443X_CTRL_BASE),
 282        .prm    = OMAP2_IO_ADDRESS(OMAP4430_PRM_BASE),
 283        .cm     = OMAP2_IO_ADDRESS(OMAP4430_CM_BASE),
 284};
 285
 286void __init omap2_set_globals_443x(void)
 287{
 288        omap2_set_globals_tap(&omap4_globals);
 289        omap2_set_globals_control(&omap4_globals);
 290}
 291#endif
 292
 293