diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2008-01-28 13:21:38 +0000 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-01-28 13:21:38 +0000 |
commit | 0ff66f0c7a5f1f4f5a0d91341b6f71fd2a49f0fa (patch) | |
tree | 7c4d74a76bf4f49e87d769c236fdd2db77fb241d /arch/arm/mach-pxa/time.c | |
parent | c00d4ffdbace1bdc9fdd888e4ba6d207ffa3b679 (diff) | |
parent | 4e4fc05a2b6e7bd2e0facd96e0c18dceb34d9349 (diff) |
Merge branch 'pxa-plat' into devel
* pxa-plat: (53 commits)
[ARM] 4762/1: Basic support for Toradex Colibri module
[ARM] pxa: fix mci_init functions returning -1
[ARM] 4737/1: Refactor corgi_lcd to improve readability + bugfix
[ARM] 4747/1: pcm027: support for pcm990 baseboard for phyCORE-PXA270
[ARM] 4746/1: pcm027: network support for phyCORE-PXA270
[ARM] 4745/1: pcm027: default configuration
[ARM] 4744/1: pcm027: add support for phyCORE-PXA270 CPU module
[NET] smc91x: Make smc91x use IRQ resource trigger flags
[ARM] pxa: add default config for littleton
[ARM] pxa: add basic support for Littleton (PXA3xx Form Factor Platform)
[ARM] 4664/1: Add basic support for HTC Magician PDA phones
[ARM] 4649/1: Base support for pxa-based Toshiba e-series PDAs.
[ARM] pxa: skip registers saving/restoring if entering standby mode
[ARM] pxa: fix PXA27x resume
[ARM] pxa: Avoid fiddling with CKEN register on suspend
[ARM] pxa: Add PXA3 standby code hooked into the IRQ wake scheme
[ARM] pxa: Add zylonite MFP wakeup configurations
[ARM] pxa: program MFPs for low power mode when suspending
[ARM] pxa: make MFP configuration processor independent
[ARM] pxa: remove un-used pxa3xx_mfp_set_xxx() functions
...
Conflicts:
arch/arm/mach-pxa/ssp.c
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-pxa/time.c')
-rw-r--r-- | arch/arm/mach-pxa/time.c | 84 |
1 files changed, 21 insertions, 63 deletions
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index fbfa1920353d..7b7c0179795b 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -59,55 +59,17 @@ unsigned long long sched_clock(void) } +#define MIN_OSCR_DELTA 16 + static irqreturn_t pxa_ost0_interrupt(int irq, void *dev_id) { - int next_match; struct clock_event_device *c = dev_id; - if (c->mode == CLOCK_EVT_MODE_ONESHOT) { - /* Disarm the compare/match, signal the event. */ - OIER &= ~OIER_E0; - OSSR = OSSR_M0; - c->event_handler(c); - } else if (c->mode == CLOCK_EVT_MODE_PERIODIC) { - /* Call the event handler as many times as necessary - * to recover missed events, if any (if we update - * OSMR0 and OSCR0 is still ahead of us, we've missed - * the event). As we're dealing with that, re-arm the - * compare/match for the next event. - * - * HACK ALERT: - * - * There's a latency between the instruction that - * writes to OSMR0 and the actual commit to the - * physical hardware, because the CPU doesn't (have - * to) run at bus speed, there's a write buffer - * between the CPU and the bus, etc. etc. So if the - * target OSCR0 is "very close", to the OSMR0 load - * value, the update to OSMR0 might not get to the - * hardware in time and we'll miss that interrupt. - * - * To be safe, if the new OSMR0 is "very close" to the - * target OSCR0 value, we call the event_handler as - * though the event actually happened. According to - * Nico's comment in the previous version of this - * code, experience has shown that 6 OSCR ticks is - * "very close" but he went with 8. We will use 16, - * based on the results of testing on PXA270. - * - * To be doubly sure, we also tell clkevt via - * clockevents_register_device() not to ask for - * anything that might put us "very close". - */ -#define MIN_OSCR_DELTA 16 - do { - OSSR = OSSR_M0; - next_match = (OSMR0 += LATCH); - c->event_handler(c); - } while (((signed long)(next_match - OSCR) <= MIN_OSCR_DELTA) - && (c->mode == CLOCK_EVT_MODE_PERIODIC)); - } + /* Disarm the compare/match, signal the event. */ + OIER &= ~OIER_E0; + OSSR = OSSR_M0; + c->event_handler(c); return IRQ_HANDLED; } @@ -133,14 +95,6 @@ pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) unsigned long irqflags; switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - raw_local_irq_save(irqflags); - OSSR = OSSR_M0; - OIER |= OIER_E0; - OSMR0 = OSCR + LATCH; - raw_local_irq_restore(irqflags); - break; - case CLOCK_EVT_MODE_ONESHOT: raw_local_irq_save(irqflags); OIER &= ~OIER_E0; @@ -158,13 +112,14 @@ pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) break; case CLOCK_EVT_MODE_RESUME: + case CLOCK_EVT_MODE_PERIODIC: break; } } static struct clock_event_device ckevt_pxa_osmr0 = { .name = "osmr0", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .features = CLOCK_EVT_FEAT_ONESHOT, .shift = 32, .rating = 200, .cpumask = CPU_MASK_CPU0, @@ -214,7 +169,7 @@ static void __init pxa_timer_init(void) ckevt_pxa_osmr0.max_delta_ns = clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0); ckevt_pxa_osmr0.min_delta_ns = - clockevent_delta2ns(MIN_OSCR_DELTA, &ckevt_pxa_osmr0) + 1; + clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_pxa_osmr0) + 1; cksrc_pxa_oscr0.mult = clocksource_hz2mult(clock_tick_rate, cksrc_pxa_oscr0.shift); @@ -226,7 +181,7 @@ static void __init pxa_timer_init(void) } #ifdef CONFIG_PM -static unsigned long osmr[4], oier; +static unsigned long osmr[4], oier, oscr; static void pxa_timer_suspend(void) { @@ -235,23 +190,26 @@ static void pxa_timer_suspend(void) osmr[2] = OSMR2; osmr[3] = OSMR3; oier = OIER; + oscr = OSCR; } static void pxa_timer_resume(void) { + /* + * Ensure that we have at least MIN_OSCR_DELTA between match + * register 0 and the OSCR, to guarantee that we will receive + * the one-shot timer interrupt. We adjust OSMR0 in preference + * to OSCR to guarantee that OSCR is monotonically incrementing. + */ + if (osmr[0] - oscr < MIN_OSCR_DELTA) + osmr[0] += MIN_OSCR_DELTA; + OSMR0 = osmr[0]; OSMR1 = osmr[1]; OSMR2 = osmr[2]; OSMR3 = osmr[3]; OIER = oier; - - /* - * OSCR0 is the system timer, which has to increase - * monotonically until it rolls over in hardware. The value - * (OSMR0 - LATCH) is OSCR0 at the most recent system tick, - * which is a handy value to restore to OSCR0. - */ - OSCR = OSMR0 - LATCH; + OSCR = oscr; } #else #define pxa_timer_suspend NULL |