aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-vexpress/v2m.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2012-02-24 07:39:18 -0500
committerArnd Bergmann <arnd@arndb.de>2012-02-24 07:39:18 -0500
commitfdc24d4ba20499febb90ff17d3b75674026712f8 (patch)
tree83cebb162add24be7b395090b4daca4bd752641b /arch/arm/mach-vexpress/v2m.c
parenta5f17d1f4c2831b9b9bf8b1a537cdbac995d6e13 (diff)
parent059289b260826deb43601644a7ad39c2608e6861 (diff)
Merge branch 'vexpress-dt-v3.3-rc4' of git://git.linaro.org/people/pawelmoll/linux into next/dt
* 'vexpress-dt-v3.3-rc4' of git://git.linaro.org/people/pawelmoll/linux: (573 commits) ARM: vexpress: Add Device Tree for V2P-CA15 core tile (TC1 variant) ARM: vexpress: Add Device Tree for V2P-CA9 core tile ARM: vexpress: Add Device Tree for V2P-CA5s core tile ARM: vexpress: Motherboard RS1 memory map support ARM: vexpress: Add Device Tree support ARM: vexpress: Use FDT data in platform SMP calls ARM: versatile: Map local timers using Device Tree when possible ARM: vexpress: Get rid of MMIO_P2V This adds full device tree boot support for the versatile express platform, as has been awaited for a long time. Conflicts: arch/arm/mach-vexpress/core.h The definition of AMBA_DEVICE was removed in one branch, and the definition of MMIO_P2V was removed in the other branch. Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/arm/mach-vexpress/v2m.c')
-rw-r--r--arch/arm/mach-vexpress/v2m.c281
1 files changed, 257 insertions, 24 deletions
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index ad64f97a2003..47cdcca5a7e7 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>
@@ -40,29 +46,45 @@
40 46
41static struct map_desc v2m_io_desc[] __initdata = { 47static struct map_desc v2m_io_desc[] __initdata = {
42 { 48 {
43 .virtual = __MMIO_P2V(V2M_PA_CS7), 49 .virtual = V2M_PERIPH,
44 .pfn = __phys_to_pfn(V2M_PA_CS7), 50 .pfn = __phys_to_pfn(V2M_PA_CS7),
45 .length = SZ_128K, 51 .length = SZ_128K,
46 .type = MT_DEVICE, 52 .type = MT_DEVICE,
47 }, 53 },
48}; 54};
49 55
50static void __init v2m_timer_init(void) 56static void __iomem *v2m_sysreg_base;
57
58static void __init v2m_sysctl_init(void __iomem *base)
51{ 59{
52 u32 scctrl; 60 u32 scctrl;
53 61
62 if (WARN_ON(!base))
63 return;
64
54 /* Select 1MHz TIMCLK as the reference clock for SP804 timers */ 65 /* Select 1MHz TIMCLK as the reference clock for SP804 timers */
55 scctrl = readl(MMIO_P2V(V2M_SYSCTL + SCCTRL)); 66 scctrl = readl(base + SCCTRL);
56 scctrl |= SCCTRL_TIMEREN0SEL_TIMCLK; 67 scctrl |= SCCTRL_TIMEREN0SEL_TIMCLK;
57 scctrl |= SCCTRL_TIMEREN1SEL_TIMCLK; 68 scctrl |= SCCTRL_TIMEREN1SEL_TIMCLK;
58 writel(scctrl, MMIO_P2V(V2M_SYSCTL + SCCTRL)); 69 writel(scctrl, base + SCCTRL);
70}
71
72static void __init v2m_sp804_init(void __iomem *base, unsigned int irq)
73{
74 if (WARN_ON(!base || irq == NO_IRQ))
75 return;
76
77 writel(0, base + TIMER_1_BASE + TIMER_CTRL);
78 writel(0, base + TIMER_2_BASE + TIMER_CTRL);
59 79
60 writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL); 80 sp804_clocksource_init(base + TIMER_2_BASE, "v2m-timer1");
61 writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL); 81 sp804_clockevents_init(base + TIMER_1_BASE, irq, "v2m-timer0");
82}
62 83
63 sp804_clocksource_init(MMIO_P2V(V2M_TIMER1), "v2m-timer1"); 84static void __init v2m_timer_init(void)
64 sp804_clockevents_init(MMIO_P2V(V2M_TIMER0), IRQ_V2M_TIMER0, 85{
65 "v2m-timer0"); 86 v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K));
87 v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
66} 88}
67 89
68static struct sys_timer v2m_timer = { 90static struct sys_timer v2m_timer = {
@@ -82,14 +104,14 @@ int v2m_cfg_write(u32 devfn, u32 data)
82 devfn |= SYS_CFG_START | SYS_CFG_WRITE; 104 devfn |= SYS_CFG_START | SYS_CFG_WRITE;
83 105
84 spin_lock(&v2m_cfg_lock); 106 spin_lock(&v2m_cfg_lock);
85 val = readl(MMIO_P2V(V2M_SYS_CFGSTAT)); 107 val = readl(v2m_sysreg_base + V2M_SYS_CFGSTAT);
86 writel(val & ~SYS_CFG_COMPLETE, MMIO_P2V(V2M_SYS_CFGSTAT)); 108 writel(val & ~SYS_CFG_COMPLETE, v2m_sysreg_base + V2M_SYS_CFGSTAT);
87 109
88 writel(data, MMIO_P2V(V2M_SYS_CFGDATA)); 110 writel(data, v2m_sysreg_base + V2M_SYS_CFGDATA);
89 writel(devfn, MMIO_P2V(V2M_SYS_CFGCTRL)); 111 writel(devfn, v2m_sysreg_base + V2M_SYS_CFGCTRL);
90 112
91 do { 113 do {
92 val = readl(MMIO_P2V(V2M_SYS_CFGSTAT)); 114 val = readl(v2m_sysreg_base + V2M_SYS_CFGSTAT);
93 } while (val == 0); 115 } while (val == 0);
94 spin_unlock(&v2m_cfg_lock); 116 spin_unlock(&v2m_cfg_lock);
95 117
@@ -103,22 +125,28 @@ int v2m_cfg_read(u32 devfn, u32 *data)
103 devfn |= SYS_CFG_START; 125 devfn |= SYS_CFG_START;
104 126
105 spin_lock(&v2m_cfg_lock); 127 spin_lock(&v2m_cfg_lock);
106 writel(0, MMIO_P2V(V2M_SYS_CFGSTAT)); 128 writel(0, v2m_sysreg_base + V2M_SYS_CFGSTAT);
107 writel(devfn, MMIO_P2V(V2M_SYS_CFGCTRL)); 129 writel(devfn, v2m_sysreg_base + V2M_SYS_CFGCTRL);
108 130
109 mb(); 131 mb();
110 132
111 do { 133 do {
112 cpu_relax(); 134 cpu_relax();
113 val = readl(MMIO_P2V(V2M_SYS_CFGSTAT)); 135 val = readl(v2m_sysreg_base + V2M_SYS_CFGSTAT);
114 } while (val == 0); 136 } while (val == 0);
115 137
116 *data = readl(MMIO_P2V(V2M_SYS_CFGDATA)); 138 *data = readl(v2m_sysreg_base + V2M_SYS_CFGDATA);
117 spin_unlock(&v2m_cfg_lock); 139 spin_unlock(&v2m_cfg_lock);
118 140
119 return !!(val & SYS_CFG_ERR); 141 return !!(val & SYS_CFG_ERR);
120} 142}
121 143
144void __init v2m_flags_set(u32 data)
145{
146 writel(~0, v2m_sysreg_base + V2M_SYS_FLAGSCLR);
147 writel(data, v2m_sysreg_base + V2M_SYS_FLAGSSET);
148}
149
122 150
123static struct resource v2m_pcie_i2c_resource = { 151static struct resource v2m_pcie_i2c_resource = {
124 .start = V2M_SERIAL_BUS_PCI, 152 .start = V2M_SERIAL_BUS_PCI,
@@ -204,7 +232,7 @@ static struct platform_device v2m_usb_device = {
204 232
205static void v2m_flash_set_vpp(struct platform_device *pdev, int on) 233static void v2m_flash_set_vpp(struct platform_device *pdev, int on)
206{ 234{
207 writel(on != 0, MMIO_P2V(V2M_SYS_FLASH)); 235 writel(on != 0, v2m_sysreg_base + V2M_SYS_FLASH);
208} 236}
209 237
210static struct physmap_flash_data v2m_flash_data = { 238static struct physmap_flash_data v2m_flash_data = {
@@ -258,7 +286,7 @@ static struct platform_device v2m_cf_device = {
258 286
259static unsigned int v2m_mmci_status(struct device *dev) 287static unsigned int v2m_mmci_status(struct device *dev)
260{ 288{
261 return readl(MMIO_P2V(V2M_SYS_MCI)) & (1 << 0); 289 return readl(v2m_sysreg_base + V2M_SYS_MCI) & (1 << 0);
262} 290}
263 291
264static struct mmci_platform_data v2m_mmci_data = { 292static struct mmci_platform_data v2m_mmci_data = {
@@ -371,7 +399,7 @@ static void __init v2m_init_early(void)
371{ 399{
372 ct_desc->init_early(); 400 ct_desc->init_early();
373 clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups)); 401 clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups));
374 versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000); 402 versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000);
375} 403}
376 404
377static void v2m_power_off(void) 405static void v2m_power_off(void)
@@ -400,20 +428,23 @@ static void __init v2m_populate_ct_desc(void)
400 u32 current_tile_id; 428 u32 current_tile_id;
401 429
402 ct_desc = NULL; 430 ct_desc = NULL;
403 current_tile_id = readl(MMIO_P2V(V2M_SYS_PROCID0)) & V2M_CT_ID_MASK; 431 current_tile_id = readl(v2m_sysreg_base + V2M_SYS_PROCID0)
432 & V2M_CT_ID_MASK;
404 433
405 for (i = 0; i < ARRAY_SIZE(ct_descs) && !ct_desc; ++i) 434 for (i = 0; i < ARRAY_SIZE(ct_descs) && !ct_desc; ++i)
406 if (ct_descs[i]->id == current_tile_id) 435 if (ct_descs[i]->id == current_tile_id)
407 ct_desc = ct_descs[i]; 436 ct_desc = ct_descs[i];
408 437
409 if (!ct_desc) 438 if (!ct_desc)
410 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"
411 "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);
412} 442}
413 443
414static void __init v2m_map_io(void) 444static void __init v2m_map_io(void)
415{ 445{
416 iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc)); 446 iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
447 v2m_sysreg_base = ioremap(V2M_SYSREGS, SZ_4K);
417 v2m_populate_ct_desc(); 448 v2m_populate_ct_desc();
418 ct_desc->map_io(); 449 ct_desc->map_io();
419} 450}
@@ -452,3 +483,205 @@ MACHINE_START(VEXPRESS, "ARM-Versatile Express")
452 .init_machine = v2m_init, 483 .init_machine = v2m_init,
453 .restart = v2m_restart, 484 .restart = v2m_restart,
454MACHINE_END 485MACHINE_END
486
487#if defined(CONFIG_ARCH_VEXPRESS_DT)
488
489static struct map_desc v2m_rs1_io_desc __initdata = {
490 .virtual = V2M_PERIPH,
491 .pfn = __phys_to_pfn(0x1c000000),
492 .length = SZ_2M,
493 .type = MT_DEVICE,
494};
495
496static int __init v2m_dt_scan_memory_map(unsigned long node, const char *uname,
497 int depth, void *data)
498{
499 const char **map = data;
500
501 if (strcmp(uname, "motherboard") != 0)
502 return 0;
503
504 *map = of_get_flat_dt_prop(node, "arm,v2m-memory-map", NULL);
505
506 return 1;
507}
508
509void __init v2m_dt_map_io(void)
510{
511 const char *map = NULL;
512
513 of_scan_flat_dt(v2m_dt_scan_memory_map, &map);
514
515 if (map && strcmp(map, "rs1") == 0)
516 iotable_init(&v2m_rs1_io_desc, 1);
517 else
518 iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
519
520#if defined(CONFIG_SMP)
521 vexpress_dt_smp_map_io();
522#endif
523}
524
525static struct clk_lookup v2m_dt_lookups[] = {
526 { /* AMBA bus clock */
527 .con_id = "apb_pclk",
528 .clk = &dummy_apb_pclk,
529 }, { /* SP804 timers */
530 .dev_id = "sp804",
531 .con_id = "v2m-timer0",
532 .clk = &v2m_sp804_clk,
533 }, { /* SP804 timers */
534 .dev_id = "sp804",
535 .con_id = "v2m-timer1",
536 .clk = &v2m_sp804_clk,
537 }, { /* PL180 MMCI */
538 .dev_id = "mb:mmci", /* 10005000.mmci */
539 .clk = &osc2_clk,
540 }, { /* PL050 KMI0 */
541 .dev_id = "10006000.kmi",
542 .clk = &osc2_clk,
543 }, { /* PL050 KMI1 */
544 .dev_id = "10007000.kmi",
545 .clk = &osc2_clk,
546 }, { /* PL011 UART0 */
547 .dev_id = "10009000.uart",
548 .clk = &osc2_clk,
549 }, { /* PL011 UART1 */
550 .dev_id = "1000a000.uart",
551 .clk = &osc2_clk,
552 }, { /* PL011 UART2 */
553 .dev_id = "1000b000.uart",
554 .clk = &osc2_clk,
555 }, { /* PL011 UART3 */
556 .dev_id = "1000c000.uart",
557 .clk = &osc2_clk,
558 }, { /* SP805 WDT */
559 .dev_id = "1000f000.wdt",
560 .clk = &v2m_ref_clk,
561 }, { /* PL111 CLCD */
562 .dev_id = "1001f000.clcd",
563 .clk = &osc1_clk,
564 },
565 /* RS1 memory map */
566 { /* PL180 MMCI */
567 .dev_id = "mb:mmci", /* 1c050000.mmci */
568 .clk = &osc2_clk,
569 }, { /* PL050 KMI0 */
570 .dev_id = "1c060000.kmi",
571 .clk = &osc2_clk,
572 }, { /* PL050 KMI1 */
573 .dev_id = "1c070000.kmi",
574 .clk = &osc2_clk,
575 }, { /* PL011 UART0 */
576 .dev_id = "1c090000.uart",
577 .clk = &osc2_clk,
578 }, { /* PL011 UART1 */
579 .dev_id = "1c0a0000.uart",
580 .clk = &osc2_clk,
581 }, { /* PL011 UART2 */
582 .dev_id = "1c0b0000.uart",
583 .clk = &osc2_clk,
584 }, { /* PL011 UART3 */
585 .dev_id = "1c0c0000.uart",
586 .clk = &osc2_clk,
587 }, { /* SP805 WDT */
588 .dev_id = "1c0f0000.wdt",
589 .clk = &v2m_ref_clk,
590 }, { /* PL111 CLCD */
591 .dev_id = "1c1f0000.clcd",
592 .clk = &osc1_clk,
593 },
594};
595
596void __init v2m_dt_init_early(void)
597{
598 struct device_node *node;
599 u32 dt_hbi;
600
601 node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg");
602 v2m_sysreg_base = of_iomap(node, 0);
603 if (WARN_ON(!v2m_sysreg_base))
604 return;
605
606 /* Confirm board type against DT property, if available */
607 if (of_property_read_u32(allnodes, "arm,hbi", &dt_hbi) == 0) {
608 u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC);
609 u32 id = readl(v2m_sysreg_base + (misc & SYS_MISC_MASTERSITE ?
610 V2M_SYS_PROCID1 : V2M_SYS_PROCID0));
611 u32 hbi = id & SYS_PROCIDx_HBI_MASK;
612
613 if (WARN_ON(dt_hbi != hbi))
614 pr_warning("vexpress: DT HBI (%x) is not matching "
615 "hardware (%x)!\n", dt_hbi, hbi);
616 }
617
618 clkdev_add_table(v2m_dt_lookups, ARRAY_SIZE(v2m_dt_lookups));
619 versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000);
620}
621
622static struct of_device_id vexpress_irq_match[] __initdata = {
623 { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
624 {}
625};
626
627static void __init v2m_dt_init_irq(void)
628{
629 of_irq_init(vexpress_irq_match);
630}
631
632static void __init v2m_dt_timer_init(void)
633{
634 struct device_node *node;
635 const char *path;
636 int err;
637
638 node = of_find_compatible_node(NULL, NULL, "arm,sp810");
639 v2m_sysctl_init(of_iomap(node, 0));
640
641 err = of_property_read_string(of_aliases, "arm,v2m_timer", &path);
642 if (WARN_ON(err))
643 return;
644 node = of_find_node_by_path(path);
645 v2m_sp804_init(of_iomap(node, 0), irq_of_parse_and_map(node, 0));
646}
647
648static struct sys_timer v2m_dt_timer = {
649 .init = v2m_dt_timer_init,
650};
651
652static struct of_dev_auxdata v2m_dt_auxdata_lookup[] __initdata = {
653 OF_DEV_AUXDATA("arm,vexpress-flash", V2M_NOR0, "physmap-flash",
654 &v2m_flash_data),
655 OF_DEV_AUXDATA("arm,primecell", V2M_MMCI, "mb:mmci", &v2m_mmci_data),
656 /* RS1 memory map */
657 OF_DEV_AUXDATA("arm,vexpress-flash", 0x08000000, "physmap-flash",
658 &v2m_flash_data),
659 OF_DEV_AUXDATA("arm,primecell", 0x1c050000, "mb:mmci", &v2m_mmci_data),
660 {}
661};
662
663static void __init v2m_dt_init(void)
664{
665 l2x0_of_init(0x00400000, 0xfe0fffff);
666 of_platform_populate(NULL, of_default_bus_match_table,
667 v2m_dt_auxdata_lookup, NULL);
668 pm_power_off = v2m_power_off;
669}
670
671const static char *v2m_dt_match[] __initconst = {
672 "arm,vexpress",
673 NULL,
674};
675
676DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
677 .dt_compat = v2m_dt_match,
678 .map_io = v2m_dt_map_io,
679 .init_early = v2m_dt_init_early,
680 .init_irq = v2m_dt_init_irq,
681 .timer = &v2m_dt_timer,
682 .init_machine = v2m_dt_init,
683 .handle_irq = gic_handle_irq,
684 .restart = v2m_restart,
685MACHINE_END
686
687#endif