diff options
-rw-r--r-- | Documentation/devicetree/bindings/arm/cpus.txt | 42 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/arm/gic.txt | 70 | ||||
-rw-r--r-- | arch/arm/boot/dts/vexpress-v2p-ca15-tc2.dts | 283 | ||||
-rw-r--r-- | arch/arm/common/gic.c | 97 | ||||
-rw-r--r-- | arch/arm/include/asm/arch_timer.h | 5 | ||||
-rw-r--r-- | arch/arm/include/asm/prom.h | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/smp_plat.h | 12 | ||||
-rw-r--r-- | arch/arm/kernel/arch_timer.c | 10 | ||||
-rw-r--r-- | arch/arm/kernel/devtree.c | 40 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/Makefile.boot | 3 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/v2m.c | 15 | ||||
-rw-r--r-- | arch/arm/plat-versatile/headsmp.S | 2 |
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 |