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.
92 if (getChipType() == SM750LE)
96 /* Set the frequency to the maximum frequency that the DDR Memory can take
98 if (frequency > MHz(336))
101 /* Calculate the divisor */
102 divisor = roundedDiv(get_mxclk_freq(), frequency);
104 /* Set the corresponding divisor in the register. */
105 reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK;
109 reg |= CURRENT_GATE_M2XCLK_DIV_1;
112 reg |= CURRENT_GATE_M2XCLK_DIV_2;
115 reg |= CURRENT_GATE_M2XCLK_DIV_3;
118 reg |= CURRENT_GATE_M2XCLK_DIV_4;
127 * This function set up the master clock (MCLK).
129 * Input: Frequency to be set.
132 * The maximum frequency the engine can run is 168MHz.
134 static void setMasterClock(unsigned int frequency)
136 unsigned int reg, divisor;
138 /* Cheok_0509: For SM750LE, the memory clock is fixed.
141 if (getChipType() == SM750LE)
145 /* Set the frequency to the maximum frequency that the SM750 engine can
146 run, which is about 190 MHz. */
147 if (frequency > MHz(190))
148 frequency = MHz(190);
150 /* Calculate the divisor */
151 divisor = roundedDiv(get_mxclk_freq(), frequency);
153 /* Set the corresponding divisor in the register. */
154 reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK;
158 reg |= CURRENT_GATE_MCLK_DIV_3;
161 reg |= CURRENT_GATE_MCLK_DIV_4;
164 reg |= CURRENT_GATE_MCLK_DIV_6;
167 reg |= CURRENT_GATE_MCLK_DIV_8;
175 unsigned int ddk750_getVMSize(void)
180 /* sm750le only use 64 mb memory*/
181 if (getChipType() == SM750LE)
184 /* for 750,always use power mode0*/
185 reg = PEEK32(MODE0_GATE);
186 reg |= MODE0_GATE_GPIO;
187 POKE32(MODE0_GATE, reg);
189 /* get frame buffer size from GPIO */
190 reg = PEEK32(MISC_CTRL) & MISC_CTRL_LOCALMEM_SIZE_MASK;
192 case MISC_CTRL_LOCALMEM_SIZE_8M:
193 data = SZ_8M; break; /* 8 Mega byte */
194 case MISC_CTRL_LOCALMEM_SIZE_16M:
195 data = SZ_16M; break; /* 16 Mega byte */
196 case MISC_CTRL_LOCALMEM_SIZE_32M:
197 data = SZ_32M; break; /* 32 Mega byte */
198 case MISC_CTRL_LOCALMEM_SIZE_64M:
199 data = SZ_64M; break; /* 64 Mega byte */
207 int ddk750_initHw(initchip_param_t *pInitParam)
211 if (pInitParam->powerMode != 0)
212 pInitParam->powerMode = 0;
213 setPowerMode(pInitParam->powerMode);
215 /* Enable display power gate & LOCALMEM power gate*/
216 reg = PEEK32(CURRENT_GATE);
217 reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM);
220 if (getChipType() != SM750LE) {
221 /* set panel pll and graphic mode via mmio_88 */
222 reg = PEEK32(VGA_CONFIGURATION);
223 reg |= (VGA_CONFIGURATION_PLL | VGA_CONFIGURATION_MODE);
224 POKE32(VGA_CONFIGURATION, reg);
226 #if defined(__i386__) || defined(__x86_64__)
227 /* set graphic mode via IO method */
233 /* Set the Main Chip Clock */
234 setChipClock(MHz((unsigned int)pInitParam->chipClock));
236 /* Set up memory clock. */
237 setMemoryClock(MHz(pInitParam->memClock));
239 /* Set up master clock */
240 setMasterClock(MHz(pInitParam->masterClock));
243 /* Reset the memory controller. If the memory controller is not reset in SM750,
244 the system might hang when sw accesses the memory.
245 The memory should be resetted after changing the MXCLK.
247 if (pInitParam->resetMemory == 1) {
248 reg = PEEK32(MISC_CTRL);
249 reg &= ~MISC_CTRL_LOCALMEM_RESET;
250 POKE32(MISC_CTRL, reg);
252 reg |= MISC_CTRL_LOCALMEM_RESET;
253 POKE32(MISC_CTRL, reg);
256 if (pInitParam->setAllEngOff == 1) {
259 /* Disable Overlay, if a former application left it on */
260 reg = PEEK32(VIDEO_DISPLAY_CTRL);
261 reg &= ~DISPLAY_CTRL_PLANE;
262 POKE32(VIDEO_DISPLAY_CTRL, reg);
264 /* Disable video alpha, if a former application left it on */
265 reg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL);
266 reg &= ~DISPLAY_CTRL_PLANE;
267 POKE32(VIDEO_ALPHA_DISPLAY_CTRL, reg);
269 /* Disable alpha plane, if a former application left it on */
270 reg = PEEK32(ALPHA_DISPLAY_CTRL);
271 reg &= ~DISPLAY_CTRL_PLANE;
272 POKE32(ALPHA_DISPLAY_CTRL, reg);
274 /* Disable DMA Channel, if a former application left it on */
275 reg = PEEK32(DMA_ABORT_INTERRUPT);
276 reg |= DMA_ABORT_INTERRUPT_ABORT_1;
277 POKE32(DMA_ABORT_INTERRUPT, reg);
279 /* Disable DMA Power, if a former application left it on */
283 /* We can add more initialization as needed. */
290 re-write the calculatePLL function of ddk750.
291 the original version function does not use some mathematics tricks and shortcut
292 when it doing the calculation of the best N,M,D combination
293 I think this version gives a little upgrade in speed
295 750 pll clock formular:
296 Request Clock = (Input Clock * M )/(N * X)
298 Input Clock = 14318181 hz
304 unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
306 /* as sm750 register definition, N located in 2,15 and M located in 1,255 */
309 unsigned int RN, quo, rem, fl_quo;
310 unsigned int input, request;
311 unsigned int tmpClock, ret;
312 const int max_OD = 3;
315 if (getChipType() == SM750LE) {
316 /* SM750LE don't have prgrammable PLL and M/N values to work on.
317 Just return the requested clock. */
323 request = request_orig / 1000;
324 input = pll->inputFreq / 1000;
326 /* for MXCLK register , no POD provided, so need be treated differently */
327 if (pll->clockType == MXCLK_PLL)
330 for (N = 15; N > 1; N--) {
331 /* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */
334 rem = RN % input;/* rem always small than 14318181 */
335 fl_quo = (rem * 10000 / input);
337 for (d = max_d; d >= 0; d--) {
340 M += fl_quo * X / 10000;
342 M += (fl_quo * X % 10000) > 5000 ? 1 : 0;
343 if (M < 256 && M > 0) {
346 tmpClock = pll->inputFreq * M / N / X;
347 diff = abs(tmpClock - request_orig);
348 if (diff < mini_diff) {
353 pll->POD = d - max_OD;
354 pll->OD = d - pll->POD;
364 unsigned int formatPllReg(pll_value_t *pPLL)
366 #ifndef VALIDATION_CHIP
367 unsigned int POD = pPLL->POD;
369 unsigned int OD = pPLL->OD;
370 unsigned int M = pPLL->M;
371 unsigned int N = pPLL->N;
372 unsigned int reg = 0;
375 * Note that all PLL's have the same format. Here, we just use
376 * Panel PLL parameter to work out the bit fields in the
377 * register. On returning a 32 bit number, the value can be
378 * applied to any PLL in the calling function.
380 reg = PLL_CTRL_POWER |
381 #ifndef VALIDATION_CHIP
382 ((POD << PLL_CTRL_POD_SHIFT) & PLL_CTRL_POD_MASK) |
384 ((OD << PLL_CTRL_OD_SHIFT) & PLL_CTRL_OD_MASK) |
385 ((N << PLL_CTRL_N_SHIFT) & PLL_CTRL_N_MASK) |
386 ((M << PLL_CTRL_M_SHIFT) & PLL_CTRL_M_MASK);