Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 188501
b: refs/heads/master
c: 6c2b707
h: refs/heads/master
i:
  188499: d27a09c
v: v3
  • Loading branch information
Graf Yang authored and Mike Frysinger committed Mar 9, 2010
1 parent 9a2d669 commit 26c990a
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 67 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3b82790c12f8122d3df07cc387d2d74355e54c75
refs/heads/master: 6c2b7072a7035837998da38809f98e4182e4c41c
1 change: 0 additions & 1 deletion trunk/arch/blackfin/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1237,7 +1237,6 @@ config PM_BFIN_WAKE_GP
endmenu

menu "CPU Frequency scaling"
depends on !SMP

source "drivers/cpufreq/Kconfig"

Expand Down
7 changes: 4 additions & 3 deletions trunk/arch/blackfin/include/asm/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,19 @@
*/

#ifndef CONFIG_CPU_FREQ
#define TIME_SCALE 1
#define __bfin_cycles_off (0)
#define __bfin_cycles_mod (0)
# 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

# ifdef CONFIG_CYCLES_CLOCKSOURCE
extern unsigned long long __bfin_cycles_off;
extern unsigned int __bfin_cycles_mod;
# endif
#endif

#if defined(CONFIG_TICKSOURCE_CORETMR)
Expand Down
4 changes: 4 additions & 0 deletions trunk/arch/blackfin/kernel/time-ts.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@

static notrace cycle_t bfin_read_cycles(struct clocksource *cs)
{
#ifdef CONFIG_CPU_FREQ
return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod);
#else
return get_cycles();
#endif
}

static struct clocksource bfin_cs_cycles = {
Expand Down
155 changes: 93 additions & 62 deletions trunk/arch/blackfin/mach-common/cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include <asm/time.h>
#include <asm/dpmc.h>

#define CPUFREQ_CPU 0

/* 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[] = {
Expand All @@ -41,64 +43,114 @@ static struct bfin_dpm_state {
unsigned int tscale; /* change the divider on the core timer interrupt */
} dpm_state_table[3];

#if defined(CONFIG_CYCLES_CLOCKSOURCE)
/*
normalized to maximum frequncy offset for CYCLES,
used in time-ts cycles clock source, but could be used
somewhere also.
* 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;
#endif

/**************************************************************************/
static void __init bfin_init_tables(unsigned long cclk, unsigned long sclk)
{

static unsigned int bfin_getfreq_khz(unsigned int cpu)
unsigned long csel, min_cclk;
int index;

/* Anomaly 273 seems to still exist on non-BF54x w/dcache turned on */
#if ANOMALY_05000273 || ANOMALY_05000274 || \
(!defined(CONFIG_BF54x) && defined(CONFIG_BFIN_EXTMEM_DCACHEABLE))
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:0x%x tscale:%d\n",
bfin_freq_table[index].frequency,
dpm_state_table[index].csel,
dpm_state_table[index].tscale);
}
return;
}

static void bfin_adjust_core_timer(void *info)
{
/* The driver only support single cpu */
if (cpu != 0)
return -1;
unsigned int tscale;
unsigned int index = *(unsigned int *)info;

/* we have to adjust the core timer, because it is using cclk */
tscale = dpm_state_table[index].tscale;
bfin_write_TSCALE(tscale);
return;
}

static unsigned int bfin_getfreq_khz(unsigned int cpu)
{
/* Both CoreA/B have the same core clock */
return get_cclk() / 1000;
}


static int bfin_target(struct cpufreq_policy *policy,
static int bfin_target(struct cpufreq_policy *poli,
unsigned int target_freq, unsigned int relation)
{
unsigned int index, plldiv, tscale;
unsigned int index, plldiv, cpu;
unsigned long flags, cclk_hz;
struct cpufreq_freqs freqs;
#if defined(CONFIG_CYCLES_CLOCKSOURCE)
cycles_t cycles;
#endif

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_khz(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_hw(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);
cycles = get_cycles();
SSYNC();
cycles += 10; /* ~10 cycles we lose after get_cycles() */
__bfin_cycles_off += (cycles << __bfin_cycles_mod) - (cycles << index);
__bfin_cycles_mod = index;
local_irq_restore_hw(flags);
/* TODO: just test case for cycles clock source, remove later */
pr_debug("cpufreq: done\n");
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
for_each_online_cpu(cpu) {
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);

if (!policy)
continue;

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_khz(0);
freqs.new = cclk_hz;
freqs.cpu = cpu;

pr_debug("cpufreq: changing cclk to %lu; target = %u, oldfreq = %u\n",
cclk_hz, target_freq, freqs.old);

cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
if (cpu == CPUFREQ_CPU) {
local_irq_save_hw(flags);
plldiv = (bfin_read_PLL_DIV() & SSEL) |
dpm_state_table[index].csel;
bfin_write_PLL_DIV(plldiv);
on_each_cpu(bfin_adjust_core_timer, &index, 1);
#if defined(CONFIG_CYCLES_CLOCKSOURCE)
cycles = get_cycles();
SSYNC();
cycles += 10; /* ~10 cycles we lose after get_cycles() */
__bfin_cycles_off +=
(cycles << __bfin_cycles_mod) - (cycles << index);
__bfin_cycles_mod = index;
#endif
local_irq_restore_hw(flags);
}
/* TODO: just test case for cycles clock source, remove later */
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}

pr_debug("cpufreq: done\n");
return 0;
}

Expand All @@ -110,37 +162,16 @@ static int bfin_verify_speed(struct cpufreq_policy *policy)
static int __init __bfin_cpu_init(struct cpufreq_policy *policy)
{

unsigned long cclk, sclk, csel, min_cclk;
int index;

if (policy->cpu != 0)
return -EINVAL;
unsigned long cclk, sclk;

cclk = get_cclk() / 1000;
sclk = get_sclk() / 1000;

#if ANOMALY_05000273 || ANOMALY_05000274 || \
(!defined(CONFIG_BF54x) && defined(CONFIG_BFIN_EXTMEM_DCACHEABLE))
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:0x%x tscale:%d\n",
bfin_freq_table[index].frequency,
dpm_state_table[index].csel,
dpm_state_table[index].tscale);
}
if (policy->cpu == CPUFREQ_CPU)
bfin_init_tables(cclk, sclk);

policy->cpuinfo.transition_latency = 50000; /* 50us assumed */

/*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);
Expand Down

0 comments on commit 26c990a

Please sign in to comment.