forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
m68knommu: switch ColdFire PIT timer to use GENERIC_TIME
Switch the ColdFire PIT timer to using GENERIC_TIME. Signed-off-by: Greg Ungerer <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
- Loading branch information
Showing
1 changed file
with
51 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,9 +3,10 @@ | |
/* | ||
* pit.c -- Freescale ColdFire PIT timer. Currently this type of | ||
* hardware timer only exists in the Freescale ColdFire | ||
* 5270/5271, 5282 and other CPUs. | ||
* 5270/5271, 5282 and 5208 CPUs. No doubt newer ColdFire | ||
* family members will probably use it too. | ||
* | ||
* Copyright (C) 1999-2007, Greg Ungerer ([email protected]) | ||
* Copyright (C) 1999-2008, Greg Ungerer ([email protected]) | ||
* Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com) | ||
*/ | ||
|
||
|
@@ -17,6 +18,7 @@ | |
#include <linux/init.h> | ||
#include <linux/interrupt.h> | ||
#include <linux/irq.h> | ||
#include <linux/clocksource.h> | ||
#include <asm/machdep.h> | ||
#include <asm/io.h> | ||
#include <asm/coldfire.h> | ||
|
@@ -28,70 +30,84 @@ | |
/* | ||
* By default use timer1 as the system clock timer. | ||
*/ | ||
#define FREQ ((MCF_CLK / 2) / 64) | ||
#define TA(a) (MCF_IPSBAR + MCFPIT_BASE1 + (a)) | ||
#define INTC0 (MCF_IPSBAR + MCFICM_INTC0) | ||
|
||
static u32 pit_cycles_per_jiffy; | ||
static u32 pit_cnt; | ||
|
||
/***************************************************************************/ | ||
|
||
static irqreturn_t hw_tick(int irq, void *dummy) | ||
static irqreturn_t pit_tick(int irq, void *dummy) | ||
{ | ||
unsigned short pcsr; | ||
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); | ||
} | ||
|
||
/***************************************************************************/ | ||
|
||
static struct irqaction coldfire_pit_irq = { | ||
static struct irqaction pit_irq = { | ||
.name = "timer", | ||
.flags = IRQF_DISABLED | IRQF_TIMER, | ||
.handler = hw_tick, | ||
.handler = pit_tick, | ||
}; | ||
|
||
void hw_timer_init(void) | ||
/***************************************************************************/ | ||
|
||
static cycle_t pit_read_clk(void) | ||
{ | ||
volatile unsigned char *icrp; | ||
volatile unsigned long *imrp; | ||
unsigned long flags; | ||
u32 cycles; | ||
u16 pcntr; | ||
|
||
setup_irq(MCFINT_VECBASE + MCFINT_PIT1, &coldfire_pit_irq); | ||
local_irq_save(flags); | ||
pcntr = __raw_readw(TA(MCFPIT_PCNTR)); | ||
cycles = pit_cnt; | ||
local_irq_restore(flags); | ||
|
||
icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 + | ||
MCFINTC_ICR0 + MCFINT_PIT1); | ||
*icrp = ICR_INTRCONF; | ||
return cycles + pit_cycles_per_jiffy - pcntr; | ||
} | ||
|
||
imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR); | ||
*imrp &= ~MCFPIT_IMR_IBIT; | ||
/***************************************************************************/ | ||
|
||
/* Set up PIT timer 1 as poll clock */ | ||
__raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR)); | ||
__raw_writew(((MCF_CLK / 2) / 64) / HZ, TA(MCFPIT_PMR)); | ||
__raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW | | ||
MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR)); | ||
} | ||
static struct clocksource pit_clk = { | ||
.name = "pit", | ||
.rating = 250, | ||
.read = pit_read_clk, | ||
.shift = 20, | ||
.mask = CLOCKSOURCE_MASK(32), | ||
.flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
}; | ||
|
||
/***************************************************************************/ | ||
|
||
unsigned long hw_timer_offset(void) | ||
void hw_timer_init(void) | ||
{ | ||
volatile unsigned long *ipr; | ||
unsigned long pmr, pcntr, offset; | ||
u32 imr; | ||
|
||
ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR); | ||
setup_irq(MCFINT_VECBASE + MCFINT_PIT1, &pit_irq); | ||
|
||
pmr = __raw_readw(TA(MCFPIT_PMR)); | ||
pcntr = __raw_readw(TA(MCFPIT_PCNTR)); | ||
__raw_writeb(ICR_INTRCONF, INTC0 + MCFINTC_ICR0 + MCFINT_PIT1); | ||
imr = __raw_readl(INTC0 + MCFPIT_IMR); | ||
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)); | ||
|
||
/* | ||
* If we are still in the first half of the upcount and a | ||
* timer interrupt is pending, then add on a ticks worth of time. | ||
*/ | ||
offset = ((pmr - pcntr) * (1000000 / HZ)) / pmr; | ||
if ((offset < (1000000 / HZ / 2)) && (*ipr & MCFPIT_IMR_IBIT)) | ||
offset += 1000000 / HZ; | ||
return offset; | ||
pit_clk.mult = clocksource_hz2mult(FREQ, pit_clk.shift); | ||
clocksource_register(&pit_clk); | ||
} | ||
|
||
/***************************************************************************/ |