aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Medhurst <tixy@linaro.org>2012-07-09 11:27:22 +0100
committerJon Medhurst <tixy@linaro.org>2012-09-05 14:54:52 +0100
commit03cf23eb243b737729c0093fdd6c5f2e96dd728e (patch)
treeb749afb2a6925f4376dce0426962450f107927f9
parent973f3d6870dfa834f679bd94a2b103fc28323430 (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.dts1
-rw-r--r--arch/arm/include/asm/arch_timer.h5
-rw-r--r--arch/arm/kernel/arch_timer.c10
-rw-r--r--arch/arm/mach-vexpress/v2m.c15
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 2d94277251b2..958e8f710c1a 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 62e75475e57e..beceba4de355 100644
--- a/arch/arm/include/asm/arch_timer.h
+++ b/arch/arm/include/asm/arch_timer.h
@@ -7,6 +7,7 @@
#define ARCH_HAS_READ_CURRENT_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)
{
@@ -17,6 +18,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 cf258807160d..16fd0fd122af 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -325,6 +325,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 37608f22ee31..7732d8b795fb 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -72,7 +72,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;
@@ -80,7 +81,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");
}
@@ -440,7 +444,7 @@ static void __init v2m_timer_init(void)
{
v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K));
v2m_clk_init();
- 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 = {
@@ -612,6 +616,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;
@@ -625,11 +630,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);
}