Merge branch 'topic/core-cleanup' into for-linus
[safe/jmp/linux-2.6] / arch / arm / plat-omap / common.c
index 8bdf0ea..f12f0e3 100644 (file)
@@ -2,6 +2,10 @@
  * linux/arch/arm/plat-omap/common.c
  *
  * Code common to all OMAP machines.
+ * The file is created by Tony Lindgren <tony@atomide.com>
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,7 +15,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/pm.h>
 #include <linux/console.h>
 #include <linux/serial.h>
 #include <linux/tty.h>
 #include <asm/mach/map.h>
 #include <asm/setup.h>
 
-#include <mach/common.h>
-#include <mach/board.h>
-#include <mach/control.h>
-#include <mach/mux.h>
-#include <mach/fpga.h>
+#include <plat/common.h>
+#include <plat/board.h>
+#include <plat/control.h>
+#include <plat/mux.h>
+#include <plat/fpga.h>
+#include <plat/serial.h>
 
-#include <mach/clock.h>
+#include <plat/clock.h>
 
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 # include "../mach-omap2/sdrc.h"
 
 #define NO_LENGTH_CHECK 0xffffffff
 
-unsigned char omap_bootloader_tag[512];
-int omap_bootloader_tag_len;
-
 struct omap_board_config_kernel *omap_board_config;
 int omap_board_config_size;
 
+/* used by omap-smp.c and board-4430sdp.c */
+void __iomem *gic_cpu_base_addr;
+
 static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
 {
        struct omap_board_config_kernel *kinfo = NULL;
        int i;
 
-#ifdef CONFIG_OMAP_BOOT_TAG
-       struct omap_board_config_entry *info = NULL;
-
-       if (omap_bootloader_tag_len > 4)
-               info = (struct omap_board_config_entry *) omap_bootloader_tag;
-       while (info != NULL) {
-               u8 *next;
-
-               if (info->tag == tag) {
-                       if (skip == 0)
-                               break;
-                       skip--;
-               }
-
-               if ((info->len & 0x03) != 0) {
-                       /* We bail out to avoid an alignment fault */
-                       printk(KERN_ERR "OMAP peripheral config: Length (%d) not word-aligned (tag %04x)\n",
-                              info->len, info->tag);
-                       return NULL;
-               }
-               next = (u8 *) info + sizeof(*info) + info->len;
-               if (next >= omap_bootloader_tag + omap_bootloader_tag_len)
-                       info = NULL;
-               else
-                       info = (struct omap_board_config_entry *) next;
-       }
-       if (info != NULL) {
-               /* Check the length as a lame attempt to check for
-                * binary inconsistency. */
-               if (len != NO_LENGTH_CHECK) {
-                       /* Word-align len */
-                       if (len & 0x03)
-                               len = (len + 3) & ~0x03;
-                       if (info->len != len) {
-                               printk(KERN_ERR "OMAP peripheral config: Length mismatch with tag %x (want %d, got %d)\n",
-                                      tag, len, info->len);
-                               return NULL;
-                       }
-               }
-               if (len_out != NULL)
-                       *len_out = info->len;
-               return info->data;
-       }
-#endif
        /* Try to find the config from the board-specific structures
         * in the kernel. */
        for (i = 0; i < omap_board_config_size; i++) {
@@ -124,50 +84,6 @@ const void *omap_get_var_config(u16 tag, size_t *len)
 }
 EXPORT_SYMBOL(omap_get_var_config);
 
-static int __init omap_add_serial_console(void)
-{
-       const struct omap_serial_console_config *con_info;
-       const struct omap_uart_config *uart_info;
-       static char speed[11], *opt = NULL;
-       int line, i, uart_idx;
-
-       uart_info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config);
-       con_info = omap_get_config(OMAP_TAG_SERIAL_CONSOLE,
-                                       struct omap_serial_console_config);
-       if (uart_info == NULL || con_info == NULL)
-               return 0;
-
-       if (con_info->console_uart == 0)
-               return 0;
-
-       if (con_info->console_speed) {
-               snprintf(speed, sizeof(speed), "%u", con_info->console_speed);
-               opt = speed;
-       }
-
-       uart_idx = con_info->console_uart - 1;
-       if (uart_idx >= OMAP_MAX_NR_PORTS) {
-               printk(KERN_INFO "Console: external UART#%d. "
-                       "Not adding it as console this time.\n",
-                       uart_idx + 1);
-               return 0;
-       }
-       if (!(uart_info->enabled_uarts & (1 << uart_idx))) {
-               printk(KERN_ERR "Console: Selected UART#%d is "
-                       "not enabled for this platform\n",
-                       uart_idx + 1);
-               return -1;
-       }
-       line = 0;
-       for (i = 0; i < uart_idx; i++) {
-               if (uart_info->enabled_uarts & (1 << i))
-                       line++;
-       }
-       return add_preferred_console("ttyS", line, opt);
-}
-console_initcall(omap_add_serial_console);
-
-
 /*
  * 32KHz clocksource ... always available, on pretty most chips except
  * OMAP 730 and 1510.  Other timers could be used as clocksources, with
@@ -175,45 +91,116 @@ console_initcall(omap_add_serial_console);
  * but systems won't necessarily want to spend resources that way.
  */
 
-#if defined(CONFIG_ARCH_OMAP16XX)
-#define TIMER_32K_SYNCHRONIZED         0xfffbc410
-#elif defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
-#define TIMER_32K_SYNCHRONIZED         (OMAP2_32KSYNCT_BASE + 0x10)
-#endif
+#define OMAP16XX_TIMER_32K_SYNCHRONIZED                0xfffbc410
 
-#ifdef TIMER_32K_SYNCHRONIZED
+#if !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX))
 
 #include <linux/clocksource.h>
 
-static cycle_t omap_32k_read(void)
+/*
+ * offset_32k holds the init time counter value. It is then subtracted
+ * from every counter read to achieve a counter that counts time from the
+ * kernel boot (needed for sched_clock()).
+ */
+static u32 offset_32k __read_mostly;
+
+#ifdef CONFIG_ARCH_OMAP16XX
+static cycle_t omap16xx_32k_read(struct clocksource *cs)
 {
-       return omap_readl(TIMER_32K_SYNCHRONIZED);
+       return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k;
+}
+#else
+#define omap16xx_32k_read      NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2420
+static cycle_t omap2420_32k_read(struct clocksource *cs)
+{
+       return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap2420_32k_read      NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2430
+static cycle_t omap2430_32k_read(struct clocksource *cs)
+{
+       return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap2430_32k_read      NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+static cycle_t omap34xx_32k_read(struct clocksource *cs)
+{
+       return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap34xx_32k_read      NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+static cycle_t omap44xx_32k_read(struct clocksource *cs)
+{
+       return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap44xx_32k_read      NULL
+#endif
+
+/*
+ * Kernel assumes that sched_clock can be called early but may not have
+ * things ready yet.
+ */
+static cycle_t omap_32k_read_dummy(struct clocksource *cs)
+{
+       return 0;
 }
 
 static struct clocksource clocksource_32k = {
        .name           = "32k_counter",
        .rating         = 250,
-       .read           = omap_32k_read,
+       .read           = omap_32k_read_dummy,
        .mask           = CLOCKSOURCE_MASK(32),
        .shift          = 10,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 /*
- * Rounds down to nearest nsec.
+ * Returns current time from boot in nsecs. It's OK for this to wrap
+ * around for now, as it's just a relative time stamp.
  */
-unsigned long long omap_32k_ticks_to_nsecs(unsigned long ticks_32k)
+unsigned long long sched_clock(void)
 {
-       return cyc2ns(&clocksource_32k, ticks_32k);
+       return clocksource_cyc2ns(clocksource_32k.read(&clocksource_32k),
+                                 clocksource_32k.mult, clocksource_32k.shift);
 }
 
-/*
- * Returns current time from boot in nsecs. It's OK for this to wrap
- * around for now, as it's just a relative time stamp.
+/**
+ * read_persistent_clock -  Return time from a persistent clock.
+ *
+ * Reads the time from a source which isn't disabled during PM, the
+ * 32k sync timer.  Convert the cycles elapsed since last read into
+ * nsecs and adds to a monotonically increasing timespec.
  */
-unsigned long long sched_clock(void)
+static struct timespec persistent_ts;
+static cycles_t cycles, last_cycles;
+void read_persistent_clock(struct timespec *ts)
 {
-       return omap_32k_ticks_to_nsecs(omap_32k_read());
+       unsigned long long nsecs;
+       cycles_t delta;
+       struct timespec *tsp = &persistent_ts;
+
+       last_cycles = cycles;
+       cycles = clocksource_32k.read(&clocksource_32k);
+       delta = cycles - last_cycles;
+
+       nsecs = clocksource_cyc2ns(delta,
+                                  clocksource_32k.mult, clocksource_32k.shift);
+
+       timespec_add_ns(tsp, nsecs);
+       *ts = *tsp;
 }
 
 static int __init omap_init_clocksource_32k(void)
@@ -224,6 +211,19 @@ static int __init omap_init_clocksource_32k(void)
        if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
                struct clk *sync_32k_ick;
 
+               if (cpu_is_omap16xx())
+                       clocksource_32k.read = omap16xx_32k_read;
+               else if (cpu_is_omap2420())
+                       clocksource_32k.read = omap2420_32k_read;
+               else if (cpu_is_omap2430())
+                       clocksource_32k.read = omap2430_32k_read;
+               else if (cpu_is_omap34xx())
+                       clocksource_32k.read = omap34xx_32k_read;
+               else if (cpu_is_omap44xx())
+                       clocksource_32k.read = omap44xx_32k_read;
+               else
+                       return -ENODEV;
+
                sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
                if (sync_32k_ick)
                        clk_enable(sync_32k_ick);
@@ -231,6 +231,8 @@ static int __init omap_init_clocksource_32k(void)
                clocksource_32k.mult = clocksource_hz2mult(32768,
                                            clocksource_32k.shift);
 
+               offset_32k = clocksource_32k.read(&clocksource_32k);
+
                if (clocksource_register(&clocksource_32k))
                        printk(err, clocksource_32k.name);
        }
@@ -238,19 +240,19 @@ static int __init omap_init_clocksource_32k(void)
 }
 arch_initcall(omap_init_clocksource_32k);
 
-#endif /* TIMER_32K_SYNCHRONIZED */
+#endif /* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */
 
 /* Global address base setup code */
 
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 
-static struct omap_globals *omap2_globals;
-
-static void __init __omap2_set_globals(void)
+static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
 {
-       omap2_set_globals_memory(omap2_globals);
+       omap2_set_globals_tap(omap2_globals);
+       omap2_set_globals_sdrc(omap2_globals);
        omap2_set_globals_control(omap2_globals);
        omap2_set_globals_prcm(omap2_globals);
+       omap2_set_globals_uart(omap2_globals);
 }
 
 #endif
@@ -258,54 +260,93 @@ static void __init __omap2_set_globals(void)
 #if defined(CONFIG_ARCH_OMAP2420)
 
 static struct omap_globals omap242x_globals = {
-       .tap    = (__force void __iomem *)OMAP2_IO_ADDRESS(0x48014000),
-       .sdrc   = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2420_SDRC_BASE),
-       .sms    = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2420_SMS_BASE),
-       .ctrl   = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2420_CTRL_BASE),
-       .prm    = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2420_PRM_BASE),
-       .cm     = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2420_CM_BASE),
+       .class  = OMAP242X_CLASS,
+       .tap    = OMAP2_L4_IO_ADDRESS(0x48014000),
+       .sdrc   = OMAP2420_SDRC_BASE,
+       .sms    = OMAP2420_SMS_BASE,
+       .ctrl   = OMAP2420_CTRL_BASE,
+       .prm    = OMAP2420_PRM_BASE,
+       .cm     = OMAP2420_CM_BASE,
+       .uart1_phys     = OMAP2_UART1_BASE,
+       .uart2_phys     = OMAP2_UART2_BASE,
+       .uart3_phys     = OMAP2_UART3_BASE,
 };
 
 void __init omap2_set_globals_242x(void)
 {
-       omap2_globals = &omap242x_globals;
-       __omap2_set_globals();
+       __omap2_set_globals(&omap242x_globals);
 }
 #endif
 
 #if defined(CONFIG_ARCH_OMAP2430)
 
 static struct omap_globals omap243x_globals = {
-       .tap    = (__force void __iomem *)OMAP2_IO_ADDRESS(0x4900a000),
-       .sdrc   = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP243X_SDRC_BASE),
-       .sms    = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP243X_SMS_BASE),
-       .ctrl   = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP243X_CTRL_BASE),
-       .prm    = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2430_PRM_BASE),
-       .cm     = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP2430_CM_BASE),
+       .class  = OMAP243X_CLASS,
+       .tap    = OMAP2_L4_IO_ADDRESS(0x4900a000),
+       .sdrc   = OMAP243X_SDRC_BASE,
+       .sms    = OMAP243X_SMS_BASE,
+       .ctrl   = OMAP243X_CTRL_BASE,
+       .prm    = OMAP2430_PRM_BASE,
+       .cm     = OMAP2430_CM_BASE,
+       .uart1_phys     = OMAP2_UART1_BASE,
+       .uart2_phys     = OMAP2_UART2_BASE,
+       .uart3_phys     = OMAP2_UART3_BASE,
 };
 
 void __init omap2_set_globals_243x(void)
 {
-       omap2_globals = &omap243x_globals;
-       __omap2_set_globals();
+       __omap2_set_globals(&omap243x_globals);
 }
 #endif
 
-#if defined(CONFIG_ARCH_OMAP3430)
-
-static struct omap_globals omap343x_globals = {
-       .tap    = (__force void __iomem *)OMAP2_IO_ADDRESS(0x4830A000),
-       .sdrc   = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP343X_SDRC_BASE),
-       .sms    = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP343X_SMS_BASE),
-       .ctrl   = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP343X_CTRL_BASE),
-       .prm    = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP3430_PRM_BASE),
-       .cm     = (__force void __iomem *)OMAP2_IO_ADDRESS(OMAP3430_CM_BASE),
+#if defined(CONFIG_ARCH_OMAP3)
+
+static struct omap_globals omap3_globals = {
+       .class  = OMAP343X_CLASS,
+       .tap    = OMAP2_L4_IO_ADDRESS(0x4830A000),
+       .sdrc   = OMAP343X_SDRC_BASE,
+       .sms    = OMAP343X_SMS_BASE,
+       .ctrl   = OMAP343X_CTRL_BASE,
+       .prm    = OMAP3430_PRM_BASE,
+       .cm     = OMAP3430_CM_BASE,
+       .uart1_phys     = OMAP3_UART1_BASE,
+       .uart2_phys     = OMAP3_UART2_BASE,
+       .uart3_phys     = OMAP3_UART3_BASE,
 };
 
 void __init omap2_set_globals_343x(void)
 {
-       omap2_globals = &omap343x_globals;
-       __omap2_set_globals();
+       __omap2_set_globals(&omap3_globals);
+}
+
+void __init omap2_set_globals_36xx(void)
+{
+       omap3_globals.uart4_phys = OMAP3_UART4_BASE;
+
+       __omap2_set_globals(&omap3_globals);
+}
+#endif
+
+#if defined(CONFIG_ARCH_OMAP4)
+static struct omap_globals omap4_globals = {
+       .class  = OMAP443X_CLASS,
+       .tap    = OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
+       .ctrl   = OMAP443X_CTRL_BASE,
+       .prm    = OMAP4430_PRM_BASE,
+       .cm     = OMAP4430_CM_BASE,
+       .cm2    = OMAP4430_CM2_BASE,
+       .uart1_phys     = OMAP4_UART1_BASE,
+       .uart2_phys     = OMAP4_UART2_BASE,
+       .uart3_phys     = OMAP4_UART3_BASE,
+       .uart4_phys     = OMAP4_UART4_BASE,
+};
+
+void __init omap2_set_globals_443x(void)
+{
+       omap2_set_globals_tap(&omap4_globals);
+       omap2_set_globals_control(&omap4_globals);
+       omap2_set_globals_prcm(&omap4_globals);
+       omap2_set_globals_uart(&omap4_globals);
 }
 #endif