[ARM] rtc-sa1100: don't assume CLOCK_TICK_RATE to be a constant
authorEric Miao <eric.miao@marvell.com>
Thu, 18 Dec 2008 03:10:32 +0000 (11:10 +0800)
committerEric Miao <eric.miao@marvell.com>
Mon, 29 Dec 2008 09:57:48 +0000 (17:57 +0800)
As Nicolas and Russell pointed out, CLOCK_TICK_RATE is no more
a constant on PXA when multiple processors and platforms are
selected, change TIMER_FREQ in rtc-sa1100.c into a variable.

Since the code to decide the clock tick rate is re-used from
timer.c, introduce a common get_clock_tick_rate() for this.

Signed-off-by: Eric Miao <eric.miao@marvell.com>
Acked-by: Nicolas Pitre <nico@marvell.com>
arch/arm/mach-pxa/generic.c
arch/arm/mach-pxa/include/mach/hardware.h
arch/arm/mach-pxa/include/mach/timex.h
arch/arm/mach-pxa/time.c
arch/arm/mach-sa1100/include/mach/hardware.h
drivers/rtc/rtc-sa1100.c

index 85ed0b3..0ccc91c 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
+#include <asm/mach-types.h>
 
 #include <mach/pxa-regs.h>
 #include <mach/reset.h>
@@ -39,6 +40,21 @@ void clear_reset_status(unsigned int mask)
                pxa3xx_clear_reset_status(mask);
 }
 
+unsigned long get_clock_tick_rate(void)
+{
+       unsigned long clock_tick_rate;
+
+       if (cpu_is_pxa25x())
+               clock_tick_rate = 3686400;
+       else if (machine_is_mainstone())
+               clock_tick_rate = 3249600;
+       else
+               clock_tick_rate = 3250000;
+
+       return clock_tick_rate;
+}
+EXPORT_SYMBOL(get_clock_tick_rate);
+
 /*
  * Get the clock frequency as reflected by CCCR and the turbo flag.
  * We assume these values have been applied via a fcs.
index e2d6784..c666796 100644 (file)
  */
 extern unsigned int get_memclk_frequency_10khz(void);
 
+/* return the clock tick rate of the OS timer */
+extern unsigned long get_clock_tick_rate(void);
 #endif
 
 #if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
index b05fc66..af6760a 100644 (file)
  * published by the Free Software Foundation.
  */
 
+/* Various drivers are still using the constant of CLOCK_TICK_RATE, for
+ * those drivers to at least work, the definition is provided here.
+ *
+ * NOTE: this is no longer accurate when multiple processors and boards
+ * are selected, newer drivers should not depend on this any more.  Use
+ * either the clocksource/clockevent or get this at run-time by calling
+ * get_clock_tick_rate() (as defined in generic.c).
+ */
 
 #if defined(CONFIG_PXA25x)
 /* PXA250/210 timer base */
index f8a9a62..986d494 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 #include <mach/pxa-regs.h>
-#include <asm/mach-types.h>
 
 /*
  * This is PXA's sched_clock implementation. This has a resolution
@@ -150,18 +149,11 @@ static struct irqaction pxa_ost0_irq = {
 
 static void __init pxa_timer_init(void)
 {
-       unsigned long clock_tick_rate;
+       unsigned long clock_tick_rate = get_clock_tick_rate();
 
        OIER = 0;
        OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3;
 
-       if (cpu_is_pxa25x())
-               clock_tick_rate = 3686400;
-       else if (machine_is_mainstone())
-               clock_tick_rate = 3249600;
-       else
-               clock_tick_rate = 3250000;
-
        set_oscr2ns_scale(clock_tick_rate);
 
        ckevt_pxa_osmr0.mult =
index b70846c..6071182 100644 (file)
 # define __REG(x)      (*((volatile unsigned long *)io_p2v(x)))
 # define __PREG(x)     (io_v2p((unsigned long)&(x)))
 
+static inline unsigned long get_clock_tick_rate(void)
+{
+       return 3686400;
+}
 #else
 
 # define __REG(x)      io_p2v(x)
index 66a9bb8..d26a5f8 100644 (file)
 #include <mach/pxa-regs.h>
 #endif
 
-#define TIMER_FREQ             CLOCK_TICK_RATE
 #define RTC_DEF_DIVIDER                32768 - 1
 #define RTC_DEF_TRIM           0
 
 static unsigned long rtc_freq = 1024;
+static unsigned long timer_freq;
 static struct rtc_time rtc_alarm;
 static DEFINE_SPINLOCK(sa1100_rtc_lock);
 
@@ -157,7 +157,7 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id)
        rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF);
 
        if (rtc_timer1_count == 1)
-               rtc_timer1_count = (rtc_freq * ((1<<30)/(TIMER_FREQ>>2)));
+               rtc_timer1_count = (rtc_freq * ((1 << 30) / (timer_freq >> 2)));
 
        return IRQ_HANDLED;
 }
@@ -166,7 +166,7 @@ static int sa1100_rtc_read_callback(struct device *dev, int data)
 {
        if (data & RTC_PF) {
                /* interpolate missed periods and set match for the next */
-               unsigned long period = TIMER_FREQ/rtc_freq;
+               unsigned long period = timer_freq / rtc_freq;
                unsigned long oscr = OSCR;
                unsigned long osmr1 = OSMR1;
                unsigned long missed = (oscr - osmr1)/period;
@@ -263,7 +263,7 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
                return 0;
        case RTC_PIE_ON:
                spin_lock_irq(&sa1100_rtc_lock);
-               OSMR1 = TIMER_FREQ/rtc_freq + OSCR;
+               OSMR1 = timer_freq / rtc_freq + OSCR;
                OIER |= OIER_E1;
                rtc_timer1_count = 1;
                spin_unlock_irq(&sa1100_rtc_lock);
@@ -271,7 +271,7 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
        case RTC_IRQP_READ:
                return put_user(rtc_freq, (unsigned long *)arg);
        case RTC_IRQP_SET:
-               if (arg < 1 || arg > TIMER_FREQ)
+               if (arg < 1 || arg > timer_freq)
                        return -EINVAL;
                rtc_freq = arg;
                return 0;
@@ -352,6 +352,8 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
 {
        struct rtc_device *rtc;
 
+       timer_freq = get_clock_tick_rate();
+
        /*
         * According to the manual we should be able to let RTTR be zero
         * and then a default diviser for a 32.768KHz clock is used.