-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
yaml --- r: 92340 b: refs/heads/master c: e6c91b6 h: refs/heads/master v: v3
- Loading branch information
Michael Hennerich
authored and
Bryan Wu
committed
Apr 24, 2008
1 parent
773d96e
commit 798798e
Showing
6 changed files
with
264 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
--- | ||
refs/heads/master: fe44193c55e26b9b835722b5ee2519972f59c540 | ||
refs/heads/master: e6c91b64dd6e4c3adf39483c85a936eef9465e19 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
/* | ||
* File: arch/blackfin/mach-common/cpufreq.c | ||
* Based on: | ||
* Author: | ||
* | ||
* Created: | ||
* Description: Blackfin core clock scaling | ||
* | ||
* Modified: | ||
* Copyright 2004-2008 Analog Devices Inc. | ||
* | ||
* Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, see the file COPYING, or write | ||
* to the Free Software Foundation, Inc., | ||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
*/ | ||
|
||
#include <linux/kernel.h> | ||
#include <linux/types.h> | ||
#include <linux/init.h> | ||
#include <linux/cpufreq.h> | ||
#include <linux/fs.h> | ||
#include <asm/blackfin.h> | ||
#include <asm/time.h> | ||
|
||
|
||
/* this is the table of CCLK frequencies, in Hz */ | ||
/* .index is the entry in the auxillary dpm_state_table[] */ | ||
static struct cpufreq_frequency_table bfin_freq_table[] = { | ||
{ | ||
.frequency = CPUFREQ_TABLE_END, | ||
.index = 0, | ||
}, | ||
{ | ||
.frequency = CPUFREQ_TABLE_END, | ||
.index = 1, | ||
}, | ||
{ | ||
.frequency = CPUFREQ_TABLE_END, | ||
.index = 2, | ||
}, | ||
{ | ||
.frequency = CPUFREQ_TABLE_END, | ||
.index = 0, | ||
}, | ||
}; | ||
|
||
static struct bfin_dpm_state { | ||
unsigned int csel; /* system clock divider */ | ||
unsigned int tscale; /* change the divider on the core timer interrupt */ | ||
} dpm_state_table[3]; | ||
|
||
/**************************************************************************/ | ||
|
||
static unsigned int bfin_getfreq(unsigned int cpu) | ||
{ | ||
/* The driver only support single cpu */ | ||
if (cpu != 0) | ||
return -1; | ||
|
||
return get_cclk(); | ||
} | ||
|
||
|
||
static int bfin_target(struct cpufreq_policy *policy, | ||
unsigned int target_freq, unsigned int relation) | ||
{ | ||
unsigned int index, plldiv, tscale; | ||
unsigned long flags, cclk_hz; | ||
struct cpufreq_freqs freqs; | ||
|
||
if (cpufreq_frequency_table_target(policy, bfin_freq_table, | ||
target_freq, relation, &index)) | ||
return -EINVAL; | ||
|
||
cclk_hz = bfin_freq_table[index].frequency; | ||
|
||
freqs.old = bfin_getfreq(0); | ||
freqs.new = cclk_hz; | ||
freqs.cpu = 0; | ||
|
||
pr_debug("cpufreq: changing cclk to %lu; target = %u, oldfreq = %u\n", | ||
cclk_hz, target_freq, freqs.old); | ||
|
||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
local_irq_save(flags); | ||
plldiv = (bfin_read_PLL_DIV() & SSEL) | dpm_state_table[index].csel; | ||
tscale = dpm_state_table[index].tscale; | ||
bfin_write_PLL_DIV(plldiv); | ||
/* we have to adjust the core timer, because it is using cclk */ | ||
bfin_write_TSCALE(tscale); | ||
SSYNC(); | ||
local_irq_restore(flags); | ||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
|
||
return 0; | ||
} | ||
|
||
static int bfin_verify_speed(struct cpufreq_policy *policy) | ||
{ | ||
return cpufreq_frequency_table_verify(policy, bfin_freq_table); | ||
} | ||
|
||
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 MONOTONIC 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; | ||
|
||
cclk = get_cclk(); | ||
sclk = get_sclk(); | ||
|
||
#if ANOMALY_05000273 | ||
min_cclk = sclk * 2; | ||
#else | ||
min_cclk = sclk; | ||
#endif | ||
csel = ((bfin_read_PLL_DIV() & CSEL) >> 4); | ||
|
||
for (index = 0; (cclk >> index) >= min_cclk && csel <= 3; index++, csel++) { | ||
bfin_freq_table[index].frequency = cclk >> index; | ||
dpm_state_table[index].csel = csel << 4; /* Shift now into PLL_DIV bitpos */ | ||
dpm_state_table[index].tscale = (TIME_SCALE / (1 << csel)) - 1; | ||
|
||
pr_debug("cpufreq: freq:%d csel:%d tscale:%d\n", | ||
bfin_freq_table[index].frequency, | ||
dpm_state_table[index].csel, | ||
dpm_state_table[index].tscale); | ||
} | ||
|
||
policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
|
||
policy->cpuinfo.transition_latency = (bfin_read_PLL_LOCKCNT() / (sclk / 1000000)) * 1000; | ||
/*Now ,only support one cpu */ | ||
policy->cur = cclk; | ||
cpufreq_frequency_table_get_attr(bfin_freq_table, policy->cpu); | ||
return cpufreq_frequency_table_cpuinfo(policy, bfin_freq_table); | ||
} | ||
|
||
static struct freq_attr *bfin_freq_attr[] = { | ||
&cpufreq_freq_attr_scaling_available_freqs, | ||
NULL, | ||
}; | ||
|
||
static struct cpufreq_driver bfin_driver = { | ||
.verify = bfin_verify_speed, | ||
.target = bfin_target, | ||
.get = bfin_getfreq, | ||
.init = __bfin_cpu_init, | ||
.name = "bfin cpufreq", | ||
.owner = THIS_MODULE, | ||
.attr = bfin_freq_attr, | ||
}; | ||
|
||
static int __init bfin_cpu_init(void) | ||
{ | ||
return cpufreq_register_driver(&bfin_driver); | ||
} | ||
|
||
static void __exit bfin_cpu_exit(void) | ||
{ | ||
cpufreq_unregister_driver(&bfin_driver); | ||
} | ||
|
||
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
MODULE_DESCRIPTION("cpufreq driver for Blackfin"); | ||
MODULE_LICENSE("GPL"); | ||
|
||
module_init(bfin_cpu_init); | ||
module_exit(bfin_cpu_exit); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
* asm-blackfin/time.h: | ||
* | ||
* Copyright 2004-2008 Analog Devices Inc. | ||
* | ||
* Licensed under the GPL-2 or later. | ||
*/ | ||
|
||
#ifndef _ASM_BLACKFIN_TIME_H | ||
#define _ASM_BLACKFIN_TIME_H | ||
|
||
/* | ||
* The way that the Blackfin core timer works is: | ||
* - CCLK is divided by a programmable 8-bit pre-scaler (TSCALE) | ||
* - Every time TSCALE ticks, a 32bit is counted down (TCOUNT) | ||
* | ||
* If you take the fastest clock (1ns, or 1GHz to make the math work easier) | ||
* 10ms is 10,000,000 clock ticks, which fits easy into a 32-bit counter | ||
* (32 bit counter is 4,294,967,296ns or 4.2 seconds) so, we don't need | ||
* to use TSCALE, and program it to zero (which is pass CCLK through). | ||
* If you feel like using it, try to keep HZ * TIMESCALE to some | ||
* value that divides easy (like power of 2). | ||
*/ | ||
|
||
#ifndef CONFIG_CPU_FREQ | ||
#define TIME_SCALE 1 | ||
#else | ||
/* | ||
* Blackfin CPU frequency scaling supports max Core Clock 1, 1/2 and 1/4 . | ||
* Whenever we change the Core Clock frequency changes we immediately | ||
* adjust the Core Timer Presale Register. This way we don't lose time. | ||
*/ | ||
#define TIME_SCALE 4 | ||
#endif | ||
|
||
#endif |