diff options
Diffstat (limited to 'arch/arm/mach-u300/timer.c')
-rw-r--r-- | arch/arm/mach-u300/timer.c | 113 |
1 files changed, 70 insertions, 43 deletions
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c index d9e73209c9b8..390ae5feb1d0 100644 --- a/arch/arm/mach-u300/timer.c +++ b/arch/arm/mach-u300/timer.c | |||
@@ -18,17 +18,15 @@ | |||
18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
19 | #include <linux/err.h> | 19 | #include <linux/err.h> |
20 | #include <linux/irq.h> | 20 | #include <linux/irq.h> |
21 | 21 | #include <linux/delay.h> | |
22 | #include <mach/hardware.h> | 22 | #include <linux/of_address.h> |
23 | #include <mach/irqs.h> | 23 | #include <linux/of_irq.h> |
24 | 24 | ||
25 | /* Generic stuff */ | 25 | /* Generic stuff */ |
26 | #include <asm/sched_clock.h> | 26 | #include <asm/sched_clock.h> |
27 | #include <asm/mach/map.h> | 27 | #include <asm/mach/map.h> |
28 | #include <asm/mach/time.h> | 28 | #include <asm/mach/time.h> |
29 | 29 | ||
30 | #include "timer.h" | ||
31 | |||
32 | /* | 30 | /* |
33 | * APP side special timer registers | 31 | * APP side special timer registers |
34 | * This timer contains four timers which can fire an interrupt each. | 32 | * This timer contains four timers which can fire an interrupt each. |
@@ -189,6 +187,8 @@ | |||
189 | #define TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ) | 187 | #define TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ) |
190 | #define US_PER_TICK ((1000000 + (HZ/2)) / HZ) | 188 | #define US_PER_TICK ((1000000 + (HZ/2)) / HZ) |
191 | 189 | ||
190 | static void __iomem *u300_timer_base; | ||
191 | |||
192 | /* | 192 | /* |
193 | * The u300_set_mode() function is always called first, if we | 193 | * The u300_set_mode() function is always called first, if we |
194 | * have oneshot timer active, the oneshot scheduling function | 194 | * have oneshot timer active, the oneshot scheduling function |
@@ -201,28 +201,28 @@ static void u300_set_mode(enum clock_event_mode mode, | |||
201 | case CLOCK_EVT_MODE_PERIODIC: | 201 | case CLOCK_EVT_MODE_PERIODIC: |
202 | /* Disable interrupts on GPT1 */ | 202 | /* Disable interrupts on GPT1 */ |
203 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, | 203 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, |
204 | U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); | 204 | u300_timer_base + U300_TIMER_APP_GPT1IE); |
205 | /* Disable GP1 while we're reprogramming it. */ | 205 | /* Disable GP1 while we're reprogramming it. */ |
206 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, | 206 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, |
207 | U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1); | 207 | u300_timer_base + U300_TIMER_APP_DGPT1); |
208 | /* | 208 | /* |
209 | * Set the periodic mode to a certain number of ticks per | 209 | * Set the periodic mode to a certain number of ticks per |
210 | * jiffy. | 210 | * jiffy. |
211 | */ | 211 | */ |
212 | writel(TICKS_PER_JIFFY, | 212 | writel(TICKS_PER_JIFFY, |
213 | U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1TC); | 213 | u300_timer_base + U300_TIMER_APP_GPT1TC); |
214 | /* | 214 | /* |
215 | * Set continuous mode, so the timer keeps triggering | 215 | * Set continuous mode, so the timer keeps triggering |
216 | * interrupts. | 216 | * interrupts. |
217 | */ | 217 | */ |
218 | writel(U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS, | 218 | writel(U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS, |
219 | U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT1M); | 219 | u300_timer_base + U300_TIMER_APP_SGPT1M); |
220 | /* Enable timer interrupts */ | 220 | /* Enable timer interrupts */ |
221 | writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, | 221 | writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, |
222 | U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); | 222 | u300_timer_base + U300_TIMER_APP_GPT1IE); |
223 | /* Then enable the OS timer again */ | 223 | /* Then enable the OS timer again */ |
224 | writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, | 224 | writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, |
225 | U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT1); | 225 | u300_timer_base + U300_TIMER_APP_EGPT1); |
226 | break; | 226 | break; |
227 | case CLOCK_EVT_MODE_ONESHOT: | 227 | case CLOCK_EVT_MODE_ONESHOT: |
228 | /* Just break; here? */ | 228 | /* Just break; here? */ |
@@ -233,33 +233,33 @@ static void u300_set_mode(enum clock_event_mode mode, | |||
233 | */ | 233 | */ |
234 | /* Disable interrupts on GPT1 */ | 234 | /* Disable interrupts on GPT1 */ |
235 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, | 235 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, |
236 | U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); | 236 | u300_timer_base + U300_TIMER_APP_GPT1IE); |
237 | /* Disable GP1 while we're reprogramming it. */ | 237 | /* Disable GP1 while we're reprogramming it. */ |
238 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, | 238 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, |
239 | U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1); | 239 | u300_timer_base + U300_TIMER_APP_DGPT1); |
240 | /* | 240 | /* |
241 | * Expire far in the future, u300_set_next_event() will be | 241 | * Expire far in the future, u300_set_next_event() will be |
242 | * called soon... | 242 | * called soon... |
243 | */ | 243 | */ |
244 | writel(0xFFFFFFFF, U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1TC); | 244 | writel(0xFFFFFFFF, u300_timer_base + U300_TIMER_APP_GPT1TC); |
245 | /* We run one shot per tick here! */ | 245 | /* We run one shot per tick here! */ |
246 | writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT, | 246 | writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT, |
247 | U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT1M); | 247 | u300_timer_base + U300_TIMER_APP_SGPT1M); |
248 | /* Enable interrupts for this timer */ | 248 | /* Enable interrupts for this timer */ |
249 | writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, | 249 | writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, |
250 | U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); | 250 | u300_timer_base + U300_TIMER_APP_GPT1IE); |
251 | /* Enable timer */ | 251 | /* Enable timer */ |
252 | writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, | 252 | writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, |
253 | U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT1); | 253 | u300_timer_base + U300_TIMER_APP_EGPT1); |
254 | break; | 254 | break; |
255 | case CLOCK_EVT_MODE_UNUSED: | 255 | case CLOCK_EVT_MODE_UNUSED: |
256 | case CLOCK_EVT_MODE_SHUTDOWN: | 256 | case CLOCK_EVT_MODE_SHUTDOWN: |
257 | /* Disable interrupts on GP1 */ | 257 | /* Disable interrupts on GP1 */ |
258 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, | 258 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, |
259 | U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); | 259 | u300_timer_base + U300_TIMER_APP_GPT1IE); |
260 | /* Disable GP1 */ | 260 | /* Disable GP1 */ |
261 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, | 261 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, |
262 | U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1); | 262 | u300_timer_base + U300_TIMER_APP_DGPT1); |
263 | break; | 263 | break; |
264 | case CLOCK_EVT_MODE_RESUME: | 264 | case CLOCK_EVT_MODE_RESUME: |
265 | /* Ignore this call */ | 265 | /* Ignore this call */ |
@@ -281,27 +281,27 @@ static int u300_set_next_event(unsigned long cycles, | |||
281 | { | 281 | { |
282 | /* Disable interrupts on GPT1 */ | 282 | /* Disable interrupts on GPT1 */ |
283 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, | 283 | writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, |
284 | U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); | 284 | u300_timer_base + U300_TIMER_APP_GPT1IE); |
285 | /* Disable GP1 while we're reprogramming it. */ | 285 | /* Disable GP1 while we're reprogramming it. */ |
286 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, | 286 | writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, |
287 | U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1); | 287 | u300_timer_base + U300_TIMER_APP_DGPT1); |
288 | /* Reset the General Purpose timer 1. */ | 288 | /* Reset the General Purpose timer 1. */ |
289 | writel(U300_TIMER_APP_RGPT1_TIMER_RESET, | 289 | writel(U300_TIMER_APP_RGPT1_TIMER_RESET, |
290 | U300_TIMER_APP_VBASE + U300_TIMER_APP_RGPT1); | 290 | u300_timer_base + U300_TIMER_APP_RGPT1); |
291 | /* IRQ in n * cycles */ | 291 | /* IRQ in n * cycles */ |
292 | writel(cycles, U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1TC); | 292 | writel(cycles, u300_timer_base + U300_TIMER_APP_GPT1TC); |
293 | /* | 293 | /* |
294 | * We run one shot per tick here! (This is necessary to reconfigure, | 294 | * We run one shot per tick here! (This is necessary to reconfigure, |
295 | * the timer will tilt if you don't!) | 295 | * the timer will tilt if you don't!) |
296 | */ | 296 | */ |
297 | writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT, | 297 | writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT, |
298 | U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT1M); | 298 | u300_timer_base + U300_TIMER_APP_SGPT1M); |
299 | /* Enable timer interrupts */ | 299 | /* Enable timer interrupts */ |
300 | writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, | 300 | writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, |
301 | U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); | 301 | u300_timer_base + U300_TIMER_APP_GPT1IE); |
302 | /* Then enable the OS timer again */ | 302 | /* Then enable the OS timer again */ |
303 | writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, | 303 | writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, |
304 | U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT1); | 304 | u300_timer_base + U300_TIMER_APP_EGPT1); |
305 | return 0; | 305 | return 0; |
306 | } | 306 | } |
307 | 307 | ||
@@ -320,8 +320,9 @@ static irqreturn_t u300_timer_interrupt(int irq, void *dev_id) | |||
320 | { | 320 | { |
321 | struct clock_event_device *evt = &clockevent_u300_1mhz; | 321 | struct clock_event_device *evt = &clockevent_u300_1mhz; |
322 | /* ACK/Clear timer IRQ for the APP GPT1 Timer */ | 322 | /* ACK/Clear timer IRQ for the APP GPT1 Timer */ |
323 | |||
323 | writel(U300_TIMER_APP_GPT1IA_IRQ_ACK, | 324 | writel(U300_TIMER_APP_GPT1IA_IRQ_ACK, |
324 | U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IA); | 325 | u300_timer_base + U300_TIMER_APP_GPT1IA); |
325 | evt->event_handler(evt); | 326 | evt->event_handler(evt); |
326 | return IRQ_HANDLED; | 327 | return IRQ_HANDLED; |
327 | } | 328 | } |
@@ -342,65 +343,88 @@ static struct irqaction u300_timer_irq = { | |||
342 | 343 | ||
343 | static u32 notrace u300_read_sched_clock(void) | 344 | static u32 notrace u300_read_sched_clock(void) |
344 | { | 345 | { |
345 | return readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC); | 346 | return readl(u300_timer_base + U300_TIMER_APP_GPT2CC); |
347 | } | ||
348 | |||
349 | static unsigned long u300_read_current_timer(void) | ||
350 | { | ||
351 | return readl(u300_timer_base + U300_TIMER_APP_GPT2CC); | ||
346 | } | 352 | } |
347 | 353 | ||
354 | static struct delay_timer u300_delay_timer; | ||
348 | 355 | ||
349 | /* | 356 | /* |
350 | * This sets up the system timers, clock source and clock event. | 357 | * This sets up the system timers, clock source and clock event. |
351 | */ | 358 | */ |
352 | void __init u300_timer_init(void) | 359 | static void __init u300_timer_init_of(struct device_node *np) |
353 | { | 360 | { |
361 | struct resource irq_res; | ||
362 | int irq; | ||
354 | struct clk *clk; | 363 | struct clk *clk; |
355 | unsigned long rate; | 364 | unsigned long rate; |
356 | 365 | ||
366 | u300_timer_base = of_iomap(np, 0); | ||
367 | if (!u300_timer_base) | ||
368 | panic("could not ioremap system timer\n"); | ||
369 | |||
370 | /* Get the IRQ for the GP1 timer */ | ||
371 | irq = of_irq_to_resource(np, 2, &irq_res); | ||
372 | if (irq <= 0) | ||
373 | panic("no IRQ for system timer\n"); | ||
374 | |||
375 | pr_info("U300 GP1 timer @ base: %p, IRQ: %d\n", u300_timer_base, irq); | ||
376 | |||
357 | /* Clock the interrupt controller */ | 377 | /* Clock the interrupt controller */ |
358 | clk = clk_get_sys("apptimer", NULL); | 378 | clk = of_clk_get(np, 0); |
359 | BUG_ON(IS_ERR(clk)); | 379 | BUG_ON(IS_ERR(clk)); |
360 | clk_prepare_enable(clk); | 380 | clk_prepare_enable(clk); |
361 | rate = clk_get_rate(clk); | 381 | rate = clk_get_rate(clk); |
362 | 382 | ||
363 | setup_sched_clock(u300_read_sched_clock, 32, rate); | 383 | setup_sched_clock(u300_read_sched_clock, 32, rate); |
364 | 384 | ||
385 | u300_delay_timer.read_current_timer = &u300_read_current_timer; | ||
386 | u300_delay_timer.freq = rate; | ||
387 | register_current_timer_delay(&u300_delay_timer); | ||
388 | |||
365 | /* | 389 | /* |
366 | * Disable the "OS" and "DD" timers - these are designed for Symbian! | 390 | * Disable the "OS" and "DD" timers - these are designed for Symbian! |
367 | * Example usage in cnh1601578 cpu subsystem pd_timer_app.c | 391 | * Example usage in cnh1601578 cpu subsystem pd_timer_app.c |
368 | */ | 392 | */ |
369 | writel(U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE, | 393 | writel(U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE, |
370 | U300_TIMER_APP_VBASE + U300_TIMER_APP_CRC); | 394 | u300_timer_base + U300_TIMER_APP_CRC); |
371 | writel(U300_TIMER_APP_ROST_TIMER_RESET, | 395 | writel(U300_TIMER_APP_ROST_TIMER_RESET, |
372 | U300_TIMER_APP_VBASE + U300_TIMER_APP_ROST); | 396 | u300_timer_base + U300_TIMER_APP_ROST); |
373 | writel(U300_TIMER_APP_DOST_TIMER_DISABLE, | 397 | writel(U300_TIMER_APP_DOST_TIMER_DISABLE, |
374 | U300_TIMER_APP_VBASE + U300_TIMER_APP_DOST); | 398 | u300_timer_base + U300_TIMER_APP_DOST); |
375 | writel(U300_TIMER_APP_RDDT_TIMER_RESET, | 399 | writel(U300_TIMER_APP_RDDT_TIMER_RESET, |
376 | U300_TIMER_APP_VBASE + U300_TIMER_APP_RDDT); | 400 | u300_timer_base + U300_TIMER_APP_RDDT); |
377 | writel(U300_TIMER_APP_DDDT_TIMER_DISABLE, | 401 | writel(U300_TIMER_APP_DDDT_TIMER_DISABLE, |
378 | U300_TIMER_APP_VBASE + U300_TIMER_APP_DDDT); | 402 | u300_timer_base + U300_TIMER_APP_DDDT); |
379 | 403 | ||
380 | /* Reset the General Purpose timer 1. */ | 404 | /* Reset the General Purpose timer 1. */ |
381 | writel(U300_TIMER_APP_RGPT1_TIMER_RESET, | 405 | writel(U300_TIMER_APP_RGPT1_TIMER_RESET, |
382 | U300_TIMER_APP_VBASE + U300_TIMER_APP_RGPT1); | 406 | u300_timer_base + U300_TIMER_APP_RGPT1); |
383 | 407 | ||
384 | /* Set up the IRQ handler */ | 408 | /* Set up the IRQ handler */ |
385 | setup_irq(IRQ_U300_TIMER_APP_GP1, &u300_timer_irq); | 409 | setup_irq(irq, &u300_timer_irq); |
386 | 410 | ||
387 | /* Reset the General Purpose timer 2 */ | 411 | /* Reset the General Purpose timer 2 */ |
388 | writel(U300_TIMER_APP_RGPT2_TIMER_RESET, | 412 | writel(U300_TIMER_APP_RGPT2_TIMER_RESET, |
389 | U300_TIMER_APP_VBASE + U300_TIMER_APP_RGPT2); | 413 | u300_timer_base + U300_TIMER_APP_RGPT2); |
390 | /* Set this timer to run around forever */ | 414 | /* Set this timer to run around forever */ |
391 | writel(0xFFFFFFFFU, U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2TC); | 415 | writel(0xFFFFFFFFU, u300_timer_base + U300_TIMER_APP_GPT2TC); |
392 | /* Set continuous mode so it wraps around */ | 416 | /* Set continuous mode so it wraps around */ |
393 | writel(U300_TIMER_APP_SGPT2M_MODE_CONTINUOUS, | 417 | writel(U300_TIMER_APP_SGPT2M_MODE_CONTINUOUS, |
394 | U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT2M); | 418 | u300_timer_base + U300_TIMER_APP_SGPT2M); |
395 | /* Disable timer interrupts */ | 419 | /* Disable timer interrupts */ |
396 | writel(U300_TIMER_APP_GPT2IE_IRQ_DISABLE, | 420 | writel(U300_TIMER_APP_GPT2IE_IRQ_DISABLE, |
397 | U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2IE); | 421 | u300_timer_base + U300_TIMER_APP_GPT2IE); |
398 | /* Then enable the GP2 timer to use as a free running us counter */ | 422 | /* Then enable the GP2 timer to use as a free running us counter */ |
399 | writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE, | 423 | writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE, |
400 | U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT2); | 424 | u300_timer_base + U300_TIMER_APP_EGPT2); |
401 | 425 | ||
402 | /* Use general purpose timer 2 as clock source */ | 426 | /* Use general purpose timer 2 as clock source */ |
403 | if (clocksource_mmio_init(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC, | 427 | if (clocksource_mmio_init(u300_timer_base + U300_TIMER_APP_GPT2CC, |
404 | "GPT2", rate, 300, 32, clocksource_mmio_readl_up)) | 428 | "GPT2", rate, 300, 32, clocksource_mmio_readl_up)) |
405 | pr_err("timer: failed to initialize U300 clock source\n"); | 429 | pr_err("timer: failed to initialize U300 clock source\n"); |
406 | 430 | ||
@@ -413,3 +437,6 @@ void __init u300_timer_init(void) | |||
413 | * used by hrtimers! | 437 | * used by hrtimers! |
414 | */ | 438 | */ |
415 | } | 439 | } |
440 | |||
441 | CLOCKSOURCE_OF_DECLARE(u300_timer, "stericsson,u300-apptimer", | ||
442 | u300_timer_init_of); | ||