mxc timer: make compile time independent
authorSascha Hauer <s.hauer@pengutronix.de>
Wed, 18 Feb 2009 19:58:40 +0000 (20:58 +0100)
committerSascha Hauer <s.hauer@pengutronix.de>
Thu, 7 May 2009 14:15:42 +0000 (16:15 +0200)
Currently we depend on hardcoded base addresses for the timer.
This prevents us from compiling in more than one i.MX architecture
at a time. This patch changes the base address to a runtime
calculated one.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
arch/arm/plat-mxc/include/mach/mxc_timer.h [deleted file]
arch/arm/plat-mxc/time.c

diff --git a/arch/arm/plat-mxc/include/mach/mxc_timer.h b/arch/arm/plat-mxc/include/mach/mxc_timer.h
deleted file mode 100644 (file)
index 6c19a13..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * mxc_timer.h
- *
- * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
- *
- * Platform independent (i.MX1, i.MX2, i.MX3) definition for timer handling.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA  02110-1301, USA.
- */
-
-#ifndef __PLAT_MXC_TIMER_H
-#define __PLAT_MXC_TIMER_H
-
-#include <linux/clk.h>
-#include <mach/hardware.h>
-
-#ifdef CONFIG_ARCH_MX1
-#define TIMER_BASE             IO_ADDRESS(TIM1_BASE_ADDR)
-#define TIMER_INTERRUPT                TIM1_INT
-
-#define TCTL_VAL               TCTL_CLK_PCLK1
-#define TCTL_IRQEN             (1<<4)
-#define TCTL_FRR               (1<<8)
-#define TCTL_CLK_PCLK1         (1<<1)
-#define TCTL_CLK_PCLK1_4       (2<<1)
-#define TCTL_CLK_TIN           (3<<1)
-#define TCTL_CLK_32            (4<<1)
-
-#define MXC_TCTL   0x00
-#define MXC_TPRER  0x04
-#define MXC_TCMP   0x08
-#define MXC_TCR    0x0c
-#define MXC_TCN    0x10
-#define MXC_TSTAT  0x14
-#define TSTAT_CAPT             (1<<1)
-#define TSTAT_COMP             (1<<0)
-
-static inline void gpt_irq_disable(void)
-{
-       unsigned int tmp;
-
-       tmp = __raw_readl(TIMER_BASE + MXC_TCTL);
-       __raw_writel(tmp & ~TCTL_IRQEN, TIMER_BASE + MXC_TCTL);
-}
-
-static inline void gpt_irq_enable(void)
-{
-       __raw_writel(__raw_readl(TIMER_BASE + MXC_TCTL) | TCTL_IRQEN,
-                               TIMER_BASE + MXC_TCTL);
-}
-
-static void gpt_irq_acknowledge(void)
-{
-       __raw_writel(0, TIMER_BASE + MXC_TSTAT);
-}
-#endif /* CONFIG_ARCH_MX1 */
-
-#ifdef CONFIG_ARCH_MX2
-#define TIMER_BASE             IO_ADDRESS(GPT1_BASE_ADDR)
-#define TIMER_INTERRUPT                MXC_INT_GPT1
-
-#define MXC_TCTL   0x00
-#define TCTL_VAL               TCTL_CLK_PCLK1
-#define TCTL_CLK_PCLK1         (1<<1)
-#define TCTL_CLK_PCLK1_4       (2<<1)
-#define TCTL_IRQEN             (1<<4)
-#define TCTL_FRR               (1<<8)
-#define MXC_TPRER  0x04
-#define MXC_TCMP   0x08
-#define MXC_TCR    0x0c
-#define MXC_TCN    0x10
-#define MXC_TSTAT  0x14
-#define TSTAT_CAPT             (1<<1)
-#define TSTAT_COMP             (1<<0)
-
-static inline void gpt_irq_disable(void)
-{
-       unsigned int tmp;
-
-       tmp = __raw_readl(TIMER_BASE + MXC_TCTL);
-       __raw_writel(tmp & ~TCTL_IRQEN, TIMER_BASE + MXC_TCTL);
-}
-
-static inline void gpt_irq_enable(void)
-{
-       __raw_writel(__raw_readl(TIMER_BASE + MXC_TCTL) | TCTL_IRQEN,
-                               TIMER_BASE + MXC_TCTL);
-}
-
-static void gpt_irq_acknowledge(void)
-{
-       __raw_writel(TSTAT_CAPT | TSTAT_COMP, TIMER_BASE + MXC_TSTAT);
-}
-#endif /* CONFIG_ARCH_MX2 */
-
-#ifdef CONFIG_ARCH_MX3
-#define TIMER_BASE             IO_ADDRESS(GPT1_BASE_ADDR)
-#define TIMER_INTERRUPT                MXC_INT_GPT
-
-#define MXC_TCTL   0x00
-#define TCTL_VAL               (TCTL_CLK_IPG | TCTL_WAITEN)
-#define TCTL_CLK_IPG           (1<<6)
-#define TCTL_FRR               (1<<9)
-#define TCTL_WAITEN            (1<<3)
-
-#define MXC_TPRER  0x04
-#define MXC_TSTAT  0x08
-#define TSTAT_OF1              (1<<0)
-#define TSTAT_OF2              (1<<1)
-#define TSTAT_OF3              (1<<2)
-#define TSTAT_IF1              (1<<3)
-#define TSTAT_IF2              (1<<4)
-#define TSTAT_ROV              (1<<5)
-#define MXC_IR     0x0c
-#define MXC_TCMP   0x10
-#define MXC_TCMP2  0x14
-#define MXC_TCMP3  0x18
-#define MXC_TCR    0x1c
-#define MXC_TCN    0x24
-
-static inline void gpt_irq_disable(void)
-{
-       __raw_writel(0, TIMER_BASE + MXC_IR);
-}
-
-static inline void gpt_irq_enable(void)
-{
-       __raw_writel(1<<0, TIMER_BASE + MXC_IR);
-}
-
-static inline void gpt_irq_acknowledge(void)
-{
-       __raw_writel(TSTAT_OF1, TIMER_BASE + MXC_TSTAT);
-}
-#endif /* CONFIG_ARCH_MX3 */
-
-#define TCTL_SWR               (1<<15)
-#define TCTL_CC                        (1<<10)
-#define TCTL_OM                        (1<<9)
-#define TCTL_CAP_RIS           (1<<6)
-#define TCTL_CAP_FAL           (2<<6)
-#define TCTL_CAP_RIS_FAL       (3<<6)
-#define TCTL_CAP_ENA           (1<<5)
-#define TCTL_TEN               (1<<0)
-
-#endif
index dab3357..85f002e 100644 (file)
 #include <mach/hardware.h>
 #include <asm/mach/time.h>
 #include <mach/common.h>
-#include <mach/mxc_timer.h>
+
+/* defines common for all i.MX */
+#define MXC_TCTL               0x00
+#define MXC_TCTL_TEN           (1 << 0)
+#define MXC_TPRER              0x04
+
+/* MX1, MX21, MX27 */
+#define MX1_2_TCTL_CLK_PCLK1   (1 << 1)
+#define MX1_2_TCTL_IRQEN       (1 << 4)
+#define MX1_2_TCTL_FRR         (1 << 8)
+#define MX1_2_TCMP             0x08
+#define MX1_2_TCN              0x10
+#define MX1_2_TSTAT            0x14
+
+/* MX21, MX27 */
+#define MX2_TSTAT_CAPT         (1 << 1)
+#define MX2_TSTAT_COMP         (1 << 0)
+
+/* MX31, MX35 */
+#define MX3_TCTL_WAITEN                (1 << 3)
+#define MX3_TCTL_CLK_IPG       (1 << 6)
+#define MX3_TCTL_FRR           (1 << 9)
+#define MX3_IR                 0x0c
+#define MX3_TSTAT              0x08
+#define MX3_TSTAT_OF1          (1 << 0)
+#define MX3_TCN                        0x24
+#define MX3_TCMP               0x10
 
 static struct clock_event_device clockevent_mxc;
 static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
 
-/* clock source */
+static void __iomem *timer_base;
 
-static cycle_t mxc_get_cycles(struct clocksource *cs)
+static inline void gpt_irq_disable(void)
 {
-       return __raw_readl(TIMER_BASE + MXC_TCN);
+       unsigned int tmp;
+
+       if (cpu_is_mx3())
+               __raw_writel(0, timer_base + MX3_IR);
+       else {
+               tmp = __raw_readl(timer_base + MXC_TCTL);
+               __raw_writel(tmp & ~MX1_2_TCTL_IRQEN, timer_base + MXC_TCTL);
+       }
+}
+
+static inline void gpt_irq_enable(void)
+{
+       if (cpu_is_mx3())
+               __raw_writel(1<<0, timer_base + MX3_IR);
+       else {
+               __raw_writel(__raw_readl(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
+                       timer_base + MXC_TCTL);
+       }
+}
+
+static void gpt_irq_acknowledge(void)
+{
+       if (cpu_is_mx1())
+               __raw_writel(0, timer_base + MX1_2_TSTAT);
+       if (cpu_is_mx2())
+               __raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP, timer_base + MX1_2_TSTAT);
+       if (cpu_is_mx3())
+               __raw_writel(MX3_TSTAT_OF1, timer_base + MX3_TSTAT);
+}
+
+static cycle_t mx1_2_get_cycles(struct clocksource *cs)
+{
+       return __raw_readl(timer_base + MX1_2_TCN);
+}
+
+static cycle_t mx3_get_cycles(struct clocksource *cs)
+{
+       return __raw_readl(timer_base + MX3_TCN);
 }
 
 static struct clocksource clocksource_mxc = {
        .name           = "mxc_timer1",
        .rating         = 200,
-       .read           = mxc_get_cycles,
+       .read           = mx1_2_get_cycles,
        .mask           = CLOCKSOURCE_MASK(32),
        .shift          = 20,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
@@ -54,6 +117,9 @@ static int __init mxc_clocksource_init(struct clk *timer_clk)
 {
        unsigned int c = clk_get_rate(timer_clk);
 
+       if (cpu_is_mx3())
+               clocksource_mxc.read = mx3_get_cycles;
+
        clocksource_mxc.mult = clocksource_hz2mult(c,
                                        clocksource_mxc.shift);
        clocksource_register(&clocksource_mxc);
@@ -63,15 +129,29 @@ static int __init mxc_clocksource_init(struct clk *timer_clk)
 
 /* clock event */
 
-static int mxc_set_next_event(unsigned long evt,
+static int mx1_2_set_next_event(unsigned long evt,
                              struct clock_event_device *unused)
 {
        unsigned long tcmp;
 
-       tcmp = __raw_readl(TIMER_BASE + MXC_TCN) + evt;
-       __raw_writel(tcmp, TIMER_BASE + MXC_TCMP);
+       tcmp = __raw_readl(timer_base + MX1_2_TCN) + evt;
 
-       return (int)(tcmp - __raw_readl(TIMER_BASE + MXC_TCN)) < 0 ?
+       __raw_writel(tcmp, timer_base + MX1_2_TCMP);
+
+       return (int)(tcmp - __raw_readl(timer_base + MX1_2_TCN)) < 0 ?
+                               -ETIME : 0;
+}
+
+static int mx3_set_next_event(unsigned long evt,
+                             struct clock_event_device *unused)
+{
+       unsigned long tcmp;
+
+       tcmp = __raw_readl(timer_base + MX3_TCN) + evt;
+
+       __raw_writel(tcmp, timer_base + MX3_TCMP);
+
+       return (int)(tcmp - __raw_readl(timer_base + MX3_TCN)) < 0 ?
                                -ETIME : 0;
 }
 
@@ -100,8 +180,13 @@ static void mxc_set_mode(enum clock_event_mode mode,
 
        if (mode != clockevent_mode) {
                /* Set event time into far-far future */
-               __raw_writel(__raw_readl(TIMER_BASE + MXC_TCN) - 3,
-                               TIMER_BASE + MXC_TCMP);
+               if (cpu_is_mx3())
+                       __raw_writel(__raw_readl(timer_base + MX3_TCN) - 3,
+                                       timer_base + MX3_TCMP);
+               else
+                       __raw_writel(__raw_readl(timer_base + MX1_2_TCN) - 3,
+                                       timer_base + MX1_2_TCMP);
+
                /* Clear pending interrupt */
                gpt_irq_acknowledge();
        }
@@ -148,7 +233,10 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
        struct clock_event_device *evt = &clockevent_mxc;
        uint32_t tstat;
 
-       tstat = __raw_readl(TIMER_BASE + MXC_TSTAT);
+       if (cpu_is_mx3())
+               tstat = __raw_readl(timer_base + MX1_2_TSTAT);
+       else
+               tstat = __raw_readl(timer_base + MX3_TSTAT);
 
        gpt_irq_acknowledge();
 
@@ -168,7 +256,7 @@ static struct clock_event_device clockevent_mxc = {
        .features       = CLOCK_EVT_FEAT_ONESHOT,
        .shift          = 32,
        .set_mode       = mxc_set_mode,
-       .set_next_event = mxc_set_next_event,
+       .set_next_event = mx1_2_set_next_event,
        .rating         = 200,
 };
 
@@ -176,6 +264,9 @@ static int __init mxc_clockevent_init(struct clk *timer_clk)
 {
        unsigned int c = clk_get_rate(timer_clk);
 
+       if (cpu_is_mx3())
+               clockevent_mxc.set_next_event = mx3_set_next_event;
+
        clockevent_mxc.mult = div_sc(c, NSEC_PER_SEC,
                                        clockevent_mxc.shift);
        clockevent_mxc.max_delta_ns =
@@ -192,23 +283,47 @@ static int __init mxc_clockevent_init(struct clk *timer_clk)
 
 void __init mxc_timer_init(struct clk *timer_clk)
 {
+       uint32_t tctl_val;
+       int irq;
+
        clk_enable(timer_clk);
 
+       if (cpu_is_mx1()) {
+#ifdef CONFIG_ARCH_MX1
+               timer_base = IO_ADDRESS(TIM1_BASE_ADDR);
+               irq = TIM1_INT;
+#endif
+       } else if (cpu_is_mx2()) {
+#ifdef CONFIG_ARCH_MX2
+               timer_base = IO_ADDRESS(GPT1_BASE_ADDR);
+               irq = MXC_INT_GPT1;
+#endif
+       } else if (cpu_is_mx3()) {
+#ifdef CONFIG_ARCH_MX3
+               timer_base = IO_ADDRESS(GPT1_BASE_ADDR);
+               irq = MXC_INT_GPT;
+#endif
+       } else
+               BUG();
+
        /*
         * Initialise to a known state (all timers off, and timing reset)
         */
-       __raw_writel(0, TIMER_BASE + MXC_TCTL);
-       __raw_writel(0, TIMER_BASE + MXC_TPRER); /* see datasheet note */
 
-       __raw_writel(TCTL_FRR | /* free running */
-                    TCTL_VAL | /* set clocksource and arch specific bits */
-                    TCTL_TEN,  /* start the timer */
-                    TIMER_BASE + MXC_TCTL);
+       __raw_writel(0, timer_base + MXC_TCTL);
+       __raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
+
+       if (cpu_is_mx3())
+               tctl_val = MX3_TCTL_CLK_IPG | MX3_TCTL_FRR | MX3_TCTL_WAITEN | MXC_TCTL_TEN;
+       else
+               tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
+
+       __raw_writel(tctl_val, timer_base + MXC_TCTL);
 
        /* init and register the timer to the framework */
        mxc_clocksource_init(timer_clk);
        mxc_clockevent_init(timer_clk);
 
        /* Make irqs happen */
-       setup_irq(TIMER_INTERRUPT, &mxc_timer_irq);
+       setup_irq(irq, &mxc_timer_irq);
 }