aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/arm/cpus.txt42
-rw-r--r--Documentation/devicetree/bindings/arm/gic.txt70
-rw-r--r--arch/arm/boot/dts/vexpress-v2p-ca15-tc2.dts283
-rw-r--r--arch/arm/common/gic.c97
-rw-r--r--arch/arm/include/asm/arch_timer.h5
-rw-r--r--arch/arm/include/asm/prom.h2
-rw-r--r--arch/arm/include/asm/smp_plat.h12
-rw-r--r--arch/arm/kernel/arch_timer.c10
-rw-r--r--arch/arm/kernel/devtree.c40
-rw-r--r--arch/arm/kernel/setup.c1
-rw-r--r--arch/arm/mach-vexpress/Makefile.boot3
-rw-r--r--arch/arm/mach-vexpress/v2m.c15
-rw-r--r--arch/arm/plat-versatile/headsmp.S2
13 files changed, 571 insertions, 11 deletions
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
new file mode 100644
index 00000000000..28f2b8c40c4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -0,0 +1,42 @@
+* ARM CPUs binding description
+
+The device tree allows to describe the layout of CPUs in a system through
+the "cpus" node, which in turn contains a number of subnodes (ie "cpu")
+defining properties for every cpu.
+
+Bindings for CPU nodes follow the ePAPR standard, available from:
+
+http://devicetree.org
+
+For the ARM architecture every CPU node must contain the following property:
+
+- reg : property defining the CPU MPIDR[23:0] register bits
+
+Every cpu node is required to set its device_type to "cpu".
+
+Example:
+
+ cpus {
+ #size-cells = <0>;
+ #address-cells = <1>;
+
+ CPU0: cpu@0x0 {
+ device_type = "cpu";
+ reg = <0x0>;
+ };
+
+ CPU1: cpu@0x1 {
+ device_type = "cpu";
+ reg = <0x1>;
+ };
+
+ CPU2: cpu@0x100 {
+ device_type = "cpu";
+ reg = <0x100>;
+ };
+
+ CPU3: cpu@0x101 {
+ device_type = "cpu";
+ reg = <0x101>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
index 62eb8df1e08..7c507bf99e7 100644
--- a/Documentation/devicetree/bindings/arm/gic.txt
+++ b/Documentation/devicetree/bindings/arm/gic.txt
@@ -88,3 +88,73 @@ Example:
<0x2c006000 0x2000>;
interrupts = <1 9 0xf04>;
};
+
+* ARM Generic Interrupt Controller CPU Interfaces
+
+ARM GIC device tree nodes contain subnodes representing its CPU interfaces.
+
+The main properties required by CPU interface nodes are:
+
+- compatible : "arm,gic-cpuif"
+- cpuif-id : specifies the CPU IF HW identifier
+- cpu : a phandle to the respective CPU node
+
+Example:
+
+ cpus {
+ #size-cells = <0>;
+ #address-cells = <1>;
+
+ CPU0: cpu@0x0 {
+ device_type = "cpu";
+ reg = <0x0>;
+ };
+
+ CPU1: cpu@0x1 {
+ device_type = "cpu";
+ reg = <0x1>;
+ };
+
+ CPU2: cpu@0x100 {
+ device_type = "cpu";
+ reg = <0x100>;
+ };
+
+ CPU3: cpu@0x101 {
+ device_type = "cpu";
+ reg = <0x101>;
+ };
+ };
+
+ intc: interrupt-controller@fff11000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <1>;
+ interrupt-controller;
+ reg = <0xfff11000 0x1000>,
+ <0xfff10100 0x100>;
+
+ gic-cpuif@0x0 {
+ compatible = "arm,gic-cpuif";
+ cpuif-id = <0x0>;
+ cpu = <&CPU0>;
+ };
+
+ gic-cpuif@0x1 {
+ compatible = "arm,gic-cpuif";
+ cpuif-id = <0x1>;
+ cpu = <&CPU1>;
+ };
+
+ gic-cpuif@0x2 {
+ compatible = "arm,gic-cpuif";
+ cpuif-id = <0x2>;
+ cpu = <&CPU2>;
+ };
+
+ gic-cpuif@0x3 {
+ compatible = "arm,gic-cpuif";
+ cpuif-id = <0x3>;
+ cpu = <&CPU3>;
+ };
+ };
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15-tc2.dts b/arch/arm/boot/dts/vexpress-v2p-ca15-tc2.dts
new file mode 100644
index 00000000000..b947cb6b48b
--- /dev/null
+++ b/arch/arm/boot/dts/vexpress-v2p-ca15-tc2.dts
@@ -0,0 +1,283 @@
+/*
+ * ARM Ltd. Versatile Express
+ *
+ * CoreTile Express A15x2 A7x3
+ * Cortex-A15_A7 MPCore (V2P-CA15_A7)
+ *
+ * This DTB describes the big (A15x2) cluster only!
+ * Make sure that you have the following lines in your board.txt:
+ *
+ * SCC: 0x018 0x00001FFF
+ * SCC: 0x700 0x00320003
+ *
+ * HBI-0249A
+ */
+
+/dts-v1/;
+
+/memreserve/ 0xff000000 0x01000000;
+
+/ {
+ model = "V2P-CA15_CA7";
+ arm,hbi = <0x249>;
+ compatible = "arm,vexpress,v2p-ca15,tc2", "arm,vexpress,v2p-ca15", "arm,vexpress";
+ interrupt-parent = <&gic>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ chosen { };
+
+ aliases {
+ serial0 = &v2m_serial0;
+ serial1 = &v2m_serial1;
+ serial2 = &v2m_serial2;
+ serial3 = &v2m_serial3;
+ i2c0 = &v2m_i2c_dvi;
+ i2c1 = &v2m_i2c_pcie;
+ };
+
+ clusters {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cluster0: cluster@0 {
+ reg = <0>;
+ cores {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ core0: core@0 {
+ reg = <0>;
+ };
+
+ core1: core@1 {
+ reg = <1>;
+ };
+
+ };
+ };
+
+ cluster1: cluster@1 {
+ reg = <1>;
+ cores {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ core2: core@0 {
+ reg = <0>;
+ };
+
+ core3: core@1 {
+ reg = <1>;
+ };
+
+ core4: core@2 {
+ reg = <2>;
+ };
+ };
+ };
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <0>;
+ cluster = <&cluster0>;
+ core = <&core0>;
+ clock-frequency = <1000000000>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <1>;
+ cluster = <&cluster0>;
+ core = <&core1>;
+ clock-frequency = <1000000000>;
+ };
+
+ cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x100>;
+ cluster = <&cluster1>;
+ core = <&core2>;
+ clock-frequency = <800000000>;
+ };
+
+ cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x101>;
+ cluster = <&cluster1>;
+ core = <&core3>;
+ clock-frequency = <800000000>;
+ };
+
+ cpu4: cpu@4 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x102>;
+ cluster = <&cluster1>;
+ core = <&core4>;
+ clock-frequency = <800000000>;
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x80000000>;
+ };
+
+ wdt@2a490000 {
+ compatible = "arm,sp805", "arm,primecell";
+ reg = <0x2a490000 0x1000>;
+ interrupts = <98>;
+ };
+
+ hdlcd@2b000000 {
+ compatible = "arm,hdlcd";
+ reg = <0x2b000000 0x1000>;
+ interrupts = <0 85 4>;
+ mode = "1024x768-16@60";
+ arm,vexpress-osc = <5>;
+ framebuffer = <0xff000000 0x01000000>;
+ };
+
+ memory-controller@2b0a0000 {
+ compatible = "arm,pl341", "arm,primecell";
+ reg = <0x2b0a0000 0x1000>;
+ };
+
+ gic: interrupt-controller@2c001000 {
+ compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0x2c001000 0x1000>,
+ <0x2c002000 0x1000>,
+ <0x2c004000 0x2000>,
+ <0x2c006000 0x2000>;
+ interrupts = <1 9 0xf04>;
+
+ gic-cpuif@0 {
+ compatible = "arm,gic-cpuif";
+ cpuif-id = <0>;
+ cpu = <&cpu0>;
+ };
+ gic-cpuif@1 {
+ compatible = "arm,gic-cpuif";
+ cpuif-id = <1>;
+ cpu = <&cpu1>;
+ };
+ gic-cpuif@2 {
+ compatible = "arm,gic-cpuif";
+ cpuif-id = <2>;
+ cpu = <&cpu2>;
+ };
+
+ gic-cpuif@3 {
+ compatible = "arm,gic-cpuif";
+ cpuif-id = <3>;
+ cpu = <&cpu3>;
+ };
+
+ gic-cpuif@4 {
+ compatible = "arm,gic-cpuif";
+ cpuif-id = <4>;
+ cpu = <&cpu4>;
+ };
+ };
+
+ memory-controller@7ffd0000 {
+ compatible = "arm,pl354", "arm,primecell";
+ reg = <0x7ffd0000 0x1000>;
+ interrupts = <0 86 4>,
+ <0 87 4>;
+ };
+
+ dma@7ffb0000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0x7ff00000 0x1000>;
+ interrupts = <0 92 4>,
+ <0 88 4>,
+ <0 89 4>,
+ <0 90 4>,
+ <0 91 4>;
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <1 13 0xf08>,
+ <1 14 0xf08>,
+ <1 11 0xf08>,
+ <1 10 0xf08>;
+ broken-for-sched-clock = <1>;
+ };
+
+ pmu {
+ compatible = "arm,cortex-a15-pmu", "arm,cortex-a9-pmu";
+ interrupts = <0 68 4>,
+ <0 69 4>;
+ };
+
+ motherboard {
+ ranges = <0 0 0x08000000 0x04000000>,
+ <1 0 0x14000000 0x04000000>,
+ <2 0 0x18000000 0x04000000>,
+ <3 0 0x1c000000 0x04000000>,
+ <4 0 0x0c000000 0x04000000>,
+ <5 0 0x10000000 0x04000000>;
+
+ interrupt-map-mask = <0 0 63>;
+ interrupt-map = <0 0 0 &gic 0 0 4>,
+ <0 0 1 &gic 0 1 4>,
+ <0 0 2 &gic 0 2 4>,
+ <0 0 3 &gic 0 3 4>,
+ <0 0 4 &gic 0 4 4>,
+ <0 0 5 &gic 0 5 4>,
+ <0 0 6 &gic 0 6 4>,
+ <0 0 7 &gic 0 7 4>,
+ <0 0 8 &gic 0 8 4>,
+ <0 0 9 &gic 0 9 4>,
+ <0 0 10 &gic 0 10 4>,
+ <0 0 11 &gic 0 11 4>,
+ <0 0 12 &gic 0 12 4>,
+ <0 0 13 &gic 0 13 4>,
+ <0 0 14 &gic 0 14 4>,
+ <0 0 15 &gic 0 15 4>,
+ <0 0 16 &gic 0 16 4>,
+ <0 0 17 &gic 0 17 4>,
+ <0 0 18 &gic 0 18 4>,
+ <0 0 19 &gic 0 19 4>,
+ <0 0 20 &gic 0 20 4>,
+ <0 0 21 &gic 0 21 4>,
+ <0 0 22 &gic 0 22 4>,
+ <0 0 23 &gic 0 23 4>,
+ <0 0 24 &gic 0 24 4>,
+ <0 0 25 &gic 0 25 4>,
+ <0 0 26 &gic 0 26 4>,
+ <0 0 27 &gic 0 27 4>,
+ <0 0 28 &gic 0 28 4>,
+ <0 0 29 &gic 0 29 4>,
+ <0 0 30 &gic 0 30 4>,
+ <0 0 31 &gic 0 31 4>,
+ <0 0 32 &gic 0 32 4>,
+ <0 0 33 &gic 0 33 4>,
+ <0 0 34 &gic 0 34 4>,
+ <0 0 35 &gic 0 35 4>,
+ <0 0 36 &gic 0 36 4>,
+ <0 0 37 &gic 0 37 4>,
+ <0 0 38 &gic 0 38 4>,
+ <0 0 39 &gic 0 39 4>,
+ <0 0 40 &gic 0 40 4>,
+ <0 0 41 &gic 0 41 4>,
+ <0 0 42 &gic 0 42 4>;
+ };
+};
+
+/include/ "vexpress-v2m-rs1.dtsi"
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index aa526998418..d108cc4e542 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -137,6 +137,86 @@ static inline unsigned int gic_irq(struct irq_data *d)
return d->hwirq;
}
+#ifdef CONFIG_OF
+static u32 gic_cpuif_logical_map[NR_CPUS];
+#define cpuif_logical_map(cpu) gic_cpuif_logical_map[cpu]
+
+/*
+ * Create a mapping of GIC CPU IF numbers to logical cpus through the device
+ * tree. GIC CPU IF are linked to the respective cpu nodes through the "cpu"
+ * phandle.
+ */
+static void __init gic_init_if_maps(struct gic_chip_data *gic)
+{
+ struct device_node *ncpu, *gic_cpuif;
+ struct irq_domain *domain = gic->domain;
+ int i;
+
+ for (i = 0; i < NR_CPUS; i++)
+ cpuif_logical_map(i) = cpu_logical_map(i);
+
+ if (!domain || !domain->of_node)
+ return;
+
+ for_each_child_of_node(domain->of_node, gic_cpuif) {
+ const u32 *cpuif_hwid, *mpidr;
+ int len;
+
+ if (!of_device_is_compatible(gic_cpuif, "arm,gic-cpuif"))
+ continue;
+
+ pr_debug(" * %s...\n", gic_cpuif->full_name);
+
+ ncpu = of_parse_phandle(gic_cpuif, "cpu", 0);
+
+ if (!ncpu) {
+ pr_err(" * %s missing cpu phandle\n",
+ gic_cpuif->full_name);
+ continue;
+ }
+
+ mpidr = of_get_property(ncpu, "reg", &len);
+
+ if (!mpidr || len != 4) {
+ pr_err(" * %s missing reg property\n",
+ ncpu->full_name);
+ continue;
+ }
+
+ cpuif_hwid = of_get_property(gic_cpuif, "cpuif-id", &len);
+
+ if (!cpuif_hwid || len != 4) {
+ pr_err(" * %s missing cpuif-id property\n",
+ gic_cpuif->full_name);
+ continue;
+ }
+
+ /*
+ * Do the logical enumeration once in arm_dt_init_cpu_maps and
+ * use it again here to avoid logical numbering mix-ups between
+ * cpu and interrupt controller ids
+ */
+
+ i = get_logical_index(be32_to_cpup(mpidr));
+
+ if (i < 0) {
+ pr_err(" * %s mpidr mismatch\n",
+ ncpu->full_name);
+ continue;
+ }
+
+ if (!i)
+ printk(KERN_INFO "Booting Linux on GIC CPU IF 0x%x\n",
+ be32_to_cpup(cpuif_hwid));
+
+ cpuif_logical_map(i) = be32_to_cpup(cpuif_hwid);
+ }
+}
+#else
+static inline void gic_init_if_maps(struct gic_chip_data *gic) {}
+#define cpuif_logical_map(cpu) cpu_logical_map(cpu)
+#endif
+
/*
* Routines to acknowledge, disable and enable interrupts
*/
@@ -242,7 +322,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
return -EINVAL;
mask = 0xff << shift;
- bit = 1 << (cpu_logical_map(cpu) + shift);
+ bit = 1 << (cpuif_logical_map(cpu) + shift);
raw_spin_lock(&irq_controller_lock);
val = readl_relaxed(reg) & ~mask;
@@ -349,7 +429,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
u32 cpumask;
unsigned int gic_irqs = gic->gic_irqs;
void __iomem *base = gic_data_dist_base(gic);
- u32 cpu = cpu_logical_map(smp_processor_id());
+ u32 cpu = cpuif_logical_map(smp_processor_id());
cpumask = 1 << cpu;
cpumask |= cpumask << 8;
@@ -651,6 +731,7 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
BUG_ON(gic_nr >= MAX_GIC_NR);
gic = &gic_data[gic_nr];
+
#ifdef CONFIG_GIC_NON_BANKED
if (percpu_offset) { /* Frankein-GIC without banked registers... */
unsigned int cpu;
@@ -665,7 +746,8 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
}
for_each_possible_cpu(cpu) {
- unsigned long offset = percpu_offset * cpu_logical_map(cpu);
+ unsigned long offset =
+ percpu_offset * cpuif_logical_map(cpu);
*per_cpu_ptr(gic->dist_base.percpu_base, cpu) = dist_base + offset;
*per_cpu_ptr(gic->cpu_base.percpu_base, cpu) = cpu_base + offset;
}
@@ -716,6 +798,13 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
if (WARN_ON(!gic->domain))
return;
+ /*
+ * create the logical/physical mapping just for the
+ * primary GIC
+ */
+ if (gic_nr == 0)
+ gic_init_if_maps(gic);
+
gic_chip.flags |= gic_arch_extn.flags;
gic_dist_init(gic);
gic_cpu_init(gic);
@@ -737,7 +826,7 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
/* Convert our logical CPU mask into a physical one. */
for_each_cpu(cpu, mask)
- map |= 1 << cpu_logical_map(cpu);
+ map |= 1 << cpuif_logical_map(cpu);
/*
* Ensure that stores to Normal memory are visible to the
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
index ed2e95d46e2..b02eba0fe82 100644
--- a/arch/arm/include/asm/arch_timer.h
+++ b/arch/arm/include/asm/arch_timer.h
@@ -4,6 +4,7 @@
#ifdef CONFIG_ARM_ARCH_TIMER
int arch_timer_of_register(void);
int arch_timer_sched_clock_init(void);
+bool arch_timer_broken_for_sched_clock(void);
#else
static inline int arch_timer_of_register(void)
{
@@ -14,6 +15,10 @@ static inline int arch_timer_sched_clock_init(void)
{
return -ENXIO;
}
+static inline bool arch_timer_broken_for_sched_clock(void)
+{
+ return false;
+}
#endif
#endif
diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h
index aeae9c609df..8dd51dc1a36 100644
--- a/arch/arm/include/asm/prom.h
+++ b/arch/arm/include/asm/prom.h
@@ -15,6 +15,7 @@
extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
extern void arm_dt_memblock_reserve(void);
+extern void __init arm_dt_init_cpu_maps(void);
#else /* CONFIG_OF */
@@ -24,6 +25,7 @@ static inline struct machine_desc *setup_machine_fdt(unsigned int dt_phys)
}
static inline void arm_dt_memblock_reserve(void) { }
+static inline void arm_dt_init_cpu_maps(void) { }
#endif /* CONFIG_OF */
#endif /* ASMARM_PROM_H */
diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h
index 558d6c80aca..deabc7806d3 100644
--- a/arch/arm/include/asm/smp_plat.h
+++ b/arch/arm/include/asm/smp_plat.h
@@ -5,6 +5,9 @@
#ifndef __ASMARM_SMP_PLAT_H
#define __ASMARM_SMP_PLAT_H
+#include <linux/cpumask.h>
+#include <linux/err.h>
+
#include <asm/cputype.h>
/*
@@ -49,4 +52,13 @@ static inline int cache_ops_need_broadcast(void)
extern int __cpu_logical_map[];
#define cpu_logical_map(cpu) __cpu_logical_map[cpu]
+static inline int get_logical_index(u32 mpidr)
+{
+ int cpu;
+ for (cpu = 0; cpu < nr_cpu_ids; cpu++)
+ if (cpu_logical_map(cpu) == mpidr)
+ return cpu;
+ return -EINVAL;
+}
+
#endif
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index dd58035621f..0925c702b0e 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -314,6 +314,16 @@ static const struct of_device_id arch_timer_of_match[] __initconst = {
{},
};
+bool __init arch_timer_broken_for_sched_clock(void)
+{
+ u32 broken = false;
+ struct device_node *np;
+ np = of_find_matching_node(NULL, arch_timer_of_match);
+ if (np)
+ of_property_read_u32(np, "broken-for-sched-clock", &broken);
+ return broken;
+}
+
int __init arch_timer_of_register(void)
{
struct device_node *np;
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index bee7f9d47f0..a4662b1c3fd 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -19,8 +19,10 @@
#include <linux/of_irq.h>
#include <linux/of_platform.h>
+#include <asm/cputype.h>
#include <asm/setup.h>
#include <asm/page.h>
+#include <asm/smp_plat.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
@@ -61,6 +63,44 @@ void __init arm_dt_memblock_reserve(void)
}
}
+/*
+ * arm_dt_init_cpu_maps - Function retrieves cpu nodes from the device tree
+ * and builds the cpu logical map array containing MPIDR values related to
+ * logical cpus
+ *
+ * Updates the cpu possible mask with the number of parsed cpu nodes
+ */
+void __init arm_dt_init_cpu_maps(void)
+{
+ struct device_node *dn = NULL;
+ int i, cpu = 1;
+
+ while ((dn = of_find_node_by_type(dn, "cpu")) && cpu <= nr_cpu_ids) {
+ const u32 *hwid;
+ int len;
+
+ pr_debug(" * %s...\n", dn->full_name);
+
+ hwid = of_get_property(dn, "reg", &len);
+
+ if (!hwid || len != 4) {
+ pr_err(" * %s missing reg property\n", dn->full_name);
+ continue;
+ }
+
+ i = (be32_to_cpup(hwid) == (read_cpuid_mpidr() & 0xffffff))
+ ? 0 : cpu++;
+
+ if (!i)
+ printk(KERN_INFO "Booting Linux on CPU HWID 0x%x\n",
+ be32_to_cpup(hwid));
+
+ cpu_logical_map(i) = be32_to_cpup(hwid);
+
+ set_cpu_possible(i, true);
+ }
+}
+
/**
* setup_machine_fdt - Machine setup when an dtb was passed to the kernel
* @dt_phys: physical address of dt blob
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index e15d83bb4ea..2389b6a8584 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -976,6 +976,7 @@ void __init setup_arch(char **cmdline_p)
unflatten_device_tree();
+ arm_dt_init_cpu_maps();
#ifdef CONFIG_SMP
if (is_smp())
smp_init_cpus();
diff --git a/arch/arm/mach-vexpress/Makefile.boot b/arch/arm/mach-vexpress/Makefile.boot
index 909f85ebf5f..1f3949d6ffc 100644
--- a/arch/arm/mach-vexpress/Makefile.boot
+++ b/arch/arm/mach-vexpress/Makefile.boot
@@ -6,4 +6,5 @@ initrd_phys-y := 0x60800000
dtb-$(CONFIG_ARCH_VEXPRESS_DT) += vexpress-v2p-ca5s.dtb \
vexpress-v2p-ca9.dtb \
- vexpress-v2p-ca15-tc1.dtb
+ vexpress-v2p-ca15-tc1.dtb \
+ vexpress-v2p-ca15-tc2.dtb
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 2371eb76c90..4a7b0a86a33 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -71,7 +71,8 @@ static void __init v2m_sysctl_init(void __iomem *base)
writel(scctrl, base + SCCTRL);
}
-static void __init v2m_sp804_init(void __iomem *base, unsigned int irq)
+static void __init v2m_sp804_init(void __iomem *base, unsigned int irq,
+ int use_sched_clock)
{
if (WARN_ON(!base || irq == NO_IRQ))
return;
@@ -79,7 +80,10 @@ static void __init v2m_sp804_init(void __iomem *base, unsigned int irq)
writel(0, base + TIMER_1_BASE + TIMER_CTRL);
writel(0, base + TIMER_2_BASE + TIMER_CTRL);
- sp804_clocksource_init(base + TIMER_2_BASE, "v2m-timer1");
+ if (use_sched_clock)
+ sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE, "v2m-timer1");
+ else
+ sp804_clocksource_init(base + TIMER_2_BASE, "v2m-timer1");
sp804_clockevents_init(base + TIMER_1_BASE, irq, "v2m-timer0");
}
@@ -436,7 +440,7 @@ static void __init v2m_timer_init(void)
v2m_clk_init();
if (ct_desc->init_clk)
ct_desc->init_clk();
- v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
+ v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0, 0);
}
static struct sys_timer v2m_timer = {
@@ -654,6 +658,7 @@ static void __init v2m_dt_init_irq(void)
static void __init v2m_dt_timer_init(void)
{
+ int sp804_sched_clock = arch_timer_broken_for_sched_clock();
struct device_node *node;
const char *path;
int err;
@@ -668,11 +673,11 @@ static void __init v2m_dt_timer_init(void)
if (WARN_ON(err))
return;
node = of_find_node_by_path(path);
- v2m_sp804_init(of_iomap(node, 0), irq_of_parse_and_map(node, 0));
+ v2m_sp804_init(of_iomap(node, 0), irq_of_parse_and_map(node, 0), sp804_sched_clock);
if (arch_timer_of_register() != 0)
twd_local_timer_of_register();
- if (arch_timer_sched_clock_init() != 0)
+ if (!sp804_sched_clock && arch_timer_sched_clock_init() != 0)
versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000);
if (v2m_dt_hdlcd_osc.site) {
diff --git a/arch/arm/plat-versatile/headsmp.S b/arch/arm/plat-versatile/headsmp.S
index dd703ef09b8..c805e0c06cf 100644
--- a/arch/arm/plat-versatile/headsmp.S
+++ b/arch/arm/plat-versatile/headsmp.S
@@ -20,7 +20,7 @@
*/
ENTRY(versatile_secondary_startup)
mrc p15, 0, r0, c0, c0, 5
- and r0, r0, #15
+ bfc r0, #24, #8
adr r4, 1f
ldmia r4, {r5, r6}
sub r4, r4, r5