From ccea0e6e49e4db8ee7968c183ecddb3e399c5f54 Mon Sep 17 00:00:00 2001
From: Michal Simek <monstr@monstr.eu>
Date: Thu, 7 Oct 2010 17:39:21 +1000
Subject: [PATCH] microblaze: Support timer on AXI lite

New microblaze systems uses two buses. One for memories
and flashes and the second for low-speed peripherals
which can run on different CLK. This is the reason
why the kernel is trying to read clock-frequency
directly from node. If there is then the kernel will
work with it. If not then cpu CLK is used.

Signed-off-by: Michal Simek <monstr@monstr.eu>
---
 arch/microblaze/include/asm/cpuinfo.h |  1 -
 arch/microblaze/kernel/timer.c        | 21 ++++++++++++++++-----
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/arch/microblaze/include/asm/cpuinfo.h b/arch/microblaze/include/asm/cpuinfo.h
index 7fab800496ae..cd257537ae54 100644
--- a/arch/microblaze/include/asm/cpuinfo.h
+++ b/arch/microblaze/include/asm/cpuinfo.h
@@ -77,7 +77,6 @@ struct cpuinfo {
 	u32 num_rd_brk;
 	u32 num_wr_brk;
 	u32 cpu_clock_freq; /* store real freq of cpu */
-	u32 freq_div_hz; /* store freq/HZ */
 
 	/* FPGA family */
 	u32 fpga_family_code;
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index fcb97e86003d..a5aa33db1df3 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -38,6 +38,9 @@ static unsigned int timer_baseaddr;
 #define TIMER_BASE	timer_baseaddr
 #endif
 
+unsigned int freq_div_hz;
+unsigned int timer_clock_freq;
+
 #define TCSR0	(0x00)
 #define TLR0	(0x04)
 #define TCR0	(0x08)
@@ -115,7 +118,7 @@ static void microblaze_timer_set_mode(enum clock_event_mode mode,
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 		printk(KERN_INFO "%s: periodic\n", __func__);
-		microblaze_timer0_start_periodic(cpuinfo.freq_div_hz);
+		microblaze_timer0_start_periodic(freq_div_hz);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
 		printk(KERN_INFO "%s: oneshot\n", __func__);
@@ -168,7 +171,7 @@ static struct irqaction timer_irqaction = {
 static __init void microblaze_clockevent_init(void)
 {
 	clockevent_microblaze_timer.mult =
-		div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC,
+		div_sc(timer_clock_freq, NSEC_PER_SEC,
 				clockevent_microblaze_timer.shift);
 	clockevent_microblaze_timer.max_delta_ns =
 		clockevent_delta2ns((u32)~0, &clockevent_microblaze_timer);
@@ -201,7 +204,7 @@ static struct cyclecounter microblaze_cc = {
 
 int __init init_microblaze_timecounter(void)
 {
-	microblaze_cc.mult = div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC,
+	microblaze_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
 				microblaze_cc.shift);
 
 	timecounter_init(&microblaze_tc, &microblaze_cc, sched_clock());
@@ -221,7 +224,7 @@ static struct clocksource clocksource_microblaze = {
 static int __init microblaze_clocksource_init(void)
 {
 	clocksource_microblaze.mult =
-			clocksource_hz2mult(cpuinfo.cpu_clock_freq,
+			clocksource_hz2mult(timer_clock_freq,
 						clocksource_microblaze.shift);
 	if (clocksource_register(&clocksource_microblaze))
 		panic("failed to register clocksource");
@@ -247,6 +250,7 @@ void __init time_init(void)
 	u32 irq, i = 0;
 	u32 timer_num = 1;
 	struct device_node *timer = NULL;
+	const void *prop;
 #ifdef CONFIG_SELFMOD_TIMER
 	unsigned int timer_baseaddr = 0;
 	int arr_func[] = {
@@ -286,7 +290,14 @@ void __init time_init(void)
 	printk(KERN_INFO "%s #0 at 0x%08x, irq=%d\n",
 		timer_list[i], timer_baseaddr, irq);
 
-	cpuinfo.freq_div_hz = cpuinfo.cpu_clock_freq / HZ;
+	/* If there is clock-frequency property than use it */
+	prop = of_get_property(timer, "clock-frequency", NULL);
+	if (prop)
+		timer_clock_freq = be32_to_cpup(prop);
+	else
+		timer_clock_freq = cpuinfo.cpu_clock_freq;
+
+	freq_div_hz = timer_clock_freq / HZ;
 
 	setup_irq(irq, &timer_irqaction);
 #ifdef CONFIG_HEART_BEAT