diff options
-rw-r--r-- | arch/m68knommu/Kconfig | 11 | ||||
-rw-r--r-- | arch/m68knommu/kernel/time.c | 2 | ||||
-rw-r--r-- | arch/m68knommu/platform/coldfire/pit.c | 91 |
3 files changed, 91 insertions, 13 deletions
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig index bfd3530..2e7515e 100644 --- a/arch/m68knommu/Kconfig +++ b/arch/m68knommu/Kconfig @@ -66,6 +66,10 @@ config TIME_LOW_RES bool default y +config GENERIC_CLOCKEVENTS + bool + default n + config NO_IOPORT def_bool y @@ -112,11 +116,13 @@ config M5206e config M520x bool "MCF520x" + select GENERIC_CLOCKEVENTS help Freescale Coldfire 5207/5208 processor support. config M523x bool "MCF523x" + select GENERIC_CLOCKEVENTS help Freescale Coldfire 5230/1/2/4/5 processor support @@ -142,6 +148,7 @@ config M5275 config M528x bool "MCF528x" + select GENERIC_CLOCKEVENTS help Motorola ColdFire 5280/5282 processor support. @@ -165,6 +172,7 @@ endchoice config M527x bool depends on (M5271 || M5275) + select GENERIC_CLOCKEVENTS default y config COLDFIRE @@ -678,6 +686,9 @@ endchoice if COLDFIRE source "kernel/Kconfig.preempt" endif + +source "kernel/time/Kconfig" + source "mm/Kconfig" endmenu diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c index 67944aa..d182b2f 100644 --- a/arch/m68knommu/kernel/time.c +++ b/arch/m68knommu/kernel/time.c @@ -33,6 +33,7 @@ static inline int set_rtc_mmss(unsigned long nowtime) return -1; } +#ifndef CONFIG_GENERIC_CLOCKEVENTS /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick @@ -54,6 +55,7 @@ irqreturn_t arch_timer_interrupt(int irq, void *dummy) #endif return(IRQ_HANDLED); } +#endif static unsigned long read_rtc_mmss(void) { diff --git a/arch/m68knommu/platform/coldfire/pit.c b/arch/m68knommu/platform/coldfire/pit.c index 4290638..c5b9167 100644 --- a/arch/m68knommu/platform/coldfire/pit.c +++ b/arch/m68knommu/platform/coldfire/pit.c @@ -18,7 +18,7 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> -#include <linux/clocksource.h> +#include <linux/clockchips.h> #include <asm/machdep.h> #include <asm/io.h> #include <asm/coldfire.h> @@ -33,22 +33,86 @@ #define FREQ ((MCF_CLK / 2) / 64) #define TA(a) (MCF_IPSBAR + MCFPIT_BASE1 + (a)) #define INTC0 (MCF_IPSBAR + MCFICM_INTC0) +#define PIT_CYCLES_PER_JIFFY (FREQ / HZ) -static u32 pit_cycles_per_jiffy; static u32 pit_cnt; +/* + * Initialize the PIT timer. + * + * This is also called after resume to bring the PIT into operation again. + */ + +static void init_cf_pit_timer(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + + __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR)); + __raw_writew(PIT_CYCLES_PER_JIFFY, TA(MCFPIT_PMR)); + __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | \ + MCFPIT_PCSR_OVW | MCFPIT_PCSR_RLD | \ + MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR)); + break; + + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + + __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR)); + break; + + case CLOCK_EVT_MODE_ONESHOT: + + __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR)); + __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | \ + MCFPIT_PCSR_OVW | MCFPIT_PCSR_CLK64, \ + TA(MCFPIT_PCSR)); + break; + + case CLOCK_EVT_MODE_RESUME: + /* Nothing to do here */ + break; + } +} + +/* + * Program the next event in oneshot mode + * + * Delta is given in PIT ticks + */ +static int cf_pit_next_event(unsigned long delta, + struct clock_event_device *evt) +{ + __raw_writew(delta, TA(MCFPIT_PMR)); + return 0; +} + +struct clock_event_device cf_pit_clockevent = { + .name = "pit", + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_mode = init_cf_pit_timer, + .set_next_event = cf_pit_next_event, + .shift = 32, + .irq = MCFINT_VECBASE + MCFINT_PIT1, +}; + + + /***************************************************************************/ static irqreturn_t pit_tick(int irq, void *dummy) { + struct clock_event_device *evt = &cf_pit_clockevent; u16 pcsr; /* Reset the ColdFire timer */ pcsr = __raw_readw(TA(MCFPIT_PCSR)); __raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR)); - pit_cnt += pit_cycles_per_jiffy; - return arch_timer_interrupt(irq, dummy); + pit_cnt += PIT_CYCLES_PER_JIFFY; + evt->event_handler(evt); + return IRQ_HANDLED; } /***************************************************************************/ @@ -72,14 +136,14 @@ static cycle_t pit_read_clk(void) cycles = pit_cnt; local_irq_restore(flags); - return cycles + pit_cycles_per_jiffy - pcntr; + return cycles + PIT_CYCLES_PER_JIFFY - pcntr; } /***************************************************************************/ static struct clocksource pit_clk = { .name = "pit", - .rating = 250, + .rating = 100, .read = pit_read_clk, .shift = 20, .mask = CLOCKSOURCE_MASK(32), @@ -92,6 +156,14 @@ void hw_timer_init(void) { u32 imr; + cf_pit_clockevent.cpumask = cpumask_of_cpu(smp_processor_id()); + cf_pit_clockevent.mult = div_sc(FREQ, NSEC_PER_SEC, 32); + cf_pit_clockevent.max_delta_ns = + clockevent_delta2ns(0xFFFF, &cf_pit_clockevent); + cf_pit_clockevent.min_delta_ns = + clockevent_delta2ns(0x3f, &cf_pit_clockevent); + clockevents_register_device(&cf_pit_clockevent); + setup_irq(MCFINT_VECBASE + MCFINT_PIT1, &pit_irq); __raw_writeb(ICR_INTRCONF, INTC0 + MCFINTC_ICR0 + MCFINT_PIT1); @@ -99,13 +171,6 @@ void hw_timer_init(void) imr &= ~MCFPIT_IMR_IBIT; __raw_writel(imr, INTC0 + MCFPIT_IMR); - /* Set up PIT timer 1 as poll clock */ - pit_cycles_per_jiffy = FREQ / HZ; - __raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR)); - __raw_writew(pit_cycles_per_jiffy, TA(MCFPIT_PMR)); - __raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW | - MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR)); - pit_clk.mult = clocksource_hz2mult(FREQ, pit_clk.shift); clocksource_register(&pit_clk); } |