summary refs log tree commit diff
path: root/arch/blackfin
diff options
context:
space:
mode:
authorVitja Makarov <vitja.makarov@gmail.com>2008-05-07 11:41:26 +0800
committerBryan Wu <cooloney@kernel.org>2008-05-07 11:41:26 +0800
commit1bfb4b21c7c39295f5535c139f796df1d51ec009 (patch)
tree5c5a58a83c5f1d5d1ff984e8f073a16416fa8abb /arch/blackfin
parent14b03204c8060d036b04cbb18bbd6f6f311f4fed (diff)
downloadlinux-1bfb4b21c7c39295f5535c139f796df1d51ec009.tar.gz
[Blackfin] arch: Support for CPU_FREQ and NOHZ
Singed-off-by: Vitja Makarov <vitja.makarov@gmail.com>

Diffstat (limited to 'arch/blackfin')
-rw-r--r--arch/blackfin/kernel/time-ts.c10
-rw-r--r--arch/blackfin/mach-common/cpufreq.c24
2 files changed, 22 insertions, 12 deletions
diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c
index 4482c47c09e5..e887efc86c29 100644
--- a/arch/blackfin/kernel/time-ts.c
+++ b/arch/blackfin/kernel/time-ts.c
@@ -60,7 +60,7 @@ static inline unsigned long long cycles_2_ns(cycle_t cyc)
 
 static cycle_t read_cycles(void)
 {
-	return get_cycles();
+	return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod);
 }
 
 unsigned long long sched_clock(void)
@@ -117,7 +117,7 @@ static void bfin_timer_set_mode(enum clock_event_mode mode,
 		break;
 	}
 	case CLOCK_EVT_MODE_ONESHOT:
-		bfin_write_TSCALE(0);
+		bfin_write_TSCALE(TIME_SCALE - 1);
 		bfin_write_TCOUNT(0);
 		bfin_write_TCNTL(TMPWR | TMREN);
 		CSYNC();
@@ -183,10 +183,14 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
 
 static int __init bfin_clockevent_init(void)
 {
+	unsigned long timer_clk;
+
+	timer_clk = get_cclk() / TIME_SCALE;
+
 	setup_irq(IRQ_CORETMR, &bfin_timer_irq);
 	bfin_timer_init();
 
-	clockevent_bfin.mult = div_sc(get_cclk(), NSEC_PER_SEC, clockevent_bfin.shift);
+	clockevent_bfin.mult = div_sc(timer_clk, NSEC_PER_SEC, clockevent_bfin.shift);
 	clockevent_bfin.max_delta_ns = clockevent_delta2ns(-1, &clockevent_bfin);
 	clockevent_bfin.min_delta_ns = clockevent_delta2ns(100, &clockevent_bfin);
 	clockevents_register_device(&clockevent_bfin);
diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c
index dd1515e4094c..75cdad291e88 100644
--- a/arch/blackfin/mach-common/cpufreq.c
+++ b/arch/blackfin/mach-common/cpufreq.c
@@ -62,6 +62,14 @@ static struct bfin_dpm_state {
 	unsigned int tscale; /* change the divider on the core timer interrupt */
 } dpm_state_table[3];
 
+/*
+   normalized to maximum frequncy offset for CYCLES,
+   used in time-ts cycles clock source, but could be used
+   somewhere also.
+ */
+unsigned long long __bfin_cycles_off;
+unsigned int __bfin_cycles_mod;
+
 /**************************************************************************/
 
 static unsigned int bfin_getfreq(unsigned int cpu)
@@ -80,6 +88,7 @@ static int bfin_target(struct cpufreq_policy *policy,
 	unsigned int index, plldiv, tscale;
 	unsigned long flags, cclk_hz;
 	struct cpufreq_freqs freqs;
+	cycles_t cycles;
 
 	if (cpufreq_frequency_table_target(policy, bfin_freq_table,
 		 target_freq, relation, &index))
@@ -101,8 +110,14 @@ static int bfin_target(struct cpufreq_policy *policy,
 		bfin_write_PLL_DIV(plldiv);
 		/* we have to adjust the core timer, because it is using cclk */
 		bfin_write_TSCALE(tscale);
+		cycles = get_cycles();
 		SSYNC();
+	cycles += 10; /* ~10 cycles we loose after get_cycles() */
+	__bfin_cycles_off += (cycles << __bfin_cycles_mod) - (cycles << index);
+	__bfin_cycles_mod = index;
 	local_irq_restore(flags);
+	/* TODO: just test case for cycles clock source, remove later */
+	pr_debug("cpufreq: done\n");
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
@@ -119,15 +134,6 @@ static int __init __bfin_cpu_init(struct cpufreq_policy *policy)
 	unsigned long cclk, sclk, csel, min_cclk;
 	int index;
 
-#ifdef CONFIG_CYCLES_CLOCKSOURCE
-/*
- * Clocksource CYCLES is still CONTINUOUS but not longer with a constant tick rate in case we enable
- * CPU frequency scaling, since CYCLES runs off Core Clock.
- */
-	printk(KERN_WARNING "CPU frequency scaling not supported: Clocksource not suitable\n"
-		return -ENODEV;
-#endif
-
 	if (policy->cpu != 0)
 		return -EINVAL;