1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86#include <linux/kernel.h>
87#include <linux/types.h>
88#include <linux/init.h>
89#include <linux/cpufreq.h>
90
91#include <asm/cputype.h>
92
93#include <mach/hardware.h>
94
95#include "generic.h"
96
97typedef struct {
98 int speed;
99 u32 mdcnfg;
100 u32 mdcas0;
101 u32 mdcas1;
102 u32 mdcas2;
103} sa1100_dram_regs_t;
104
105
106static struct cpufreq_driver sa1100_driver;
107
108static sa1100_dram_regs_t sa1100_dram_settings[] =
109{
110
111 { 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff },
112 { 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff },
113 { 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff },
114 { 103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff },
115 { 118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff },
116 { 132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff },
117 { 147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff },
118 { 162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff },
119 { 176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff },
120 { 191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff },
121 { 206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff },
122 { 221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff },
123 { 235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1 },
124 { 250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3 },
125 { 265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3 },
126 { 280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87 },
127 { 0, 0, 0, 0, 0 }
128};
129
130static void sa1100_update_dram_timings(int current_speed, int new_speed)
131{
132 sa1100_dram_regs_t *settings = sa1100_dram_settings;
133
134
135 while (settings->speed != 0) {
136 if(new_speed == settings->speed)
137 break;
138
139 settings++;
140 }
141
142 if (settings->speed == 0) {
143 panic("%s: couldn't find dram setting for speed %d\n",
144 __func__, new_speed);
145 }
146
147
148 if (new_speed > current_speed) {
149
150
151
152
153
154 MDCNFG |= MDCNFG_CDB2;
155
156
157
158
159 MDCAS2 = settings->mdcas2;
160 MDCAS1 = settings->mdcas1;
161 MDCAS0 = settings->mdcas0;
162 MDCNFG = settings->mdcnfg;
163 } else {
164
165
166
167
168
169 MDCNFG |= MDCNFG_CDB2;
170
171
172
173
174 MDCAS0 = settings->mdcas0;
175 MDCAS1 = settings->mdcas1;
176 MDCAS2 = settings->mdcas2;
177 MDCNFG = settings->mdcnfg;
178 }
179}
180
181static int sa1100_target(struct cpufreq_policy *policy,
182 unsigned int target_freq,
183 unsigned int relation)
184{
185 unsigned int cur = sa11x0_getspeed(0);
186 unsigned int new_ppcr;
187
188 struct cpufreq_freqs freqs;
189 switch(relation){
190 case CPUFREQ_RELATION_L:
191 new_ppcr = sa11x0_freq_to_ppcr(target_freq);
192 if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max)
193 new_ppcr--;
194 break;
195 case CPUFREQ_RELATION_H:
196 new_ppcr = sa11x0_freq_to_ppcr(target_freq);
197 if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) &&
198 (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min))
199 new_ppcr--;
200 break;
201 }
202
203 freqs.old = cur;
204 freqs.new = sa11x0_ppcr_to_freq(new_ppcr);
205 freqs.cpu = 0;
206
207 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
208
209 if (freqs.new > cur)
210 sa1100_update_dram_timings(cur, freqs.new);
211
212 PPCR = new_ppcr;
213
214 if (freqs.new < cur)
215 sa1100_update_dram_timings(cur, freqs.new);
216
217 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
218
219 return 0;
220}
221
222static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
223{
224 if (policy->cpu != 0)
225 return -EINVAL;
226 policy->cur = policy->min = policy->max = sa11x0_getspeed(0);
227 policy->cpuinfo.min_freq = 59000;
228 policy->cpuinfo.max_freq = 287000;
229 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
230 return 0;
231}
232
233static struct cpufreq_driver sa1100_driver = {
234 .flags = CPUFREQ_STICKY,
235 .verify = sa11x0_verify_speed,
236 .target = sa1100_target,
237 .get = sa11x0_getspeed,
238 .init = sa1100_cpu_init,
239 .name = "sa1100",
240};
241
242static int __init sa1100_dram_init(void)
243{
244 if (cpu_is_sa1100())
245 return cpufreq_register_driver(&sa1100_driver);
246 else
247 return -ENODEV;
248}
249
250arch_initcall(sa1100_dram_init);
251