1 #include <linux/kernel.h>
2 #include <linux/sizes.h>
4 #include "ddk750_help.h"
5 #include "ddk750_reg.h"
6 #include "ddk750_chip.h"
7 #include "ddk750_power.h"
9 /* n / d + 1 / 2 = (2n + d) / 2d */
10 #define roundedDiv(num, denom) ((2 * (num) + (denom)) / (2 * (denom)))
11 #define MHz(x) ((x) * 1000000)
13 logical_chip_type_t getChipType(void)
15 unsigned short physicalID;
17 logical_chip_type_t chip;
19 physicalID = devId750; /* either 0x718 or 0x750 */
20 physicalRev = revId750;
22 if (physicalID == 0x718)
24 else if (physicalID == 0x750) {
26 /* SM750 and SM750LE are different in their revision ID only. */
27 if (physicalRev == SM750LE_REVISION_ID)
35 static unsigned int get_mxclk_freq(void)
38 unsigned int M, N, OD, POD;
40 if (getChipType() == SM750LE)
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;
49 return DEFAULT_INPUT_CLOCK * M / N / (1 << OD) / (1 << POD);
53 * This function set up the main chip clock.
55 * Input: Frequency to be set.
57 static void setChipClock(unsigned int frequency)
60 unsigned int ulActualMxClk;
62 /* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
63 if (getChipType() == SM750LE)
68 * Set up PLL, a structure to hold the value to be set in clocks.
70 pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */
71 pll.clockType = MXCLK_PLL;
74 * Call calcPllValue() to fill up the other fields for PLL structure.
75 * Sometime, the chip cannot set up the exact clock required by User.
76 * Return value from calcPllValue() gives the actual possible clock.
78 ulActualMxClk = calcPllValue(frequency, &pll);
80 /* Master Clock Control: MXCLK_PLL */
81 POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll));
85 static void setMemoryClock(unsigned int frequency)
87 unsigned int reg, divisor;
89 /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
90 if (getChipType() == SM750LE)
94 /* Set the frequency to the maximum frequency that the DDR Memory can take
96 if (frequency > MHz(336))
99 /* Calculate the divisor */
100 divisor = roundedDiv(get_mxclk_freq(), frequency);
102 /* Set the corresponding divisor in the register. */
103 reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK;
107 reg |= CURRENT_GATE_M2XCLK_DIV_1;
110 reg |= CURRENT_GATE_M2XCLK_DIV_2;
113 reg |= CURRENT_GATE_M2XCLK_DIV_3;
116 reg |= CURRENT_GATE_M2XCLK_DIV_4;
125 * This function set up the master clock (MCLK).
127 * Input: Frequency to be set.
130 * The maximum frequency the engine can run is 168MHz.
132 static void setMasterClock(unsigned int frequency)
134 unsigned int reg, divisor;
136 /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
137 if (getChipType() == SM750LE)
141 /* Set the frequency to the maximum frequency that the SM750 engine can
142 run, which is about 190 MHz. */
143 if (frequency > MHz(190))
144 frequency = MHz(190);
146 /* Calculate the divisor */
147 divisor = roundedDiv(get_mxclk_freq(), frequency);
149 /* Set the corresponding divisor in the register. */
150 reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK;
154 reg |= CURRENT_GATE_MCLK_DIV_3;
157 reg |= CURRENT_GATE_MCLK_DIV_4;
160 reg |= CURRENT_GATE_MCLK_DIV_6;
163 reg |= CURRENT_GATE_MCLK_DIV_8;
171 unsigned int ddk750_getVMSize(void)
176 /* sm750le only use 64 mb memory*/
177 if (getChipType() == SM750LE)
180 /* for 750,always use power mode0*/
181 reg = PEEK32(MODE0_GATE);
182 reg |= MODE0_GATE_GPIO;
183 POKE32(MODE0_GATE, reg);
185 /* get frame buffer size from GPIO */
186 reg = PEEK32(MISC_CTRL) & MISC_CTRL_LOCALMEM_SIZE_MASK;
188 case MISC_CTRL_LOCALMEM_SIZE_8M:
189 data = SZ_8M; break; /* 8 Mega byte */
190 case MISC_CTRL_LOCALMEM_SIZE_16M:
191 data = SZ_16M; break; /* 16 Mega byte */
192 case MISC_CTRL_LOCALMEM_SIZE_32M:
193 data = SZ_32M; break; /* 32 Mega byte */
194 case MISC_CTRL_LOCALMEM_SIZE_64M:
195 data = SZ_64M; break; /* 64 Mega byte */
203 int ddk750_initHw(initchip_param_t *pInitParam)
207 if (pInitParam->powerMode != 0)
208 pInitParam->powerMode = 0;
209 setPowerMode(pInitParam->powerMode);
211 /* Enable display power gate & LOCALMEM power gate*/
212 reg = PEEK32(CURRENT_GATE);
213 reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM);
216 if (getChipType() != SM750LE) {
217 /* set panel pll and graphic mode via mmio_88 */
218 reg = PEEK32(VGA_CONFIGURATION);
219 reg |= (VGA_CONFIGURATION_PLL | VGA_CONFIGURATION_MODE);
220 POKE32(VGA_CONFIGURATION, reg);
222 #if defined(__i386__) || defined(__x86_64__)
223 /* set graphic mode via IO method */
229 /* Set the Main Chip Clock */
230 setChipClock(MHz((unsigned int)pInitParam->chipClock));
232 /* Set up memory clock. */
233 setMemoryClock(MHz(pInitParam->memClock));
235 /* Set up master clock */
236 setMasterClock(MHz(pInitParam->masterClock));
239 /* Reset the memory controller. If the memory controller is not reset in SM750,
240 the system might hang when sw accesses the memory.
241 The memory should be resetted after changing the MXCLK.
243 if (pInitParam->resetMemory == 1) {
244 reg = PEEK32(MISC_CTRL);
245 reg &= ~MISC_CTRL_LOCALMEM_RESET;
246 POKE32(MISC_CTRL, reg);
248 reg |= MISC_CTRL_LOCALMEM_RESET;
249 POKE32(MISC_CTRL, reg);
252 if (pInitParam->setAllEngOff == 1) {
255 /* Disable Overlay, if a former application left it on */
256 reg = PEEK32(VIDEO_DISPLAY_CTRL);
257 reg &= ~DISPLAY_CTRL_PLANE;
258 POKE32(VIDEO_DISPLAY_CTRL, reg);
260 /* Disable video alpha, if a former application left it on */
261 reg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL);
262 reg &= ~DISPLAY_CTRL_PLANE;
263 POKE32(VIDEO_ALPHA_DISPLAY_CTRL, reg);
265 /* Disable alpha plane, if a former application left it on */
266 reg = PEEK32(ALPHA_DISPLAY_CTRL);
267 reg &= ~DISPLAY_CTRL_PLANE;
268 POKE32(ALPHA_DISPLAY_CTRL, reg);
270 /* Disable DMA Channel, if a former application left it on */
271 reg = PEEK32(DMA_ABORT_INTERRUPT);
272 reg |= DMA_ABORT_INTERRUPT_ABORT_1;
273 POKE32(DMA_ABORT_INTERRUPT, reg);
275 /* Disable DMA Power, if a former application left it on */
279 /* We can add more initialization as needed. */
286 re-write the calculatePLL function of ddk750.
287 the original version function does not use some mathematics tricks and shortcut
288 when it doing the calculation of the best N,M,D combination
289 I think this version gives a little upgrade in speed
291 750 pll clock formular:
292 Request Clock = (Input Clock * M )/(N * X)
294 Input Clock = 14318181 hz
300 unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
302 /* as sm750 register definition, N located in 2,15 and M located in 1,255 */
305 unsigned int RN, quo, rem, fl_quo;
306 unsigned int input, request;
307 unsigned int tmpClock, ret;
308 const int max_OD = 3;
311 if (getChipType() == SM750LE) {
312 /* SM750LE don't have prgrammable PLL and M/N values to work on.
313 Just return the requested clock. */
319 request = request_orig / 1000;
320 input = pll->inputFreq / 1000;
322 /* for MXCLK register , no POD provided, so need be treated differently */
323 if (pll->clockType == MXCLK_PLL)
326 for (N = 15; N > 1; N--) {
327 /* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */
330 rem = RN % input;/* rem always small than 14318181 */
331 fl_quo = (rem * 10000 / input);
333 for (d = max_d; d >= 0; d--) {
336 M += fl_quo * X / 10000;
338 M += (fl_quo * X % 10000) > 5000 ? 1 : 0;
339 if (M < 256 && M > 0) {
342 tmpClock = pll->inputFreq * M / N / X;
343 diff = abs(tmpClock - request_orig);
344 if (diff < mini_diff) {
349 pll->POD = d - max_OD;
350 pll->OD = d - pll->POD;
360 unsigned int formatPllReg(pll_value_t *pPLL)
362 #ifndef VALIDATION_CHIP
363 unsigned int POD = pPLL->POD;
365 unsigned int OD = pPLL->OD;
366 unsigned int M = pPLL->M;
367 unsigned int N = pPLL->N;
368 unsigned int reg = 0;
371 * Note that all PLL's have the same format. Here, we just use
372 * Panel PLL parameter to work out the bit fields in the
373 * register. On returning a 32 bit number, the value can be
374 * applied to any PLL in the calling function.
376 reg = PLL_CTRL_POWER |
377 #ifndef VALIDATION_CHIP
378 ((POD << PLL_CTRL_POD_SHIFT) & PLL_CTRL_POD_MASK) |
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);