m68knommu: MCF5307 PIT GENERIC_CLOCKEVENTS support

The PIT code has been changed in order to suppport GENERIC_CLOCKEVENTS.
The priority of the PIT clocksource has been decreased in favor of the
DMA timer.

pit_cycles_per_jiffy become a constant (PIT_CYCLES_PER_JIFFY) because it
is known at compile time and does not change afterwards.

Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
Signed-off-by: Sebastian Siewior <bigeasy@linutronix.de>
Signed-off-by: Greg Ungerer <gerg@uclinux.org>
This commit is contained in:
Sebastian Siewior 2008-04-28 11:43:04 +02:00 committed by Greg Ungerer
parent 6dbeb456ba
commit 2b9a69861c
3 changed files with 91 additions and 13 deletions

View File

@ -66,6 +66,10 @@ config TIME_LOW_RES
bool bool
default y default y
config GENERIC_CLOCKEVENTS
bool
default n
config NO_IOPORT config NO_IOPORT
def_bool y def_bool y
@ -112,11 +116,13 @@ config M5206e
config M520x config M520x
bool "MCF520x" bool "MCF520x"
select GENERIC_CLOCKEVENTS
help help
Freescale Coldfire 5207/5208 processor support. Freescale Coldfire 5207/5208 processor support.
config M523x config M523x
bool "MCF523x" bool "MCF523x"
select GENERIC_CLOCKEVENTS
help help
Freescale Coldfire 5230/1/2/4/5 processor support Freescale Coldfire 5230/1/2/4/5 processor support
@ -142,6 +148,7 @@ config M5275
config M528x config M528x
bool "MCF528x" bool "MCF528x"
select GENERIC_CLOCKEVENTS
help help
Motorola ColdFire 5280/5282 processor support. Motorola ColdFire 5280/5282 processor support.
@ -165,6 +172,7 @@ endchoice
config M527x config M527x
bool bool
depends on (M5271 || M5275) depends on (M5271 || M5275)
select GENERIC_CLOCKEVENTS
default y default y
config COLDFIRE config COLDFIRE
@ -678,6 +686,9 @@ endchoice
if COLDFIRE if COLDFIRE
source "kernel/Kconfig.preempt" source "kernel/Kconfig.preempt"
endif endif
source "kernel/time/Kconfig"
source "mm/Kconfig" source "mm/Kconfig"
endmenu endmenu

View File

@ -33,6 +33,7 @@ static inline int set_rtc_mmss(unsigned long nowtime)
return -1; return -1;
} }
#ifndef CONFIG_GENERIC_CLOCKEVENTS
/* /*
* timer_interrupt() needs to keep up the real-time clock, * timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick * as well as call the "do_timer()" routine every clocktick
@ -54,6 +55,7 @@ irqreturn_t arch_timer_interrupt(int irq, void *dummy)
#endif #endif
return(IRQ_HANDLED); return(IRQ_HANDLED);
} }
#endif
static unsigned long read_rtc_mmss(void) static unsigned long read_rtc_mmss(void)
{ {

View File

@ -18,7 +18,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/clocksource.h> #include <linux/clockchips.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/coldfire.h> #include <asm/coldfire.h>
@ -33,22 +33,86 @@
#define FREQ ((MCF_CLK / 2) / 64) #define FREQ ((MCF_CLK / 2) / 64)
#define TA(a) (MCF_IPSBAR + MCFPIT_BASE1 + (a)) #define TA(a) (MCF_IPSBAR + MCFPIT_BASE1 + (a))
#define INTC0 (MCF_IPSBAR + MCFICM_INTC0) #define INTC0 (MCF_IPSBAR + MCFICM_INTC0)
#define PIT_CYCLES_PER_JIFFY (FREQ / HZ)
static u32 pit_cycles_per_jiffy;
static u32 pit_cnt; 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) static irqreturn_t pit_tick(int irq, void *dummy)
{ {
struct clock_event_device *evt = &cf_pit_clockevent;
u16 pcsr; u16 pcsr;
/* Reset the ColdFire timer */ /* Reset the ColdFire timer */
pcsr = __raw_readw(TA(MCFPIT_PCSR)); pcsr = __raw_readw(TA(MCFPIT_PCSR));
__raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR)); __raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR));
pit_cnt += pit_cycles_per_jiffy; pit_cnt += PIT_CYCLES_PER_JIFFY;
return arch_timer_interrupt(irq, dummy); evt->event_handler(evt);
return IRQ_HANDLED;
} }
/***************************************************************************/ /***************************************************************************/
@ -72,14 +136,14 @@ static cycle_t pit_read_clk(void)
cycles = pit_cnt; cycles = pit_cnt;
local_irq_restore(flags); local_irq_restore(flags);
return cycles + pit_cycles_per_jiffy - pcntr; return cycles + PIT_CYCLES_PER_JIFFY - pcntr;
} }
/***************************************************************************/ /***************************************************************************/
static struct clocksource pit_clk = { static struct clocksource pit_clk = {
.name = "pit", .name = "pit",
.rating = 250, .rating = 100,
.read = pit_read_clk, .read = pit_read_clk,
.shift = 20, .shift = 20,
.mask = CLOCKSOURCE_MASK(32), .mask = CLOCKSOURCE_MASK(32),
@ -92,6 +156,14 @@ void hw_timer_init(void)
{ {
u32 imr; 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); setup_irq(MCFINT_VECBASE + MCFINT_PIT1, &pit_irq);
__raw_writeb(ICR_INTRCONF, INTC0 + MCFINTC_ICR0 + MCFINT_PIT1); __raw_writeb(ICR_INTRCONF, INTC0 + MCFINTC_ICR0 + MCFINT_PIT1);
@ -99,13 +171,6 @@ void hw_timer_init(void)
imr &= ~MCFPIT_IMR_IBIT; imr &= ~MCFPIT_IMR_IBIT;
__raw_writel(imr, INTC0 + MCFPIT_IMR); __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); pit_clk.mult = clocksource_hz2mult(FREQ, pit_clk.shift);
clocksource_register(&pit_clk); clocksource_register(&pit_clk);
} }