ARM: 6771/1: vexpress: add support for multiple core tiles
authorWill Deacon <will.deacon@arm.com>
Mon, 28 Feb 2011 16:01:04 +0000 (17:01 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sun, 20 Mar 2011 09:32:21 +0000 (09:32 +0000)
The current Versatile Express BSP defines the MACHINE_START macro
in the core tile code.

This patch moves this into the generic board code and introduces a
method for determining the current tile at runtime, allowing the
Kernel to have support for multiple tiles compiled in. Tile-specific
functions are executed via a descriptor struct containing the correct
implementations for the current tile.

Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/mach-vexpress/core.h
arch/arm/mach-vexpress/ct-ca9x4.c
arch/arm/mach-vexpress/include/mach/ct-ca9x4.h
arch/arm/mach-vexpress/include/mach/motherboard.h
arch/arm/mach-vexpress/platsmp.c
arch/arm/mach-vexpress/v2m.c

index e0312a1dce3a851b2a9624fc654290c5dbf55089..f4397159c173277da92d7c1bb0dbb60549bab8f2 100644 (file)
@@ -17,9 +17,3 @@ struct amba_device name##_device = {          \
        .irq            = IRQ_##base,           \
        /* .dma         = DMA_##base,*/         \
 }
-
-struct map_desc;
-
-void v2m_map_io(struct map_desc *tile, size_t num);
-void v2m_init_early(void);
-extern struct sys_timer v2m_timer;
index 30d5a5b0ac2172b9cd123ff89ef669cfbb6b281c..ebc22e759325a8b11efa731e49f6ea451cce8cfc 100644 (file)
 #include <linux/amba/clcd.h>
 #include <linux/clkdev.h>
 
-#include <asm/pgtable.h>
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/gic.h>
-#include <asm/mach-types.h>
 #include <asm/pmu.h>
+#include <asm/smp_scu.h>
 #include <asm/smp_twd.h>
 
 #include <mach/ct-ca9x4.h>
 
 #include <asm/hardware/timer-sp.h>
 
-#include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 
@@ -58,7 +56,7 @@ static void __init ct_ca9x4_map_io(void)
 #ifdef CONFIG_LOCAL_TIMERS
        twd_base = MMIO_P2V(A9_MPCORE_TWD);
 #endif
-       v2m_map_io(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
+       iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
 }
 
 static void __init ct_ca9x4_init_irq(void)
@@ -183,8 +181,6 @@ static struct platform_device pmu_device = {
 static void __init ct_ca9x4_init_early(void)
 {
        clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
-       v2m_init_early();
 }
 
 static void __init ct_ca9x4_init(void)
@@ -207,15 +203,34 @@ static void __init ct_ca9x4_init(void)
        platform_device_register(&pmu_device);
 }
 
-MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4")
-       .boot_params    = PLAT_PHYS_OFFSET + 0x00000100,
+#ifdef CONFIG_SMP
+static void ct_ca9x4_init_cpu_map(void)
+{
+       int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU));
+
+       for (i = 0; i < ncores; ++i)
+               set_cpu_possible(i, true);
+}
+
+static void ct_ca9x4_smp_enable(unsigned int max_cpus)
+{
+       int i;
+       for (i = 0; i < max_cpus; i++)
+               set_cpu_present(i, true);
+
+       scu_enable(MMIO_P2V(A9_MPCORE_SCU));
+}
+#endif
+
+struct ct_desc ct_ca9x4_desc __initdata = {
+       .id             = V2M_CT_ID_CA9,
+       .name           = "CA9x4",
        .map_io         = ct_ca9x4_map_io,
-       .init_irq       = ct_ca9x4_init_irq,
        .init_early     = ct_ca9x4_init_early,
-#if 0
-       .timer          = &ct_ca9x4_timer,
-#else
-       .timer          = &v2m_timer,
+       .init_irq       = ct_ca9x4_init_irq,
+       .init_tile      = ct_ca9x4_init,
+#ifdef CONFIG_SMP
+       .init_cpu_map   = ct_ca9x4_init_cpu_map,
+       .smp_enable     = ct_ca9x4_smp_enable,
 #endif
-       .init_machine   = ct_ca9x4_init,
-MACHINE_END
+};
index f9e2f8d229623d5825251e1999b0bf501a18b4a6..a34d3d4faae19c264d34372c09a11b8b274b219c 100644 (file)
@@ -45,4 +45,6 @@
 #define IRQ_CT_CA9X4_PMU_CPU2  94
 #define IRQ_CT_CA9X4_PMU_CPU3  95
 
+extern struct ct_desc ct_ca9x4_desc;
+
 #endif
index 98a8ded055bf87cd01991c1c4703c46fd5637208..0a3a375184052a81ea64f7588555919aeee899a4 100644 (file)
 int v2m_cfg_write(u32 devfn, u32 data);
 int v2m_cfg_read(u32 devfn, u32 *data);
 
+/*
+ * Core tile IDs
+ */
+#define V2M_CT_ID_CA9          0x0c000191
+#define V2M_CT_ID_UNSUPPORTED  0xff000191
+#define V2M_CT_ID_MASK         0xff000fff
+
+struct ct_desc {
+       u32                     id;
+       const char              *name;
+       void                    (*map_io)(void);
+       void                    (*init_early)(void);
+       void                    (*init_irq)(void);
+       void                    (*init_tile)(void);
+#ifdef CONFIG_SMP
+       void                    (*init_cpu_map)(void);
+       void                    (*smp_enable)(unsigned int);
+#endif
+};
+
+extern struct ct_desc *ct_desc;
+
 #endif
index 18927023c2cc4afce07c46e9486f2b23c4d72e57..2b5f7ac001a3326a160c346b9a3a0706d9e3c858 100644 (file)
 #include <linux/smp.h>
 #include <linux/io.h>
 
-#include <asm/smp_scu.h>
 #include <asm/unified.h>
 
-#include <mach/ct-ca9x4.h>
 #include <mach/motherboard.h>
 #define V2M_PA_CS7 0x10000000
 
 
 extern void versatile_secondary_startup(void);
 
-static void __iomem *scu_base_addr(void)
-{
-       return MMIO_P2V(A9_MPCORE_SCU);
-}
-
 /*
  * Initialise the CPU possible map early - this describes the CPUs
  * which may be present or become present in the system.
  */
 void __init smp_init_cpus(void)
 {
-       void __iomem *scu_base = scu_base_addr();
-       unsigned int i, ncores;
-
-       ncores = scu_base ? scu_get_core_count(scu_base) : 1;
-
-       /* sanity check */
-       if (ncores > NR_CPUS) {
-               printk(KERN_WARNING
-                      "vexpress: no. of cores (%d) greater than configured "
-                      "maximum of %d - clipping\n",
-                      ncores, NR_CPUS);
-               ncores = NR_CPUS;
-       }
-
-       for (i = 0; i < ncores; i++)
-               set_cpu_possible(i, true);
+       ct_desc->init_cpu_map();
 }
 
 void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-       int i;
-
        /*
         * Initialise the present map, which describes the set of CPUs
         * actually populated at the present time.
         */
-       for (i = 0; i < max_cpus; i++)
-               set_cpu_present(i, true);
-
-       scu_enable(scu_base_addr());
+       ct_desc->smp_enable(max_cpus);
 
        /*
         * Write the address of secondary startup into the
index 63ef663fb0be7faa6a97c056d71c40b87b378b47..ba46e8e0743713b4ddbfed79c2615600b8e37506 100644 (file)
@@ -14,7 +14,9 @@
 #include <linux/usb/isp1760.h>
 #include <linux/clkdev.h>
 
+#include <asm/mach-types.h>
 #include <asm/sizes.h>
+#include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
@@ -22,6 +24,7 @@
 #include <asm/hardware/timer-sp.h>
 #include <asm/hardware/sp810.h>
 
+#include <mach/ct-ca9x4.h>
 #include <mach/motherboard.h>
 
 #include <plat/sched_clock.h>
@@ -43,14 +46,9 @@ static struct map_desc v2m_io_desc[] __initdata = {
        },
 };
 
-void __init v2m_map_io(struct map_desc *tile, size_t num)
-{
-       iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
-       iotable_init(tile, num);
-}
-
-void __init v2m_init_early(void)
+static void __init v2m_init_early(void)
 {
+       ct_desc->init_early();
        versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000);
 }
 
@@ -71,7 +69,7 @@ static void __init v2m_timer_init(void)
        sp804_clockevents_init(MMIO_P2V(V2M_TIMER0), IRQ_V2M_TIMER0);
 }
 
-struct sys_timer v2m_timer = {
+static struct sys_timer v2m_timer = {
        .init   = v2m_timer_init,
 };
 
@@ -380,7 +378,44 @@ static void v2m_restart(char str, const char *cmd)
                printk(KERN_EMERG "Unable to reboot\n");
 }
 
-static int __init v2m_init(void)
+struct ct_desc *ct_desc;
+
+static struct ct_desc *ct_descs[] __initdata = {
+#ifdef CONFIG_ARCH_VEXPRESS_CA9X4
+       &ct_ca9x4_desc,
+#endif
+};
+
+static void __init v2m_populate_ct_desc(void)
+{
+       int i;
+       u32 current_tile_id;
+
+       ct_desc = NULL;
+       current_tile_id = readl(MMIO_P2V(V2M_SYS_PROCID0)) & V2M_CT_ID_MASK;
+
+       for (i = 0; i < ARRAY_SIZE(ct_descs) && !ct_desc; ++i)
+               if (ct_descs[i]->id == current_tile_id)
+                       ct_desc = ct_descs[i];
+
+       if (!ct_desc)
+               panic("vexpress: failed to populate core tile description "
+                     "for tile ID 0x%8x\n", current_tile_id);
+}
+
+static void __init v2m_map_io(void)
+{
+       iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
+       v2m_populate_ct_desc();
+       ct_desc->map_io();
+}
+
+static void __init v2m_init_irq(void)
+{
+       ct_desc->init_irq();
+}
+
+static void __init v2m_init(void)
 {
        int i;
 
@@ -399,6 +434,14 @@ static int __init v2m_init(void)
        pm_power_off = v2m_power_off;
        arm_pm_restart = v2m_restart;
 
-       return 0;
+       ct_desc->init_tile();
 }
-arch_initcall(v2m_init);
+
+MACHINE_START(VEXPRESS, "ARM-Versatile Express")
+       .boot_params    = PLAT_PHYS_OFFSET + 0x00000100,
+       .map_io         = v2m_map_io,
+       .init_early     = v2m_init_early,
+       .init_irq       = v2m_init_irq,
+       .timer          = &v2m_timer,
+       .init_machine   = v2m_init,
+MACHINE_END