diff options
| author | Vitja Makarov <vitja.makarov@gmail.com> | 2008-05-06 23:41:26 -0400 |
|---|---|---|
| committer | Bryan Wu <cooloney@kernel.org> | 2008-05-06 23:41:26 -0400 |
| commit | 1bfb4b21c7c39295f5535c139f796df1d51ec009 (patch) | |
| tree | 5c5a58a83c5f1d5d1ff984e8f073a16416fa8abb | |
| parent | 14b03204c8060d036b04cbb18bbd6f6f311f4fed (diff) | |
[Blackfin] arch: Support for CPU_FREQ and NOHZ
Singed-off-by: Vitja Makarov <vitja.makarov@gmail.com>
| -rw-r--r-- | arch/blackfin/kernel/time-ts.c | 10 | ||||
| -rw-r--r-- | arch/blackfin/mach-common/cpufreq.c | 24 | ||||
| -rw-r--r-- | include/asm-blackfin/time.h | 4 |
3 files changed, 26 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) | |||
| 60 | 60 | ||
| 61 | static cycle_t read_cycles(void) | 61 | static cycle_t read_cycles(void) |
| 62 | { | 62 | { |
| 63 | return get_cycles(); | 63 | return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod); |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | unsigned long long sched_clock(void) | 66 | unsigned long long sched_clock(void) |
| @@ -117,7 +117,7 @@ static void bfin_timer_set_mode(enum clock_event_mode mode, | |||
| 117 | break; | 117 | break; |
| 118 | } | 118 | } |
| 119 | case CLOCK_EVT_MODE_ONESHOT: | 119 | case CLOCK_EVT_MODE_ONESHOT: |
| 120 | bfin_write_TSCALE(0); | 120 | bfin_write_TSCALE(TIME_SCALE - 1); |
| 121 | bfin_write_TCOUNT(0); | 121 | bfin_write_TCOUNT(0); |
| 122 | bfin_write_TCNTL(TMPWR | TMREN); | 122 | bfin_write_TCNTL(TMPWR | TMREN); |
| 123 | CSYNC(); | 123 | CSYNC(); |
| @@ -183,10 +183,14 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) | |||
| 183 | 183 | ||
| 184 | static int __init bfin_clockevent_init(void) | 184 | static int __init bfin_clockevent_init(void) |
| 185 | { | 185 | { |
| 186 | unsigned long timer_clk; | ||
| 187 | |||
| 188 | timer_clk = get_cclk() / TIME_SCALE; | ||
| 189 | |||
| 186 | setup_irq(IRQ_CORETMR, &bfin_timer_irq); | 190 | setup_irq(IRQ_CORETMR, &bfin_timer_irq); |
| 187 | bfin_timer_init(); | 191 | bfin_timer_init(); |
| 188 | 192 | ||
| 189 | clockevent_bfin.mult = div_sc(get_cclk(), NSEC_PER_SEC, clockevent_bfin.shift); | 193 | clockevent_bfin.mult = div_sc(timer_clk, NSEC_PER_SEC, clockevent_bfin.shift); |
| 190 | clockevent_bfin.max_delta_ns = clockevent_delta2ns(-1, &clockevent_bfin); | 194 | clockevent_bfin.max_delta_ns = clockevent_delta2ns(-1, &clockevent_bfin); |
| 191 | clockevent_bfin.min_delta_ns = clockevent_delta2ns(100, &clockevent_bfin); | 195 | clockevent_bfin.min_delta_ns = clockevent_delta2ns(100, &clockevent_bfin); |
| 192 | clockevents_register_device(&clockevent_bfin); | 196 | 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 { | |||
| 62 | unsigned int tscale; /* change the divider on the core timer interrupt */ | 62 | unsigned int tscale; /* change the divider on the core timer interrupt */ |
| 63 | } dpm_state_table[3]; | 63 | } dpm_state_table[3]; |
| 64 | 64 | ||
| 65 | /* | ||
| 66 | normalized to maximum frequncy offset for CYCLES, | ||
| 67 | used in time-ts cycles clock source, but could be used | ||
| 68 | somewhere also. | ||
| 69 | */ | ||
| 70 | unsigned long long __bfin_cycles_off; | ||
| 71 | unsigned int __bfin_cycles_mod; | ||
| 72 | |||
| 65 | /**************************************************************************/ | 73 | /**************************************************************************/ |
| 66 | 74 | ||
| 67 | static unsigned int bfin_getfreq(unsigned int cpu) | 75 | static unsigned int bfin_getfreq(unsigned int cpu) |
| @@ -80,6 +88,7 @@ static int bfin_target(struct cpufreq_policy *policy, | |||
| 80 | unsigned int index, plldiv, tscale; | 88 | unsigned int index, plldiv, tscale; |
| 81 | unsigned long flags, cclk_hz; | 89 | unsigned long flags, cclk_hz; |
| 82 | struct cpufreq_freqs freqs; | 90 | struct cpufreq_freqs freqs; |
| 91 | cycles_t cycles; | ||
| 83 | 92 | ||
| 84 | if (cpufreq_frequency_table_target(policy, bfin_freq_table, | 93 | if (cpufreq_frequency_table_target(policy, bfin_freq_table, |
| 85 | target_freq, relation, &index)) | 94 | target_freq, relation, &index)) |
| @@ -101,8 +110,14 @@ static int bfin_target(struct cpufreq_policy *policy, | |||
| 101 | bfin_write_PLL_DIV(plldiv); | 110 | bfin_write_PLL_DIV(plldiv); |
| 102 | /* we have to adjust the core timer, because it is using cclk */ | 111 | /* we have to adjust the core timer, because it is using cclk */ |
| 103 | bfin_write_TSCALE(tscale); | 112 | bfin_write_TSCALE(tscale); |
| 113 | cycles = get_cycles(); | ||
| 104 | SSYNC(); | 114 | SSYNC(); |
| 115 | cycles += 10; /* ~10 cycles we loose after get_cycles() */ | ||
| 116 | __bfin_cycles_off += (cycles << __bfin_cycles_mod) - (cycles << index); | ||
| 117 | __bfin_cycles_mod = index; | ||
| 105 | local_irq_restore(flags); | 118 | local_irq_restore(flags); |
| 119 | /* TODO: just test case for cycles clock source, remove later */ | ||
| 120 | pr_debug("cpufreq: done\n"); | ||
| 106 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 121 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); |
| 107 | 122 | ||
| 108 | return 0; | 123 | return 0; |
| @@ -119,15 +134,6 @@ static int __init __bfin_cpu_init(struct cpufreq_policy *policy) | |||
| 119 | unsigned long cclk, sclk, csel, min_cclk; | 134 | unsigned long cclk, sclk, csel, min_cclk; |
| 120 | int index; | 135 | int index; |
| 121 | 136 | ||
| 122 | #ifdef CONFIG_CYCLES_CLOCKSOURCE | ||
| 123 | /* | ||
| 124 | * Clocksource CYCLES is still CONTINUOUS but not longer with a constant tick rate in case we enable | ||
| 125 | * CPU frequency scaling, since CYCLES runs off Core Clock. | ||
| 126 | */ | ||
| 127 | printk(KERN_WARNING "CPU frequency scaling not supported: Clocksource not suitable\n" | ||
| 128 | return -ENODEV; | ||
| 129 | #endif | ||
| 130 | |||
| 131 | if (policy->cpu != 0) | 137 | if (policy->cpu != 0) |
| 132 | return -EINVAL; | 138 | return -EINVAL; |
| 133 | 139 | ||
diff --git a/include/asm-blackfin/time.h b/include/asm-blackfin/time.h index 6e5859b6ea32..ddc43ce38533 100644 --- a/include/asm-blackfin/time.h +++ b/include/asm-blackfin/time.h | |||
| @@ -24,6 +24,8 @@ | |||
| 24 | 24 | ||
| 25 | #ifndef CONFIG_CPU_FREQ | 25 | #ifndef CONFIG_CPU_FREQ |
| 26 | #define TIME_SCALE 1 | 26 | #define TIME_SCALE 1 |
| 27 | #define __bfin_cycles_off (0) | ||
| 28 | #define __bfin_cycles_mod (0) | ||
| 27 | #else | 29 | #else |
| 28 | /* | 30 | /* |
| 29 | * Blackfin CPU frequency scaling supports max Core Clock 1, 1/2 and 1/4 . | 31 | * Blackfin CPU frequency scaling supports max Core Clock 1, 1/2 and 1/4 . |
| @@ -31,6 +33,8 @@ | |||
| 31 | * adjust the Core Timer Presale Register. This way we don't lose time. | 33 | * adjust the Core Timer Presale Register. This way we don't lose time. |
| 32 | */ | 34 | */ |
| 33 | #define TIME_SCALE 4 | 35 | #define TIME_SCALE 4 |
| 36 | extern unsigned long long __bfin_cycles_off; | ||
| 37 | extern unsigned int __bfin_cycles_mod; | ||
| 34 | #endif | 38 | #endif |
| 35 | 39 | ||
| 36 | #endif | 40 | #endif |
