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