]>
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" | |
81dee67e | 7 | |
6fa7db83 | 8 | logical_chip_type_t getChipType(void) |
81dee67e SM |
9 | { |
10 | unsigned short physicalID; | |
11 | char physicalRev; | |
12 | logical_chip_type_t chip; | |
13 | ||
5ee35ea7 | 14 | physicalID = devId750; /* either 0x718 or 0x750 */ |
81dee67e SM |
15 | physicalRev = revId750; |
16 | ||
de99befd | 17 | if (physicalID == 0x718) |
de99befd | 18 | chip = SM718; |
9767fc51 | 19 | else if (physicalID == 0x750) { |
de99befd | 20 | chip = SM750; |
81dee67e | 21 | /* SM750 and SM750LE are different in their revision ID only. */ |
9767fc51 | 22 | if (physicalRev == SM750LE_REVISION_ID) |
81dee67e | 23 | chip = SM750LE; |
9767fc51 | 24 | } else |
de99befd | 25 | chip = SM_UNKNOWN; |
81dee67e SM |
26 | |
27 | return chip; | |
28 | } | |
29 | ||
7092d76f | 30 | static unsigned int get_mxclk_freq(void) |
81dee67e | 31 | { |
7751e0e2 MR |
32 | unsigned int pll_reg; |
33 | unsigned int M, N, OD, POD; | |
34 | ||
82736d22 | 35 | if (getChipType() == SM750LE) |
81dee67e | 36 | return MHz(130); |
81dee67e | 37 | |
7751e0e2 | 38 | pll_reg = PEEK32(MXCLK_PLL_CTRL); |
cdd5df64 MR |
39 | M = (pll_reg & PLL_CTRL_M_MASK) >> PLL_CTRL_M_SHIFT; |
40 | N = (pll_reg & PLL_CTRL_N_MASK) >> PLL_CTRL_M_SHIFT; | |
41 | OD = (pll_reg & PLL_CTRL_OD_MASK) >> PLL_CTRL_OD_SHIFT; | |
42 | POD = (pll_reg & PLL_CTRL_POD_MASK) >> PLL_CTRL_POD_SHIFT; | |
7751e0e2 MR |
43 | |
44 | return DEFAULT_INPUT_CLOCK * M / N / (1 << OD) / (1 << POD); | |
81dee67e SM |
45 | } |
46 | ||
81dee67e SM |
47 | /* |
48 | * This function set up the main chip clock. | |
49 | * | |
50 | * Input: Frequency to be set. | |
51 | */ | |
fb6f37a8 | 52 | static void setChipClock(unsigned int frequency) |
81dee67e | 53 | { |
de99befd RN |
54 | pll_value_t pll; |
55 | unsigned int ulActualMxClk; | |
cfac7d6a | 56 | |
de99befd RN |
57 | /* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */ |
58 | if (getChipType() == SM750LE) | |
59 | return; | |
81dee67e | 60 | |
59f08407 | 61 | if (frequency) { |
de99befd RN |
62 | /* |
63 | * Set up PLL, a structure to hold the value to be set in clocks. | |
64 | */ | |
65 | pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */ | |
66 | pll.clockType = MXCLK_PLL; | |
67 | ||
68 | /* | |
69 | * Call calcPllValue() to fill up the other fields for PLL structure. | |
70 | * Sometime, the chip cannot set up the exact clock required by User. | |
71 | * Return value from calcPllValue() gives the actual possible clock. | |
72 | */ | |
73 | ulActualMxClk = calcPllValue(frequency, &pll); | |
74 | ||
75 | /* Master Clock Control: MXCLK_PLL */ | |
76 | POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll)); | |
77 | } | |
81dee67e SM |
78 | } |
79 | ||
fb6f37a8 | 80 | static void setMemoryClock(unsigned int frequency) |
81dee67e | 81 | { |
19aa2113 | 82 | unsigned int reg, divisor; |
cfac7d6a | 83 | |
81dee67e SM |
84 | /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */ |
85 | if (getChipType() == SM750LE) | |
86 | return; | |
cfac7d6a | 87 | |
59f08407 | 88 | if (frequency) { |
de99befd RN |
89 | /* Set the frequency to the maximum frequency that the DDR Memory can take |
90 | which is 336MHz. */ | |
91 | if (frequency > MHz(336)) | |
92 | frequency = MHz(336); | |
93 | ||
94 | /* Calculate the divisor */ | |
b02f9240 | 95 | divisor = roundedDiv(get_mxclk_freq(), frequency); |
de99befd RN |
96 | |
97 | /* Set the corresponding divisor in the register. */ | |
6e8aa4a1 | 98 | reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK; |
c107243b | 99 | switch (divisor) { |
de99befd RN |
100 | default: |
101 | case 1: | |
6e8aa4a1 | 102 | reg |= CURRENT_GATE_M2XCLK_DIV_1; |
de99befd RN |
103 | break; |
104 | case 2: | |
6e8aa4a1 | 105 | reg |= CURRENT_GATE_M2XCLK_DIV_2; |
de99befd RN |
106 | break; |
107 | case 3: | |
6e8aa4a1 | 108 | reg |= CURRENT_GATE_M2XCLK_DIV_3; |
de99befd RN |
109 | break; |
110 | case 4: | |
6e8aa4a1 | 111 | reg |= CURRENT_GATE_M2XCLK_DIV_4; |
de99befd RN |
112 | break; |
113 | } | |
114 | ||
19aa2113 | 115 | setCurrentGate(reg); |
de99befd | 116 | } |
81dee67e SM |
117 | } |
118 | ||
81dee67e SM |
119 | /* |
120 | * This function set up the master clock (MCLK). | |
121 | * | |
122 | * Input: Frequency to be set. | |
123 | * | |
124 | * NOTE: | |
125 | * The maximum frequency the engine can run is 168MHz. | |
126 | */ | |
fb6f37a8 | 127 | static void setMasterClock(unsigned int frequency) |
81dee67e | 128 | { |
19aa2113 | 129 | unsigned int reg, divisor; |
cfac7d6a | 130 | |
81dee67e SM |
131 | /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */ |
132 | if (getChipType() == SM750LE) | |
133 | return; | |
cfac7d6a | 134 | |
59f08407 | 135 | if (frequency) { |
de99befd RN |
136 | /* Set the frequency to the maximum frequency that the SM750 engine can |
137 | run, which is about 190 MHz. */ | |
138 | if (frequency > MHz(190)) | |
139 | frequency = MHz(190); | |
140 | ||
141 | /* Calculate the divisor */ | |
b02f9240 | 142 | divisor = roundedDiv(get_mxclk_freq(), frequency); |
de99befd RN |
143 | |
144 | /* Set the corresponding divisor in the register. */ | |
6e8aa4a1 | 145 | reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK; |
c107243b | 146 | switch (divisor) { |
de99befd RN |
147 | default: |
148 | case 3: | |
6e8aa4a1 | 149 | reg |= CURRENT_GATE_MCLK_DIV_3; |
de99befd RN |
150 | break; |
151 | case 4: | |
6e8aa4a1 | 152 | reg |= CURRENT_GATE_MCLK_DIV_4; |
de99befd RN |
153 | break; |
154 | case 6: | |
6e8aa4a1 | 155 | reg |= CURRENT_GATE_MCLK_DIV_6; |
de99befd RN |
156 | break; |
157 | case 8: | |
6e8aa4a1 | 158 | reg |= CURRENT_GATE_MCLK_DIV_8; |
de99befd RN |
159 | break; |
160 | } | |
161 | ||
19aa2113 | 162 | setCurrentGate(reg); |
de99befd | 163 | } |
81dee67e SM |
164 | } |
165 | ||
6fa7db83 | 166 | unsigned int ddk750_getVMSize(void) |
81dee67e SM |
167 | { |
168 | unsigned int reg; | |
169 | unsigned int data; | |
170 | ||
171 | /* sm750le only use 64 mb memory*/ | |
82736d22 | 172 | if (getChipType() == SM750LE) |
4cf26d85 | 173 | return SZ_64M; |
81dee67e SM |
174 | |
175 | /* for 750,always use power mode0*/ | |
176 | reg = PEEK32(MODE0_GATE); | |
05e9d9ea | 177 | reg |= MODE0_GATE_GPIO; |
c04051f5 | 178 | POKE32(MODE0_GATE, reg); |
81dee67e SM |
179 | |
180 | /* get frame buffer size from GPIO */ | |
5538d5c8 | 181 | reg = PEEK32(MISC_CTRL) & MISC_CTRL_LOCALMEM_SIZE_MASK; |
c107243b | 182 | switch (reg) { |
ae59c465 | 183 | case MISC_CTRL_LOCALMEM_SIZE_8M: |
4cf26d85 | 184 | data = SZ_8M; break; /* 8 Mega byte */ |
ae59c465 | 185 | case MISC_CTRL_LOCALMEM_SIZE_16M: |
4cf26d85 | 186 | data = SZ_16M; break; /* 16 Mega byte */ |
ae59c465 | 187 | case MISC_CTRL_LOCALMEM_SIZE_32M: |
4cf26d85 | 188 | data = SZ_32M; break; /* 32 Mega byte */ |
ae59c465 | 189 | case MISC_CTRL_LOCALMEM_SIZE_64M: |
4cf26d85 | 190 | data = SZ_64M; break; /* 64 Mega byte */ |
ae59c465 | 191 | default: |
e261e69e AKC |
192 | data = 0; |
193 | break; | |
81dee67e SM |
194 | } |
195 | return data; | |
81dee67e SM |
196 | } |
197 | ||
f8da055a | 198 | int ddk750_initHw(initchip_param_t *pInitParam) |
81dee67e | 199 | { |
8bc728cf | 200 | unsigned int reg; |
81dee67e | 201 | |
8332d94c | 202 | if (pInitParam->powerMode != 0) |
81dee67e SM |
203 | pInitParam->powerMode = 0; |
204 | setPowerMode(pInitParam->powerMode); | |
205 | ||
206 | /* Enable display power gate & LOCALMEM power gate*/ | |
8bc728cf | 207 | reg = PEEK32(CURRENT_GATE); |
90946e52 | 208 | reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM); |
8bc728cf | 209 | setCurrentGate(reg); |
81dee67e | 210 | |
82736d22 | 211 | if (getChipType() != SM750LE) { |
81dee67e | 212 | /* set panel pll and graphic mode via mmio_88 */ |
8bc728cf | 213 | reg = PEEK32(VGA_CONFIGURATION); |
d9798143 | 214 | reg |= (VGA_CONFIGURATION_PLL | VGA_CONFIGURATION_MODE); |
8bc728cf | 215 | POKE32(VGA_CONFIGURATION, reg); |
9767fc51 | 216 | } else { |
31296ba5 | 217 | #if defined(__i386__) || defined(__x86_64__) |
81dee67e | 218 | /* set graphic mode via IO method */ |
c04051f5 HF |
219 | outb_p(0x88, 0x3d4); |
220 | outb_p(0x06, 0x3d5); | |
81dee67e SM |
221 | #endif |
222 | } | |
223 | ||
224 | /* Set the Main Chip Clock */ | |
225 | setChipClock(MHz((unsigned int)pInitParam->chipClock)); | |
226 | ||
227 | /* Set up memory clock. */ | |
228 | setMemoryClock(MHz(pInitParam->memClock)); | |
229 | ||
230 | /* Set up master clock */ | |
231 | setMasterClock(MHz(pInitParam->masterClock)); | |
232 | ||
233 | ||
234 | /* Reset the memory controller. If the memory controller is not reset in SM750, | |
235 | the system might hang when sw accesses the memory. | |
236 | The memory should be resetted after changing the MXCLK. | |
237 | */ | |
9767fc51 | 238 | if (pInitParam->resetMemory == 1) { |
8bc728cf | 239 | reg = PEEK32(MISC_CTRL); |
5372350b | 240 | reg &= ~MISC_CTRL_LOCALMEM_RESET; |
8bc728cf | 241 | POKE32(MISC_CTRL, reg); |
81dee67e | 242 | |
5372350b | 243 | reg |= MISC_CTRL_LOCALMEM_RESET; |
8bc728cf | 244 | POKE32(MISC_CTRL, reg); |
81dee67e SM |
245 | } |
246 | ||
9767fc51 | 247 | if (pInitParam->setAllEngOff == 1) { |
81dee67e SM |
248 | enable2DEngine(0); |
249 | ||
250 | /* Disable Overlay, if a former application left it on */ | |
8bc728cf | 251 | reg = PEEK32(VIDEO_DISPLAY_CTRL); |
6fba39cf | 252 | reg &= ~DISPLAY_CTRL_PLANE; |
8bc728cf | 253 | POKE32(VIDEO_DISPLAY_CTRL, reg); |
81dee67e SM |
254 | |
255 | /* Disable video alpha, if a former application left it on */ | |
8bc728cf | 256 | reg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL); |
6fba39cf | 257 | reg &= ~DISPLAY_CTRL_PLANE; |
8bc728cf | 258 | POKE32(VIDEO_ALPHA_DISPLAY_CTRL, reg); |
81dee67e SM |
259 | |
260 | /* Disable alpha plane, if a former application left it on */ | |
8bc728cf | 261 | reg = PEEK32(ALPHA_DISPLAY_CTRL); |
6fba39cf | 262 | reg &= ~DISPLAY_CTRL_PLANE; |
8bc728cf | 263 | POKE32(ALPHA_DISPLAY_CTRL, reg); |
81dee67e | 264 | |
81dee67e | 265 | /* Disable DMA Channel, if a former application left it on */ |
8bc728cf MR |
266 | reg = PEEK32(DMA_ABORT_INTERRUPT); |
267 | reg = FIELD_SET(reg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT); | |
268 | POKE32(DMA_ABORT_INTERRUPT, reg); | |
81dee67e SM |
269 | |
270 | /* Disable DMA Power, if a former application left it on */ | |
271 | enableDMA(0); | |
272 | } | |
273 | ||
274 | /* We can add more initialization as needed. */ | |
275 | ||
276 | return 0; | |
277 | } | |
278 | ||
81dee67e SM |
279 | /* |
280 | monk liu @ 4/6/2011: | |
281 | re-write the calculatePLL function of ddk750. | |
282 | the original version function does not use some mathematics tricks and shortcut | |
283 | when it doing the calculation of the best N,M,D combination | |
284 | I think this version gives a little upgrade in speed | |
285 | ||
286 | 750 pll clock formular: | |
287 | Request Clock = (Input Clock * M )/(N * X) | |
288 | ||
289 | Input Clock = 14318181 hz | |
290 | X = 2 power D | |
291 | D ={0,1,2,3,4,5,6} | |
292 | M = {1,...,255} | |
293 | N = {2,...,15} | |
294 | */ | |
c04051f5 | 295 | unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) |
81dee67e | 296 | { |
de99befd | 297 | /* as sm750 register definition, N located in 2,15 and M located in 1,255 */ |
c04051f5 | 298 | int N, M, X, d; |
43ce0b53 | 299 | int mini_diff; |
c04051f5 HF |
300 | unsigned int RN, quo, rem, fl_quo; |
301 | unsigned int input, request; | |
302 | unsigned int tmpClock, ret; | |
a61dc139 MR |
303 | const int max_OD = 3; |
304 | int max_d; | |
81dee67e | 305 | |
9767fc51 | 306 | if (getChipType() == SM750LE) { |
de99befd RN |
307 | /* SM750LE don't have prgrammable PLL and M/N values to work on. |
308 | Just return the requested clock. */ | |
309 | return request_orig; | |
310 | } | |
81dee67e SM |
311 | |
312 | ret = 0; | |
43ce0b53 | 313 | mini_diff = ~0; |
81dee67e SM |
314 | request = request_orig / 1000; |
315 | input = pll->inputFreq / 1000; | |
316 | ||
317 | /* for MXCLK register , no POD provided, so need be treated differently */ | |
a61dc139 MR |
318 | if (pll->clockType == MXCLK_PLL) |
319 | max_d = 3; | |
81dee67e | 320 | |
ce02a16a | 321 | for (N = 15; N > 1; N--) { |
81dee67e SM |
322 | /* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */ |
323 | RN = N * request; | |
324 | quo = RN / input; | |
325 | rem = RN % input;/* rem always small than 14318181 */ | |
6ab5b6d1 | 326 | fl_quo = (rem * 10000 / input); |
81dee67e | 327 | |
a61dc139 MR |
328 | for (d = max_d; d >= 0; d--) { |
329 | X = (1 << d); | |
f40917ea | 330 | M = quo * X; |
81dee67e SM |
331 | M += fl_quo * X / 10000; |
332 | /* round step */ | |
07387cba | 333 | M += (fl_quo * X % 10000) > 5000 ? 1 : 0; |
82736d22 | 334 | if (M < 256 && M > 0) { |
81dee67e | 335 | unsigned int diff; |
40403c1b | 336 | |
6ab5b6d1 | 337 | tmpClock = pll->inputFreq * M / N / X; |
c04051f5 | 338 | diff = absDiff(tmpClock, request_orig); |
43ce0b53 | 339 | if (diff < mini_diff) { |
81dee67e SM |
340 | pll->M = M; |
341 | pll->N = N; | |
a61dc139 MR |
342 | pll->POD = 0; |
343 | if (d > max_OD) | |
344 | pll->POD = d - max_OD; | |
345 | pll->OD = d - pll->POD; | |
43ce0b53 | 346 | mini_diff = diff; |
81dee67e SM |
347 | ret = tmpClock; |
348 | } | |
349 | } | |
350 | } | |
351 | } | |
81dee67e SM |
352 | return ret; |
353 | } | |
354 | ||
81dee67e SM |
355 | unsigned int formatPllReg(pll_value_t *pPLL) |
356 | { | |
cdd5df64 MR |
357 | #ifndef VALIDATION_CHIP |
358 | unsigned int POD = pPLL->POD; | |
359 | #endif | |
360 | unsigned int OD = pPLL->OD; | |
361 | unsigned int M = pPLL->M; | |
362 | unsigned int N = pPLL->N; | |
375b4d42 | 363 | unsigned int reg = 0; |
81dee67e | 364 | |
0c4d85fc MR |
365 | /* |
366 | * Note that all PLL's have the same format. Here, we just use | |
367 | * Panel PLL parameter to work out the bit fields in the | |
368 | * register. On returning a 32 bit number, the value can be | |
369 | * applied to any PLL in the calling function. | |
370 | */ | |
cdd5df64 | 371 | reg = PLL_CTRL_POWER | |
81dee67e | 372 | #ifndef VALIDATION_CHIP |
cdd5df64 | 373 | ((POD << PLL_CTRL_POD_SHIFT) & PLL_CTRL_POD_MASK) | |
81dee67e | 374 | #endif |
cdd5df64 MR |
375 | ((OD << PLL_CTRL_OD_SHIFT) & PLL_CTRL_OD_MASK) | |
376 | ((N << PLL_CTRL_N_SHIFT) & PLL_CTRL_N_MASK) | | |
377 | ((M << PLL_CTRL_M_SHIFT) & PLL_CTRL_M_MASK); | |
81dee67e | 378 | |
375b4d42 | 379 | return reg; |
81dee67e SM |
380 | } |
381 | ||
382 |