Commit 6769717d5d51596618f6b143008d8ace11ec8a69

Authored by Eric Miao
1 parent 9f1442bbf9

[ARM] rtc-sa1100: don't assume CLOCK_TICK_RATE to be a constant

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>

Showing 6 changed files with 38 additions and 14 deletions Side-by-side Diff

arch/arm/mach-pxa/generic.c
... ... @@ -24,6 +24,7 @@
24 24 #include <asm/system.h>
25 25 #include <asm/pgtable.h>
26 26 #include <asm/mach/map.h>
  27 +#include <asm/mach-types.h>
27 28  
28 29 #include <mach/pxa-regs.h>
29 30 #include <mach/reset.h>
... ... @@ -38,6 +39,21 @@
38 39 if (cpu_is_pxa3xx())
39 40 pxa3xx_clear_reset_status(mask);
40 41 }
  42 +
  43 +unsigned long get_clock_tick_rate(void)
  44 +{
  45 + unsigned long clock_tick_rate;
  46 +
  47 + if (cpu_is_pxa25x())
  48 + clock_tick_rate = 3686400;
  49 + else if (machine_is_mainstone())
  50 + clock_tick_rate = 3249600;
  51 + else
  52 + clock_tick_rate = 3250000;
  53 +
  54 + return clock_tick_rate;
  55 +}
  56 +EXPORT_SYMBOL(get_clock_tick_rate);
41 57  
42 58 /*
43 59 * Get the clock frequency as reflected by CCCR and the turbo flag.
arch/arm/mach-pxa/include/mach/hardware.h
... ... @@ -291,6 +291,8 @@
291 291 */
292 292 extern unsigned int get_memclk_frequency_10khz(void);
293 293  
  294 +/* return the clock tick rate of the OS timer */
  295 +extern unsigned long get_clock_tick_rate(void);
294 296 #endif
295 297  
296 298 #if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
arch/arm/mach-pxa/include/mach/timex.h
... ... @@ -10,6 +10,14 @@
10 10 * published by the Free Software Foundation.
11 11 */
12 12  
  13 +/* Various drivers are still using the constant of CLOCK_TICK_RATE, for
  14 + * those drivers to at least work, the definition is provided here.
  15 + *
  16 + * NOTE: this is no longer accurate when multiple processors and boards
  17 + * are selected, newer drivers should not depend on this any more. Use
  18 + * either the clocksource/clockevent or get this at run-time by calling
  19 + * get_clock_tick_rate() (as defined in generic.c).
  20 + */
13 21  
14 22 #if defined(CONFIG_PXA25x)
15 23 /* PXA250/210 timer base */
arch/arm/mach-pxa/time.c
... ... @@ -23,7 +23,6 @@
23 23 #include <asm/mach/irq.h>
24 24 #include <asm/mach/time.h>
25 25 #include <mach/pxa-regs.h>
26   -#include <asm/mach-types.h>
27 26  
28 27 /*
29 28 * This is PXA's sched_clock implementation. This has a resolution
30 29  
... ... @@ -150,17 +149,10 @@
150 149  
151 150 static void __init pxa_timer_init(void)
152 151 {
153   - unsigned long clock_tick_rate;
  152 + unsigned long clock_tick_rate = get_clock_tick_rate();
154 153  
155 154 OIER = 0;
156 155 OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3;
157   -
158   - if (cpu_is_pxa25x())
159   - clock_tick_rate = 3686400;
160   - else if (machine_is_mainstone())
161   - clock_tick_rate = 3249600;
162   - else
163   - clock_tick_rate = 3250000;
164 156  
165 157 set_oscr2ns_scale(clock_tick_rate);
166 158  
arch/arm/mach-sa1100/include/mach/hardware.h
... ... @@ -59,6 +59,10 @@
59 59 # define __REG(x) (*((volatile unsigned long *)io_p2v(x)))
60 60 # define __PREG(x) (io_v2p((unsigned long)&(x)))
61 61  
  62 +static inline unsigned long get_clock_tick_rate(void)
  63 +{
  64 + return 3686400;
  65 +}
62 66 #else
63 67  
64 68 # define __REG(x) io_p2v(x)
drivers/rtc/rtc-sa1100.c
... ... @@ -38,11 +38,11 @@
38 38 #include <mach/pxa-regs.h>
39 39 #endif
40 40  
41   -#define TIMER_FREQ CLOCK_TICK_RATE
42 41 #define RTC_DEF_DIVIDER 32768 - 1
43 42 #define RTC_DEF_TRIM 0
44 43  
45 44 static unsigned long rtc_freq = 1024;
  45 +static unsigned long timer_freq;
46 46 static struct rtc_time rtc_alarm;
47 47 static DEFINE_SPINLOCK(sa1100_rtc_lock);
48 48  
... ... @@ -157,7 +157,7 @@
157 157 rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF);
158 158  
159 159 if (rtc_timer1_count == 1)
160   - rtc_timer1_count = (rtc_freq * ((1<<30)/(TIMER_FREQ>>2)));
  160 + rtc_timer1_count = (rtc_freq * ((1 << 30) / (timer_freq >> 2)));
161 161  
162 162 return IRQ_HANDLED;
163 163 }
... ... @@ -166,7 +166,7 @@
166 166 {
167 167 if (data & RTC_PF) {
168 168 /* interpolate missed periods and set match for the next */
169   - unsigned long period = TIMER_FREQ/rtc_freq;
  169 + unsigned long period = timer_freq / rtc_freq;
170 170 unsigned long oscr = OSCR;
171 171 unsigned long osmr1 = OSMR1;
172 172 unsigned long missed = (oscr - osmr1)/period;
... ... @@ -263,7 +263,7 @@
263 263 return 0;
264 264 case RTC_PIE_ON:
265 265 spin_lock_irq(&sa1100_rtc_lock);
266   - OSMR1 = TIMER_FREQ/rtc_freq + OSCR;
  266 + OSMR1 = timer_freq / rtc_freq + OSCR;
267 267 OIER |= OIER_E1;
268 268 rtc_timer1_count = 1;
269 269 spin_unlock_irq(&sa1100_rtc_lock);
... ... @@ -271,7 +271,7 @@
271 271 case RTC_IRQP_READ:
272 272 return put_user(rtc_freq, (unsigned long *)arg);
273 273 case RTC_IRQP_SET:
274   - if (arg < 1 || arg > TIMER_FREQ)
  274 + if (arg < 1 || arg > timer_freq)
275 275 return -EINVAL;
276 276 rtc_freq = arg;
277 277 return 0;
... ... @@ -351,6 +351,8 @@
351 351 static int sa1100_rtc_probe(struct platform_device *pdev)
352 352 {
353 353 struct rtc_device *rtc;
  354 +
  355 + timer_freq = get_clock_tick_rate();
354 356  
355 357 /*
356 358 * According to the manual we should be able to let RTTR be zero