diff options
author | Jon Medhurst <tixy@linaro.org> | 2012-07-09 11:27:22 +0100 |
---|---|---|
committer | Jon Medhurst <tixy@linaro.org> | 2012-07-16 14:22:22 +0100 |
commit | 64ea47e3fdb61b0b5db039599a05b1b9724bd7e3 (patch) | |
tree | 9e57286ea0dade2a0faf941ecfc7ab7b3373adcf | |
parent | ac30ff2af04aee919028702550e745c277f7868b (diff) |
ARM: vexpress: TC2 use sp804 timer as sched_clock
Use SP804 timer as sched_clock instead of arch timers as work-around
until the arch timers have been fixed.
Inspired by patch from Morten Rasmussen <Morten.Rasmussen@arm.com>
with the same description but made configurable by a device tree hack,
to enable a single kernel binary to be used with multiple CoreTiles.
Signed-off-by: Jon Medhurst <tixy@linaro.org>
-rw-r--r-- | arch/arm/boot/dts/vexpress-v2p-ca15-tc2.dts | 1 | ||||
-rw-r--r-- | arch/arm/include/asm/arch_timer.h | 5 | ||||
-rw-r--r-- | arch/arm/kernel/arch_timer.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/v2m.c | 15 |
4 files changed, 26 insertions, 5 deletions
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15-tc2.dts b/arch/arm/boot/dts/vexpress-v2p-ca15-tc2.dts index eadd587d35c7..6c863d5d29da 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca15-tc2.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca15-tc2.dts @@ -211,6 +211,7 @@ <1 14 0xf08>, <1 11 0xf08>, <1 10 0xf08>; + broken-for-sched-clock = <1>; }; pmu { diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index ed2e95d46e29..b02eba0fe824 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/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c index dd58035621f7..0925c702b0ef 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/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index fde26adaef32..d2dfa02cefee 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -69,7 +69,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; @@ -77,14 +78,17 @@ 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"); } static void __init v2m_timer_init(void) { v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K)); - 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 = { @@ -630,6 +634,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; @@ -641,11 +646,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); } |