Commit aa2cbc19 authored by Russell King's avatar Russell King

[ARM] Remove 200Hz -> 100Hz conversion for ebsa110 timer.

We now really run the ebsa110 kernel timer at 200Hz, and convert
where necessary to 100Hz for user space.
parent bc870c88
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# Object file lists. # Object file lists.
obj-y := core.o io.o time.o obj-y := core.o io.o
obj-m := obj-m :=
obj-n := obj-n :=
obj- := obj- :=
......
/*
* linux/arch/arm/mach-ebsa110/time.c
*
* Copyright (C) 2001 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <asm/io.h>
#define PIT_CTRL (PIT_BASE + 0x0d)
#define PIT_T2 (PIT_BASE + 0x09)
#define PIT_T1 (PIT_BASE + 0x05)
#define PIT_T0 (PIT_BASE + 0x01)
/*
* This is the rate at which your MCLK signal toggles (in Hz)
* This was measured on a 10 digit frequency counter sampling
* over 1 second.
*/
#define MCLK 47894000
/*
* This is the rate at which the PIT timers get clocked
*/
#define CLKBY7 (MCLK / 7)
/*
* If CLKBY7 is larger than this, then we must do software
* division of the timer interrupt.
*/
#if CLKBY7 > 6553500
#define DIVISOR 2
#else
#define DIVISOR 1
#endif
/*
* This is the counter value
*/
#define COUNT ((CLKBY7 + (DIVISOR * HZ / 2)) / (DIVISOR * HZ))
extern unsigned long (*gettimeoffset)(void);
static unsigned long divisor;
/*
* Get the time offset from the system PIT. Note that if we have missed an
* interrupt, then the PIT counter will roll over (ie, be negative).
* This actually works out to be convenient.
*/
static unsigned long ebsa110_gettimeoffset(void)
{
unsigned long offset, count;
__raw_writeb(0x40, PIT_CTRL);
count = __raw_readb(PIT_T1);
count |= __raw_readb(PIT_T1) << 8;
/*
* If count > COUNT, make the number negative.
*/
if (count > COUNT)
count |= 0xffff0000;
offset = COUNT * (DIVISOR - divisor);
offset -= count;
/*
* `offset' is in units of timer counts. Convert
* offset to units of microseconds.
*/
offset = offset * (1000000 / HZ) / (COUNT * DIVISOR);
return offset;
}
int ebsa110_reset_timer(void)
{
u32 count;
/* latch and read timer 1 */
__raw_writeb(0x40, PIT_CTRL);
count = __raw_readb(PIT_T1);
count |= __raw_readb(PIT_T1) << 8;
count += COUNT;
__raw_writeb(count & 0xff, PIT_T1);
__raw_writeb(count >> 8, PIT_T1);
if (divisor == 0)
divisor = DIVISOR;
divisor -= 1;
return divisor;
}
void __init ebsa110_setup_timer(void)
{
/*
* Timer 1, mode 2, LSB/MSB
*/
__raw_writeb(0x70, PIT_CTRL);
__raw_writeb(COUNT & 0xff, PIT_T1);
__raw_writeb(COUNT >> 8, PIT_T1);
divisor = DIVISOR - 1;
gettimeoffset = ebsa110_gettimeoffset;
}
/* /*
* linux/include/asm-arm/arch-ebsa110/param.h * linux/include/asm-arm/arch-ebsa110/param.h
*/ */
#define __KERNEL_HZ 200
...@@ -17,17 +17,80 @@ ...@@ -17,17 +17,80 @@
*/ */
#include <asm/leds.h> #include <asm/leds.h>
#include <asm/io.h>
extern int ebsa110_reset_timer(void); extern unsigned long (*gettimeoffset)(void);
extern void ebsa110_setup_timer(void);
#define PIT_CTRL (PIT_BASE + 0x0d)
#define PIT_T2 (PIT_BASE + 0x09)
#define PIT_T1 (PIT_BASE + 0x05)
#define PIT_T0 (PIT_BASE + 0x01)
/*
* This is the rate at which your MCLK signal toggles (in Hz)
* This was measured on a 10 digit frequency counter sampling
* over 1 second.
*/
#define MCLK 47894000
/*
* This is the rate at which the PIT timers get clocked
*/
#define CLKBY7 (MCLK / 7)
/*
* This is the counter value. We tick at 200Hz on this platform.
*/
#define COUNT ((CLKBY7 + (HZ / 2)) / HZ)
/*
* Get the time offset from the system PIT. Note that if we have missed an
* interrupt, then the PIT counter will roll over (ie, be negative).
* This actually works out to be convenient.
*/
static unsigned long ebsa110_gettimeoffset(void)
{
unsigned long offset, count;
__raw_writeb(0x40, PIT_CTRL);
count = __raw_readb(PIT_T1);
count |= __raw_readb(PIT_T1) << 8;
/*
* If count > COUNT, make the number negative.
*/
if (count > COUNT)
count |= 0xffff0000;
offset = COUNT;
offset -= count;
/*
* `offset' is in units of timer counts. Convert
* offset to units of microseconds.
*/
offset = offset * (1000000 / HZ) / COUNT;
return offset;
}
static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
if (ebsa110_reset_timer()) { u32 count;
do_leds();
do_timer(regs); /* latch and read timer 1 */
do_profile(regs); __raw_writeb(0x40, PIT_CTRL);
} count = __raw_readb(PIT_T1);
count |= __raw_readb(PIT_T1) << 8;
count += COUNT;
__raw_writeb(count & 0xff, PIT_T1);
__raw_writeb(count >> 8, PIT_T1);
do_leds();
do_timer(regs);
do_profile(regs);
} }
/* /*
...@@ -35,7 +98,14 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -35,7 +98,14 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/ */
void __init time_init(void) void __init time_init(void)
{ {
ebsa110_setup_timer(); /*
* Timer 1, mode 2, LSB/MSB
*/
__raw_writeb(0x70, PIT_CTRL);
__raw_writeb(COUNT & 0xff, PIT_T1);
__raw_writeb(COUNT >> 8, PIT_T1);
gettimeoffset = ebsa110_gettimeoffset;
timer_irq.handler = timer_interrupt; timer_irq.handler = timer_interrupt;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment