Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] ARM: Convert ARM timer implementations to use readl/writel

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>

authored by

Russell King and committed by
Russell King
b720f732 6904b246

+58 -64
+14 -28
arch/arm/mach-integrator/core.c
··· 20 20 #include <asm/irq.h> 21 21 #include <asm/io.h> 22 22 #include <asm/hardware/amba.h> 23 + #include <asm/hardware/arm_timer.h> 23 24 #include <asm/arch/cm.h> 24 25 #include <asm/system.h> 25 26 #include <asm/leds.h> ··· 157 156 #define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) 158 157 #endif 159 158 160 - /* 161 - * What does it look like? 162 - */ 163 - typedef struct TimerStruct { 164 - unsigned long TimerLoad; 165 - unsigned long TimerValue; 166 - unsigned long TimerControl; 167 - unsigned long TimerClear; 168 - } TimerStruct_t; 169 - 170 159 static unsigned long timer_reload; 171 160 172 161 /* ··· 165 174 */ 166 175 unsigned long integrator_gettimeoffset(void) 167 176 { 168 - volatile TimerStruct_t *timer1 = (TimerStruct_t *)TIMER1_VA_BASE; 169 177 unsigned long ticks1, ticks2, status; 170 178 171 179 /* ··· 173 183 * an interrupt. We get around this by ensuring that the 174 184 * counter has not reloaded between our two reads. 175 185 */ 176 - ticks2 = timer1->TimerValue & 0xffff; 186 + ticks2 = readl(TIMER1_VA_BASE + TIMER_VALUE) & 0xffff; 177 187 do { 178 188 ticks1 = ticks2; 179 189 status = __raw_readl(VA_IC_BASE + IRQ_RAW_STATUS); 180 - ticks2 = timer1->TimerValue & 0xffff; 190 + ticks2 = readl(TIMER1_VA_BASE + TIMER_VALUE) & 0xffff; 181 191 } while (ticks2 > ticks1); 182 192 183 193 /* ··· 203 213 static irqreturn_t 204 214 integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) 205 215 { 206 - volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE; 207 - 208 216 write_seqlock(&xtime_lock); 209 217 210 218 /* 211 219 * clear the interrupt 212 220 */ 213 - timer1->TimerClear = 1; 221 + writel(1, TIMER1_VA_BASE + TIMER_INTCLR); 214 222 215 223 /* 216 224 * the clock tick routines are only processed on the 217 225 * primary CPU 218 226 */ 219 227 if (hard_smp_processor_id() == 0) { 228 + nmi_tick(); 220 229 timer_tick(regs); 221 230 #ifdef CONFIG_SMP 222 231 smp_send_timer(); ··· 245 256 */ 246 257 void __init integrator_time_init(unsigned long reload, unsigned int ctrl) 247 258 { 248 - volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE; 249 - volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE; 250 - volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE; 251 - unsigned int timer_ctrl = 0x80 | 0x40; /* periodic */ 259 + unsigned int timer_ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC; 252 260 253 261 timer_reload = reload; 254 262 timer_ctrl |= ctrl; 255 263 256 264 if (timer_reload > 0x100000) { 257 265 timer_reload >>= 8; 258 - timer_ctrl |= 0x08; /* /256 */ 266 + timer_ctrl |= TIMER_CTRL_DIV256; 259 267 } else if (timer_reload > 0x010000) { 260 268 timer_reload >>= 4; 261 - timer_ctrl |= 0x04; /* /16 */ 269 + timer_ctrl |= TIMER_CTRL_DIV16; 262 270 } 263 271 264 272 /* 265 273 * Initialise to a known state (all timers off) 266 274 */ 267 - timer0->TimerControl = 0; 268 - timer1->TimerControl = 0; 269 - timer2->TimerControl = 0; 275 + writel(0, TIMER0_VA_BASE + TIMER_CTRL); 276 + writel(0, TIMER1_VA_BASE + TIMER_CTRL); 277 + writel(0, TIMER2_VA_BASE + TIMER_CTRL); 270 278 271 - timer1->TimerLoad = timer_reload; 272 - timer1->TimerValue = timer_reload; 273 - timer1->TimerControl = timer_ctrl; 279 + writel(timer_reload, TIMER1_VA_BASE + TIMER_LOAD); 280 + writel(timer_reload, TIMER1_VA_BASE + TIMER_VALUE); 281 + writel(timer_ctrl, TIMER1_VA_BASE + TIMER_CTRL); 274 282 275 283 /* 276 284 * Make irqs happen for the system timer
+23 -36
arch/arm/mach-versatile/core.c
··· 33 33 #include <asm/mach-types.h> 34 34 #include <asm/hardware/amba.h> 35 35 #include <asm/hardware/amba_clcd.h> 36 + #include <asm/hardware/arm_timer.h> 36 37 #include <asm/hardware/icst307.h> 37 38 38 39 #include <asm/mach/arch.h> ··· 789 788 */ 790 789 #define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10) 791 790 #if TIMER_INTERVAL >= 0x100000 792 - #define TIMER_RELOAD (TIMER_INTERVAL >> 8) /* Divide by 256 */ 793 - #define TIMER_CTRL 0x88 /* Enable, Clock / 256 */ 791 + #define TIMER_RELOAD (TIMER_INTERVAL >> 8) 792 + #define TIMER_DIVISOR (TIMER_CTRL_DIV256) 794 793 #define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC) 795 794 #elif TIMER_INTERVAL >= 0x10000 796 795 #define TIMER_RELOAD (TIMER_INTERVAL >> 4) /* Divide by 16 */ 797 - #define TIMER_CTRL 0x84 /* Enable, Clock / 16 */ 796 + #define TIMER_DIVISOR (TIMER_CTRL_DIV16) 798 797 #define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC) 799 798 #else 800 799 #define TIMER_RELOAD (TIMER_INTERVAL) 801 - #define TIMER_CTRL 0x80 /* Enable */ 800 + #define TIMER_DIVISOR (TIMER_CTRL_DIV1) 802 801 #define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) 803 802 #endif 804 - 805 - #define TIMER_CTRL_IE (1 << 5) /* Interrupt Enable */ 806 - 807 - /* 808 - * What does it look like? 809 - */ 810 - typedef struct TimerStruct { 811 - unsigned long TimerLoad; 812 - unsigned long TimerValue; 813 - unsigned long TimerControl; 814 - unsigned long TimerClear; 815 - } TimerStruct_t; 816 803 817 804 /* 818 805 * Returns number of ms since last clock interrupt. Note that interrupts ··· 808 819 */ 809 820 static unsigned long versatile_gettimeoffset(void) 810 821 { 811 - volatile TimerStruct_t *timer0 = (TimerStruct_t *)TIMER0_VA_BASE; 812 822 unsigned long ticks1, ticks2, status; 813 823 814 824 /* ··· 816 828 * an interrupt. We get around this by ensuring that the 817 829 * counter has not reloaded between our two reads. 818 830 */ 819 - ticks2 = timer0->TimerValue & 0xffff; 831 + ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff; 820 832 do { 821 833 ticks1 = ticks2; 822 834 status = __raw_readl(VA_IC_BASE + VIC_IRQ_RAW_STATUS); 823 - ticks2 = timer0->TimerValue & 0xffff; 835 + ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff; 824 836 } while (ticks2 > ticks1); 825 837 826 838 /* ··· 847 859 */ 848 860 static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) 849 861 { 850 - volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE; 851 - 852 862 write_seqlock(&xtime_lock); 853 863 854 864 // ...clear the interrupt 855 - timer0->TimerClear = 1; 865 + writel(1, TIMER0_VA_BASE + TIMER_INTCLR); 856 866 857 867 timer_tick(regs); 858 868 ··· 870 884 */ 871 885 static void __init versatile_timer_init(void) 872 886 { 873 - volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE; 874 - volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE; 875 - volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE; 876 - volatile TimerStruct_t *timer3 = (volatile TimerStruct_t *)TIMER3_VA_BASE; 887 + u32 val; 877 888 878 889 /* 879 890 * set clock frequency: 880 891 * VERSATILE_REFCLK is 32KHz 881 892 * VERSATILE_TIMCLK is 1MHz 882 893 */ 883 - *(volatile unsigned int *)IO_ADDRESS(VERSATILE_SCTL_BASE) |= 884 - ((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | 885 - (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel)); 894 + val = readl(IO_ADDRESS(VERSATILE_SCTL_BASE)); 895 + writel((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | 896 + (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | 897 + (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | 898 + (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel) | val, 899 + IO_ADDRESS(VERSATILE_SCTL_BASE)); 886 900 887 901 /* 888 902 * Initialise to a known state (all timers off) 889 903 */ 890 - timer0->TimerControl = 0; 891 - timer1->TimerControl = 0; 892 - timer2->TimerControl = 0; 893 - timer3->TimerControl = 0; 904 + writel(0, TIMER0_VA_BASE + TIMER_CTRL); 905 + writel(0, TIMER1_VA_BASE + TIMER_CTRL); 906 + writel(0, TIMER2_VA_BASE + TIMER_CTRL); 907 + writel(0, TIMER3_VA_BASE + TIMER_CTRL); 894 908 895 - timer0->TimerLoad = TIMER_RELOAD; 896 - timer0->TimerValue = TIMER_RELOAD; 897 - timer0->TimerControl = TIMER_CTRL | 0x40 | TIMER_CTRL_IE; /* periodic + IE */ 909 + writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD); 910 + writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE); 911 + writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC | 912 + TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL); 898 913 899 914 /* 900 915 * Make irqs happen for the system timer
+21
include/asm-arm/hardware/arm_timer.h
··· 1 + #ifndef __ASM_ARM_HARDWARE_ARM_TIMER_H 2 + #define __ASM_ARM_HARDWARE_ARM_TIMER_H 3 + 4 + #define TIMER_LOAD 0x00 5 + #define TIMER_VALUE 0x04 6 + #define TIMER_CTRL 0x08 7 + #define TIMER_CTRL_ONESHOT (1 << 0) 8 + #define TIMER_CTRL_32BIT (1 << 1) 9 + #define TIMER_CTRL_DIV1 (0 << 2) 10 + #define TIMER_CTRL_DIV16 (1 << 2) 11 + #define TIMER_CTRL_DIV256 (2 << 2) 12 + #define TIMER_CTRL_IE (1 << 5) /* Interrupt Enable (versatile only) */ 13 + #define TIMER_CTRL_PERIODIC (1 << 6) 14 + #define TIMER_CTRL_ENABLE (1 << 7) 15 + 16 + #define TIMER_INTCLR 0x0c 17 + #define TIMER_RIS 0x10 18 + #define TIMER_MIS 0x14 19 + #define TIMER_BGLOAD 0x18 20 + 21 + #endif