1 #include "ddk750_help.h"
2 #include "ddk750_reg.h"
3 #include "ddk750_chip.h"
4 #include "ddk750_power.h"
5 typedef struct _pllcalparam
{
6 unsigned char power
;/* d : 0~ 6*/
9 unsigned char value
;/* value of 2 power d (2^d) */
14 logical_chip_type_t
getChipType(void)
16 unsigned short physicalID
;
18 logical_chip_type_t chip
;
20 physicalID
= devId750
;//either 0x718 or 0x750
21 physicalRev
= revId750
;
23 if (physicalID
== 0x718)
25 else if (physicalID
== 0x750) {
27 /* SM750 and SM750LE are different in their revision ID only. */
28 if (physicalRev
== SM750LE_REVISION_ID
)
37 inline unsigned int twoToPowerOfx(unsigned long x
)
40 unsigned long result
= 1;
42 for (i
= 1; i
<= x
; i
++)
47 inline unsigned int calcPLL(pll_value_t
*pPLL
)
49 return (pPLL
->inputFreq
* pPLL
->M
/ pPLL
->N
/ twoToPowerOfx(pPLL
->OD
) / twoToPowerOfx(pPLL
->POD
));
52 unsigned int getPllValue(clock_type_t clockType
, pll_value_t
*pPLL
)
54 unsigned int ulPllReg
= 0;
56 pPLL
->inputFreq
= DEFAULT_INPUT_CLOCK
;
57 pPLL
->clockType
= clockType
;
61 ulPllReg
= PEEK32(MXCLK_PLL_CTRL
);
64 ulPllReg
= PEEK32(PANEL_PLL_CTRL
);
67 ulPllReg
= PEEK32(CRT_PLL_CTRL
);
70 ulPllReg
= PEEK32(VGA_PLL0_CTRL
);
73 ulPllReg
= PEEK32(VGA_PLL1_CTRL
);
77 pPLL
->M
= FIELD_GET(ulPllReg
, PANEL_PLL_CTRL
, M
);
78 pPLL
->N
= FIELD_GET(ulPllReg
, PANEL_PLL_CTRL
, N
);
79 pPLL
->OD
= FIELD_GET(ulPllReg
, PANEL_PLL_CTRL
, OD
);
80 pPLL
->POD
= FIELD_GET(ulPllReg
, PANEL_PLL_CTRL
, POD
);
86 unsigned int getChipClock(void)
90 if (getChipType() == SM750LE
)
94 return getPllValue(MXCLK_PLL
, &pll
);
99 * This function set up the main chip clock.
101 * Input: Frequency to be set.
103 void setChipClock(unsigned int frequency
)
106 unsigned int ulActualMxClk
;
108 /* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
109 if (getChipType() == SM750LE
)
115 * Set up PLL, a structure to hold the value to be set in clocks.
117 pll
.inputFreq
= DEFAULT_INPUT_CLOCK
; /* Defined in CLOCK.H */
118 pll
.clockType
= MXCLK_PLL
;
121 * Call calcPllValue() to fill up the other fields for PLL structure.
122 * Sometime, the chip cannot set up the exact clock required by User.
123 * Return value from calcPllValue() gives the actual possible clock.
125 ulActualMxClk
= calcPllValue(frequency
, &pll
);
127 /* Master Clock Control: MXCLK_PLL */
128 POKE32(MXCLK_PLL_CTRL
, formatPllReg(&pll
));
134 void setMemoryClock(unsigned int frequency
)
136 unsigned int ulReg
, divisor
;
138 /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
139 if (getChipType() == SM750LE
)
143 /* Set the frequency to the maximum frequency that the DDR Memory can take
145 if (frequency
> MHz(336))
146 frequency
= MHz(336);
148 /* Calculate the divisor */
149 divisor
= (unsigned int) roundedDiv(getChipClock(), frequency
);
151 /* Set the corresponding divisor in the register. */
152 ulReg
= PEEK32(CURRENT_GATE
);
156 ulReg
= FIELD_SET(ulReg
, CURRENT_GATE
, M2XCLK
, DIV_1
);
159 ulReg
= FIELD_SET(ulReg
, CURRENT_GATE
, M2XCLK
, DIV_2
);
162 ulReg
= FIELD_SET(ulReg
, CURRENT_GATE
, M2XCLK
, DIV_3
);
165 ulReg
= FIELD_SET(ulReg
, CURRENT_GATE
, M2XCLK
, DIV_4
);
169 setCurrentGate(ulReg
);
175 * This function set up the master clock (MCLK).
177 * Input: Frequency to be set.
180 * The maximum frequency the engine can run is 168MHz.
182 void setMasterClock(unsigned int frequency
)
184 unsigned int ulReg
, divisor
;
186 /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
187 if (getChipType() == SM750LE
)
191 /* Set the frequency to the maximum frequency that the SM750 engine can
192 run, which is about 190 MHz. */
193 if (frequency
> MHz(190))
194 frequency
= MHz(190);
196 /* Calculate the divisor */
197 divisor
= (unsigned int) roundedDiv(getChipClock(), frequency
);
199 /* Set the corresponding divisor in the register. */
200 ulReg
= PEEK32(CURRENT_GATE
);
204 ulReg
= FIELD_SET(ulReg
, CURRENT_GATE
, MCLK
, DIV_3
);
207 ulReg
= FIELD_SET(ulReg
, CURRENT_GATE
, MCLK
, DIV_4
);
210 ulReg
= FIELD_SET(ulReg
, CURRENT_GATE
, MCLK
, DIV_6
);
213 ulReg
= FIELD_SET(ulReg
, CURRENT_GATE
, MCLK
, DIV_8
);
217 setCurrentGate(ulReg
);
222 unsigned int ddk750_getVMSize(void)
227 /* sm750le only use 64 mb memory*/
228 if (getChipType() == SM750LE
)
231 /* for 750,always use power mode0*/
232 reg
= PEEK32(MODE0_GATE
);
233 reg
= FIELD_SET(reg
, MODE0_GATE
, GPIO
, ON
);
234 POKE32(MODE0_GATE
, reg
);
236 /* get frame buffer size from GPIO */
237 reg
= FIELD_GET(PEEK32(MISC_CTRL
), MISC_CTRL
, LOCALMEM_SIZE
);
239 case MISC_CTRL_LOCALMEM_SIZE_8M
:
240 data
= MB(8); break; /* 8 Mega byte */
241 case MISC_CTRL_LOCALMEM_SIZE_16M
:
242 data
= MB(16); break; /* 16 Mega byte */
243 case MISC_CTRL_LOCALMEM_SIZE_32M
:
244 data
= MB(32); break; /* 32 Mega byte */
245 case MISC_CTRL_LOCALMEM_SIZE_64M
:
246 data
= MB(64); break; /* 64 Mega byte */
255 int ddk750_initHw(initchip_param_t
*pInitParam
)
260 //move the code to map regiter function.
261 if (getChipType() == SM718
) {
262 /* turn on big endian bit*/
263 ulReg
= PEEK32(0x74);
264 /* now consider register definition in a big endian pattern*/
265 POKE32(0x74, ulReg
|0x80000000);
271 if (pInitParam
->powerMode
!= 0 )
272 pInitParam
->powerMode
= 0;
273 setPowerMode(pInitParam
->powerMode
);
275 /* Enable display power gate & LOCALMEM power gate*/
276 ulReg
= PEEK32(CURRENT_GATE
);
277 ulReg
= FIELD_SET(ulReg
, CURRENT_GATE
, DISPLAY
, ON
);
278 ulReg
= FIELD_SET(ulReg
, CURRENT_GATE
, LOCALMEM
, ON
);
279 setCurrentGate(ulReg
);
281 if (getChipType() != SM750LE
) {
282 /* set panel pll and graphic mode via mmio_88 */
283 ulReg
= PEEK32(VGA_CONFIGURATION
);
284 ulReg
= FIELD_SET(ulReg
, VGA_CONFIGURATION
, PLL
, PANEL
);
285 ulReg
= FIELD_SET(ulReg
, VGA_CONFIGURATION
, MODE
, GRAPHIC
);
286 POKE32(VGA_CONFIGURATION
, ulReg
);
288 #if defined(__i386__) || defined( __x86_64__)
289 /* set graphic mode via IO method */
295 /* Set the Main Chip Clock */
296 setChipClock(MHz((unsigned int)pInitParam
->chipClock
));
298 /* Set up memory clock. */
299 setMemoryClock(MHz(pInitParam
->memClock
));
301 /* Set up master clock */
302 setMasterClock(MHz(pInitParam
->masterClock
));
305 /* Reset the memory controller. If the memory controller is not reset in SM750,
306 the system might hang when sw accesses the memory.
307 The memory should be resetted after changing the MXCLK.
309 if (pInitParam
->resetMemory
== 1) {
310 ulReg
= PEEK32(MISC_CTRL
);
311 ulReg
= FIELD_SET(ulReg
, MISC_CTRL
, LOCALMEM_RESET
, RESET
);
312 POKE32(MISC_CTRL
, ulReg
);
314 ulReg
= FIELD_SET(ulReg
, MISC_CTRL
, LOCALMEM_RESET
, NORMAL
);
315 POKE32(MISC_CTRL
, ulReg
);
318 if (pInitParam
->setAllEngOff
== 1) {
321 /* Disable Overlay, if a former application left it on */
322 ulReg
= PEEK32(VIDEO_DISPLAY_CTRL
);
323 ulReg
= FIELD_SET(ulReg
, VIDEO_DISPLAY_CTRL
, PLANE
, DISABLE
);
324 POKE32(VIDEO_DISPLAY_CTRL
, ulReg
);
326 /* Disable video alpha, if a former application left it on */
327 ulReg
= PEEK32(VIDEO_ALPHA_DISPLAY_CTRL
);
328 ulReg
= FIELD_SET(ulReg
, VIDEO_ALPHA_DISPLAY_CTRL
, PLANE
, DISABLE
);
329 POKE32(VIDEO_ALPHA_DISPLAY_CTRL
, ulReg
);
331 /* Disable alpha plane, if a former application left it on */
332 ulReg
= PEEK32(ALPHA_DISPLAY_CTRL
);
333 ulReg
= FIELD_SET(ulReg
, ALPHA_DISPLAY_CTRL
, PLANE
, DISABLE
);
334 POKE32(ALPHA_DISPLAY_CTRL
, ulReg
);
337 /* Disable LCD hardware cursor, if a former application left it on */
338 ulReg
= PEEK32(PANEL_HWC_ADDRESS
);
339 ulReg
= FIELD_SET(ulReg
, PANEL_HWC_ADDRESS
, ENABLE
, DISABLE
);
340 POKE32(PANEL_HWC_ADDRESS
, ulReg
);
342 /* Disable CRT hardware cursor, if a former application left it on */
343 ulReg
= PEEK32(CRT_HWC_ADDRESS
);
344 ulReg
= FIELD_SET(ulReg
, CRT_HWC_ADDRESS
, ENABLE
, DISABLE
);
345 POKE32(CRT_HWC_ADDRESS
, ulReg
);
347 /* Disable ZV Port 0, if a former application left it on */
348 ulReg
= PEEK32(ZV0_CAPTURE_CTRL
);
349 ulReg
= FIELD_SET(ulReg
, ZV0_CAPTURE_CTRL
, CAP
, DISABLE
);
350 POKE32(ZV0_CAPTURE_CTRL
, ulReg
);
352 /* Disable ZV Port 1, if a former application left it on */
353 ulReg
= PEEK32(ZV1_CAPTURE_CTRL
);
354 ulReg
= FIELD_SET(ulReg
, ZV1_CAPTURE_CTRL
, CAP
, DISABLE
);
355 POKE32(ZV1_CAPTURE_CTRL
, ulReg
);
357 /* Disable ZV Port Power, if a former application left it on */
359 /* Disable DMA Channel, if a former application left it on */
360 ulReg
= PEEK32(DMA_ABORT_INTERRUPT
);
361 ulReg
= FIELD_SET(ulReg
, DMA_ABORT_INTERRUPT
, ABORT_1
, ABORT
);
362 POKE32(DMA_ABORT_INTERRUPT
, ulReg
);
367 /* Disable DMA Channel, if a former application left it on */
368 ulReg
= PEEK32(DMA_ABORT_INTERRUPT
);
369 ulReg
= FIELD_SET(ulReg
, DMA_ABORT_INTERRUPT
, ABORT_1
, ABORT
);
370 POKE32(DMA_ABORT_INTERRUPT
, ulReg
);
372 /* Disable DMA Power, if a former application left it on */
376 /* We can add more initialization as needed. */
383 unsigned int absDiff(unsigned int a
, unsigned int b
)
394 re-write the calculatePLL function of ddk750.
395 the original version function does not use some mathematics tricks and shortcut
396 when it doing the calculation of the best N,M,D combination
397 I think this version gives a little upgrade in speed
399 750 pll clock formular:
400 Request Clock = (Input Clock * M )/(N * X)
402 Input Clock = 14318181 hz
408 unsigned int calcPllValue(unsigned int request_orig
, pll_value_t
*pll
)
410 /* used for primary and secondary channel pixel clock pll */
411 static pllcalparam xparm_PIXEL
[] = {
412 /* 2^0 = 1*/ {0, 0, 0, 1},
413 /* 2^ 1 =2*/ {1, 0, 1, 2},
414 /* 2^ 2 = 4*/ {2, 0, 2, 4},
418 /* 2^6 = 64 */ {6, 3, 3, 64},
421 /* used for MXCLK (chip clock) */
422 static pllcalparam xparm_MXCLK
[] = {
423 /* 2^0 = 1*/ {0, 0, 0, 1},
424 /* 2^ 1 =2*/ {1, 0, 1, 2},
425 /* 2^ 2 = 4*/ {2, 0, 2, 4},
429 /* as sm750 register definition, N located in 2,15 and M located in 1,255 */
433 unsigned int RN
, quo
, rem
, fl_quo
;
434 unsigned int input
, request
;
435 unsigned int tmpClock
, ret
;
439 if (getChipType() == SM750LE
) {
440 /* SM750LE don't have prgrammable PLL and M/N values to work on.
441 Just return the requested clock. */
448 request
= request_orig
/ 1000;
449 input
= pll
->inputFreq
/ 1000;
451 /* for MXCLK register , no POD provided, so need be treated differently */
453 if (pll
->clockType
!= MXCLK_PLL
) {
454 xparm
= &xparm_PIXEL
[0];
455 xcnt
= sizeof(xparm_PIXEL
)/sizeof(xparm_PIXEL
[0]);
457 xparm
= &xparm_MXCLK
[0];
458 xcnt
= sizeof(xparm_MXCLK
)/sizeof(xparm_MXCLK
[0]);
462 for (N
= 15; N
> 1; N
--) {
463 /* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */
466 rem
= RN
% input
;/* rem always small than 14318181 */
467 fl_quo
= (rem
* 10000 /input
);
469 for (d
= xcnt
- 1; d
>= 0; d
--) {
472 M
+= fl_quo
* X
/ 10000;
474 M
+= (fl_quo
*X
% 10000)>5000?1:0;
475 if (M
< 256 && M
> 0) {
477 tmpClock
= pll
->inputFreq
*M
/ N
/ X
;
478 diff
= absDiff(tmpClock
, request_orig
);
479 if (diff
< miniDiff
) {
482 pll
->OD
= xparm
[d
].od
;
483 pll
->POD
= xparm
[d
].pod
;
491 //printk("Finally: pll->n[%lu],m[%lu],od[%lu],pod[%lu]\n",pll->N,pll->M,pll->OD,pll->POD);
495 unsigned int calcPllValue2(
496 unsigned int ulRequestClk
, /* Required pixel clock in Hz unit */
497 pll_value_t
*pPLL
/* Structure to hold the value to be set in PLL */
500 unsigned int M
, N
, OD
, POD
= 0, diff
, pllClk
, odPower
, podPower
;
501 unsigned int bestDiff
= 0xffffffff; /* biggest 32 bit unsigned number */
503 /* Init PLL structure to know states */
509 /* Sanity check: None at the moment */
511 /* Convert everything in Khz range in order to avoid calculation overflow */
512 pPLL
->inputFreq
/= 1000;
513 ulRequestClk
/= 1000;
515 #ifndef VALIDATION_CHIP
516 /* The maximum of post divider is 8. */
517 for (POD
= 0; POD
<= 3; POD
++)
521 #ifndef VALIDATION_CHIP
522 /* MXCLK_PLL does not have post divider. */
523 if ((POD
> 0) && (pPLL
->clockType
== MXCLK_PLL
))
527 /* Work out 2 to the power of POD */
528 podPower
= twoToPowerOfx(POD
);
530 /* OD has only 2 bits [15:14] and its value must between 0 to 3 */
531 for (OD
= 0; OD
<= 3; OD
++) {
532 /* Work out 2 to the power of OD */
533 odPower
= twoToPowerOfx(OD
);
535 #ifdef VALIDATION_CHIP
542 /* N has 4 bits [11:8] and its value must between 2 and 15.
543 The N == 1 will behave differently --> Result is not correct. */
544 for (N
= 2; N
<= 15; N
++) {
545 /* The formula for PLL is ulRequestClk = inputFreq * M / N / (2^OD)
546 In the following steps, we try to work out a best M value given the others are known.
547 To avoid decimal calculation, we use 1000 as multiplier for up to 3 decimal places of accuracy.
549 M
= ulRequestClk
* N
* odPower
* 1000 / pPLL
->inputFreq
;
550 M
= roundedDiv(M
, 1000);
552 /* M field has only 8 bits, reject value bigger than 8 bits */
554 /* Calculate the actual clock for a given M & N */
555 pllClk
= pPLL
->inputFreq
* M
/ N
/ odPower
/ podPower
;
557 /* How much are we different from the requirement */
558 diff
= absDiff(pllClk
, ulRequestClk
);
560 if (diff
< bestDiff
) {
563 /* Store M and N values */
568 #ifdef VALIDATION_CHIP
582 /* Restore input frequency from Khz to hz unit */
583 // pPLL->inputFreq *= 1000;
584 ulRequestClk
*= 1000;
585 pPLL
->inputFreq
= DEFAULT_INPUT_CLOCK
; /* Default reference clock */
587 /* Output debug information */
588 //DDKDEBUGPRINT((DISPLAY_LEVEL, "calcPllValue: Requested Frequency = %d\n", ulRequestClk));
589 //DDKDEBUGPRINT((DISPLAY_LEVEL, "calcPllValue: Input CLK = %dHz, M=%d, N=%d, OD=%d, POD=%d\n", pPLL->inputFreq, pPLL->M, pPLL->N, pPLL->OD, pPLL->POD));
591 /* Return actual frequency that the PLL can set */
600 unsigned int formatPllReg(pll_value_t
*pPLL
)
602 unsigned int ulPllReg
= 0;
604 /* Note that all PLL's have the same format. Here, we just use Panel PLL parameter
605 to work out the bit fields in the register.
606 On returning a 32 bit number, the value can be applied to any PLL in the calling function.
609 FIELD_SET( 0, PANEL_PLL_CTRL
, BYPASS
, OFF
)
610 | FIELD_SET( 0, PANEL_PLL_CTRL
, POWER
, ON
)
611 | FIELD_SET( 0, PANEL_PLL_CTRL
, INPUT
, OSC
)
612 #ifndef VALIDATION_CHIP
613 | FIELD_VALUE(0, PANEL_PLL_CTRL
, POD
, pPLL
->POD
)
615 | FIELD_VALUE(0, PANEL_PLL_CTRL
, OD
, pPLL
->OD
)
616 | FIELD_VALUE(0, PANEL_PLL_CTRL
, N
, pPLL
->N
)
617 | FIELD_VALUE(0, PANEL_PLL_CTRL
, M
, pPLL
->M
);