diff options
author | Pawel Moll <pawel.moll@arm.com> | 2012-02-23 08:04:51 -0500 |
---|---|---|
committer | Pawel Moll <pawel.moll@arm.com> | 2012-02-24 04:18:19 -0500 |
commit | 8deed1786a6479d0ccda51226582920ab1d6976c (patch) | |
tree | dd857ef58ef0094a1db5e7a088843b3241fa59ab /arch/arm/mach-vexpress/v2m.c | |
parent | 95d59741d281a64eba60c3283827b73680849770 (diff) |
ARM: vexpress: Add Device Tree support
This patch adds generic Versatile Express DT machine description,
Device Tree description for the motherboard and documentation for
the bindings.
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Diffstat (limited to 'arch/arm/mach-vexpress/v2m.c')
-rw-r--r-- | arch/arm/mach-vexpress/v2m.c | 153 |
1 files changed, 151 insertions, 2 deletions
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index c76f9144898a..dbf055103000 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c | |||
@@ -6,6 +6,10 @@ | |||
6 | #include <linux/amba/mmci.h> | 6 | #include <linux/amba/mmci.h> |
7 | #include <linux/io.h> | 7 | #include <linux/io.h> |
8 | #include <linux/init.h> | 8 | #include <linux/init.h> |
9 | #include <linux/of_address.h> | ||
10 | #include <linux/of_fdt.h> | ||
11 | #include <linux/of_irq.h> | ||
12 | #include <linux/of_platform.h> | ||
9 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
10 | #include <linux/ata_platform.h> | 14 | #include <linux/ata_platform.h> |
11 | #include <linux/smsc911x.h> | 15 | #include <linux/smsc911x.h> |
@@ -21,6 +25,8 @@ | |||
21 | #include <asm/mach/map.h> | 25 | #include <asm/mach/map.h> |
22 | #include <asm/mach/time.h> | 26 | #include <asm/mach/time.h> |
23 | #include <asm/hardware/arm_timer.h> | 27 | #include <asm/hardware/arm_timer.h> |
28 | #include <asm/hardware/cache-l2x0.h> | ||
29 | #include <asm/hardware/gic.h> | ||
24 | #include <asm/hardware/timer-sp.h> | 30 | #include <asm/hardware/timer-sp.h> |
25 | #include <asm/hardware/sp810.h> | 31 | #include <asm/hardware/sp810.h> |
26 | #include <asm/hardware/gic.h> | 32 | #include <asm/hardware/gic.h> |
@@ -430,8 +436,9 @@ static void __init v2m_populate_ct_desc(void) | |||
430 | ct_desc = ct_descs[i]; | 436 | ct_desc = ct_descs[i]; |
431 | 437 | ||
432 | if (!ct_desc) | 438 | if (!ct_desc) |
433 | panic("vexpress: failed to populate core tile description " | 439 | panic("vexpress: this kernel does not support core tile ID 0x%08x when booting via ATAGs.\n" |
434 | "for tile ID 0x%8x\n", current_tile_id); | 440 | "You may need a device tree blob or a different kernel to boot on this board.\n", |
441 | current_tile_id); | ||
435 | } | 442 | } |
436 | 443 | ||
437 | static void __init v2m_map_io(void) | 444 | static void __init v2m_map_io(void) |
@@ -476,3 +483,145 @@ MACHINE_START(VEXPRESS, "ARM-Versatile Express") | |||
476 | .init_machine = v2m_init, | 483 | .init_machine = v2m_init, |
477 | .restart = v2m_restart, | 484 | .restart = v2m_restart, |
478 | MACHINE_END | 485 | MACHINE_END |
486 | |||
487 | #if defined(CONFIG_ARCH_VEXPRESS_DT) | ||
488 | |||
489 | void __init v2m_dt_map_io(void) | ||
490 | { | ||
491 | iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc)); | ||
492 | |||
493 | #if defined(CONFIG_SMP) | ||
494 | vexpress_dt_smp_map_io(); | ||
495 | #endif | ||
496 | } | ||
497 | |||
498 | static struct clk_lookup v2m_dt_lookups[] = { | ||
499 | { /* AMBA bus clock */ | ||
500 | .con_id = "apb_pclk", | ||
501 | .clk = &dummy_apb_pclk, | ||
502 | }, { /* SP804 timers */ | ||
503 | .dev_id = "sp804", | ||
504 | .con_id = "v2m-timer0", | ||
505 | .clk = &v2m_sp804_clk, | ||
506 | }, { /* SP804 timers */ | ||
507 | .dev_id = "sp804", | ||
508 | .con_id = "v2m-timer1", | ||
509 | .clk = &v2m_sp804_clk, | ||
510 | }, { /* PL180 MMCI */ | ||
511 | .dev_id = "mb:mmci", /* 10005000.mmci */ | ||
512 | .clk = &osc2_clk, | ||
513 | }, { /* PL050 KMI0 */ | ||
514 | .dev_id = "10006000.kmi", | ||
515 | .clk = &osc2_clk, | ||
516 | }, { /* PL050 KMI1 */ | ||
517 | .dev_id = "10007000.kmi", | ||
518 | .clk = &osc2_clk, | ||
519 | }, { /* PL011 UART0 */ | ||
520 | .dev_id = "10009000.uart", | ||
521 | .clk = &osc2_clk, | ||
522 | }, { /* PL011 UART1 */ | ||
523 | .dev_id = "1000a000.uart", | ||
524 | .clk = &osc2_clk, | ||
525 | }, { /* PL011 UART2 */ | ||
526 | .dev_id = "1000b000.uart", | ||
527 | .clk = &osc2_clk, | ||
528 | }, { /* PL011 UART3 */ | ||
529 | .dev_id = "1000c000.uart", | ||
530 | .clk = &osc2_clk, | ||
531 | }, { /* SP805 WDT */ | ||
532 | .dev_id = "1000f000.wdt", | ||
533 | .clk = &v2m_ref_clk, | ||
534 | }, { /* PL111 CLCD */ | ||
535 | .dev_id = "1001f000.clcd", | ||
536 | .clk = &osc1_clk, | ||
537 | }, | ||
538 | }; | ||
539 | |||
540 | void __init v2m_dt_init_early(void) | ||
541 | { | ||
542 | struct device_node *node; | ||
543 | u32 dt_hbi; | ||
544 | |||
545 | node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg"); | ||
546 | v2m_sysreg_base = of_iomap(node, 0); | ||
547 | if (WARN_ON(!v2m_sysreg_base)) | ||
548 | return; | ||
549 | |||
550 | /* Confirm board type against DT property, if available */ | ||
551 | if (of_property_read_u32(allnodes, "arm,hbi", &dt_hbi) == 0) { | ||
552 | u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC); | ||
553 | u32 id = readl(v2m_sysreg_base + (misc & SYS_MISC_MASTERSITE ? | ||
554 | V2M_SYS_PROCID1 : V2M_SYS_PROCID0)); | ||
555 | u32 hbi = id & SYS_PROCIDx_HBI_MASK; | ||
556 | |||
557 | if (WARN_ON(dt_hbi != hbi)) | ||
558 | pr_warning("vexpress: DT HBI (%x) is not matching " | ||
559 | "hardware (%x)!\n", dt_hbi, hbi); | ||
560 | } | ||
561 | |||
562 | clkdev_add_table(v2m_dt_lookups, ARRAY_SIZE(v2m_dt_lookups)); | ||
563 | versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000); | ||
564 | } | ||
565 | |||
566 | static struct of_device_id vexpress_irq_match[] __initdata = { | ||
567 | { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, | ||
568 | {} | ||
569 | }; | ||
570 | |||
571 | static void __init v2m_dt_init_irq(void) | ||
572 | { | ||
573 | of_irq_init(vexpress_irq_match); | ||
574 | } | ||
575 | |||
576 | static void __init v2m_dt_timer_init(void) | ||
577 | { | ||
578 | struct device_node *node; | ||
579 | const char *path; | ||
580 | int err; | ||
581 | |||
582 | node = of_find_compatible_node(NULL, NULL, "arm,sp810"); | ||
583 | v2m_sysctl_init(of_iomap(node, 0)); | ||
584 | |||
585 | err = of_property_read_string(of_aliases, "arm,v2m_timer", &path); | ||
586 | if (WARN_ON(err)) | ||
587 | return; | ||
588 | node = of_find_node_by_path(path); | ||
589 | v2m_sp804_init(of_iomap(node, 0), irq_of_parse_and_map(node, 0)); | ||
590 | } | ||
591 | |||
592 | static struct sys_timer v2m_dt_timer = { | ||
593 | .init = v2m_dt_timer_init, | ||
594 | }; | ||
595 | |||
596 | static struct of_dev_auxdata v2m_dt_auxdata_lookup[] __initdata = { | ||
597 | OF_DEV_AUXDATA("arm,vexpress-flash", V2M_NOR0, "physmap-flash", | ||
598 | &v2m_flash_data), | ||
599 | OF_DEV_AUXDATA("arm,primecell", V2M_MMCI, "mb:mmci", &v2m_mmci_data), | ||
600 | {} | ||
601 | }; | ||
602 | |||
603 | static void __init v2m_dt_init(void) | ||
604 | { | ||
605 | l2x0_of_init(0x00400000, 0xfe0fffff); | ||
606 | of_platform_populate(NULL, of_default_bus_match_table, | ||
607 | v2m_dt_auxdata_lookup, NULL); | ||
608 | pm_power_off = v2m_power_off; | ||
609 | } | ||
610 | |||
611 | const static char *v2m_dt_match[] __initconst = { | ||
612 | "arm,vexpress", | ||
613 | NULL, | ||
614 | }; | ||
615 | |||
616 | DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express") | ||
617 | .dt_compat = v2m_dt_match, | ||
618 | .map_io = v2m_dt_map_io, | ||
619 | .init_early = v2m_dt_init_early, | ||
620 | .init_irq = v2m_dt_init_irq, | ||
621 | .timer = &v2m_dt_timer, | ||
622 | .init_machine = v2m_dt_init, | ||
623 | .handle_irq = gic_handle_irq, | ||
624 | .restart = v2m_restart, | ||
625 | MACHINE_END | ||
626 | |||
627 | #endif | ||