1#include <linux/kernel.h>
2#include <linux/sizes.h>
3
4#include "ddk750_help.h"
5#include "ddk750_reg.h"
6#include "ddk750_chip.h"
7#include "ddk750_power.h"
8
9
10#define roundedDiv(num, denom) ((2 * (num) + (denom)) / (2 * (denom)))
11#define MHz(x) ((x) * 1000000)
12
13logical_chip_type_t getChipType(void)
14{
15 unsigned short physicalID;
16 char physicalRev;
17 logical_chip_type_t chip;
18
19 physicalID = devId750;
20 physicalRev = revId750;
21
22 if (physicalID == 0x718)
23 chip = SM718;
24 else if (physicalID == 0x750) {
25 chip = SM750;
26
27 if (physicalRev == SM750LE_REVISION_ID)
28 chip = SM750LE;
29 } else
30 chip = SM_UNKNOWN;
31
32 return chip;
33}
34
35static unsigned int get_mxclk_freq(void)
36{
37 unsigned int pll_reg;
38 unsigned int M, N, OD, POD;
39
40 if (getChipType() == SM750LE)
41 return MHz(130);
42
43 pll_reg = PEEK32(MXCLK_PLL_CTRL);
44 M = (pll_reg & PLL_CTRL_M_MASK) >> PLL_CTRL_M_SHIFT;
45 N = (pll_reg & PLL_CTRL_N_MASK) >> PLL_CTRL_M_SHIFT;
46 OD = (pll_reg & PLL_CTRL_OD_MASK) >> PLL_CTRL_OD_SHIFT;
47 POD = (pll_reg & PLL_CTRL_POD_MASK) >> PLL_CTRL_POD_SHIFT;
48
49 return DEFAULT_INPUT_CLOCK * M / N / (1 << OD) / (1 << POD);
50}
51
52
53
54
55
56
57static void setChipClock(unsigned int frequency)
58{
59 pll_value_t pll;
60 unsigned int ulActualMxClk;
61
62
63 if (getChipType() == SM750LE)
64 return;
65
66 if (frequency) {
67
68
69
70 pll.inputFreq = DEFAULT_INPUT_CLOCK;
71 pll.clockType = MXCLK_PLL;
72
73
74
75
76
77
78 ulActualMxClk = calcPllValue(frequency, &pll);
79
80
81 POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll));
82 }
83}
84
85static void setMemoryClock(unsigned int frequency)
86{
87 unsigned int reg, divisor;
88
89
90 if (getChipType() == SM750LE)
91 return;
92
93 if (frequency) {
94
95
96 if (frequency > MHz(336))
97 frequency = MHz(336);
98
99
100 divisor = roundedDiv(get_mxclk_freq(), frequency);
101
102
103 reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK;
104 switch (divisor) {
105 default:
106 case 1:
107 reg |= CURRENT_GATE_M2XCLK_DIV_1;
108 break;
109 case 2:
110 reg |= CURRENT_GATE_M2XCLK_DIV_2;
111 break;
112 case 3:
113 reg |= CURRENT_GATE_M2XCLK_DIV_3;
114 break;
115 case 4:
116 reg |= CURRENT_GATE_M2XCLK_DIV_4;
117 break;
118 }
119
120 setCurrentGate(reg);
121 }
122}
123
124
125
126
127
128
129
130
131
132static void setMasterClock(unsigned int frequency)
133{
134 unsigned int reg, divisor;
135
136
137 if (getChipType() == SM750LE)
138 return;
139
140 if (frequency) {
141
142
143 if (frequency > MHz(190))
144 frequency = MHz(190);
145
146
147 divisor = roundedDiv(get_mxclk_freq(), frequency);
148
149
150 reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK;
151 switch (divisor) {
152 default:
153 case 3:
154 reg |= CURRENT_GATE_MCLK_DIV_3;
155 break;
156 case 4:
157 reg |= CURRENT_GATE_MCLK_DIV_4;
158 break;
159 case 6:
160 reg |= CURRENT_GATE_MCLK_DIV_6;
161 break;
162 case 8:
163 reg |= CURRENT_GATE_MCLK_DIV_8;
164 break;
165 }
166
167 setCurrentGate(reg);
168 }
169}
170
171unsigned int ddk750_getVMSize(void)
172{
173 unsigned int reg;
174 unsigned int data;
175
176
177 if (getChipType() == SM750LE)
178 return SZ_64M;
179
180
181 reg = PEEK32(MODE0_GATE);
182 reg |= MODE0_GATE_GPIO;
183 POKE32(MODE0_GATE, reg);
184
185
186 reg = PEEK32(MISC_CTRL) & MISC_CTRL_LOCALMEM_SIZE_MASK;
187 switch (reg) {
188 case MISC_CTRL_LOCALMEM_SIZE_8M:
189 data = SZ_8M; break;
190 case MISC_CTRL_LOCALMEM_SIZE_16M:
191 data = SZ_16M; break;
192 case MISC_CTRL_LOCALMEM_SIZE_32M:
193 data = SZ_32M; break;
194 case MISC_CTRL_LOCALMEM_SIZE_64M:
195 data = SZ_64M; break;
196 default:
197 data = 0;
198 break;
199 }
200 return data;
201}
202
203int ddk750_initHw(initchip_param_t *pInitParam)
204{
205 unsigned int reg;
206
207 if (pInitParam->powerMode != 0)
208 pInitParam->powerMode = 0;
209 setPowerMode(pInitParam->powerMode);
210
211
212 reg = PEEK32(CURRENT_GATE);
213 reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM);
214 setCurrentGate(reg);
215
216 if (getChipType() != SM750LE) {
217
218 reg = PEEK32(VGA_CONFIGURATION);
219 reg |= (VGA_CONFIGURATION_PLL | VGA_CONFIGURATION_MODE);
220 POKE32(VGA_CONFIGURATION, reg);
221 } else {
222#if defined(__i386__) || defined(__x86_64__)
223
224 outb_p(0x88, 0x3d4);
225 outb_p(0x06, 0x3d5);
226#endif
227 }
228
229
230 setChipClock(MHz((unsigned int)pInitParam->chipClock));
231
232
233 setMemoryClock(MHz(pInitParam->memClock));
234
235
236 setMasterClock(MHz(pInitParam->masterClock));
237
238
239
240
241
242
243 if (pInitParam->resetMemory == 1) {
244 reg = PEEK32(MISC_CTRL);
245 reg &= ~MISC_CTRL_LOCALMEM_RESET;
246 POKE32(MISC_CTRL, reg);
247
248 reg |= MISC_CTRL_LOCALMEM_RESET;
249 POKE32(MISC_CTRL, reg);
250 }
251
252 if (pInitParam->setAllEngOff == 1) {
253 enable2DEngine(0);
254
255
256 reg = PEEK32(VIDEO_DISPLAY_CTRL);
257 reg &= ~DISPLAY_CTRL_PLANE;
258 POKE32(VIDEO_DISPLAY_CTRL, reg);
259
260
261 reg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL);
262 reg &= ~DISPLAY_CTRL_PLANE;
263 POKE32(VIDEO_ALPHA_DISPLAY_CTRL, reg);
264
265
266 reg = PEEK32(ALPHA_DISPLAY_CTRL);
267 reg &= ~DISPLAY_CTRL_PLANE;
268 POKE32(ALPHA_DISPLAY_CTRL, reg);
269
270
271 reg = PEEK32(DMA_ABORT_INTERRUPT);
272 reg |= DMA_ABORT_INTERRUPT_ABORT_1;
273 POKE32(DMA_ABORT_INTERRUPT, reg);
274
275
276 enableDMA(0);
277 }
278
279
280
281 return 0;
282}
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
301{
302
303 int N, M, X, d;
304 int mini_diff;
305 unsigned int RN, quo, rem, fl_quo;
306 unsigned int input, request;
307 unsigned int tmpClock, ret;
308 const int max_OD = 3;
309 int max_d;
310
311 if (getChipType() == SM750LE) {
312
313
314 return request_orig;
315 }
316
317 ret = 0;
318 mini_diff = ~0;
319 request = request_orig / 1000;
320 input = pll->inputFreq / 1000;
321
322
323 if (pll->clockType == MXCLK_PLL)
324 max_d = 3;
325
326 for (N = 15; N > 1; N--) {
327
328 RN = N * request;
329 quo = RN / input;
330 rem = RN % input;
331 fl_quo = (rem * 10000 / input);
332
333 for (d = max_d; d >= 0; d--) {
334 X = (1 << d);
335 M = quo * X;
336 M += fl_quo * X / 10000;
337
338 M += (fl_quo * X % 10000) > 5000 ? 1 : 0;
339 if (M < 256 && M > 0) {
340 unsigned int diff;
341
342 tmpClock = pll->inputFreq * M / N / X;
343 diff = abs(tmpClock - request_orig);
344 if (diff < mini_diff) {
345 pll->M = M;
346 pll->N = N;
347 pll->POD = 0;
348 if (d > max_OD)
349 pll->POD = d - max_OD;
350 pll->OD = d - pll->POD;
351 mini_diff = diff;
352 ret = tmpClock;
353 }
354 }
355 }
356 }
357 return ret;
358}
359
360unsigned int formatPllReg(pll_value_t *pPLL)
361{
362#ifndef VALIDATION_CHIP
363 unsigned int POD = pPLL->POD;
364#endif
365 unsigned int OD = pPLL->OD;
366 unsigned int M = pPLL->M;
367 unsigned int N = pPLL->N;
368 unsigned int reg = 0;
369
370
371
372
373
374
375
376 reg = PLL_CTRL_POWER |
377#ifndef VALIDATION_CHIP
378 ((POD << PLL_CTRL_POD_SHIFT) & PLL_CTRL_POD_MASK) |
379#endif
380 ((OD << PLL_CTRL_OD_SHIFT) & PLL_CTRL_OD_MASK) |
381 ((N << PLL_CTRL_N_SHIFT) & PLL_CTRL_N_MASK) |
382 ((M << PLL_CTRL_M_SHIFT) & PLL_CTRL_M_MASK);
383
384 return reg;
385}
386
387
388