[PATCH] ARM: Convert ARM timer implementations to use readl/writel
authorRussell King <rmk@dyn-67.arm.linux.org.uk>
Wed, 29 Jun 2005 14:15:54 +0000 (15:15 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Wed, 29 Jun 2005 14:15:54 +0000 (15:15 +0100)
Convert ARMs timer implementations to use readl/writel instead of accessing
the registers via a struct.

People have recently asked if accessing timers via a structure is the
"right way" and its not the Linux way.  So fix this code to conform to
"The Linux Way"(tm).

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm/mach-integrator/core.c
arch/arm/mach-versatile/core.c
include/asm-arm/hardware/arm_timer.h [new file with mode: 0644]

index 9222e57..797c7fd 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/hardware/amba.h>
+#include <asm/hardware/arm_timer.h>
 #include <asm/arch/cm.h>
 #include <asm/system.h>
 #include <asm/leds.h>
@@ -156,16 +157,6 @@ EXPORT_SYMBOL(cm_control);
 #define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
 #endif
 
-/*
- * What does it look like?
- */
-typedef struct TimerStruct {
-       unsigned long TimerLoad;
-       unsigned long TimerValue;
-       unsigned long TimerControl;
-       unsigned long TimerClear;
-} TimerStruct_t;
-
 static unsigned long timer_reload;
 
 /*
@@ -174,7 +165,6 @@ static unsigned long timer_reload;
  */
 unsigned long integrator_gettimeoffset(void)
 {
-       volatile TimerStruct_t *timer1 = (TimerStruct_t *)TIMER1_VA_BASE;
        unsigned long ticks1, ticks2, status;
 
        /*
@@ -183,11 +173,11 @@ unsigned long integrator_gettimeoffset(void)
         * an interrupt.  We get around this by ensuring that the
         * counter has not reloaded between our two reads.
         */
-       ticks2 = timer1->TimerValue & 0xffff;
+       ticks2 = readl(TIMER1_VA_BASE + TIMER_VALUE) & 0xffff;
        do {
                ticks1 = ticks2;
                status = __raw_readl(VA_IC_BASE + IRQ_RAW_STATUS);
-               ticks2 = timer1->TimerValue & 0xffff;
+               ticks2 = readl(TIMER1_VA_BASE + TIMER_VALUE) & 0xffff;
        } while (ticks2 > ticks1);
 
        /*
@@ -213,20 +203,19 @@ unsigned long integrator_gettimeoffset(void)
 static irqreturn_t
 integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
-
        write_seqlock(&xtime_lock);
 
        /*
         * clear the interrupt
         */
-       timer1->TimerClear = 1;
+       writel(1, TIMER1_VA_BASE + TIMER_INTCLR);
 
        /*
         * the clock tick routines are only processed on the
         * primary CPU
         */
        if (hard_smp_processor_id() == 0) {
+               nmi_tick();
                timer_tick(regs);
 #ifdef CONFIG_SMP
                smp_send_timer();
@@ -256,32 +245,29 @@ static struct irqaction integrator_timer_irq = {
  */
 void __init integrator_time_init(unsigned long reload, unsigned int ctrl)
 {
-       volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
-       volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
-       volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE;
-       unsigned int timer_ctrl = 0x80 | 0x40;  /* periodic */
+       unsigned int timer_ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
 
        timer_reload = reload;
        timer_ctrl |= ctrl;
 
        if (timer_reload > 0x100000) {
                timer_reload >>= 8;
-               timer_ctrl |= 0x08; /* /256 */
+               timer_ctrl |= TIMER_CTRL_DIV256;
        } else if (timer_reload > 0x010000) {
                timer_reload >>= 4;
-               timer_ctrl |= 0x04; /* /16 */
+               timer_ctrl |= TIMER_CTRL_DIV16;
        }
 
        /*
         * Initialise to a known state (all timers off)
         */
-       timer0->TimerControl = 0;
-       timer1->TimerControl = 0;
-       timer2->TimerControl = 0;
+       writel(0, TIMER0_VA_BASE + TIMER_CTRL);
+       writel(0, TIMER1_VA_BASE + TIMER_CTRL);
+       writel(0, TIMER2_VA_BASE + TIMER_CTRL);
 
-       timer1->TimerLoad    = timer_reload;
-       timer1->TimerValue   = timer_reload;
-       timer1->TimerControl = timer_ctrl;
+       writel(timer_reload, TIMER1_VA_BASE + TIMER_LOAD);
+       writel(timer_reload, TIMER1_VA_BASE + TIMER_VALUE);
+       writel(timer_ctrl, TIMER1_VA_BASE + TIMER_CTRL);
 
        /*
         * Make irqs happen for the system timer
index 9d1f225..f01c0f8 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/mach-types.h>
 #include <asm/hardware/amba.h>
 #include <asm/hardware/amba_clcd.h>
+#include <asm/hardware/arm_timer.h>
 #include <asm/hardware/icst307.h>
 
 #include <asm/mach/arch.h>
@@ -788,38 +789,25 @@ void __init versatile_init(void)
  */
 #define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)
 #if TIMER_INTERVAL >= 0x100000
-#define TIMER_RELOAD   (TIMER_INTERVAL >> 8)           /* Divide by 256 */
-#define TIMER_CTRL     0x88                            /* Enable, Clock / 256 */
+#define TIMER_RELOAD   (TIMER_INTERVAL >> 8)
+#define TIMER_DIVISOR  (TIMER_CTRL_DIV256)
 #define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC)
 #elif TIMER_INTERVAL >= 0x10000
 #define TIMER_RELOAD   (TIMER_INTERVAL >> 4)           /* Divide by 16 */
-#define TIMER_CTRL     0x84                            /* Enable, Clock / 16 */
+#define TIMER_DIVISOR  (TIMER_CTRL_DIV16)
 #define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC)
 #else
 #define TIMER_RELOAD   (TIMER_INTERVAL)
-#define TIMER_CTRL     0x80                            /* Enable */
+#define TIMER_DIVISOR  (TIMER_CTRL_DIV1)
 #define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
 #endif
 
-#define TIMER_CTRL_IE  (1 << 5)        /* Interrupt Enable */
-
-/*
- * What does it look like?
- */
-typedef struct TimerStruct {
-       unsigned long TimerLoad;
-       unsigned long TimerValue;
-       unsigned long TimerControl;
-       unsigned long TimerClear;
-} TimerStruct_t;
-
 /*
  * Returns number of ms since last clock interrupt.  Note that interrupts
  * will have been disabled by do_gettimeoffset()
  */
 static unsigned long versatile_gettimeoffset(void)
 {
-       volatile TimerStruct_t *timer0 = (TimerStruct_t *)TIMER0_VA_BASE;
        unsigned long ticks1, ticks2, status;
 
        /*
@@ -828,11 +816,11 @@ static unsigned long versatile_gettimeoffset(void)
         * an interrupt.  We get around this by ensuring that the
         * counter has not reloaded between our two reads.
         */
-       ticks2 = timer0->TimerValue & 0xffff;
+       ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
        do {
                ticks1 = ticks2;
                status = __raw_readl(VA_IC_BASE + VIC_IRQ_RAW_STATUS);
-               ticks2 = timer0->TimerValue & 0xffff;
+               ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
        } while (ticks2 > ticks1);
 
        /*
@@ -859,12 +847,10 @@ static unsigned long versatile_gettimeoffset(void)
  */
 static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
-
        write_seqlock(&xtime_lock);
 
        // ...clear the interrupt
-       timer0->TimerClear = 1;
+       writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
 
        timer_tick(regs);
 
@@ -884,31 +870,32 @@ static struct irqaction versatile_timer_irq = {
  */
 static void __init versatile_timer_init(void)
 {
-       volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
-       volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
-       volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE;
-       volatile TimerStruct_t *timer3 = (volatile TimerStruct_t *)TIMER3_VA_BASE;
+       u32 val;
 
        /* 
         * set clock frequency: 
         *      VERSATILE_REFCLK is 32KHz
         *      VERSATILE_TIMCLK is 1MHz
         */
-       *(volatile unsigned int *)IO_ADDRESS(VERSATILE_SCTL_BASE) |= 
-         ((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | 
-          (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel));
+       val = readl(IO_ADDRESS(VERSATILE_SCTL_BASE));
+       writel((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) |
+              (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | 
+              (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) |
+              (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel) | val,
+              IO_ADDRESS(VERSATILE_SCTL_BASE));
 
        /*
         * Initialise to a known state (all timers off)
         */
-       timer0->TimerControl = 0;
-       timer1->TimerControl = 0;
-       timer2->TimerControl = 0;
-       timer3->TimerControl = 0;
-
-       timer0->TimerLoad    = TIMER_RELOAD;
-       timer0->TimerValue   = TIMER_RELOAD;
-       timer0->TimerControl = TIMER_CTRL | 0x40 | TIMER_CTRL_IE;  /* periodic + IE */
+       writel(0, TIMER0_VA_BASE + TIMER_CTRL);
+       writel(0, TIMER1_VA_BASE + TIMER_CTRL);
+       writel(0, TIMER2_VA_BASE + TIMER_CTRL);
+       writel(0, TIMER3_VA_BASE + TIMER_CTRL);
+
+       writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
+       writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE);
+       writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC |
+              TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL);
 
        /* 
         * Make irqs happen for the system timer
diff --git a/include/asm-arm/hardware/arm_timer.h b/include/asm-arm/hardware/arm_timer.h
new file mode 100644 (file)
index 0000000..04be3bd
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __ASM_ARM_HARDWARE_ARM_TIMER_H
+#define __ASM_ARM_HARDWARE_ARM_TIMER_H
+
+#define TIMER_LOAD     0x00
+#define TIMER_VALUE    0x04
+#define TIMER_CTRL     0x08
+#define TIMER_CTRL_ONESHOT     (1 << 0)
+#define TIMER_CTRL_32BIT       (1 << 1)
+#define TIMER_CTRL_DIV1                (0 << 2)
+#define TIMER_CTRL_DIV16       (1 << 2)
+#define TIMER_CTRL_DIV256      (2 << 2)
+#define TIMER_CTRL_IE          (1 << 5)        /* Interrupt Enable (versatile only) */
+#define TIMER_CTRL_PERIODIC    (1 << 6)
+#define TIMER_CTRL_ENABLE      (1 << 7)
+
+#define TIMER_INTCLR   0x0c
+#define TIMER_RIS      0x10
+#define TIMER_MIS      0x14
+#define TIMER_BGLOAD   0x18
+
+#endif