[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>
This commit is contained in:
Родитель
9f1442bbf9
Коммит
6769717d5d
|
@ -24,6 +24,7 @@
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/mach/map.h>
|
#include <asm/mach/map.h>
|
||||||
|
#include <asm/mach-types.h>
|
||||||
|
|
||||||
#include <mach/pxa-regs.h>
|
#include <mach/pxa-regs.h>
|
||||||
#include <mach/reset.h>
|
#include <mach/reset.h>
|
||||||
|
@ -39,6 +40,21 @@ void clear_reset_status(unsigned int mask)
|
||||||
pxa3xx_clear_reset_status(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.
|
* Get the clock frequency as reflected by CCCR and the turbo flag.
|
||||||
* We assume these values have been applied via a fcs.
|
* We assume these values have been applied via a fcs.
|
||||||
|
|
|
@ -291,6 +291,8 @@
|
||||||
*/
|
*/
|
||||||
extern unsigned int get_memclk_frequency_10khz(void);
|
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
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
|
#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
|
||||||
|
|
|
@ -10,6 +10,14 @@
|
||||||
* published by the Free Software Foundation.
|
* 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)
|
#if defined(CONFIG_PXA25x)
|
||||||
/* PXA250/210 timer base */
|
/* PXA250/210 timer base */
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
#include <asm/mach/irq.h>
|
#include <asm/mach/irq.h>
|
||||||
#include <asm/mach/time.h>
|
#include <asm/mach/time.h>
|
||||||
#include <mach/pxa-regs.h>
|
#include <mach/pxa-regs.h>
|
||||||
#include <asm/mach-types.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is PXA's sched_clock implementation. This has a resolution
|
* 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)
|
static void __init pxa_timer_init(void)
|
||||||
{
|
{
|
||||||
unsigned long clock_tick_rate;
|
unsigned long clock_tick_rate = get_clock_tick_rate();
|
||||||
|
|
||||||
OIER = 0;
|
OIER = 0;
|
||||||
OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3;
|
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);
|
set_oscr2ns_scale(clock_tick_rate);
|
||||||
|
|
||||||
ckevt_pxa_osmr0.mult =
|
ckevt_pxa_osmr0.mult =
|
||||||
|
|
|
@ -59,6 +59,10 @@
|
||||||
# define __REG(x) (*((volatile unsigned long *)io_p2v(x)))
|
# define __REG(x) (*((volatile unsigned long *)io_p2v(x)))
|
||||||
# define __PREG(x) (io_v2p((unsigned long)&(x)))
|
# define __PREG(x) (io_v2p((unsigned long)&(x)))
|
||||||
|
|
||||||
|
static inline unsigned long get_clock_tick_rate(void)
|
||||||
|
{
|
||||||
|
return 3686400;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
# define __REG(x) io_p2v(x)
|
# define __REG(x) io_p2v(x)
|
||||||
|
|
|
@ -38,11 +38,11 @@
|
||||||
#include <mach/pxa-regs.h>
|
#include <mach/pxa-regs.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TIMER_FREQ CLOCK_TICK_RATE
|
|
||||||
#define RTC_DEF_DIVIDER 32768 - 1
|
#define RTC_DEF_DIVIDER 32768 - 1
|
||||||
#define RTC_DEF_TRIM 0
|
#define RTC_DEF_TRIM 0
|
||||||
|
|
||||||
static unsigned long rtc_freq = 1024;
|
static unsigned long rtc_freq = 1024;
|
||||||
|
static unsigned long timer_freq;
|
||||||
static struct rtc_time rtc_alarm;
|
static struct rtc_time rtc_alarm;
|
||||||
static DEFINE_SPINLOCK(sa1100_rtc_lock);
|
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);
|
rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF);
|
||||||
|
|
||||||
if (rtc_timer1_count == 1)
|
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;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ static int sa1100_rtc_read_callback(struct device *dev, int data)
|
||||||
{
|
{
|
||||||
if (data & RTC_PF) {
|
if (data & RTC_PF) {
|
||||||
/* interpolate missed periods and set match for the next */
|
/* 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 oscr = OSCR;
|
||||||
unsigned long osmr1 = OSMR1;
|
unsigned long osmr1 = OSMR1;
|
||||||
unsigned long missed = (oscr - osmr1)/period;
|
unsigned long missed = (oscr - osmr1)/period;
|
||||||
|
@ -263,7 +263,7 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
|
||||||
return 0;
|
return 0;
|
||||||
case RTC_PIE_ON:
|
case RTC_PIE_ON:
|
||||||
spin_lock_irq(&sa1100_rtc_lock);
|
spin_lock_irq(&sa1100_rtc_lock);
|
||||||
OSMR1 = TIMER_FREQ/rtc_freq + OSCR;
|
OSMR1 = timer_freq / rtc_freq + OSCR;
|
||||||
OIER |= OIER_E1;
|
OIER |= OIER_E1;
|
||||||
rtc_timer1_count = 1;
|
rtc_timer1_count = 1;
|
||||||
spin_unlock_irq(&sa1100_rtc_lock);
|
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:
|
case RTC_IRQP_READ:
|
||||||
return put_user(rtc_freq, (unsigned long *)arg);
|
return put_user(rtc_freq, (unsigned long *)arg);
|
||||||
case RTC_IRQP_SET:
|
case RTC_IRQP_SET:
|
||||||
if (arg < 1 || arg > TIMER_FREQ)
|
if (arg < 1 || arg > timer_freq)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
rtc_freq = arg;
|
rtc_freq = arg;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -352,6 +352,8 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct rtc_device *rtc;
|
struct rtc_device *rtc;
|
||||||
|
|
||||||
|
timer_freq = get_clock_tick_rate();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* According to the manual we should be able to let RTTR be zero
|
* 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.
|
* and then a default diviser for a 32.768KHz clock is used.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче