diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-pxa/cpu-pxa.c | 98 |
1 files changed, 51 insertions, 47 deletions
diff --git a/arch/arm/mach-pxa/cpu-pxa.c b/arch/arm/mach-pxa/cpu-pxa.c index 4b21479332ae..0f5660200bf9 100644 --- a/arch/arm/mach-pxa/cpu-pxa.c +++ b/arch/arm/mach-pxa/cpu-pxa.c | |||
@@ -57,29 +57,29 @@ typedef struct { | |||
57 | } pxa_freqs_t; | 57 | } pxa_freqs_t; |
58 | 58 | ||
59 | /* Define the refresh period in mSec for the SDRAM and the number of rows */ | 59 | /* Define the refresh period in mSec for the SDRAM and the number of rows */ |
60 | #define SDRAM_TREF 64 /* standard 64ms SDRAM */ | 60 | #define SDRAM_TREF 64 /* standard 64ms SDRAM */ |
61 | #define SDRAM_ROWS 4096 /* 64MB=8192 32MB=4096 */ | 61 | #define SDRAM_ROWS 4096 /* 64MB=8192 32MB=4096 */ |
62 | #define MDREFR_DRI(x) (((x) * SDRAM_TREF) / (SDRAM_ROWS * 32)) | 62 | #define MDREFR_DRI(x) (((x) * SDRAM_TREF) / (SDRAM_ROWS * 32)) |
63 | 63 | ||
64 | #define CCLKCFG_TURBO 0x1 | 64 | #define CCLKCFG_TURBO 0x1 |
65 | #define CCLKCFG_FCS 0x2 | 65 | #define CCLKCFG_FCS 0x2 |
66 | #define PXA25x_MIN_FREQ 99500 | 66 | #define PXA25x_MIN_FREQ 99500 |
67 | #define PXA25x_MAX_FREQ 398100 | 67 | #define PXA25x_MAX_FREQ 398100 |
68 | #define MDREFR_DB2_MASK (MDREFR_K2DB2 | MDREFR_K1DB2) | 68 | #define MDREFR_DB2_MASK (MDREFR_K2DB2 | MDREFR_K1DB2) |
69 | #define MDREFR_DRI_MASK 0xFFF | 69 | #define MDREFR_DRI_MASK 0xFFF |
70 | 70 | ||
71 | 71 | ||
72 | /* Use the run mode frequencies for the CPUFREQ_POLICY_PERFORMANCE policy */ | 72 | /* Use the run mode frequencies for the CPUFREQ_POLICY_PERFORMANCE policy */ |
73 | static pxa_freqs_t pxa255_run_freqs[] = | 73 | static pxa_freqs_t pxa255_run_freqs[] = |
74 | { | 74 | { |
75 | /* CPU MEMBUS CCCR DIV2*/ | 75 | /* CPU MEMBUS CCCR DIV2 run turbo PXbus SDRAM */ |
76 | { 99500, 99500, 0x121, 1}, /* run= 99, turbo= 99, PXbus=50, SDRAM=50 */ | 76 | { 99500, 99500, 0x121, 1}, /* 99, 99, 50, 50 */ |
77 | {132700, 132700, 0x123, 1}, /* run=133, turbo=133, PXbus=66, SDRAM=66 */ | 77 | {132700, 132700, 0x123, 1}, /* 133, 133, 66, 66 */ |
78 | {199100, 99500, 0x141, 0}, /* run=199, turbo=199, PXbus=99, SDRAM=99 */ | 78 | {199100, 99500, 0x141, 0}, /* 199, 199, 99, 99 */ |
79 | {265400, 132700, 0x143, 1}, /* run=265, turbo=265, PXbus=133, SDRAM=66 */ | 79 | {265400, 132700, 0x143, 1}, /* 265, 265, 133, 66 */ |
80 | {331800, 165900, 0x145, 1}, /* run=331, turbo=331, PXbus=166, SDRAM=83 */ | 80 | {331800, 165900, 0x145, 1}, /* 331, 331, 166, 83 */ |
81 | {398100, 99500, 0x161, 0}, /* run=398, turbo=398, PXbus=196, SDRAM=99 */ | 81 | {398100, 99500, 0x161, 0}, /* 398, 398, 196, 99 */ |
82 | {0,} | 82 | {0,} |
83 | }; | 83 | }; |
84 | #define NUM_RUN_FREQS ARRAY_SIZE(pxa255_run_freqs) | 84 | #define NUM_RUN_FREQS ARRAY_SIZE(pxa255_run_freqs) |
85 | 85 | ||
@@ -88,17 +88,18 @@ static struct cpufreq_frequency_table pxa255_run_freq_table[NUM_RUN_FREQS+1]; | |||
88 | /* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */ | 88 | /* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */ |
89 | static pxa_freqs_t pxa255_turbo_freqs[] = | 89 | static pxa_freqs_t pxa255_turbo_freqs[] = |
90 | { | 90 | { |
91 | /* CPU MEMBUS CCCR DIV2*/ | 91 | /* CPU MEMBUS CCCR DIV2 run turbo PXbus SDRAM */ |
92 | { 99500, 99500, 0x121, 1}, /* run=99, turbo= 99, PXbus=50, SDRAM=50 */ | 92 | { 99500, 99500, 0x121, 1}, /* 99, 99, 50, 50 */ |
93 | {199100, 99500, 0x221, 0}, /* run=99, turbo=199, PXbus=50, SDRAM=99 */ | 93 | {199100, 99500, 0x221, 0}, /* 99, 199, 50, 99 */ |
94 | {298500, 99500, 0x321, 0}, /* run=99, turbo=287, PXbus=50, SDRAM=99 */ | 94 | {298500, 99500, 0x321, 0}, /* 99, 287, 50, 99 */ |
95 | {298600, 99500, 0x1c1, 0}, /* run=199, turbo=287, PXbus=99, SDRAM=99 */ | 95 | {298600, 99500, 0x1c1, 0}, /* 199, 287, 99, 99 */ |
96 | {398100, 99500, 0x241, 0}, /* run=199, turbo=398, PXbus=99, SDRAM=99 */ | 96 | {398100, 99500, 0x241, 0}, /* 199, 398, 99, 99 */ |
97 | {0,} | 97 | {0,} |
98 | }; | 98 | }; |
99 | #define NUM_TURBO_FREQS ARRAY_SIZE(pxa255_turbo_freqs) | 99 | #define NUM_TURBO_FREQS ARRAY_SIZE(pxa255_turbo_freqs) |
100 | 100 | ||
101 | static struct cpufreq_frequency_table pxa255_turbo_freq_table[NUM_TURBO_FREQS+1]; | 101 | static struct cpufreq_frequency_table |
102 | pxa255_turbo_freq_table[NUM_TURBO_FREQS+1]; | ||
102 | 103 | ||
103 | extern unsigned get_clk_frequency_khz(int info); | 104 | extern unsigned get_clk_frequency_khz(int info); |
104 | 105 | ||
@@ -122,14 +123,14 @@ static int pxa_verify_policy(struct cpufreq_policy *policy) | |||
122 | 123 | ||
123 | if (freq_debug) | 124 | if (freq_debug) |
124 | pr_debug("Verified CPU policy: %dKhz min to %dKhz max\n", | 125 | pr_debug("Verified CPU policy: %dKhz min to %dKhz max\n", |
125 | policy->min, policy->max); | 126 | policy->min, policy->max); |
126 | 127 | ||
127 | return ret; | 128 | return ret; |
128 | } | 129 | } |
129 | 130 | ||
130 | static int pxa_set_target(struct cpufreq_policy *policy, | 131 | static int pxa_set_target(struct cpufreq_policy *policy, |
131 | unsigned int target_freq, | 132 | unsigned int target_freq, |
132 | unsigned int relation) | 133 | unsigned int relation) |
133 | { | 134 | { |
134 | struct cpufreq_frequency_table *pxa_freqs_table; | 135 | struct cpufreq_frequency_table *pxa_freqs_table; |
135 | pxa_freqs_t *pxa_freq_settings; | 136 | pxa_freqs_t *pxa_freq_settings; |
@@ -155,7 +156,7 @@ static int pxa_set_target(struct cpufreq_policy *policy, | |||
155 | 156 | ||
156 | /* Lookup the next frequency */ | 157 | /* Lookup the next frequency */ |
157 | if (cpufreq_frequency_table_target(policy, pxa_freqs_table, | 158 | if (cpufreq_frequency_table_target(policy, pxa_freqs_table, |
158 | target_freq, relation, &idx)) { | 159 | target_freq, relation, &idx)) { |
159 | return -EINVAL; | 160 | return -EINVAL; |
160 | } | 161 | } |
161 | 162 | ||
@@ -164,10 +165,11 @@ static int pxa_set_target(struct cpufreq_policy *policy, | |||
164 | freqs.cpu = policy->cpu; | 165 | freqs.cpu = policy->cpu; |
165 | 166 | ||
166 | if (freq_debug) | 167 | if (freq_debug) |
167 | pr_debug(KERN_INFO "Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n", | 168 | pr_debug(KERN_INFO "Changing CPU frequency to %d Mhz, " |
168 | freqs.new / 1000, (pxa_freq_settings[idx].div2) ? | 169 | "(SDRAM %d Mhz)\n", |
169 | (pxa_freq_settings[idx].membus / 2000) : | 170 | freqs.new / 1000, (pxa_freq_settings[idx].div2) ? |
170 | (pxa_freq_settings[idx].membus / 1000)); | 171 | (pxa_freq_settings[idx].membus / 2000) : |
172 | (pxa_freq_settings[idx].membus / 1000)); | ||
171 | 173 | ||
172 | /* | 174 | /* |
173 | * Tell everyone what we're about to do... | 175 | * Tell everyone what we're about to do... |
@@ -177,16 +179,17 @@ static int pxa_set_target(struct cpufreq_policy *policy, | |||
177 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | 179 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); |
178 | 180 | ||
179 | /* Calculate the next MDREFR. If we're slowing down the SDRAM clock | 181 | /* Calculate the next MDREFR. If we're slowing down the SDRAM clock |
180 | * we need to preset the smaller DRI before the change. If we're speeding | 182 | * we need to preset the smaller DRI before the change. If we're |
181 | * up we need to set the larger DRI value after the change. | 183 | * speeding up we need to set the larger DRI value after the change. |
182 | */ | 184 | */ |
183 | preset_mdrefr = postset_mdrefr = MDREFR; | 185 | preset_mdrefr = postset_mdrefr = MDREFR; |
184 | if ((MDREFR & MDREFR_DRI_MASK) > MDREFR_DRI(pxa_freq_settings[idx].membus)) { | 186 | if ((MDREFR & MDREFR_DRI_MASK) > |
187 | MDREFR_DRI(pxa_freq_settings[idx].membus)) { | ||
185 | preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK) | | 188 | preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK) | |
186 | MDREFR_DRI(pxa_freq_settings[idx].membus); | 189 | MDREFR_DRI(pxa_freq_settings[idx].membus); |
187 | } | 190 | } |
188 | postset_mdrefr = (postset_mdrefr & ~MDREFR_DRI_MASK) | | 191 | postset_mdrefr = (postset_mdrefr & ~MDREFR_DRI_MASK) | |
189 | MDREFR_DRI(pxa_freq_settings[idx].membus); | 192 | MDREFR_DRI(pxa_freq_settings[idx].membus); |
190 | 193 | ||
191 | /* If we're dividing the memory clock by two for the SDRAM clock, this | 194 | /* If we're dividing the memory clock by two for the SDRAM clock, this |
192 | * must be set prior to the change. Clearing the divide must be done | 195 | * must be set prior to the change. Clearing the divide must be done |
@@ -207,7 +210,7 @@ static int pxa_set_target(struct cpufreq_policy *policy, | |||
207 | asm volatile(" \n\ | 210 | asm volatile(" \n\ |
208 | ldr r4, [%1] /* load MDREFR */ \n\ | 211 | ldr r4, [%1] /* load MDREFR */ \n\ |
209 | b 2f \n\ | 212 | b 2f \n\ |
210 | .align 5 \n\ | 213 | .align 5 \n\ |
211 | 1: \n\ | 214 | 1: \n\ |
212 | str %4, [%1] /* preset the MDREFR */ \n\ | 215 | str %4, [%1] /* preset the MDREFR */ \n\ |
213 | mcr p14, 0, %2, c6, c0, 0 /* set CCLKCFG[FCS] */ \n\ | 216 | mcr p14, 0, %2, c6, c0, 0 /* set CCLKCFG[FCS] */ \n\ |
@@ -217,10 +220,10 @@ static int pxa_set_target(struct cpufreq_policy *policy, | |||
217 | 2: b 1b \n\ | 220 | 2: b 1b \n\ |
218 | 3: nop \n\ | 221 | 3: nop \n\ |
219 | " | 222 | " |
220 | : "=&r" (unused) | 223 | : "=&r" (unused) |
221 | : "r" (&MDREFR), "r" (CCLKCFG_TURBO|CCLKCFG_FCS), "r" (ramstart), | 224 | : "r" (&MDREFR), "r" (CCLKCFG_TURBO|CCLKCFG_FCS), "r" (ramstart), |
222 | "r" (preset_mdrefr), "r" (postset_mdrefr) | 225 | "r" (preset_mdrefr), "r" (postset_mdrefr) |
223 | : "r4", "r5"); | 226 | : "r4", "r5"); |
224 | local_irq_restore(flags); | 227 | local_irq_restore(flags); |
225 | 228 | ||
226 | /* | 229 | /* |
@@ -248,7 +251,7 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy) | |||
248 | policy->cpuinfo.max_freq = PXA25x_MAX_FREQ; | 251 | policy->cpuinfo.max_freq = PXA25x_MAX_FREQ; |
249 | policy->cpuinfo.min_freq = PXA25x_MIN_FREQ; | 252 | policy->cpuinfo.min_freq = PXA25x_MIN_FREQ; |
250 | policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */ | 253 | policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */ |
251 | policy->cur = get_clk_frequency_khz(0); /* current freq */ | 254 | policy->cur = get_clk_frequency_khz(0); /* current freq */ |
252 | policy->min = policy->max = policy->cur; | 255 | policy->min = policy->max = policy->cur; |
253 | 256 | ||
254 | /* Generate the run cpufreq_frequency_table struct */ | 257 | /* Generate the run cpufreq_frequency_table struct */ |
@@ -260,7 +263,8 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy) | |||
260 | pxa255_run_freq_table[i].frequency = CPUFREQ_TABLE_END; | 263 | pxa255_run_freq_table[i].frequency = CPUFREQ_TABLE_END; |
261 | /* Generate the turbo cpufreq_frequency_table struct */ | 264 | /* Generate the turbo cpufreq_frequency_table struct */ |
262 | for (i = 0; i < NUM_TURBO_FREQS; i++) { | 265 | for (i = 0; i < NUM_TURBO_FREQS; i++) { |
263 | pxa255_turbo_freq_table[i].frequency = pxa255_turbo_freqs[i].khz; | 266 | pxa255_turbo_freq_table[i].frequency = |
267 | pxa255_turbo_freqs[i].khz; | ||
264 | pxa255_turbo_freq_table[i].index = i; | 268 | pxa255_turbo_freq_table[i].index = i; |
265 | } | 269 | } |
266 | pxa255_turbo_freq_table[i].frequency = CPUFREQ_TABLE_END; | 270 | pxa255_turbo_freq_table[i].frequency = CPUFREQ_TABLE_END; |
@@ -293,8 +297,8 @@ static void __exit pxa_cpu_exit(void) | |||
293 | } | 297 | } |
294 | 298 | ||
295 | 299 | ||
296 | MODULE_AUTHOR ("Intrinsyc Software Inc."); | 300 | MODULE_AUTHOR("Intrinsyc Software Inc."); |
297 | MODULE_DESCRIPTION ("CPU frequency changing driver for the PXA architecture"); | 301 | MODULE_DESCRIPTION("CPU frequency changing driver for the PXA architecture"); |
298 | MODULE_LICENSE("GPL"); | 302 | MODULE_LICENSE("GPL"); |
299 | module_init(pxa_cpu_init); | 303 | module_init(pxa_cpu_init); |
300 | module_exit(pxa_cpu_exit); | 304 | module_exit(pxa_cpu_exit); |