diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2012-09-06 04:08:24 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-09-17 18:20:22 -0400 |
commit | 4980f9bc2cec0f8ff0e0f2b021d46c7606ae1849 (patch) | |
tree | 0a840b3f1a2aa83836658efdf621654c0a6f2e5b /arch/arm/mach-integrator | |
parent | dc81df520bfb918a5cd4adc2ddcc7f1701fd1455 (diff) |
ARM: 7517/1: integrator: initial device tree support
This is initial device tree support for the ARM Integrator family,
we create a very basic device tree, #ifdef out the non-DT machines
when compiling for device tree.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-integrator')
-rw-r--r-- | arch/arm/mach-integrator/integrator_ap.c | 139 | ||||
-rw-r--r-- | arch/arm/mach-integrator/integrator_cp.c | 154 |
2 files changed, 225 insertions, 68 deletions
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index ff966d83281c..57add86c4a69 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <linux/mtd/physmap.h> | 34 | #include <linux/mtd/physmap.h> |
35 | #include <linux/clk.h> | 35 | #include <linux/clk.h> |
36 | #include <linux/platform_data/clk-integrator.h> | 36 | #include <linux/platform_data/clk-integrator.h> |
37 | #include <linux/of_irq.h> | ||
38 | #include <linux/of_address.h> | ||
37 | #include <video/vga.h> | 39 | #include <video/vga.h> |
38 | 40 | ||
39 | #include <mach/hardware.h> | 41 | #include <mach/hardware.h> |
@@ -161,23 +163,6 @@ static void __init ap_map_io(void) | |||
161 | vga_base = PCI_MEMORY_VADDR; | 163 | vga_base = PCI_MEMORY_VADDR; |
162 | } | 164 | } |
163 | 165 | ||
164 | #define INTEGRATOR_SC_VALID_INT 0x003fffff | ||
165 | |||
166 | static void __init ap_init_irq(void) | ||
167 | { | ||
168 | /* Disable all interrupts initially. */ | ||
169 | /* Do the core module ones */ | ||
170 | writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR); | ||
171 | |||
172 | /* do the header card stuff next */ | ||
173 | writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR); | ||
174 | writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR); | ||
175 | |||
176 | fpga_irq_init(VA_IC_BASE, "SC", IRQ_PIC_START, | ||
177 | -1, INTEGRATOR_SC_VALID_INT, NULL); | ||
178 | integrator_clk_init(false); | ||
179 | } | ||
180 | |||
181 | #ifdef CONFIG_PM | 166 | #ifdef CONFIG_PM |
182 | static unsigned long ic_irq_enable; | 167 | static unsigned long ic_irq_enable; |
183 | 168 | ||
@@ -330,9 +315,9 @@ static u32 notrace integrator_read_sched_clock(void) | |||
330 | return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE); | 315 | return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE); |
331 | } | 316 | } |
332 | 317 | ||
333 | static void integrator_clocksource_init(unsigned long inrate) | 318 | static void integrator_clocksource_init(unsigned long inrate, |
319 | void __iomem *base) | ||
334 | { | 320 | { |
335 | void __iomem *base = (void __iomem *)TIMER2_VA_BASE; | ||
336 | u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC; | 321 | u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC; |
337 | unsigned long rate = inrate; | 322 | unsigned long rate = inrate; |
338 | 323 | ||
@@ -349,7 +334,7 @@ static void integrator_clocksource_init(unsigned long inrate) | |||
349 | setup_sched_clock(integrator_read_sched_clock, 16, rate); | 334 | setup_sched_clock(integrator_read_sched_clock, 16, rate); |
350 | } | 335 | } |
351 | 336 | ||
352 | static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE; | 337 | static void __iomem * clkevt_base; |
353 | 338 | ||
354 | /* | 339 | /* |
355 | * IRQ handler for the timer | 340 | * IRQ handler for the timer |
@@ -421,11 +406,13 @@ static struct irqaction integrator_timer_irq = { | |||
421 | .dev_id = &integrator_clockevent, | 406 | .dev_id = &integrator_clockevent, |
422 | }; | 407 | }; |
423 | 408 | ||
424 | static void integrator_clockevent_init(unsigned long inrate) | 409 | static void integrator_clockevent_init(unsigned long inrate, |
410 | void __iomem *base, int irq) | ||
425 | { | 411 | { |
426 | unsigned long rate = inrate; | 412 | unsigned long rate = inrate; |
427 | unsigned int ctrl = 0; | 413 | unsigned int ctrl = 0; |
428 | 414 | ||
415 | clkevt_base = base; | ||
429 | /* Calculate and program a divisor */ | 416 | /* Calculate and program a divisor */ |
430 | if (rate > 0x100000 * HZ) { | 417 | if (rate > 0x100000 * HZ) { |
431 | rate /= 256; | 418 | rate /= 256; |
@@ -437,7 +424,7 @@ static void integrator_clockevent_init(unsigned long inrate) | |||
437 | timer_reload = rate / HZ; | 424 | timer_reload = rate / HZ; |
438 | writel(ctrl, clkevt_base + TIMER_CTRL); | 425 | writel(ctrl, clkevt_base + TIMER_CTRL); |
439 | 426 | ||
440 | setup_irq(IRQ_TIMERINT1, &integrator_timer_irq); | 427 | setup_irq(irq, &integrator_timer_irq); |
441 | clockevents_config_and_register(&integrator_clockevent, | 428 | clockevents_config_and_register(&integrator_clockevent, |
442 | rate, | 429 | rate, |
443 | 1, | 430 | 1, |
@@ -448,9 +435,91 @@ void __init ap_init_early(void) | |||
448 | { | 435 | { |
449 | } | 436 | } |
450 | 437 | ||
438 | #ifdef CONFIG_OF | ||
439 | |||
440 | static void __init ap_init_timer_of(void) | ||
441 | { | ||
442 | struct device_node *node; | ||
443 | const char *path; | ||
444 | void __iomem *base; | ||
445 | int err; | ||
446 | int irq; | ||
447 | struct clk *clk; | ||
448 | unsigned long rate; | ||
449 | |||
450 | clk = clk_get_sys("ap_timer", NULL); | ||
451 | BUG_ON(IS_ERR(clk)); | ||
452 | clk_prepare_enable(clk); | ||
453 | rate = clk_get_rate(clk); | ||
454 | |||
455 | err = of_property_read_string(of_aliases, | ||
456 | "arm,timer-primary", &path); | ||
457 | if (WARN_ON(err)) | ||
458 | return; | ||
459 | node = of_find_node_by_path(path); | ||
460 | base = of_iomap(node, 0); | ||
461 | if (WARN_ON(!base)) | ||
462 | return; | ||
463 | writel(0, base + TIMER_CTRL); | ||
464 | integrator_clocksource_init(rate, base); | ||
465 | |||
466 | err = of_property_read_string(of_aliases, | ||
467 | "arm,timer-secondary", &path); | ||
468 | if (WARN_ON(err)) | ||
469 | return; | ||
470 | node = of_find_node_by_path(path); | ||
471 | base = of_iomap(node, 0); | ||
472 | if (WARN_ON(!base)) | ||
473 | return; | ||
474 | irq = irq_of_parse_and_map(node, 0); | ||
475 | writel(0, base + TIMER_CTRL); | ||
476 | integrator_clockevent_init(rate, base, irq); | ||
477 | } | ||
478 | |||
479 | static struct sys_timer ap_of_timer = { | ||
480 | .init = ap_init_timer_of, | ||
481 | }; | ||
482 | |||
483 | static const struct of_device_id fpga_irq_of_match[] __initconst = { | ||
484 | { .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, }, | ||
485 | { /* Sentinel */ } | ||
486 | }; | ||
487 | |||
488 | static void __init ap_init_irq_of(void) | ||
489 | { | ||
490 | /* disable core module IRQs */ | ||
491 | writel(0xffffffffU, VA_CMIC_BASE + IRQ_ENABLE_CLEAR); | ||
492 | of_irq_init(fpga_irq_of_match); | ||
493 | integrator_clk_init(false); | ||
494 | } | ||
495 | |||
496 | static const char * ap_dt_board_compat[] = { | ||
497 | "arm,integrator-ap", | ||
498 | NULL, | ||
499 | }; | ||
500 | |||
501 | DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)") | ||
502 | .reserve = integrator_reserve, | ||
503 | .map_io = ap_map_io, | ||
504 | .nr_irqs = NR_IRQS_INTEGRATOR_AP, | ||
505 | .init_early = ap_init_early, | ||
506 | .init_irq = ap_init_irq_of, | ||
507 | .handle_irq = fpga_handle_irq, | ||
508 | .timer = &ap_of_timer, | ||
509 | .init_machine = ap_init, | ||
510 | .restart = integrator_restart, | ||
511 | .dt_compat = ap_dt_board_compat, | ||
512 | MACHINE_END | ||
513 | |||
514 | #endif | ||
515 | |||
516 | #ifdef CONFIG_ATAGS | ||
517 | |||
451 | /* | 518 | /* |
452 | * Set up timer(s). | 519 | * This is where non-devicetree initialization code is collected and stashed |
520 | * for eventual deletion. | ||
453 | */ | 521 | */ |
522 | |||
454 | static void __init ap_init_timer(void) | 523 | static void __init ap_init_timer(void) |
455 | { | 524 | { |
456 | struct clk *clk; | 525 | struct clk *clk; |
@@ -465,14 +534,32 @@ static void __init ap_init_timer(void) | |||
465 | writel(0, TIMER1_VA_BASE + TIMER_CTRL); | 534 | writel(0, TIMER1_VA_BASE + TIMER_CTRL); |
466 | writel(0, TIMER2_VA_BASE + TIMER_CTRL); | 535 | writel(0, TIMER2_VA_BASE + TIMER_CTRL); |
467 | 536 | ||
468 | integrator_clocksource_init(rate); | 537 | integrator_clocksource_init(rate, (void __iomem *)TIMER2_VA_BASE); |
469 | integrator_clockevent_init(rate); | 538 | integrator_clockevent_init(rate, (void __iomem *)TIMER1_VA_BASE, |
539 | IRQ_TIMERINT1); | ||
470 | } | 540 | } |
471 | 541 | ||
472 | static struct sys_timer ap_timer = { | 542 | static struct sys_timer ap_timer = { |
473 | .init = ap_init_timer, | 543 | .init = ap_init_timer, |
474 | }; | 544 | }; |
475 | 545 | ||
546 | #define INTEGRATOR_SC_VALID_INT 0x003fffff | ||
547 | |||
548 | static void __init ap_init_irq(void) | ||
549 | { | ||
550 | /* Disable all interrupts initially. */ | ||
551 | /* Do the core module ones */ | ||
552 | writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR); | ||
553 | |||
554 | /* do the header card stuff next */ | ||
555 | writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR); | ||
556 | writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR); | ||
557 | |||
558 | fpga_irq_init(VA_IC_BASE, "SC", IRQ_PIC_START, | ||
559 | -1, INTEGRATOR_SC_VALID_INT, NULL); | ||
560 | integrator_clk_init(false); | ||
561 | } | ||
562 | |||
476 | MACHINE_START(INTEGRATOR, "ARM-Integrator") | 563 | MACHINE_START(INTEGRATOR, "ARM-Integrator") |
477 | /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ | 564 | /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ |
478 | .atag_offset = 0x100, | 565 | .atag_offset = 0x100, |
@@ -486,3 +573,5 @@ MACHINE_START(INTEGRATOR, "ARM-Integrator") | |||
486 | .init_machine = ap_init, | 573 | .init_machine = ap_init, |
487 | .restart = integrator_restart, | 574 | .restart = integrator_restart, |
488 | MACHINE_END | 575 | MACHINE_END |
576 | |||
577 | #endif | ||
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 2b40bc10b388..6a2293a28a84 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/gfp.h> | 23 | #include <linux/gfp.h> |
24 | #include <linux/mtd/physmap.h> | 24 | #include <linux/mtd/physmap.h> |
25 | #include <linux/platform_data/clk-integrator.h> | 25 | #include <linux/platform_data/clk-integrator.h> |
26 | #include <linux/of_irq.h> | ||
27 | #include <linux/of_address.h> | ||
26 | 28 | ||
27 | #include <mach/hardware.h> | 29 | #include <mach/hardware.h> |
28 | #include <mach/platform.h> | 30 | #include <mach/platform.h> |
@@ -53,10 +55,6 @@ | |||
53 | 55 | ||
54 | #define INTCP_PA_CLCD_BASE 0xc0000000 | 56 | #define INTCP_PA_CLCD_BASE 0xc0000000 |
55 | 57 | ||
56 | #define INTCP_VA_CIC_BASE __io_address(INTEGRATOR_HDR_BASE + 0x40) | ||
57 | #define INTCP_VA_PIC_BASE __io_address(INTEGRATOR_IC_BASE) | ||
58 | #define INTCP_VA_SIC_BASE __io_address(INTEGRATOR_CP_SIC_BASE) | ||
59 | |||
60 | #define INTCP_ETH_SIZE 0x10 | 58 | #define INTCP_ETH_SIZE 0x10 |
61 | 59 | ||
62 | #define INTCP_VA_CTRL_BASE IO_ADDRESS(INTEGRATOR_CP_CTL_BASE) | 60 | #define INTCP_VA_CTRL_BASE IO_ADDRESS(INTEGRATOR_CP_CTL_BASE) |
@@ -143,37 +141,6 @@ static void __init intcp_map_io(void) | |||
143 | iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc)); | 141 | iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc)); |
144 | } | 142 | } |
145 | 143 | ||
146 | static void __init intcp_init_irq(void) | ||
147 | { | ||
148 | u32 pic_mask, cic_mask, sic_mask; | ||
149 | |||
150 | /* These masks are for the HW IRQ registers */ | ||
151 | pic_mask = ~((~0u) << (11 - IRQ_PIC_START)); | ||
152 | pic_mask |= (~((~0u) << (29 - 22))) << 22; | ||
153 | cic_mask = ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START)); | ||
154 | sic_mask = ~((~0u) << (1 + IRQ_SIC_END - IRQ_SIC_START)); | ||
155 | |||
156 | /* | ||
157 | * Disable all interrupt sources | ||
158 | */ | ||
159 | writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR); | ||
160 | writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR); | ||
161 | writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR); | ||
162 | writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR); | ||
163 | writel(sic_mask, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR); | ||
164 | writel(sic_mask, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR); | ||
165 | |||
166 | fpga_irq_init(INTCP_VA_PIC_BASE, "PIC", IRQ_PIC_START, | ||
167 | -1, pic_mask, NULL); | ||
168 | |||
169 | fpga_irq_init(INTCP_VA_CIC_BASE, "CIC", IRQ_CIC_START, | ||
170 | -1, cic_mask, NULL); | ||
171 | |||
172 | fpga_irq_init(INTCP_VA_SIC_BASE, "SIC", IRQ_SIC_START, | ||
173 | IRQ_CP_CPPLDINT, sic_mask, NULL); | ||
174 | integrator_clk_init(true); | ||
175 | } | ||
176 | |||
177 | /* | 144 | /* |
178 | * Flash handling. | 145 | * Flash handling. |
179 | */ | 146 | */ |
@@ -356,17 +323,116 @@ static void __init intcp_init_early(void) | |||
356 | #endif | 323 | #endif |
357 | } | 324 | } |
358 | 325 | ||
359 | static void __init intcp_init(void) | 326 | static void __init intcp_timer_init_of(void) |
327 | { | ||
328 | struct device_node *node; | ||
329 | const char *path; | ||
330 | void __iomem *base; | ||
331 | int err; | ||
332 | int irq; | ||
333 | |||
334 | err = of_property_read_string(of_aliases, | ||
335 | "arm,timer-primary", &path); | ||
336 | if (WARN_ON(err)) | ||
337 | return; | ||
338 | node = of_find_node_by_path(path); | ||
339 | base = of_iomap(node, 0); | ||
340 | if (WARN_ON(!base)) | ||
341 | return; | ||
342 | writel(0, base + TIMER_CTRL); | ||
343 | sp804_clocksource_init(base, node->name); | ||
344 | |||
345 | err = of_property_read_string(of_aliases, | ||
346 | "arm,timer-secondary", &path); | ||
347 | if (WARN_ON(err)) | ||
348 | return; | ||
349 | node = of_find_node_by_path(path); | ||
350 | base = of_iomap(node, 0); | ||
351 | if (WARN_ON(!base)) | ||
352 | return; | ||
353 | irq = irq_of_parse_and_map(node, 0); | ||
354 | writel(0, base + TIMER_CTRL); | ||
355 | sp804_clockevents_init(base, irq, node->name); | ||
356 | } | ||
357 | |||
358 | static struct sys_timer cp_of_timer = { | ||
359 | .init = intcp_timer_init_of, | ||
360 | }; | ||
361 | |||
362 | #ifdef CONFIG_OF | ||
363 | |||
364 | static const struct of_device_id fpga_irq_of_match[] __initconst = { | ||
365 | { .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, }, | ||
366 | { /* Sentinel */ } | ||
367 | }; | ||
368 | |||
369 | static void __init intcp_init_irq_of(void) | ||
360 | { | 370 | { |
361 | int i; | 371 | of_irq_init(fpga_irq_of_match); |
372 | integrator_clk_init(true); | ||
373 | } | ||
362 | 374 | ||
363 | platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs)); | 375 | static const char * intcp_dt_board_compat[] = { |
376 | "arm,integrator-cp", | ||
377 | NULL, | ||
378 | }; | ||
364 | 379 | ||
365 | for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { | 380 | DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)") |
366 | struct amba_device *d = amba_devs[i]; | 381 | .reserve = integrator_reserve, |
367 | amba_device_register(d, &iomem_resource); | 382 | .map_io = intcp_map_io, |
368 | } | 383 | .nr_irqs = NR_IRQS_INTEGRATOR_CP, |
369 | integrator_init(true); | 384 | .init_early = intcp_init_early, |
385 | .init_irq = intcp_init_irq_of, | ||
386 | .handle_irq = fpga_handle_irq, | ||
387 | .timer = &cp_of_timer, | ||
388 | .init_machine = intcp_init, | ||
389 | .restart = integrator_restart, | ||
390 | .dt_compat = intcp_dt_board_compat, | ||
391 | MACHINE_END | ||
392 | |||
393 | #endif | ||
394 | |||
395 | #ifdef CONFIG_ATAGS | ||
396 | |||
397 | /* | ||
398 | * This is where non-devicetree initialization code is collected and stashed | ||
399 | * for eventual deletion. | ||
400 | */ | ||
401 | |||
402 | #define INTCP_VA_CIC_BASE __io_address(INTEGRATOR_HDR_BASE + 0x40) | ||
403 | #define INTCP_VA_PIC_BASE __io_address(INTEGRATOR_IC_BASE) | ||
404 | #define INTCP_VA_SIC_BASE __io_address(INTEGRATOR_CP_SIC_BASE) | ||
405 | |||
406 | static void __init intcp_init_irq(void) | ||
407 | { | ||
408 | u32 pic_mask, cic_mask, sic_mask; | ||
409 | |||
410 | /* These masks are for the HW IRQ registers */ | ||
411 | pic_mask = ~((~0u) << (11 - IRQ_PIC_START)); | ||
412 | pic_mask |= (~((~0u) << (29 - 22))) << 22; | ||
413 | cic_mask = ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START)); | ||
414 | sic_mask = ~((~0u) << (1 + IRQ_SIC_END - IRQ_SIC_START)); | ||
415 | |||
416 | /* | ||
417 | * Disable all interrupt sources | ||
418 | */ | ||
419 | writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR); | ||
420 | writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR); | ||
421 | writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR); | ||
422 | writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR); | ||
423 | writel(sic_mask, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR); | ||
424 | writel(sic_mask, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR); | ||
425 | |||
426 | fpga_irq_init(INTCP_VA_PIC_BASE, "PIC", IRQ_PIC_START, | ||
427 | -1, pic_mask, NULL); | ||
428 | |||
429 | fpga_irq_init(INTCP_VA_CIC_BASE, "CIC", IRQ_CIC_START, | ||
430 | -1, cic_mask, NULL); | ||
431 | |||
432 | fpga_irq_init(INTCP_VA_SIC_BASE, "SIC", IRQ_SIC_START, | ||
433 | IRQ_CP_CPPLDINT, sic_mask, NULL); | ||
434 | |||
435 | integrator_clk_init(true); | ||
370 | } | 436 | } |
371 | 437 | ||
372 | #define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE) | 438 | #define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE) |
@@ -400,3 +466,5 @@ MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP") | |||
400 | .init_machine = intcp_init, | 466 | .init_machine = intcp_init, |
401 | .restart = integrator_restart, | 467 | .restart = integrator_restart, |
402 | MACHINE_END | 468 | MACHINE_END |
469 | |||
470 | #endif | ||