]>
Commit | Line | Data |
---|---|---|
4cf26d85 MR |
1 | #include <linux/sizes.h> |
2 | ||
81dee67e SM |
3 | #include "ddk750_help.h" |
4 | #include "ddk750_reg.h" | |
5 | #include "ddk750_chip.h" | |
6 | #include "ddk750_power.h" | |
569a6dcf | 7 | typedef struct _pllcalparam { |
81dee67e SM |
8 | unsigned char power;/* d : 0~ 6*/ |
9 | unsigned char pod; | |
10 | unsigned char od; | |
11 | unsigned char value;/* value of 2 power d (2^d) */ | |
12 | } | |
13 | pllcalparam; | |
14 | ||
6fa7db83 | 15 | logical_chip_type_t getChipType(void) |
81dee67e SM |
16 | { |
17 | unsigned short physicalID; | |
18 | char physicalRev; | |
19 | logical_chip_type_t chip; | |
20 | ||
5ee35ea7 | 21 | physicalID = devId750; /* either 0x718 or 0x750 */ |
81dee67e SM |
22 | physicalRev = revId750; |
23 | ||
de99befd | 24 | if (physicalID == 0x718) |
de99befd | 25 | chip = SM718; |
9767fc51 | 26 | else if (physicalID == 0x750) { |
de99befd | 27 | chip = SM750; |
81dee67e | 28 | /* SM750 and SM750LE are different in their revision ID only. */ |
9767fc51 | 29 | if (physicalRev == SM750LE_REVISION_ID) |
81dee67e | 30 | chip = SM750LE; |
9767fc51 | 31 | } else |
de99befd | 32 | chip = SM_UNKNOWN; |
81dee67e SM |
33 | |
34 | return chip; | |
35 | } | |
36 | ||
fb6f37a8 | 37 | static inline unsigned int calcPLL(pll_value_t *pPLL) |
81dee67e | 38 | { |
174f2642 MR |
39 | return (pPLL->inputFreq * pPLL->M / pPLL->N / (1 << pPLL->OD) / |
40 | (1 << pPLL->POD)); | |
81dee67e SM |
41 | } |
42 | ||
fb6f37a8 | 43 | static unsigned int getPllValue(clock_type_t clockType, pll_value_t *pPLL) |
81dee67e | 44 | { |
de99befd RN |
45 | unsigned int ulPllReg = 0; |
46 | ||
47 | pPLL->inputFreq = DEFAULT_INPUT_CLOCK; | |
48 | pPLL->clockType = clockType; | |
49 | ||
9767fc51 | 50 | switch (clockType) { |
de99befd RN |
51 | case MXCLK_PLL: |
52 | ulPllReg = PEEK32(MXCLK_PLL_CTRL); | |
53 | break; | |
54 | case PRIMARY_PLL: | |
55 | ulPllReg = PEEK32(PANEL_PLL_CTRL); | |
56 | break; | |
57 | case SECONDARY_PLL: | |
58 | ulPllReg = PEEK32(CRT_PLL_CTRL); | |
59 | break; | |
60 | case VGA0_PLL: | |
61 | ulPllReg = PEEK32(VGA_PLL0_CTRL); | |
62 | break; | |
63 | case VGA1_PLL: | |
64 | ulPllReg = PEEK32(VGA_PLL1_CTRL); | |
65 | break; | |
66 | } | |
67 | ||
68 | pPLL->M = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, M); | |
69 | pPLL->N = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, N); | |
70 | pPLL->OD = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, OD); | |
71 | pPLL->POD = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, POD); | |
72 | ||
73 | return calcPLL(pPLL); | |
81dee67e SM |
74 | } |
75 | ||
fb6f37a8 | 76 | static unsigned int getChipClock(void) |
81dee67e | 77 | { |
de99befd | 78 | pll_value_t pll; |
81dee67e | 79 | #if 1 |
82736d22 | 80 | if (getChipType() == SM750LE) |
81dee67e SM |
81 | return MHz(130); |
82 | #endif | |
83 | ||
de99befd | 84 | return getPllValue(MXCLK_PLL, &pll); |
81dee67e SM |
85 | } |
86 | ||
81dee67e SM |
87 | /* |
88 | * This function set up the main chip clock. | |
89 | * | |
90 | * Input: Frequency to be set. | |
91 | */ | |
fb6f37a8 | 92 | static void setChipClock(unsigned int frequency) |
81dee67e | 93 | { |
de99befd RN |
94 | pll_value_t pll; |
95 | unsigned int ulActualMxClk; | |
81dee67e | 96 | #if 1 |
de99befd RN |
97 | /* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */ |
98 | if (getChipType() == SM750LE) | |
99 | return; | |
81dee67e SM |
100 | #endif |
101 | ||
59f08407 | 102 | if (frequency) { |
de99befd RN |
103 | /* |
104 | * Set up PLL, a structure to hold the value to be set in clocks. | |
105 | */ | |
106 | pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */ | |
107 | pll.clockType = MXCLK_PLL; | |
108 | ||
109 | /* | |
110 | * Call calcPllValue() to fill up the other fields for PLL structure. | |
111 | * Sometime, the chip cannot set up the exact clock required by User. | |
112 | * Return value from calcPllValue() gives the actual possible clock. | |
113 | */ | |
114 | ulActualMxClk = calcPllValue(frequency, &pll); | |
115 | ||
116 | /* Master Clock Control: MXCLK_PLL */ | |
117 | POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll)); | |
118 | } | |
81dee67e SM |
119 | } |
120 | ||
fb6f37a8 | 121 | static void setMemoryClock(unsigned int frequency) |
81dee67e | 122 | { |
de99befd | 123 | unsigned int ulReg, divisor; |
81dee67e SM |
124 | #if 1 |
125 | /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */ | |
126 | if (getChipType() == SM750LE) | |
127 | return; | |
128 | #endif | |
59f08407 | 129 | if (frequency) { |
de99befd RN |
130 | /* Set the frequency to the maximum frequency that the DDR Memory can take |
131 | which is 336MHz. */ | |
132 | if (frequency > MHz(336)) | |
133 | frequency = MHz(336); | |
134 | ||
135 | /* Calculate the divisor */ | |
a0fd4b57 | 136 | divisor = (unsigned int)roundedDiv(getChipClock(), frequency); |
de99befd RN |
137 | |
138 | /* Set the corresponding divisor in the register. */ | |
139 | ulReg = PEEK32(CURRENT_GATE); | |
c107243b | 140 | switch (divisor) { |
de99befd RN |
141 | default: |
142 | case 1: | |
143 | ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_1); | |
144 | break; | |
145 | case 2: | |
146 | ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_2); | |
147 | break; | |
148 | case 3: | |
149 | ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_3); | |
150 | break; | |
151 | case 4: | |
152 | ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_4); | |
153 | break; | |
154 | } | |
155 | ||
156 | setCurrentGate(ulReg); | |
157 | } | |
81dee67e SM |
158 | } |
159 | ||
81dee67e SM |
160 | /* |
161 | * This function set up the master clock (MCLK). | |
162 | * | |
163 | * Input: Frequency to be set. | |
164 | * | |
165 | * NOTE: | |
166 | * The maximum frequency the engine can run is 168MHz. | |
167 | */ | |
fb6f37a8 | 168 | static void setMasterClock(unsigned int frequency) |
81dee67e | 169 | { |
de99befd RN |
170 | unsigned int ulReg, divisor; |
171 | #if 1 | |
81dee67e SM |
172 | /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */ |
173 | if (getChipType() == SM750LE) | |
174 | return; | |
175 | #endif | |
59f08407 | 176 | if (frequency) { |
de99befd RN |
177 | /* Set the frequency to the maximum frequency that the SM750 engine can |
178 | run, which is about 190 MHz. */ | |
179 | if (frequency > MHz(190)) | |
180 | frequency = MHz(190); | |
181 | ||
182 | /* Calculate the divisor */ | |
a0fd4b57 | 183 | divisor = (unsigned int)roundedDiv(getChipClock(), frequency); |
de99befd RN |
184 | |
185 | /* Set the corresponding divisor in the register. */ | |
186 | ulReg = PEEK32(CURRENT_GATE); | |
c107243b | 187 | switch (divisor) { |
de99befd RN |
188 | default: |
189 | case 3: | |
190 | ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_3); | |
191 | break; | |
192 | case 4: | |
193 | ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_4); | |
194 | break; | |
195 | case 6: | |
196 | ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_6); | |
197 | break; | |
198 | case 8: | |
199 | ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_8); | |
200 | break; | |
201 | } | |
202 | ||
203 | setCurrentGate(ulReg); | |
204 | } | |
81dee67e SM |
205 | } |
206 | ||
6fa7db83 | 207 | unsigned int ddk750_getVMSize(void) |
81dee67e SM |
208 | { |
209 | unsigned int reg; | |
210 | unsigned int data; | |
211 | ||
212 | /* sm750le only use 64 mb memory*/ | |
82736d22 | 213 | if (getChipType() == SM750LE) |
4cf26d85 | 214 | return SZ_64M; |
81dee67e SM |
215 | |
216 | /* for 750,always use power mode0*/ | |
217 | reg = PEEK32(MODE0_GATE); | |
c04051f5 HF |
218 | reg = FIELD_SET(reg, MODE0_GATE, GPIO, ON); |
219 | POKE32(MODE0_GATE, reg); | |
81dee67e SM |
220 | |
221 | /* get frame buffer size from GPIO */ | |
c04051f5 | 222 | reg = FIELD_GET(PEEK32(MISC_CTRL), MISC_CTRL, LOCALMEM_SIZE); |
c107243b | 223 | switch (reg) { |
ae59c465 | 224 | case MISC_CTRL_LOCALMEM_SIZE_8M: |
4cf26d85 | 225 | data = SZ_8M; break; /* 8 Mega byte */ |
ae59c465 | 226 | case MISC_CTRL_LOCALMEM_SIZE_16M: |
4cf26d85 | 227 | data = SZ_16M; break; /* 16 Mega byte */ |
ae59c465 | 228 | case MISC_CTRL_LOCALMEM_SIZE_32M: |
4cf26d85 | 229 | data = SZ_32M; break; /* 32 Mega byte */ |
ae59c465 | 230 | case MISC_CTRL_LOCALMEM_SIZE_64M: |
4cf26d85 | 231 | data = SZ_64M; break; /* 64 Mega byte */ |
ae59c465 | 232 | default: |
e261e69e AKC |
233 | data = 0; |
234 | break; | |
81dee67e SM |
235 | } |
236 | return data; | |
81dee67e SM |
237 | } |
238 | ||
f8da055a | 239 | int ddk750_initHw(initchip_param_t *pInitParam) |
81dee67e | 240 | { |
81dee67e | 241 | unsigned int ulReg; |
81dee67e | 242 | |
8332d94c | 243 | if (pInitParam->powerMode != 0) |
81dee67e SM |
244 | pInitParam->powerMode = 0; |
245 | setPowerMode(pInitParam->powerMode); | |
246 | ||
247 | /* Enable display power gate & LOCALMEM power gate*/ | |
248 | ulReg = PEEK32(CURRENT_GATE); | |
249 | ulReg = FIELD_SET(ulReg, CURRENT_GATE, DISPLAY, ON); | |
c04051f5 | 250 | ulReg = FIELD_SET(ulReg, CURRENT_GATE, LOCALMEM, ON); |
81dee67e SM |
251 | setCurrentGate(ulReg); |
252 | ||
82736d22 | 253 | if (getChipType() != SM750LE) { |
81dee67e SM |
254 | /* set panel pll and graphic mode via mmio_88 */ |
255 | ulReg = PEEK32(VGA_CONFIGURATION); | |
c04051f5 HF |
256 | ulReg = FIELD_SET(ulReg, VGA_CONFIGURATION, PLL, PANEL); |
257 | ulReg = FIELD_SET(ulReg, VGA_CONFIGURATION, MODE, GRAPHIC); | |
258 | POKE32(VGA_CONFIGURATION, ulReg); | |
9767fc51 | 259 | } else { |
31296ba5 | 260 | #if defined(__i386__) || defined(__x86_64__) |
81dee67e | 261 | /* set graphic mode via IO method */ |
c04051f5 HF |
262 | outb_p(0x88, 0x3d4); |
263 | outb_p(0x06, 0x3d5); | |
81dee67e SM |
264 | #endif |
265 | } | |
266 | ||
267 | /* Set the Main Chip Clock */ | |
268 | setChipClock(MHz((unsigned int)pInitParam->chipClock)); | |
269 | ||
270 | /* Set up memory clock. */ | |
271 | setMemoryClock(MHz(pInitParam->memClock)); | |
272 | ||
273 | /* Set up master clock */ | |
274 | setMasterClock(MHz(pInitParam->masterClock)); | |
275 | ||
276 | ||
277 | /* Reset the memory controller. If the memory controller is not reset in SM750, | |
278 | the system might hang when sw accesses the memory. | |
279 | The memory should be resetted after changing the MXCLK. | |
280 | */ | |
9767fc51 | 281 | if (pInitParam->resetMemory == 1) { |
81dee67e SM |
282 | ulReg = PEEK32(MISC_CTRL); |
283 | ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, RESET); | |
284 | POKE32(MISC_CTRL, ulReg); | |
285 | ||
286 | ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, NORMAL); | |
287 | POKE32(MISC_CTRL, ulReg); | |
288 | } | |
289 | ||
9767fc51 | 290 | if (pInitParam->setAllEngOff == 1) { |
81dee67e SM |
291 | enable2DEngine(0); |
292 | ||
293 | /* Disable Overlay, if a former application left it on */ | |
294 | ulReg = PEEK32(VIDEO_DISPLAY_CTRL); | |
295 | ulReg = FIELD_SET(ulReg, VIDEO_DISPLAY_CTRL, PLANE, DISABLE); | |
296 | POKE32(VIDEO_DISPLAY_CTRL, ulReg); | |
297 | ||
298 | /* Disable video alpha, if a former application left it on */ | |
299 | ulReg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL); | |
300 | ulReg = FIELD_SET(ulReg, VIDEO_ALPHA_DISPLAY_CTRL, PLANE, DISABLE); | |
301 | POKE32(VIDEO_ALPHA_DISPLAY_CTRL, ulReg); | |
302 | ||
303 | /* Disable alpha plane, if a former application left it on */ | |
304 | ulReg = PEEK32(ALPHA_DISPLAY_CTRL); | |
305 | ulReg = FIELD_SET(ulReg, ALPHA_DISPLAY_CTRL, PLANE, DISABLE); | |
306 | POKE32(ALPHA_DISPLAY_CTRL, ulReg); | |
307 | ||
81dee67e SM |
308 | /* Disable DMA Channel, if a former application left it on */ |
309 | ulReg = PEEK32(DMA_ABORT_INTERRUPT); | |
310 | ulReg = FIELD_SET(ulReg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT); | |
311 | POKE32(DMA_ABORT_INTERRUPT, ulReg); | |
312 | ||
313 | /* Disable DMA Power, if a former application left it on */ | |
314 | enableDMA(0); | |
315 | } | |
316 | ||
317 | /* We can add more initialization as needed. */ | |
318 | ||
319 | return 0; | |
320 | } | |
321 | ||
81dee67e SM |
322 | /* |
323 | monk liu @ 4/6/2011: | |
324 | re-write the calculatePLL function of ddk750. | |
325 | the original version function does not use some mathematics tricks and shortcut | |
326 | when it doing the calculation of the best N,M,D combination | |
327 | I think this version gives a little upgrade in speed | |
328 | ||
329 | 750 pll clock formular: | |
330 | Request Clock = (Input Clock * M )/(N * X) | |
331 | ||
332 | Input Clock = 14318181 hz | |
333 | X = 2 power D | |
334 | D ={0,1,2,3,4,5,6} | |
335 | M = {1,...,255} | |
336 | N = {2,...,15} | |
337 | */ | |
c04051f5 | 338 | unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) |
81dee67e SM |
339 | { |
340 | /* used for primary and secondary channel pixel clock pll */ | |
341 | static pllcalparam xparm_PIXEL[] = { | |
c04051f5 HF |
342 | /* 2^0 = 1*/ {0, 0, 0, 1}, |
343 | /* 2^ 1 =2*/ {1, 0, 1, 2}, | |
344 | /* 2^ 2 = 4*/ {2, 0, 2, 4}, | |
345 | {3, 0, 3, 8}, | |
346 | {4, 1, 3, 16}, | |
347 | {5, 2, 3, 32}, | |
348 | /* 2^6 = 64 */ {6, 3, 3, 64}, | |
81dee67e SM |
349 | }; |
350 | ||
351 | /* used for MXCLK (chip clock) */ | |
352 | static pllcalparam xparm_MXCLK[] = { | |
c04051f5 HF |
353 | /* 2^0 = 1*/ {0, 0, 0, 1}, |
354 | /* 2^ 1 =2*/ {1, 0, 1, 2}, | |
355 | /* 2^ 2 = 4*/ {2, 0, 2, 4}, | |
356 | {3, 0, 3, 8}, | |
81dee67e SM |
357 | }; |
358 | ||
de99befd | 359 | /* as sm750 register definition, N located in 2,15 and M located in 1,255 */ |
c04051f5 | 360 | int N, M, X, d; |
81dee67e | 361 | int xcnt; |
43ce0b53 | 362 | int mini_diff; |
c04051f5 HF |
363 | unsigned int RN, quo, rem, fl_quo; |
364 | unsigned int input, request; | |
365 | unsigned int tmpClock, ret; | |
eb0f4271 | 366 | pllcalparam *xparm; |
81dee67e SM |
367 | |
368 | #if 1 | |
9767fc51 | 369 | if (getChipType() == SM750LE) { |
de99befd RN |
370 | /* SM750LE don't have prgrammable PLL and M/N values to work on. |
371 | Just return the requested clock. */ | |
372 | return request_orig; | |
373 | } | |
81dee67e SM |
374 | #endif |
375 | ||
376 | ret = 0; | |
43ce0b53 | 377 | mini_diff = ~0; |
81dee67e SM |
378 | request = request_orig / 1000; |
379 | input = pll->inputFreq / 1000; | |
380 | ||
381 | /* for MXCLK register , no POD provided, so need be treated differently */ | |
382 | ||
82736d22 | 383 | if (pll->clockType != MXCLK_PLL) { |
81dee67e | 384 | xparm = &xparm_PIXEL[0]; |
80fb74c3 | 385 | xcnt = ARRAY_SIZE(xparm_PIXEL); |
9767fc51 | 386 | } else { |
81dee67e | 387 | xparm = &xparm_MXCLK[0]; |
80fb74c3 | 388 | xcnt = ARRAY_SIZE(xparm_MXCLK); |
81dee67e SM |
389 | } |
390 | ||
391 | ||
ce02a16a | 392 | for (N = 15; N > 1; N--) { |
81dee67e SM |
393 | /* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */ |
394 | RN = N * request; | |
395 | quo = RN / input; | |
396 | rem = RN % input;/* rem always small than 14318181 */ | |
6ab5b6d1 | 397 | fl_quo = (rem * 10000 / input); |
81dee67e | 398 | |
ce02a16a | 399 | for (d = xcnt - 1; d >= 0; d--) { |
81dee67e | 400 | X = xparm[d].value; |
f40917ea | 401 | M = quo * X; |
81dee67e SM |
402 | M += fl_quo * X / 10000; |
403 | /* round step */ | |
07387cba | 404 | M += (fl_quo * X % 10000) > 5000 ? 1 : 0; |
82736d22 | 405 | if (M < 256 && M > 0) { |
81dee67e | 406 | unsigned int diff; |
40403c1b | 407 | |
6ab5b6d1 | 408 | tmpClock = pll->inputFreq * M / N / X; |
c04051f5 | 409 | diff = absDiff(tmpClock, request_orig); |
43ce0b53 | 410 | if (diff < mini_diff) { |
81dee67e SM |
411 | pll->M = M; |
412 | pll->N = N; | |
413 | pll->OD = xparm[d].od; | |
414 | pll->POD = xparm[d].pod; | |
43ce0b53 | 415 | mini_diff = diff; |
81dee67e SM |
416 | ret = tmpClock; |
417 | } | |
418 | } | |
419 | } | |
420 | } | |
81dee67e SM |
421 | return ret; |
422 | } | |
423 | ||
81dee67e SM |
424 | unsigned int formatPllReg(pll_value_t *pPLL) |
425 | { | |
de99befd | 426 | unsigned int ulPllReg = 0; |
81dee67e SM |
427 | |
428 | /* Note that all PLL's have the same format. Here, we just use Panel PLL parameter | |
429 | to work out the bit fields in the register. | |
430 | On returning a 32 bit number, the value can be applied to any PLL in the calling function. | |
431 | */ | |
de99befd | 432 | ulPllReg = |
7f0ebcc2 JL |
433 | FIELD_SET(0, PANEL_PLL_CTRL, BYPASS, OFF) |
434 | | FIELD_SET(0, PANEL_PLL_CTRL, POWER, ON) | |
435 | | FIELD_SET(0, PANEL_PLL_CTRL, INPUT, OSC) | |
81dee67e | 436 | #ifndef VALIDATION_CHIP |
de99befd | 437 | | FIELD_VALUE(0, PANEL_PLL_CTRL, POD, pPLL->POD) |
81dee67e | 438 | #endif |
de99befd RN |
439 | | FIELD_VALUE(0, PANEL_PLL_CTRL, OD, pPLL->OD) |
440 | | FIELD_VALUE(0, PANEL_PLL_CTRL, N, pPLL->N) | |
441 | | FIELD_VALUE(0, PANEL_PLL_CTRL, M, pPLL->M); | |
81dee67e | 442 | |
63de0eb0 | 443 | return ulPllReg; |
81dee67e SM |
444 | } |
445 | ||
446 |