diff options
Diffstat (limited to 'arch/arm/mach-davinci/time.c')
-rw-r--r-- | arch/arm/mach-davinci/time.c | 105 |
1 files changed, 66 insertions, 39 deletions
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c index f8bcd29d17a6..494e01bff5c3 100644 --- a/arch/arm/mach-davinci/time.c +++ b/arch/arm/mach-davinci/time.c | |||
@@ -16,6 +16,9 @@ | |||
16 | #include <linux/clockchips.h> | 16 | #include <linux/clockchips.h> |
17 | #include <linux/spinlock.h> | 17 | #include <linux/spinlock.h> |
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | #include <linux/clk.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/device.h> | ||
19 | 22 | ||
20 | #include <mach/hardware.h> | 23 | #include <mach/hardware.h> |
21 | #include <asm/system.h> | 24 | #include <asm/system.h> |
@@ -24,8 +27,11 @@ | |||
24 | #include <asm/mach/time.h> | 27 | #include <asm/mach/time.h> |
25 | #include <asm/errno.h> | 28 | #include <asm/errno.h> |
26 | #include <mach/io.h> | 29 | #include <mach/io.h> |
30 | #include <mach/cputype.h> | ||
31 | #include "clock.h" | ||
27 | 32 | ||
28 | static struct clock_event_device clockevent_davinci; | 33 | static struct clock_event_device clockevent_davinci; |
34 | static unsigned int davinci_clock_tick_rate; | ||
29 | 35 | ||
30 | #define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400) | 36 | #define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400) |
31 | #define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800) | 37 | #define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800) |
@@ -99,9 +105,9 @@ struct timer_s { | |||
99 | unsigned int id; | 105 | unsigned int id; |
100 | unsigned long period; | 106 | unsigned long period; |
101 | unsigned long opts; | 107 | unsigned long opts; |
102 | unsigned long reg_base; | 108 | void __iomem *base; |
103 | unsigned long tim_reg; | 109 | unsigned long tim_off; |
104 | unsigned long prd_reg; | 110 | unsigned long prd_off; |
105 | unsigned long enamode_shift; | 111 | unsigned long enamode_shift; |
106 | struct irqaction irqaction; | 112 | struct irqaction irqaction; |
107 | }; | 113 | }; |
@@ -114,15 +120,15 @@ static struct timer_s timers[]; | |||
114 | 120 | ||
115 | static int timer32_config(struct timer_s *t) | 121 | static int timer32_config(struct timer_s *t) |
116 | { | 122 | { |
117 | u32 tcr = davinci_readl(t->reg_base + TCR); | 123 | u32 tcr = __raw_readl(t->base + TCR); |
118 | 124 | ||
119 | /* disable timer */ | 125 | /* disable timer */ |
120 | tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift); | 126 | tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift); |
121 | davinci_writel(tcr, t->reg_base + TCR); | 127 | __raw_writel(tcr, t->base + TCR); |
122 | 128 | ||
123 | /* reset counter to zero, set new period */ | 129 | /* reset counter to zero, set new period */ |
124 | davinci_writel(0, t->tim_reg); | 130 | __raw_writel(0, t->base + t->tim_off); |
125 | davinci_writel(t->period, t->prd_reg); | 131 | __raw_writel(t->period, t->base + t->prd_off); |
126 | 132 | ||
127 | /* Set enable mode */ | 133 | /* Set enable mode */ |
128 | if (t->opts & TIMER_OPTS_ONESHOT) { | 134 | if (t->opts & TIMER_OPTS_ONESHOT) { |
@@ -131,13 +137,13 @@ static int timer32_config(struct timer_s *t) | |||
131 | tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift; | 137 | tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift; |
132 | } | 138 | } |
133 | 139 | ||
134 | davinci_writel(tcr, t->reg_base + TCR); | 140 | __raw_writel(tcr, t->base + TCR); |
135 | return 0; | 141 | return 0; |
136 | } | 142 | } |
137 | 143 | ||
138 | static inline u32 timer32_read(struct timer_s *t) | 144 | static inline u32 timer32_read(struct timer_s *t) |
139 | { | 145 | { |
140 | return davinci_readl(t->tim_reg); | 146 | return __raw_readl(t->base + t->tim_off); |
141 | } | 147 | } |
142 | 148 | ||
143 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | 149 | static irqreturn_t timer_interrupt(int irq, void *dev_id) |
@@ -176,51 +182,54 @@ static struct timer_s timers[] = { | |||
176 | 182 | ||
177 | static void __init timer_init(void) | 183 | static void __init timer_init(void) |
178 | { | 184 | { |
179 | u32 bases[] = {DAVINCI_TIMER0_BASE, DAVINCI_TIMER1_BASE}; | 185 | u32 phys_bases[] = {DAVINCI_TIMER0_BASE, DAVINCI_TIMER1_BASE}; |
180 | int i; | 186 | int i; |
181 | 187 | ||
182 | /* Global init of each 64-bit timer as a whole */ | 188 | /* Global init of each 64-bit timer as a whole */ |
183 | for(i=0; i<2; i++) { | 189 | for(i=0; i<2; i++) { |
184 | u32 tgcr, base = bases[i]; | 190 | u32 tgcr; |
191 | void __iomem *base = IO_ADDRESS(phys_bases[i]); | ||
185 | 192 | ||
186 | /* Disabled, Internal clock source */ | 193 | /* Disabled, Internal clock source */ |
187 | davinci_writel(0, base + TCR); | 194 | __raw_writel(0, base + TCR); |
188 | 195 | ||
189 | /* reset both timers, no pre-scaler for timer34 */ | 196 | /* reset both timers, no pre-scaler for timer34 */ |
190 | tgcr = 0; | 197 | tgcr = 0; |
191 | davinci_writel(tgcr, base + TGCR); | 198 | __raw_writel(tgcr, base + TGCR); |
192 | 199 | ||
193 | /* Set both timers to unchained 32-bit */ | 200 | /* Set both timers to unchained 32-bit */ |
194 | tgcr = TGCR_TIMMODE_32BIT_UNCHAINED << TGCR_TIMMODE_SHIFT; | 201 | tgcr = TGCR_TIMMODE_32BIT_UNCHAINED << TGCR_TIMMODE_SHIFT; |
195 | davinci_writel(tgcr, base + TGCR); | 202 | __raw_writel(tgcr, base + TGCR); |
196 | 203 | ||
197 | /* Unreset timers */ | 204 | /* Unreset timers */ |
198 | tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) | | 205 | tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) | |
199 | (TGCR_UNRESET << TGCR_TIM34RS_SHIFT); | 206 | (TGCR_UNRESET << TGCR_TIM34RS_SHIFT); |
200 | davinci_writel(tgcr, base + TGCR); | 207 | __raw_writel(tgcr, base + TGCR); |
201 | 208 | ||
202 | /* Init both counters to zero */ | 209 | /* Init both counters to zero */ |
203 | davinci_writel(0, base + TIM12); | 210 | __raw_writel(0, base + TIM12); |
204 | davinci_writel(0, base + TIM34); | 211 | __raw_writel(0, base + TIM34); |
205 | } | 212 | } |
206 | 213 | ||
207 | /* Init of each timer as a 32-bit timer */ | 214 | /* Init of each timer as a 32-bit timer */ |
208 | for (i=0; i< ARRAY_SIZE(timers); i++) { | 215 | for (i=0; i< ARRAY_SIZE(timers); i++) { |
209 | struct timer_s *t = &timers[i]; | 216 | struct timer_s *t = &timers[i]; |
217 | u32 phys_base; | ||
210 | 218 | ||
211 | if (t->name) { | 219 | if (t->name) { |
212 | t->id = i; | 220 | t->id = i; |
213 | t->reg_base = (IS_TIMER1(t->id) ? | 221 | phys_base = (IS_TIMER1(t->id) ? |
214 | DAVINCI_TIMER1_BASE : DAVINCI_TIMER0_BASE); | 222 | DAVINCI_TIMER1_BASE : DAVINCI_TIMER0_BASE); |
223 | t->base = IO_ADDRESS(phys_base); | ||
215 | 224 | ||
216 | if (IS_TIMER_BOT(t->id)) { | 225 | if (IS_TIMER_BOT(t->id)) { |
217 | t->enamode_shift = 6; | 226 | t->enamode_shift = 6; |
218 | t->tim_reg = t->reg_base + TIM12; | 227 | t->tim_off = TIM12; |
219 | t->prd_reg = t->reg_base + PRD12; | 228 | t->prd_off = PRD12; |
220 | } else { | 229 | } else { |
221 | t->enamode_shift = 22; | 230 | t->enamode_shift = 22; |
222 | t->tim_reg = t->reg_base + TIM34; | 231 | t->tim_off = TIM34; |
223 | t->prd_reg = t->reg_base + PRD34; | 232 | t->prd_off = PRD34; |
224 | } | 233 | } |
225 | 234 | ||
226 | /* Register interrupt */ | 235 | /* Register interrupt */ |
@@ -238,7 +247,7 @@ static void __init timer_init(void) | |||
238 | /* | 247 | /* |
239 | * clocksource | 248 | * clocksource |
240 | */ | 249 | */ |
241 | static cycle_t read_cycles(void) | 250 | static cycle_t read_cycles(struct clocksource *cs) |
242 | { | 251 | { |
243 | struct timer_s *t = &timers[TID_CLOCKSOURCE]; | 252 | struct timer_s *t = &timers[TID_CLOCKSOURCE]; |
244 | 253 | ||
@@ -274,7 +283,7 @@ static void davinci_set_mode(enum clock_event_mode mode, | |||
274 | 283 | ||
275 | switch (mode) { | 284 | switch (mode) { |
276 | case CLOCK_EVT_MODE_PERIODIC: | 285 | case CLOCK_EVT_MODE_PERIODIC: |
277 | t->period = CLOCK_TICK_RATE / (HZ); | 286 | t->period = davinci_clock_tick_rate / (HZ); |
278 | t->opts = TIMER_OPTS_PERIODIC; | 287 | t->opts = TIMER_OPTS_PERIODIC; |
279 | timer32_config(t); | 288 | timer32_config(t); |
280 | break; | 289 | break; |
@@ -301,21 +310,29 @@ static struct clock_event_device clockevent_davinci = { | |||
301 | 310 | ||
302 | static void __init davinci_timer_init(void) | 311 | static void __init davinci_timer_init(void) |
303 | { | 312 | { |
313 | struct clk *timer_clk; | ||
314 | |||
304 | static char err[] __initdata = KERN_ERR | 315 | static char err[] __initdata = KERN_ERR |
305 | "%s: can't register clocksource!\n"; | 316 | "%s: can't register clocksource!\n"; |
306 | 317 | ||
307 | /* init timer hw */ | 318 | /* init timer hw */ |
308 | timer_init(); | 319 | timer_init(); |
309 | 320 | ||
321 | timer_clk = clk_get(NULL, "timer0"); | ||
322 | BUG_ON(IS_ERR(timer_clk)); | ||
323 | clk_enable(timer_clk); | ||
324 | |||
325 | davinci_clock_tick_rate = clk_get_rate(timer_clk); | ||
326 | |||
310 | /* setup clocksource */ | 327 | /* setup clocksource */ |
311 | clocksource_davinci.mult = | 328 | clocksource_davinci.mult = |
312 | clocksource_khz2mult(CLOCK_TICK_RATE/1000, | 329 | clocksource_khz2mult(davinci_clock_tick_rate/1000, |
313 | clocksource_davinci.shift); | 330 | clocksource_davinci.shift); |
314 | if (clocksource_register(&clocksource_davinci)) | 331 | if (clocksource_register(&clocksource_davinci)) |
315 | printk(err, clocksource_davinci.name); | 332 | printk(err, clocksource_davinci.name); |
316 | 333 | ||
317 | /* setup clockevent */ | 334 | /* setup clockevent */ |
318 | clockevent_davinci.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, | 335 | clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC, |
319 | clockevent_davinci.shift); | 336 | clockevent_davinci.shift); |
320 | clockevent_davinci.max_delta_ns = | 337 | clockevent_davinci.max_delta_ns = |
321 | clockevent_delta2ns(0xfffffffe, &clockevent_davinci); | 338 | clockevent_delta2ns(0xfffffffe, &clockevent_davinci); |
@@ -333,42 +350,52 @@ struct sys_timer davinci_timer = { | |||
333 | 350 | ||
334 | /* reset board using watchdog timer */ | 351 | /* reset board using watchdog timer */ |
335 | void davinci_watchdog_reset(void) { | 352 | void davinci_watchdog_reset(void) { |
336 | u32 tgcr, wdtcr, base = DAVINCI_WDOG_BASE; | 353 | u32 tgcr, wdtcr; |
354 | void __iomem *base = IO_ADDRESS(DAVINCI_WDOG_BASE); | ||
355 | struct device dev; | ||
356 | struct clk *wd_clk; | ||
357 | char *name = "watchdog"; | ||
358 | |||
359 | dev_set_name(&dev, name); | ||
360 | wd_clk = clk_get(&dev, NULL); | ||
361 | if (WARN_ON(IS_ERR(wd_clk))) | ||
362 | return; | ||
363 | clk_enable(wd_clk); | ||
337 | 364 | ||
338 | /* disable, internal clock source */ | 365 | /* disable, internal clock source */ |
339 | davinci_writel(0, base + TCR); | 366 | __raw_writel(0, base + TCR); |
340 | 367 | ||
341 | /* reset timer, set mode to 64-bit watchdog, and unreset */ | 368 | /* reset timer, set mode to 64-bit watchdog, and unreset */ |
342 | tgcr = 0; | 369 | tgcr = 0; |
343 | davinci_writel(tgcr, base + TCR); | 370 | __raw_writel(tgcr, base + TCR); |
344 | tgcr = TGCR_TIMMODE_64BIT_WDOG << TGCR_TIMMODE_SHIFT; | 371 | tgcr = TGCR_TIMMODE_64BIT_WDOG << TGCR_TIMMODE_SHIFT; |
345 | tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) | | 372 | tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) | |
346 | (TGCR_UNRESET << TGCR_TIM34RS_SHIFT); | 373 | (TGCR_UNRESET << TGCR_TIM34RS_SHIFT); |
347 | davinci_writel(tgcr, base + TCR); | 374 | __raw_writel(tgcr, base + TCR); |
348 | 375 | ||
349 | /* clear counter and period regs */ | 376 | /* clear counter and period regs */ |
350 | davinci_writel(0, base + TIM12); | 377 | __raw_writel(0, base + TIM12); |
351 | davinci_writel(0, base + TIM34); | 378 | __raw_writel(0, base + TIM34); |
352 | davinci_writel(0, base + PRD12); | 379 | __raw_writel(0, base + PRD12); |
353 | davinci_writel(0, base + PRD34); | 380 | __raw_writel(0, base + PRD34); |
354 | 381 | ||
355 | /* enable */ | 382 | /* enable */ |
356 | wdtcr = davinci_readl(base + WDTCR); | 383 | wdtcr = __raw_readl(base + WDTCR); |
357 | wdtcr |= WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT; | 384 | wdtcr |= WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT; |
358 | davinci_writel(wdtcr, base + WDTCR); | 385 | __raw_writel(wdtcr, base + WDTCR); |
359 | 386 | ||
360 | /* put watchdog in pre-active state */ | 387 | /* put watchdog in pre-active state */ |
361 | wdtcr = (WDTCR_WDKEY_SEQ0 << WDTCR_WDKEY_SHIFT) | | 388 | wdtcr = (WDTCR_WDKEY_SEQ0 << WDTCR_WDKEY_SHIFT) | |
362 | (WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT); | 389 | (WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT); |
363 | davinci_writel(wdtcr, base + WDTCR); | 390 | __raw_writel(wdtcr, base + WDTCR); |
364 | 391 | ||
365 | /* put watchdog in active state */ | 392 | /* put watchdog in active state */ |
366 | wdtcr = (WDTCR_WDKEY_SEQ1 << WDTCR_WDKEY_SHIFT) | | 393 | wdtcr = (WDTCR_WDKEY_SEQ1 << WDTCR_WDKEY_SHIFT) | |
367 | (WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT); | 394 | (WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT); |
368 | davinci_writel(wdtcr, base + WDTCR); | 395 | __raw_writel(wdtcr, base + WDTCR); |
369 | 396 | ||
370 | /* write an invalid value to the WDKEY field to trigger | 397 | /* write an invalid value to the WDKEY field to trigger |
371 | * a watchdog reset */ | 398 | * a watchdog reset */ |
372 | wdtcr = 0x00004000; | 399 | wdtcr = 0x00004000; |
373 | davinci_writel(wdtcr, base + WDTCR); | 400 | __raw_writel(wdtcr, base + WDTCR); |
374 | } | 401 | } |