From 6e84acc531b9f6e999481f94876e9e06ffe189a4 Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Mon, 9 Jul 2012 11:27:22 +0100 Subject: 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 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 --- arch/arm/boot/dts/vexpress-v2p-ca15-tc2.dts | 1 + arch/arm/kernel/arch_timer.c | 10 ++++++++++ arch/arm/mach-vexpress/v2m.c | 17 ++++++++++++----- 3 files changed, 23 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/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..ddf4cb388fa7 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 = { @@ -628,8 +632,11 @@ static void __init v2m_dt_init_irq(void) of_irq_init(vexpress_irq_match); } +extern bool __init arch_timer_broken_for_sched_clock(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 +648,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); } -- cgit v1.2.3