davinci: Add base address and timer flexibility
authorMark A. Greer <mgreer@mvista.com>
Wed, 15 Apr 2009 19:40:11 +0000 (12:40 -0700)
committerKevin Hilman <khilman@deeprootsystems.com>
Tue, 26 May 2009 15:19:04 +0000 (08:19 -0700)
The davinci timer code currently hardcodes the timer register
base addresses, the timer irq numbers, and the timers to use
for clock events and clocksource.  This won't work for some
a new SoC so put those values into the soc_info structure
and set them up in the SoC-specific files.

Signed-off-by: Mark A. Greer <mgreer@mvista.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
arch/arm/mach-davinci/devices.c
arch/arm/mach-davinci/dm355.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-davinci/dm646x.c
arch/arm/mach-davinci/include/mach/common.h
arch/arm/mach-davinci/include/mach/time.h [new file with mode: 0644]
arch/arm/mach-davinci/time.c

index 56c19319a7d25736e414659b0734ea1432c06957..36c528ff30f9586b08d33091bda052b8330ce127 100644 (file)
@@ -25,6 +25,7 @@
 #include <mach/mux.h>
 #include <mach/edma.h>
 #include <mach/mmc.h>
+#include <mach/time.h>
 
 #define DAVINCI_I2C_BASE            0x01C21000
 #define DAVINCI_MMCSD0_BASE         0x01E10000
@@ -235,6 +236,52 @@ static void davinci_init_wdt(void)
 
 /*-------------------------------------------------------------------------*/
 
+struct davinci_timer_instance davinci_timer_instance[2] = {
+       {
+               .base           = IO_ADDRESS(DAVINCI_TIMER0_BASE),
+               .bottom_irq     = IRQ_TINT0_TINT12,
+               .top_irq        = IRQ_TINT0_TINT34,
+       },
+       {
+               .base           = IO_ADDRESS(DAVINCI_TIMER1_BASE),
+               .bottom_irq     = IRQ_TINT1_TINT12,
+               .top_irq        = IRQ_TINT1_TINT34,
+       },
+};
+
+/*-------------------------------------------------------------------------*/
+
+#if defined(CONFIG_TI_DAVINCI_EMAC) || defined(CONFIG_TI_DAVINCI_EMAC_MODULE)
+
+void davinci_init_emac(struct emac_platform_data *pdata)
+{
+       DECLARE_MAC_BUF(buf);
+
+       if (cpu_is_davinci_dm644x())
+               dm644x_init_emac(pdata);
+       else if (cpu_is_davinci_dm646x())
+               dm646x_init_emac(pdata);
+
+       /* if valid MAC exists, don't re-register */
+       if (is_valid_ether_addr(pdata->mac_addr))
+               return;
+       else {
+               /* Use random MAC if none passed */
+               random_ether_addr(pdata->mac_addr);
+
+               printk(KERN_WARNING "%s: using random MAC addr: %s\n",
+                      __func__, print_mac(buf, pdata->mac_addr));
+       }
+}
+
+#else
+
+void davinci_init_emac(struct emac_platform_data *unused) {}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 static int __init davinci_init_devices(void)
 {
        /* please keep these calls, and their implementations above,
index e8c01ffe818a021cd2c4b30379d9a107c56075ea..293a419a4a8e1caeb84b32741814d53c706fbd05 100644 (file)
@@ -25,6 +25,7 @@
 #include <mach/psc.h>
 #include <mach/mux.h>
 #include <mach/irqs.h>
+#include <mach/time.h>
 #include <mach/common.h>
 
 #include "clock.h"
@@ -616,6 +617,18 @@ static void __iomem *dm355_psc_bases[] = {
        IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE),
 };
 
+/*
+ * T0_BOT: Timer 0, bottom:  clockevent source for hrtimers
+ * T0_TOP: Timer 0, top   :  clocksource for generic timekeeping
+ * T1_BOT: Timer 1, bottom:  (used by DSP in TI DSPLink code)
+ * T1_TOP: Timer 1, top   :  <unused>
+ */
+struct davinci_timer_info dm355_timer_info = {
+       .timers         = davinci_timer_instance,
+       .clockevent_id  = T0_BOT,
+       .clocksource_id = T0_TOP,
+};
+
 static struct davinci_soc_info davinci_soc_info_dm355 = {
        .io_desc                = dm355_io_desc,
        .io_desc_num            = ARRAY_SIZE(dm355_io_desc),
@@ -632,6 +645,7 @@ static struct davinci_soc_info davinci_soc_info_dm355 = {
        .intc_type              = DAVINCI_INTC_TYPE_AINTC,
        .intc_irq_prios         = dm355_default_priorities,
        .intc_irq_num           = DAVINCI_N_AINTC_IRQ,
+       .timer_info             = &dm355_timer_info,
 };
 
 void __init dm355_init(void)
index 5c6a7b175786c7668f8d39f10060df4abc914514..8e9385c3485325481b4bb5125907c59a3ca79a45 100644 (file)
@@ -22,6 +22,7 @@
 #include <mach/irqs.h>
 #include <mach/psc.h>
 #include <mach/mux.h>
+#include <mach/time.h>
 #include <mach/common.h>
 
 #include "clock.h"
@@ -559,6 +560,18 @@ static void __iomem *dm644x_psc_bases[] = {
        IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE),
 };
 
+/*
+ * T0_BOT: Timer 0, bottom:  clockevent source for hrtimers
+ * T0_TOP: Timer 0, top   :  clocksource for generic timekeeping
+ * T1_BOT: Timer 1, bottom:  (used by DSP in TI DSPLink code)
+ * T1_TOP: Timer 1, top   :  <unused>
+ */
+struct davinci_timer_info dm644x_timer_info = {
+       .timers         = davinci_timer_instance,
+       .clockevent_id  = T0_BOT,
+       .clocksource_id = T0_TOP,
+};
+
 static struct davinci_soc_info davinci_soc_info_dm644x = {
        .io_desc                = dm644x_io_desc,
        .io_desc_num            = ARRAY_SIZE(dm644x_io_desc),
@@ -575,6 +588,7 @@ static struct davinci_soc_info davinci_soc_info_dm644x = {
        .intc_type              = DAVINCI_INTC_TYPE_AINTC,
        .intc_irq_prios         = dm644x_default_priorities,
        .intc_irq_num           = DAVINCI_N_AINTC_IRQ,
+       .timer_info             = &dm644x_timer_info,
 };
 
 void __init dm644x_init(void)
index beb522e8a1a501c647447ef94d47cfedf003b88d..219063f4d000e6c12058bbfcc4bfe02ba31f04b5 100644 (file)
@@ -22,6 +22,7 @@
 #include <mach/irqs.h>
 #include <mach/psc.h>
 #include <mach/mux.h>
+#include <mach/time.h>
 #include <mach/common.h>
 
 #include "clock.h"
@@ -538,6 +539,18 @@ static void __iomem *dm646x_psc_bases[] = {
        IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE),
 };
 
+/*
+ * T0_BOT: Timer 0, bottom:  clockevent source for hrtimers
+ * T0_TOP: Timer 0, top   :  clocksource for generic timekeeping
+ * T1_BOT: Timer 1, bottom:  (used by DSP in TI DSPLink code)
+ * T1_TOP: Timer 1, top   :  <unused>
+ */
+struct davinci_timer_info dm646x_timer_info = {
+       .timers         = davinci_timer_instance,
+       .clockevent_id  = T0_BOT,
+       .clocksource_id = T0_TOP,
+};
+
 static struct davinci_soc_info davinci_soc_info_dm646x = {
        .io_desc                = dm646x_io_desc,
        .io_desc_num            = ARRAY_SIZE(dm646x_io_desc),
@@ -554,6 +567,7 @@ static struct davinci_soc_info davinci_soc_info_dm646x = {
        .intc_type              = DAVINCI_INTC_TYPE_AINTC,
        .intc_irq_prios         = dm646x_default_priorities,
        .intc_irq_num           = DAVINCI_N_AINTC_IRQ,
+       .timer_info             = &dm646x_timer_info,
 };
 
 void __init dm646x_init(void)
index 838ae13595a4e0b6ccc5f29fb88b50a5b16a47f5..90b43be1174e57ea4b132365a7f1a1fddc43f1b0 100644 (file)
@@ -25,6 +25,18 @@ extern void setup_usb(unsigned mA, unsigned potpgt_msec);
 /* parameters describe VBUS sourcing for host mode */
 extern void setup_usb(unsigned mA, unsigned potpgt_msec);
 
+struct davinci_timer_instance {
+       void __iomem    *base;
+       u32             bottom_irq;
+       u32             top_irq;
+};
+
+struct davinci_timer_info {
+       struct davinci_timer_instance   *timers;
+       unsigned int                    clockevent_id;
+       unsigned int                    clocksource_id;
+};
+
 /* SoC specific init support */
 struct davinci_soc_info {
        struct map_desc                 *io_desc;
@@ -44,6 +56,7 @@ struct davinci_soc_info {
        int                             intc_type;
        u8                              *intc_irq_prios;
        unsigned long                   intc_irq_num;
+       struct davinci_timer_info       *timer_info;
 };
 
 extern struct davinci_soc_info davinci_soc_info;
diff --git a/arch/arm/mach-davinci/include/mach/time.h b/arch/arm/mach-davinci/include/mach/time.h
new file mode 100644 (file)
index 0000000..1428d77
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Local header file for DaVinci time code.
+ *
+ * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ARCH_ARM_MACH_DAVINCI_TIME_H
+#define __ARCH_ARM_MACH_DAVINCI_TIME_H
+
+#define DAVINCI_TIMER0_BASE            (IO_PHYS + 0x21400)
+#define DAVINCI_TIMER1_BASE            (IO_PHYS + 0x21800)
+
+enum {
+       T0_BOT,
+       T0_TOP,
+       T1_BOT,
+       T1_TOP,
+       NUM_TIMERS
+};
+
+#define IS_TIMER1(id)          (id & 0x2)
+#define IS_TIMER0(id)          (!IS_TIMER1(id))
+#define IS_TIMER_TOP(id)       ((id & 0x1))
+#define IS_TIMER_BOT(id)       (!IS_TIMER_TOP(id))
+
+#define ID_TO_TIMER(id)                (IS_TIMER1(id) != 0)
+
+extern struct davinci_timer_instance davinci_timer_instance[];
+
+#endif /* __ARCH_ARM_MACH_DAVINCI_TIME_H */
index efbbc2ac63b4f82e1cf7e40fc17a530b4629c98c..faafb897f4bd5a97cb878e540febb150cda9f21e 100644 (file)
 #include <asm/errno.h>
 #include <mach/io.h>
 #include <mach/cputype.h>
+#include <mach/time.h>
 #include "clock.h"
 
 static struct clock_event_device clockevent_davinci;
 static unsigned int davinci_clock_tick_rate;
 
-#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400)
-#define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800)
 #define DAVINCI_WDOG_BASE   (IO_PHYS + 0x21C00)
 
-enum {
-       T0_BOT = 0, T0_TOP, T1_BOT, T1_TOP, NUM_TIMERS,
-};
-
-#define IS_TIMER1(id)    (id & 0x2)
-#define IS_TIMER0(id)    (!IS_TIMER1(id))
-#define IS_TIMER_TOP(id) ((id & 0x1))
-#define IS_TIMER_BOT(id) (!IS_TIMER_TOP(id))
-
-static int timer_irqs[NUM_TIMERS] = {
-       IRQ_TINT0_TINT12,
-       IRQ_TINT0_TINT34,
-       IRQ_TINT1_TINT12,
-       IRQ_TINT1_TINT34,
-};
-
 /*
  * This driver configures the 2 64-bit count-up timers as 4 independent
  * 32-bit count-up timers used as follows:
- *
- * T0_BOT: Timer 0, bottom:  clockevent source for hrtimers
- * T0_TOP: Timer 0, top   :  clocksource for generic timekeeping
- * T1_BOT: Timer 1, bottom:  (used by DSP in TI DSPLink code)
- * T1_TOP: Timer 1, top   :  <unused>
  */
-#define TID_CLOCKEVENT  T0_BOT
-#define TID_CLOCKSOURCE T0_TOP
+
+enum {
+       TID_CLOCKEVENT,
+       TID_CLOCKSOURCE,
+};
 
 /* Timer register offsets */
 #define PID12                        0x0
@@ -119,6 +100,13 @@ static struct timer_s timers[];
 #define TIMER_OPTS_ONESHOT    0x01
 #define TIMER_OPTS_PERIODIC   0x02
 
+static char *id_to_name[] = {
+       [T0_BOT]        = "timer0_0",
+       [T0_TOP]        = "timer0_1",
+       [T1_BOT]        = "timer1_0",
+       [T1_TOP]        = "timer1_1",
+};
+
 static int timer32_config(struct timer_s *t)
 {
        u32 tcr = __raw_readl(t->base + TCR);
@@ -183,13 +171,14 @@ static struct timer_s timers[] = {
 
 static void __init timer_init(void)
 {
-       u32 phys_bases[] = {DAVINCI_TIMER0_BASE, DAVINCI_TIMER1_BASE};
+       struct davinci_soc_info *soc_info = &davinci_soc_info;
+       struct davinci_timer_instance *dtip = soc_info->timer_info->timers;
        int i;
 
        /* Global init of each 64-bit timer as a whole */
        for(i=0; i<2; i++) {
                u32 tgcr;
-               void __iomem *base = IO_ADDRESS(phys_bases[i]);
+               void __iomem *base = dtip[i].base;
 
                /* Disabled, Internal clock source */
                __raw_writel(0, base + TCR);
@@ -215,33 +204,30 @@ static void __init timer_init(void)
        /* Init of each timer as a 32-bit timer */
        for (i=0; i< ARRAY_SIZE(timers); i++) {
                struct timer_s *t = &timers[i];
-               u32 phys_base;
-
-               if (t->name) {
-                       t->id = i;
-                       phys_base = (IS_TIMER1(t->id) ?
-                              DAVINCI_TIMER1_BASE : DAVINCI_TIMER0_BASE);
-                       t->base = IO_ADDRESS(phys_base);
-
-                       if (IS_TIMER_BOT(t->id)) {
-                               t->enamode_shift = 6;
-                               t->tim_off = TIM12;
-                               t->prd_off = PRD12;
-                       } else {
-                               t->enamode_shift = 22;
-                               t->tim_off = TIM34;
-                               t->prd_off = PRD34;
-                       }
-
-                       /* Register interrupt */
-                       t->irqaction.name = t->name;
-                       t->irqaction.dev_id = (void *)t;
-                       if (t->irqaction.handler != NULL) {
-                               setup_irq(timer_irqs[t->id], &t->irqaction);
-                       }
-
-                       timer32_config(&timers[i]);
+               int timer = ID_TO_TIMER(t->id);
+               u32 irq;
+
+               t->base = dtip[timer].base;
+
+               if (IS_TIMER_BOT(t->id)) {
+                       t->enamode_shift = 6;
+                       t->tim_off = TIM12;
+                       t->prd_off = PRD12;
+                       irq = dtip[timer].bottom_irq;
+               } else {
+                       t->enamode_shift = 22;
+                       t->tim_off = TIM34;
+                       t->prd_off = PRD34;
+                       irq = dtip[timer].top_irq;
                }
+
+               /* Register interrupt */
+               t->irqaction.name = t->name;
+               t->irqaction.dev_id = (void *)t;
+               if (t->irqaction.handler != NULL)
+                       setup_irq(irq, &t->irqaction);
+
+               timer32_config(&timers[i]);
        }
 }
 
@@ -256,7 +242,6 @@ static cycle_t read_cycles(struct clocksource *cs)
 }
 
 static struct clocksource clocksource_davinci = {
-       .name           = "timer0_1",
        .rating         = 300,
        .read           = read_cycles,
        .mask           = CLOCKSOURCE_MASK(32),
@@ -301,7 +286,6 @@ static void davinci_set_mode(enum clock_event_mode mode,
 }
 
 static struct clock_event_device clockevent_davinci = {
-       .name           = "timer0_0",
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
        .shift          = 32,
        .set_next_event = davinci_set_next_event,
@@ -312,10 +296,14 @@ static struct clock_event_device clockevent_davinci = {
 static void __init davinci_timer_init(void)
 {
        struct clk *timer_clk;
+       struct davinci_soc_info *soc_info = &davinci_soc_info;
 
        static char err[] __initdata = KERN_ERR
                "%s: can't register clocksource!\n";
 
+       timers[TID_CLOCKEVENT].id = soc_info->timer_info->clockevent_id;
+       timers[TID_CLOCKSOURCE].id = soc_info->timer_info->clocksource_id;
+
        /* init timer hw */
        timer_init();
 
@@ -326,6 +314,7 @@ static void __init davinci_timer_init(void)
        davinci_clock_tick_rate = clk_get_rate(timer_clk);
 
        /* setup clocksource */
+       clocksource_davinci.name = id_to_name[timers[TID_CLOCKSOURCE].id];
        clocksource_davinci.mult =
                clocksource_khz2mult(davinci_clock_tick_rate/1000,
                                     clocksource_davinci.shift);
@@ -333,6 +322,7 @@ static void __init davinci_timer_init(void)
                printk(err, clocksource_davinci.name);
 
        /* setup clockevent */
+       clockevent_davinci.name = id_to_name[timers[TID_CLOCKEVENT].id];
        clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC,
                                         clockevent_davinci.shift);
        clockevent_davinci.max_delta_ns =