aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-u300
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2013-04-08 04:50:11 -0400
committerLinus Walleij <linus.walleij@linaro.org>2013-05-31 05:24:44 -0400
commit5a5056cccfb0479f52a0464a6b371b441c84aa0c (patch)
tree38c7a3edd27425a05eb4bfecfe9d5ef144f699d8 /arch/arm/mach-u300
parent3c96d8ea8101936959dede664ac7b97b30fafbe8 (diff)
ARM: u300: device tree support for the timer
This adds device tree support for the U300 timer, by making the memory base offset and IRQ dynamically assigned, then optionally looking them up from the device tree. Since the timer needs to be registered before any platform devices are created, we will go into the device tree and look up the "/timer@c0014000" node and read our base address and IRQ from there. Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'arch/arm/mach-u300')
-rw-r--r--arch/arm/mach-u300/timer.c109
-rw-r--r--arch/arm/mach-u300/timer.h1
2 files changed, 72 insertions, 38 deletions
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c
index c3d3802b46a0..df1e3b5427b6 100644
--- a/arch/arm/mach-u300/timer.c
+++ b/arch/arm/mach-u300/timer.c
@@ -19,6 +19,8 @@
19#include <linux/err.h> 19#include <linux/err.h>
20#include <linux/irq.h> 20#include <linux/irq.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/of_address.h>
23#include <linux/of_irq.h>
22 24
23#include <mach/hardware.h> 25#include <mach/hardware.h>
24#include <mach/irqs.h> 26#include <mach/irqs.h>
@@ -190,6 +192,8 @@
190#define TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ) 192#define TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ)
191#define US_PER_TICK ((1000000 + (HZ/2)) / HZ) 193#define US_PER_TICK ((1000000 + (HZ/2)) / HZ)
192 194
195static void __iomem *u300_timer_base;
196
193/* 197/*
194 * The u300_set_mode() function is always called first, if we 198 * The u300_set_mode() function is always called first, if we
195 * have oneshot timer active, the oneshot scheduling function 199 * have oneshot timer active, the oneshot scheduling function
@@ -202,28 +206,28 @@ static void u300_set_mode(enum clock_event_mode mode,
202 case CLOCK_EVT_MODE_PERIODIC: 206 case CLOCK_EVT_MODE_PERIODIC:
203 /* Disable interrupts on GPT1 */ 207 /* Disable interrupts on GPT1 */
204 writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, 208 writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
205 U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); 209 u300_timer_base + U300_TIMER_APP_GPT1IE);
206 /* Disable GP1 while we're reprogramming it. */ 210 /* Disable GP1 while we're reprogramming it. */
207 writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, 211 writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
208 U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1); 212 u300_timer_base + U300_TIMER_APP_DGPT1);
209 /* 213 /*
210 * Set the periodic mode to a certain number of ticks per 214 * Set the periodic mode to a certain number of ticks per
211 * jiffy. 215 * jiffy.
212 */ 216 */
213 writel(TICKS_PER_JIFFY, 217 writel(TICKS_PER_JIFFY,
214 U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1TC); 218 u300_timer_base + U300_TIMER_APP_GPT1TC);
215 /* 219 /*
216 * Set continuous mode, so the timer keeps triggering 220 * Set continuous mode, so the timer keeps triggering
217 * interrupts. 221 * interrupts.
218 */ 222 */
219 writel(U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS, 223 writel(U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS,
220 U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT1M); 224 u300_timer_base + U300_TIMER_APP_SGPT1M);
221 /* Enable timer interrupts */ 225 /* Enable timer interrupts */
222 writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, 226 writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
223 U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); 227 u300_timer_base + U300_TIMER_APP_GPT1IE);
224 /* Then enable the OS timer again */ 228 /* Then enable the OS timer again */
225 writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, 229 writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
226 U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT1); 230 u300_timer_base + U300_TIMER_APP_EGPT1);
227 break; 231 break;
228 case CLOCK_EVT_MODE_ONESHOT: 232 case CLOCK_EVT_MODE_ONESHOT:
229 /* Just break; here? */ 233 /* Just break; here? */
@@ -234,33 +238,33 @@ static void u300_set_mode(enum clock_event_mode mode,
234 */ 238 */
235 /* Disable interrupts on GPT1 */ 239 /* Disable interrupts on GPT1 */
236 writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, 240 writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
237 U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); 241 u300_timer_base + U300_TIMER_APP_GPT1IE);
238 /* Disable GP1 while we're reprogramming it. */ 242 /* Disable GP1 while we're reprogramming it. */
239 writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, 243 writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
240 U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1); 244 u300_timer_base + U300_TIMER_APP_DGPT1);
241 /* 245 /*
242 * Expire far in the future, u300_set_next_event() will be 246 * Expire far in the future, u300_set_next_event() will be
243 * called soon... 247 * called soon...
244 */ 248 */
245 writel(0xFFFFFFFF, U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1TC); 249 writel(0xFFFFFFFF, u300_timer_base + U300_TIMER_APP_GPT1TC);
246 /* We run one shot per tick here! */ 250 /* We run one shot per tick here! */
247 writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT, 251 writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT,
248 U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT1M); 252 u300_timer_base + U300_TIMER_APP_SGPT1M);
249 /* Enable interrupts for this timer */ 253 /* Enable interrupts for this timer */
250 writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, 254 writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
251 U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); 255 u300_timer_base + U300_TIMER_APP_GPT1IE);
252 /* Enable timer */ 256 /* Enable timer */
253 writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, 257 writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
254 U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT1); 258 u300_timer_base + U300_TIMER_APP_EGPT1);
255 break; 259 break;
256 case CLOCK_EVT_MODE_UNUSED: 260 case CLOCK_EVT_MODE_UNUSED:
257 case CLOCK_EVT_MODE_SHUTDOWN: 261 case CLOCK_EVT_MODE_SHUTDOWN:
258 /* Disable interrupts on GP1 */ 262 /* Disable interrupts on GP1 */
259 writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, 263 writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
260 U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); 264 u300_timer_base + U300_TIMER_APP_GPT1IE);
261 /* Disable GP1 */ 265 /* Disable GP1 */
262 writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, 266 writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
263 U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1); 267 u300_timer_base + U300_TIMER_APP_DGPT1);
264 break; 268 break;
265 case CLOCK_EVT_MODE_RESUME: 269 case CLOCK_EVT_MODE_RESUME:
266 /* Ignore this call */ 270 /* Ignore this call */
@@ -282,27 +286,27 @@ static int u300_set_next_event(unsigned long cycles,
282{ 286{
283 /* Disable interrupts on GPT1 */ 287 /* Disable interrupts on GPT1 */
284 writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, 288 writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
285 U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); 289 u300_timer_base + U300_TIMER_APP_GPT1IE);
286 /* Disable GP1 while we're reprogramming it. */ 290 /* Disable GP1 while we're reprogramming it. */
287 writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, 291 writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
288 U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1); 292 u300_timer_base + U300_TIMER_APP_DGPT1);
289 /* Reset the General Purpose timer 1. */ 293 /* Reset the General Purpose timer 1. */
290 writel(U300_TIMER_APP_RGPT1_TIMER_RESET, 294 writel(U300_TIMER_APP_RGPT1_TIMER_RESET,
291 U300_TIMER_APP_VBASE + U300_TIMER_APP_RGPT1); 295 u300_timer_base + U300_TIMER_APP_RGPT1);
292 /* IRQ in n * cycles */ 296 /* IRQ in n * cycles */
293 writel(cycles, U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1TC); 297 writel(cycles, u300_timer_base + U300_TIMER_APP_GPT1TC);
294 /* 298 /*
295 * We run one shot per tick here! (This is necessary to reconfigure, 299 * We run one shot per tick here! (This is necessary to reconfigure,
296 * the timer will tilt if you don't!) 300 * the timer will tilt if you don't!)
297 */ 301 */
298 writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT, 302 writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT,
299 U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT1M); 303 u300_timer_base + U300_TIMER_APP_SGPT1M);
300 /* Enable timer interrupts */ 304 /* Enable timer interrupts */
301 writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, 305 writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
302 U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); 306 u300_timer_base + U300_TIMER_APP_GPT1IE);
303 /* Then enable the OS timer again */ 307 /* Then enable the OS timer again */
304 writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, 308 writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
305 U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT1); 309 u300_timer_base + U300_TIMER_APP_EGPT1);
306 return 0; 310 return 0;
307} 311}
308 312
@@ -321,8 +325,9 @@ static irqreturn_t u300_timer_interrupt(int irq, void *dev_id)
321{ 325{
322 struct clock_event_device *evt = &clockevent_u300_1mhz; 326 struct clock_event_device *evt = &clockevent_u300_1mhz;
323 /* ACK/Clear timer IRQ for the APP GPT1 Timer */ 327 /* ACK/Clear timer IRQ for the APP GPT1 Timer */
328
324 writel(U300_TIMER_APP_GPT1IA_IRQ_ACK, 329 writel(U300_TIMER_APP_GPT1IA_IRQ_ACK,
325 U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IA); 330 u300_timer_base + U300_TIMER_APP_GPT1IA);
326 evt->event_handler(evt); 331 evt->event_handler(evt);
327 return IRQ_HANDLED; 332 return IRQ_HANDLED;
328} 333}
@@ -343,12 +348,12 @@ static struct irqaction u300_timer_irq = {
343 348
344static u32 notrace u300_read_sched_clock(void) 349static u32 notrace u300_read_sched_clock(void)
345{ 350{
346 return readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC); 351 return readl(u300_timer_base + U300_TIMER_APP_GPT2CC);
347} 352}
348 353
349static unsigned long u300_read_current_timer(void) 354static unsigned long u300_read_current_timer(void)
350{ 355{
351 return readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC); 356 return readl(u300_timer_base + U300_TIMER_APP_GPT2CC);
352} 357}
353 358
354static struct delay_timer u300_delay_timer; 359static struct delay_timer u300_delay_timer;
@@ -356,11 +361,14 @@ static struct delay_timer u300_delay_timer;
356/* 361/*
357 * This sets up the system timers, clock source and clock event. 362 * This sets up the system timers, clock source and clock event.
358 */ 363 */
359void __init u300_timer_init(void) 364static void __init u300_timer_setup(void __iomem *base, int irq)
360{ 365{
361 struct clk *clk; 366 struct clk *clk;
362 unsigned long rate; 367 unsigned long rate;
363 368
369 u300_timer_base = base;
370 pr_info("U300 GP1 timer @ base: %p, IRQ: %d\n", u300_timer_base, irq);
371
364 /* Clock the interrupt controller */ 372 /* Clock the interrupt controller */
365 clk = clk_get_sys("apptimer", NULL); 373 clk = clk_get_sys("apptimer", NULL);
366 BUG_ON(IS_ERR(clk)); 374 BUG_ON(IS_ERR(clk));
@@ -378,40 +386,40 @@ void __init u300_timer_init(void)
378 * Example usage in cnh1601578 cpu subsystem pd_timer_app.c 386 * Example usage in cnh1601578 cpu subsystem pd_timer_app.c
379 */ 387 */
380 writel(U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE, 388 writel(U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE,
381 U300_TIMER_APP_VBASE + U300_TIMER_APP_CRC); 389 u300_timer_base + U300_TIMER_APP_CRC);
382 writel(U300_TIMER_APP_ROST_TIMER_RESET, 390 writel(U300_TIMER_APP_ROST_TIMER_RESET,
383 U300_TIMER_APP_VBASE + U300_TIMER_APP_ROST); 391 u300_timer_base + U300_TIMER_APP_ROST);
384 writel(U300_TIMER_APP_DOST_TIMER_DISABLE, 392 writel(U300_TIMER_APP_DOST_TIMER_DISABLE,
385 U300_TIMER_APP_VBASE + U300_TIMER_APP_DOST); 393 u300_timer_base + U300_TIMER_APP_DOST);
386 writel(U300_TIMER_APP_RDDT_TIMER_RESET, 394 writel(U300_TIMER_APP_RDDT_TIMER_RESET,
387 U300_TIMER_APP_VBASE + U300_TIMER_APP_RDDT); 395 u300_timer_base + U300_TIMER_APP_RDDT);
388 writel(U300_TIMER_APP_DDDT_TIMER_DISABLE, 396 writel(U300_TIMER_APP_DDDT_TIMER_DISABLE,
389 U300_TIMER_APP_VBASE + U300_TIMER_APP_DDDT); 397 u300_timer_base + U300_TIMER_APP_DDDT);
390 398
391 /* Reset the General Purpose timer 1. */ 399 /* Reset the General Purpose timer 1. */
392 writel(U300_TIMER_APP_RGPT1_TIMER_RESET, 400 writel(U300_TIMER_APP_RGPT1_TIMER_RESET,
393 U300_TIMER_APP_VBASE + U300_TIMER_APP_RGPT1); 401 u300_timer_base + U300_TIMER_APP_RGPT1);
394 402
395 /* Set up the IRQ handler */ 403 /* Set up the IRQ handler */
396 setup_irq(IRQ_U300_TIMER_APP_GP1, &u300_timer_irq); 404 setup_irq(irq, &u300_timer_irq);
397 405
398 /* Reset the General Purpose timer 2 */ 406 /* Reset the General Purpose timer 2 */
399 writel(U300_TIMER_APP_RGPT2_TIMER_RESET, 407 writel(U300_TIMER_APP_RGPT2_TIMER_RESET,
400 U300_TIMER_APP_VBASE + U300_TIMER_APP_RGPT2); 408 u300_timer_base + U300_TIMER_APP_RGPT2);
401 /* Set this timer to run around forever */ 409 /* Set this timer to run around forever */
402 writel(0xFFFFFFFFU, U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2TC); 410 writel(0xFFFFFFFFU, u300_timer_base + U300_TIMER_APP_GPT2TC);
403 /* Set continuous mode so it wraps around */ 411 /* Set continuous mode so it wraps around */
404 writel(U300_TIMER_APP_SGPT2M_MODE_CONTINUOUS, 412 writel(U300_TIMER_APP_SGPT2M_MODE_CONTINUOUS,
405 U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT2M); 413 u300_timer_base + U300_TIMER_APP_SGPT2M);
406 /* Disable timer interrupts */ 414 /* Disable timer interrupts */
407 writel(U300_TIMER_APP_GPT2IE_IRQ_DISABLE, 415 writel(U300_TIMER_APP_GPT2IE_IRQ_DISABLE,
408 U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2IE); 416 u300_timer_base + U300_TIMER_APP_GPT2IE);
409 /* Then enable the GP2 timer to use as a free running us counter */ 417 /* Then enable the GP2 timer to use as a free running us counter */
410 writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE, 418 writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE,
411 U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT2); 419 u300_timer_base + U300_TIMER_APP_EGPT2);
412 420
413 /* Use general purpose timer 2 as clock source */ 421 /* Use general purpose timer 2 as clock source */
414 if (clocksource_mmio_init(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC, 422 if (clocksource_mmio_init(u300_timer_base + U300_TIMER_APP_GPT2CC,
415 "GPT2", rate, 300, 32, clocksource_mmio_readl_up)) 423 "GPT2", rate, 300, 32, clocksource_mmio_readl_up))
416 pr_err("timer: failed to initialize U300 clock source\n"); 424 pr_err("timer: failed to initialize U300 clock source\n");
417 425
@@ -424,3 +432,28 @@ void __init u300_timer_init(void)
424 * used by hrtimers! 432 * used by hrtimers!
425 */ 433 */
426} 434}
435
436
437void __init u300_timer_init()
438{
439 u300_timer_setup(U300_TIMER_APP_VBASE, IRQ_U300_TIMER_APP_GP1);
440}
441
442#ifdef CONFIG_OF
443
444static void __init u300_timer_init_of(struct device_node *np)
445{
446 void __iomem *base;
447 struct resource irq_res;
448 int irq;
449
450 base = of_iomap(np, 0);
451 /* Get the IRQ for the GP1 timer */
452 irq = of_irq_to_resource(np, 2, &irq_res);
453 u300_timer_setup(base, irq);
454}
455
456CLOCKSOURCE_OF_DECLARE(u300_timer, "stericsson,u300-apptimer",
457 u300_timer_init_of);
458
459#endif
diff --git a/arch/arm/mach-u300/timer.h b/arch/arm/mach-u300/timer.h
index d34287bc34f5..7766dfa6979d 100644
--- a/arch/arm/mach-u300/timer.h
+++ b/arch/arm/mach-u300/timer.h
@@ -1 +1,2 @@
1extern void u300_timer_init(void); 1extern void u300_timer_init(void);
2