X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Farm%2Fmach-ebsa110%2Fcore.c;h=07c556392a0344e9ca16958c4947cdbd06822bf5;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=5c14e04eae1be69e124f8d6b4e3b2d0d00c8c44b;hpb=db216c3d5e4c040e557a50f8f5d35d5c415e8c1c;p=linux-2.6.git diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c index 5c14e04ea..07c556392 100644 --- a/arch/arm/mach-ebsa110/core.c +++ b/arch/arm/mach-ebsa110/core.c @@ -11,6 +11,7 @@ */ #include #include +#include #include #include @@ -26,6 +27,8 @@ #include #include +#include + #define IRQ_MASK 0xfe000000 /* read */ #define IRQ_MSET 0xfe000000 /* write */ #define IRQ_STAT 0xff000000 /* read */ @@ -89,6 +92,103 @@ static void __init ebsa110_map_io(void) iotable_init(ebsa110_io_desc, ARRAY_SIZE(ebsa110_io_desc)); } + +#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 irqreturn_t +ebsa110_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + 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); + + timer_tick(regs); + + return IRQ_HANDLED; +} + +static struct irqaction ebsa110_timer_irq = { + .name = "EBSA110 Timer Tick", + .flags = SA_INTERRUPT, + .handler = ebsa110_timer_interrupt +}; + +/* + * Set up timer interrupt. + */ +static void __init ebsa110_init_time(void) +{ + /* + * 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; + + setup_irq(IRQ_EBSA110_TIMER0, &ebsa110_timer_irq); +} + MACHINE_START(EBSA110, "EBSA110") MAINTAINER("Russell King") BOOT_MEM(0x00000000, 0xe0000000, 0xe0000000) @@ -98,4 +198,5 @@ MACHINE_START(EBSA110, "EBSA110") SOFT_REBOOT MAPIO(ebsa110_map_io) INITIRQ(ebsa110_init_irq) + INITTIME(ebsa110_init_time) MACHINE_END