diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-11-20 18:53:11 -0500 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-11-20 18:53:11 -0500 |
| commit | 749f583f3405f93bf56ed5dd0be1d65c06db6f0f (patch) | |
| tree | c65a5139a9122a140a8d46c08ea882a6a900f4be | |
| parent | ef1a68848a968f7347cf7eea24072464059af8f1 (diff) | |
| parent | 345a32296b1f9f6121379e0240915e0e2be2dbf5 (diff) | |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/xscaleiop into devel-stable
| -rw-r--r-- | arch/arm/Kconfig | 2 | ||||
| -rw-r--r-- | arch/arm/include/asm/hardware/iop3xx.h | 18 | ||||
| -rw-r--r-- | arch/arm/mach-iop13xx/include/mach/time.h | 18 | ||||
| -rw-r--r-- | arch/arm/mach-iop13xx/iq81340mc.c | 1 | ||||
| -rw-r--r-- | arch/arm/mach-iop13xx/iq81340sc.c | 1 | ||||
| -rw-r--r-- | arch/arm/mach-iop32x/em7210.c | 1 | ||||
| -rw-r--r-- | arch/arm/mach-iop32x/glantank.c | 1 | ||||
| -rw-r--r-- | arch/arm/mach-iop32x/iq31244.c | 1 | ||||
| -rw-r--r-- | arch/arm/mach-iop32x/iq80321.c | 1 | ||||
| -rw-r--r-- | arch/arm/mach-iop32x/n2100.c | 1 | ||||
| -rw-r--r-- | arch/arm/mach-iop33x/iq80331.c | 1 | ||||
| -rw-r--r-- | arch/arm/mach-iop33x/iq80332.c | 1 | ||||
| -rw-r--r-- | arch/arm/mm/proc-xsc3.S | 2 | ||||
| -rw-r--r-- | arch/arm/plat-iop/time.c | 176 |
14 files changed, 178 insertions, 47 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 1c4119c60040..455284edda25 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -810,6 +810,8 @@ config ARCH_ACORN | |||
| 810 | 810 | ||
| 811 | config PLAT_IOP | 811 | config PLAT_IOP |
| 812 | bool | 812 | bool |
| 813 | select GENERIC_CLOCKEVENTS | ||
| 814 | select GENERIC_TIME | ||
| 813 | 815 | ||
| 814 | config PLAT_ORION | 816 | config PLAT_ORION |
| 815 | bool | 817 | bool |
diff --git a/arch/arm/include/asm/hardware/iop3xx.h b/arch/arm/include/asm/hardware/iop3xx.h index 8d60ad267e3a..5daea2961d48 100644 --- a/arch/arm/include/asm/hardware/iop3xx.h +++ b/arch/arm/include/asm/hardware/iop3xx.h | |||
| @@ -234,7 +234,13 @@ extern int iop3xx_get_init_atu(void); | |||
| 234 | void iop3xx_map_io(void); | 234 | void iop3xx_map_io(void); |
| 235 | void iop_init_cp6_handler(void); | 235 | void iop_init_cp6_handler(void); |
| 236 | void iop_init_time(unsigned long tickrate); | 236 | void iop_init_time(unsigned long tickrate); |
| 237 | unsigned long iop_gettimeoffset(void); | 237 | |
| 238 | static inline u32 read_tmr0(void) | ||
| 239 | { | ||
| 240 | u32 val; | ||
| 241 | asm volatile("mrc p6, 0, %0, c0, c1, 0" : "=r" (val)); | ||
| 242 | return val; | ||
| 243 | } | ||
| 238 | 244 | ||
| 239 | static inline void write_tmr0(u32 val) | 245 | static inline void write_tmr0(u32 val) |
| 240 | { | 246 | { |
| @@ -253,6 +259,11 @@ static inline u32 read_tcr0(void) | |||
| 253 | return val; | 259 | return val; |
| 254 | } | 260 | } |
| 255 | 261 | ||
| 262 | static inline void write_tcr0(u32 val) | ||
| 263 | { | ||
| 264 | asm volatile("mcr p6, 0, %0, c2, c1, 0" : : "r" (val)); | ||
| 265 | } | ||
| 266 | |||
| 256 | static inline u32 read_tcr1(void) | 267 | static inline u32 read_tcr1(void) |
| 257 | { | 268 | { |
| 258 | u32 val; | 269 | u32 val; |
| @@ -260,6 +271,11 @@ static inline u32 read_tcr1(void) | |||
| 260 | return val; | 271 | return val; |
| 261 | } | 272 | } |
| 262 | 273 | ||
| 274 | static inline void write_tcr1(u32 val) | ||
| 275 | { | ||
| 276 | asm volatile("mcr p6, 0, %0, c3, c1, 0" : : "r" (val)); | ||
| 277 | } | ||
| 278 | |||
| 263 | static inline void write_trr0(u32 val) | 279 | static inline void write_trr0(u32 val) |
| 264 | { | 280 | { |
| 265 | asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (val)); | 281 | asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (val)); |
diff --git a/arch/arm/mach-iop13xx/include/mach/time.h b/arch/arm/mach-iop13xx/include/mach/time.h index d6d52527589d..f1c00d6d560b 100644 --- a/arch/arm/mach-iop13xx/include/mach/time.h +++ b/arch/arm/mach-iop13xx/include/mach/time.h | |||
| @@ -20,7 +20,6 @@ | |||
| 20 | #define IOP13XX_CORE_FREQ_1200 (5 << 16) | 20 | #define IOP13XX_CORE_FREQ_1200 (5 << 16) |
| 21 | 21 | ||
| 22 | void iop_init_time(unsigned long tickrate); | 22 | void iop_init_time(unsigned long tickrate); |
| 23 | unsigned long iop_gettimeoffset(void); | ||
| 24 | 23 | ||
| 25 | static inline unsigned long iop13xx_core_freq(void) | 24 | static inline unsigned long iop13xx_core_freq(void) |
| 26 | { | 25 | { |
| @@ -66,6 +65,13 @@ static inline unsigned long iop13xx_xsi_bus_ratio(void) | |||
| 66 | return 2; | 65 | return 2; |
| 67 | } | 66 | } |
| 68 | 67 | ||
| 68 | static inline u32 read_tmr0(void) | ||
| 69 | { | ||
| 70 | u32 val; | ||
| 71 | asm volatile("mrc p6, 0, %0, c0, c9, 0" : "=r" (val)); | ||
| 72 | return val; | ||
| 73 | } | ||
| 74 | |||
| 69 | static inline void write_tmr0(u32 val) | 75 | static inline void write_tmr0(u32 val) |
| 70 | { | 76 | { |
| 71 | asm volatile("mcr p6, 0, %0, c0, c9, 0" : : "r" (val)); | 77 | asm volatile("mcr p6, 0, %0, c0, c9, 0" : : "r" (val)); |
| @@ -83,6 +89,11 @@ static inline u32 read_tcr0(void) | |||
| 83 | return val; | 89 | return val; |
| 84 | } | 90 | } |
| 85 | 91 | ||
| 92 | static inline void write_tcr0(u32 val) | ||
| 93 | { | ||
| 94 | asm volatile("mcr p6, 0, %0, c2, c9, 0" : : "r" (val)); | ||
| 95 | } | ||
| 96 | |||
| 86 | static inline u32 read_tcr1(void) | 97 | static inline u32 read_tcr1(void) |
| 87 | { | 98 | { |
| 88 | u32 val; | 99 | u32 val; |
| @@ -90,6 +101,11 @@ static inline u32 read_tcr1(void) | |||
| 90 | return val; | 101 | return val; |
| 91 | } | 102 | } |
| 92 | 103 | ||
| 104 | static inline void write_tcr1(u32 val) | ||
| 105 | { | ||
| 106 | asm volatile("mcr p6, 0, %0, c3, c9, 0" : : "r" (val)); | ||
| 107 | } | ||
| 108 | |||
| 93 | static inline void write_trr0(u32 val) | 109 | static inline void write_trr0(u32 val) |
| 94 | { | 110 | { |
| 95 | asm volatile("mcr p6, 0, %0, c4, c9, 0" : : "r" (val)); | 111 | asm volatile("mcr p6, 0, %0, c4, c9, 0" : : "r" (val)); |
diff --git a/arch/arm/mach-iop13xx/iq81340mc.c b/arch/arm/mach-iop13xx/iq81340mc.c index 5051c03d437c..f91f3154577d 100644 --- a/arch/arm/mach-iop13xx/iq81340mc.c +++ b/arch/arm/mach-iop13xx/iq81340mc.c | |||
| @@ -87,7 +87,6 @@ static void __init iq81340mc_timer_init(void) | |||
| 87 | 87 | ||
| 88 | static struct sys_timer iq81340mc_timer = { | 88 | static struct sys_timer iq81340mc_timer = { |
| 89 | .init = iq81340mc_timer_init, | 89 | .init = iq81340mc_timer_init, |
| 90 | .offset = iop_gettimeoffset, | ||
| 91 | }; | 90 | }; |
| 92 | 91 | ||
| 93 | MACHINE_START(IQ81340MC, "Intel IQ81340MC") | 92 | MACHINE_START(IQ81340MC, "Intel IQ81340MC") |
diff --git a/arch/arm/mach-iop13xx/iq81340sc.c b/arch/arm/mach-iop13xx/iq81340sc.c index bc443073a8e3..ddb7a3435de9 100644 --- a/arch/arm/mach-iop13xx/iq81340sc.c +++ b/arch/arm/mach-iop13xx/iq81340sc.c | |||
| @@ -89,7 +89,6 @@ static void __init iq81340sc_timer_init(void) | |||
| 89 | 89 | ||
| 90 | static struct sys_timer iq81340sc_timer = { | 90 | static struct sys_timer iq81340sc_timer = { |
| 91 | .init = iq81340sc_timer_init, | 91 | .init = iq81340sc_timer_init, |
| 92 | .offset = iop_gettimeoffset, | ||
| 93 | }; | 92 | }; |
| 94 | 93 | ||
| 95 | MACHINE_START(IQ81340SC, "Intel IQ81340SC") | 94 | MACHINE_START(IQ81340SC, "Intel IQ81340SC") |
diff --git a/arch/arm/mach-iop32x/em7210.c b/arch/arm/mach-iop32x/em7210.c index 3ad4696ade42..2bef9b6e1cc9 100644 --- a/arch/arm/mach-iop32x/em7210.c +++ b/arch/arm/mach-iop32x/em7210.c | |||
| @@ -42,7 +42,6 @@ static void __init em7210_timer_init(void) | |||
| 42 | 42 | ||
| 43 | static struct sys_timer em7210_timer = { | 43 | static struct sys_timer em7210_timer = { |
| 44 | .init = em7210_timer_init, | 44 | .init = em7210_timer_init, |
| 45 | .offset = iop_gettimeoffset, | ||
| 46 | }; | 45 | }; |
| 47 | 46 | ||
| 48 | /* | 47 | /* |
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c index a9c2dfdb2507..93370a46b620 100644 --- a/arch/arm/mach-iop32x/glantank.c +++ b/arch/arm/mach-iop32x/glantank.c | |||
| @@ -47,7 +47,6 @@ static void __init glantank_timer_init(void) | |||
| 47 | 47 | ||
| 48 | static struct sys_timer glantank_timer = { | 48 | static struct sys_timer glantank_timer = { |
| 49 | .init = glantank_timer_init, | 49 | .init = glantank_timer_init, |
| 50 | .offset = iop_gettimeoffset, | ||
| 51 | }; | 50 | }; |
| 52 | 51 | ||
| 53 | 52 | ||
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c index dd1cd9904518..a7a08dda7f33 100644 --- a/arch/arm/mach-iop32x/iq31244.c +++ b/arch/arm/mach-iop32x/iq31244.c | |||
| @@ -78,7 +78,6 @@ static void __init iq31244_timer_init(void) | |||
| 78 | 78 | ||
| 79 | static struct sys_timer iq31244_timer = { | 79 | static struct sys_timer iq31244_timer = { |
| 80 | .init = iq31244_timer_init, | 80 | .init = iq31244_timer_init, |
| 81 | .offset = iop_gettimeoffset, | ||
| 82 | }; | 81 | }; |
| 83 | 82 | ||
| 84 | 83 | ||
diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c index fbe27798759d..0200f80c1e17 100644 --- a/arch/arm/mach-iop32x/iq80321.c +++ b/arch/arm/mach-iop32x/iq80321.c | |||
| @@ -46,7 +46,6 @@ static void __init iq80321_timer_init(void) | |||
| 46 | 46 | ||
| 47 | static struct sys_timer iq80321_timer = { | 47 | static struct sys_timer iq80321_timer = { |
| 48 | .init = iq80321_timer_init, | 48 | .init = iq80321_timer_init, |
| 49 | .offset = iop_gettimeoffset, | ||
| 50 | }; | 49 | }; |
| 51 | 50 | ||
| 52 | 51 | ||
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c index d2e427899729..2a5c637639bb 100644 --- a/arch/arm/mach-iop32x/n2100.c +++ b/arch/arm/mach-iop32x/n2100.c | |||
| @@ -53,7 +53,6 @@ static void __init n2100_timer_init(void) | |||
| 53 | 53 | ||
| 54 | static struct sys_timer n2100_timer = { | 54 | static struct sys_timer n2100_timer = { |
| 55 | .init = n2100_timer_init, | 55 | .init = n2100_timer_init, |
| 56 | .offset = iop_gettimeoffset, | ||
| 57 | }; | 56 | }; |
| 58 | 57 | ||
| 59 | 58 | ||
diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c index d51e10cddf20..394e95a30b75 100644 --- a/arch/arm/mach-iop33x/iq80331.c +++ b/arch/arm/mach-iop33x/iq80331.c | |||
| @@ -48,7 +48,6 @@ static void __init iq80331_timer_init(void) | |||
| 48 | 48 | ||
| 49 | static struct sys_timer iq80331_timer = { | 49 | static struct sys_timer iq80331_timer = { |
| 50 | .init = iq80331_timer_init, | 50 | .init = iq80331_timer_init, |
| 51 | .offset = iop_gettimeoffset, | ||
| 52 | }; | 51 | }; |
| 53 | 52 | ||
| 54 | 53 | ||
diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c index 92fb44cdbcad..a40badf126c2 100644 --- a/arch/arm/mach-iop33x/iq80332.c +++ b/arch/arm/mach-iop33x/iq80332.c | |||
| @@ -48,7 +48,6 @@ static void __init iq80332_timer_init(void) | |||
| 48 | 48 | ||
| 49 | static struct sys_timer iq80332_timer = { | 49 | static struct sys_timer iq80332_timer = { |
| 50 | .init = iq80332_timer_init, | 50 | .init = iq80332_timer_init, |
| 51 | .offset = iop_gettimeoffset, | ||
| 52 | }; | 51 | }; |
| 53 | 52 | ||
| 54 | 53 | ||
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index 2028f3702881..fab134e29826 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S | |||
| @@ -396,7 +396,7 @@ __xsc3_setup: | |||
| 396 | orr r4, r4, #0x18 @ cache the page table in L2 | 396 | orr r4, r4, #0x18 @ cache the page table in L2 |
| 397 | mcr p15, 0, r4, c2, c0, 0 @ load page table pointer | 397 | mcr p15, 0, r4, c2, c0, 0 @ load page table pointer |
| 398 | 398 | ||
| 399 | mov r0, #0 @ don't allow CP access | 399 | mov r0, #1 << 6 @ cp6 access for early sched_clock |
| 400 | mcr p15, 0, r0, c15, c1, 0 @ write CP access register | 400 | mcr p15, 0, r0, c15, c1, 0 @ write CP access register |
| 401 | 401 | ||
| 402 | mrc p15, 0, r0, c1, c0, 1 @ get auxiliary control reg | 402 | mrc p15, 0, r0, c1, c0, 1 @ get auxiliary control reg |
diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c index 8da95d57c21f..6c8a02ad98e3 100644 --- a/arch/arm/plat-iop/time.c +++ b/arch/arm/plat-iop/time.c | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| 20 | #include <linux/timex.h> | 20 | #include <linux/timex.h> |
| 21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
| 22 | #include <linux/clocksource.h> | ||
| 23 | #include <linux/clockchips.h> | ||
| 22 | #include <mach/hardware.h> | 24 | #include <mach/hardware.h> |
| 23 | #include <asm/irq.h> | 25 | #include <asm/irq.h> |
| 24 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
| @@ -26,45 +28,136 @@ | |||
| 26 | #include <asm/mach/time.h> | 28 | #include <asm/mach/time.h> |
| 27 | #include <mach/time.h> | 29 | #include <mach/time.h> |
| 28 | 30 | ||
| 31 | /* | ||
| 32 | * IOP clocksource (free-running timer 1). | ||
| 33 | */ | ||
| 34 | static cycle_t iop_clocksource_read(struct clocksource *unused) | ||
| 35 | { | ||
| 36 | return 0xffffffffu - read_tcr1(); | ||
| 37 | } | ||
| 38 | |||
| 39 | static struct clocksource iop_clocksource = { | ||
| 40 | .name = "iop_timer1", | ||
| 41 | .rating = 300, | ||
| 42 | .read = iop_clocksource_read, | ||
| 43 | .mask = CLOCKSOURCE_MASK(32), | ||
| 44 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
| 45 | }; | ||
| 46 | |||
| 47 | static void __init iop_clocksource_set_hz(struct clocksource *cs, unsigned int hz) | ||
| 48 | { | ||
| 49 | u64 temp; | ||
| 50 | u32 shift; | ||
| 51 | |||
| 52 | /* Find shift and mult values for hz. */ | ||
| 53 | shift = 32; | ||
| 54 | do { | ||
| 55 | temp = (u64) NSEC_PER_SEC << shift; | ||
| 56 | do_div(temp, hz); | ||
| 57 | if ((temp >> 32) == 0) | ||
| 58 | break; | ||
| 59 | } while (--shift != 0); | ||
| 60 | |||
| 61 | cs->shift = shift; | ||
| 62 | cs->mult = (u32) temp; | ||
| 63 | |||
| 64 | printk(KERN_INFO "clocksource: %s uses shift %u mult %#x\n", | ||
| 65 | cs->name, cs->shift, cs->mult); | ||
| 66 | } | ||
| 67 | |||
| 68 | /* | ||
| 69 | * IOP sched_clock() implementation via its clocksource. | ||
| 70 | */ | ||
| 71 | unsigned long long sched_clock(void) | ||
| 72 | { | ||
| 73 | cycle_t cyc = iop_clocksource_read(NULL); | ||
| 74 | struct clocksource *cs = &iop_clocksource; | ||
| 75 | |||
| 76 | return clocksource_cyc2ns(cyc, cs->mult, cs->shift); | ||
| 77 | } | ||
| 78 | |||
| 79 | /* | ||
| 80 | * IOP clockevents (interrupting timer 0). | ||
| 81 | */ | ||
| 82 | static int iop_set_next_event(unsigned long delta, | ||
| 83 | struct clock_event_device *unused) | ||
| 84 | { | ||
| 85 | u32 tmr = IOP_TMR_PRIVILEGED | IOP_TMR_RATIO_1_1; | ||
| 86 | |||
| 87 | BUG_ON(delta == 0); | ||
| 88 | write_tmr0(tmr & ~(IOP_TMR_EN | IOP_TMR_RELOAD)); | ||
| 89 | write_tcr0(delta); | ||
| 90 | write_tmr0((tmr & ~IOP_TMR_RELOAD) | IOP_TMR_EN); | ||
| 91 | |||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | |||
| 29 | static unsigned long ticks_per_jiffy; | 95 | static unsigned long ticks_per_jiffy; |
| 30 | static unsigned long ticks_per_usec; | ||
| 31 | static unsigned long next_jiffy_time; | ||
| 32 | 96 | ||
| 33 | unsigned long iop_gettimeoffset(void) | 97 | static void iop_set_mode(enum clock_event_mode mode, |
| 98 | struct clock_event_device *unused) | ||
| 34 | { | 99 | { |
| 35 | unsigned long offset, temp; | 100 | u32 tmr = read_tmr0(); |
| 101 | |||
| 102 | switch (mode) { | ||
| 103 | case CLOCK_EVT_MODE_PERIODIC: | ||
| 104 | write_tmr0(tmr & ~IOP_TMR_EN); | ||
| 105 | write_tcr0(ticks_per_jiffy - 1); | ||
| 106 | tmr |= (IOP_TMR_RELOAD | IOP_TMR_EN); | ||
| 107 | break; | ||
| 108 | case CLOCK_EVT_MODE_ONESHOT: | ||
| 109 | /* ->set_next_event sets period and enables timer */ | ||
| 110 | tmr &= ~(IOP_TMR_RELOAD | IOP_TMR_EN); | ||
| 111 | break; | ||
| 112 | case CLOCK_EVT_MODE_RESUME: | ||
| 113 | tmr |= IOP_TMR_EN; | ||
| 114 | break; | ||
| 115 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
| 116 | case CLOCK_EVT_MODE_UNUSED: | ||
| 117 | default: | ||
| 118 | tmr &= ~IOP_TMR_EN; | ||
| 119 | break; | ||
| 120 | } | ||
| 36 | 121 | ||
| 37 | /* enable cp6, if necessary, to avoid taking the overhead of an | 122 | write_tmr0(tmr); |
| 38 | * undefined instruction trap | 123 | } |
| 39 | */ | 124 | |
| 40 | asm volatile ( | 125 | static struct clock_event_device iop_clockevent = { |
| 41 | "mrc p15, 0, %0, c15, c1, 0\n\t" | 126 | .name = "iop_timer0", |
| 42 | "tst %0, #(1 << 6)\n\t" | 127 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, |
| 43 | "orreq %0, %0, #(1 << 6)\n\t" | 128 | .rating = 300, |
| 44 | "mcreq p15, 0, %0, c15, c1, 0\n\t" | 129 | .set_next_event = iop_set_next_event, |
| 45 | #ifdef CONFIG_CPU_XSCALE | 130 | .set_mode = iop_set_mode, |
| 46 | "mrceq p15, 0, %0, c15, c1, 0\n\t" | 131 | }; |
| 47 | "moveq %0, %0\n\t" | 132 | |
| 48 | "subeq pc, pc, #4\n\t" | 133 | static void __init iop_clockevent_set_hz(struct clock_event_device *ce, unsigned int hz) |
| 49 | #endif | 134 | { |
| 50 | : "=r"(temp) : : "cc"); | 135 | u64 temp; |
| 51 | 136 | u32 shift; | |
| 52 | offset = next_jiffy_time - read_tcr1(); | 137 | |
| 53 | 138 | /* Find shift and mult values for hz. */ | |
| 54 | return offset / ticks_per_usec; | 139 | shift = 32; |
| 140 | do { | ||
| 141 | temp = (u64) hz << shift; | ||
| 142 | do_div(temp, NSEC_PER_SEC); | ||
| 143 | if ((temp >> 32) == 0) | ||
| 144 | break; | ||
| 145 | } while (--shift != 0); | ||
| 146 | |||
| 147 | ce->shift = shift; | ||
| 148 | ce->mult = (u32) temp; | ||
| 149 | |||
| 150 | printk(KERN_INFO "clockevent: %s uses shift %u mult %#lx\n", | ||
| 151 | ce->name, ce->shift, ce->mult); | ||
| 55 | } | 152 | } |
| 56 | 153 | ||
| 57 | static irqreturn_t | 154 | static irqreturn_t |
| 58 | iop_timer_interrupt(int irq, void *dev_id) | 155 | iop_timer_interrupt(int irq, void *dev_id) |
| 59 | { | 156 | { |
| 60 | write_tisr(1); | 157 | struct clock_event_device *evt = dev_id; |
| 61 | |||
| 62 | while ((signed long)(next_jiffy_time - read_tcr1()) | ||
| 63 | >= ticks_per_jiffy) { | ||
| 64 | timer_tick(); | ||
| 65 | next_jiffy_time -= ticks_per_jiffy; | ||
| 66 | } | ||
| 67 | 158 | ||
| 159 | write_tisr(1); | ||
| 160 | evt->event_handler(evt); | ||
| 68 | return IRQ_HANDLED; | 161 | return IRQ_HANDLED; |
| 69 | } | 162 | } |
| 70 | 163 | ||
| @@ -72,6 +165,7 @@ static struct irqaction iop_timer_irq = { | |||
| 72 | .name = "IOP Timer Tick", | 165 | .name = "IOP Timer Tick", |
| 73 | .handler = iop_timer_interrupt, | 166 | .handler = iop_timer_interrupt, |
| 74 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | 167 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, |
| 168 | .dev_id = &iop_clockevent, | ||
| 75 | }; | 169 | }; |
| 76 | 170 | ||
| 77 | static unsigned long iop_tick_rate; | 171 | static unsigned long iop_tick_rate; |
| @@ -86,21 +180,33 @@ void __init iop_init_time(unsigned long tick_rate) | |||
| 86 | u32 timer_ctl; | 180 | u32 timer_ctl; |
| 87 | 181 | ||
| 88 | ticks_per_jiffy = DIV_ROUND_CLOSEST(tick_rate, HZ); | 182 | ticks_per_jiffy = DIV_ROUND_CLOSEST(tick_rate, HZ); |
| 89 | ticks_per_usec = tick_rate / 1000000; | ||
| 90 | next_jiffy_time = 0xffffffff; | ||
| 91 | iop_tick_rate = tick_rate; | 183 | iop_tick_rate = tick_rate; |
| 92 | 184 | ||
| 93 | timer_ctl = IOP_TMR_EN | IOP_TMR_PRIVILEGED | | 185 | timer_ctl = IOP_TMR_EN | IOP_TMR_PRIVILEGED | |
| 94 | IOP_TMR_RELOAD | IOP_TMR_RATIO_1_1; | 186 | IOP_TMR_RELOAD | IOP_TMR_RATIO_1_1; |
| 95 | 187 | ||
| 96 | /* | 188 | /* |
| 97 | * We use timer 0 for our timer interrupt, and timer 1 as | 189 | * Set up interrupting clockevent timer 0. |
| 98 | * monotonic counter for tracking missed jiffies. | ||
| 99 | */ | 190 | */ |
| 191 | write_tmr0(timer_ctl & ~IOP_TMR_EN); | ||
| 192 | setup_irq(IRQ_IOP_TIMER0, &iop_timer_irq); | ||
| 193 | iop_clockevent_set_hz(&iop_clockevent, tick_rate); | ||
| 194 | iop_clockevent.max_delta_ns = | ||
| 195 | clockevent_delta2ns(0xfffffffe, &iop_clockevent); | ||
| 196 | iop_clockevent.min_delta_ns = | ||
| 197 | clockevent_delta2ns(0xf, &iop_clockevent); | ||
| 198 | iop_clockevent.cpumask = cpumask_of(0); | ||
| 199 | clockevents_register_device(&iop_clockevent); | ||
| 100 | write_trr0(ticks_per_jiffy - 1); | 200 | write_trr0(ticks_per_jiffy - 1); |
| 201 | write_tcr0(ticks_per_jiffy - 1); | ||
| 101 | write_tmr0(timer_ctl); | 202 | write_tmr0(timer_ctl); |
| 203 | |||
| 204 | /* | ||
| 205 | * Set up free-running clocksource timer 1. | ||
| 206 | */ | ||
| 102 | write_trr1(0xffffffff); | 207 | write_trr1(0xffffffff); |
| 208 | write_tcr1(0xffffffff); | ||
| 103 | write_tmr1(timer_ctl); | 209 | write_tmr1(timer_ctl); |
| 104 | 210 | iop_clocksource_set_hz(&iop_clocksource, tick_rate); | |
| 105 | setup_irq(IRQ_IOP_TIMER0, &iop_timer_irq); | 211 | clocksource_register(&iop_clocksource); |
| 106 | } | 212 | } |
