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 #define MHz(x) ((x) * 1000000)
11 logical_chip_type_t sm750_get_chip_type(void)
13 unsigned short physicalID;
15 logical_chip_type_t chip;
17 physicalID = devId750; /* either 0x718 or 0x750 */
18 physicalRev = revId750;
20 if (physicalID == 0x718)
22 else if (physicalID == 0x750) {
24 /* SM750 and SM750LE are different in their revision ID only. */
25 if (physicalRev == SM750LE_REVISION_ID)
33 static unsigned int get_mxclk_freq(void)
36 unsigned int M, N, OD, POD;
38 if (sm750_get_chip_type() == SM750LE)
41 pll_reg = PEEK32(MXCLK_PLL_CTRL);
42 M = (pll_reg & PLL_CTRL_M_MASK) >> PLL_CTRL_M_SHIFT;
43 N = (pll_reg & PLL_CTRL_N_MASK) >> PLL_CTRL_M_SHIFT;
44 OD = (pll_reg & PLL_CTRL_OD_MASK) >> PLL_CTRL_OD_SHIFT;
45 POD = (pll_reg & PLL_CTRL_POD_MASK) >> PLL_CTRL_POD_SHIFT;
47 return DEFAULT_INPUT_CLOCK * M / N / (1 << OD) / (1 << POD);
51 * This function set up the main chip clock.
53 * Input: Frequency to be set.
55 static void setChipClock(unsigned int frequency)
58 unsigned int ulActualMxClk;
60 /* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
61 if (sm750_get_chip_type() == SM750LE)
66 * Set up PLL, a structure to hold the value to be set in clocks.
68 pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */
69 pll.clockType = MXCLK_PLL;
72 * Call calcPllValue() to fill the other fields of PLL structure.
73 * Sometime, the chip cannot set up the exact clock
74 * required by the User.
75 * Return value of calcPllValue gives the actual possible clock.
77 ulActualMxClk = calcPllValue(frequency, &pll);
79 /* Master Clock Control: MXCLK_PLL */
80 POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll));
84 static void setMemoryClock(unsigned int frequency)
86 unsigned int reg, divisor;
88 /* Cheok_0509: For SM750LE, the memory clock is fixed.
91 if (sm750_get_chip_type() == SM750LE)
96 * Set the frequency to the maximum frequency
97 * that the DDR Memory can take which is 336MHz.
99 if (frequency > MHz(336))
100 frequency = MHz(336);
102 /* Calculate the divisor */
103 divisor = DIV_ROUND_CLOSEST(get_mxclk_freq(), frequency);
105 /* Set the corresponding divisor in the register. */
106 reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK;
110 reg |= CURRENT_GATE_M2XCLK_DIV_1;
113 reg |= CURRENT_GATE_M2XCLK_DIV_2;
116 reg |= CURRENT_GATE_M2XCLK_DIV_3;
119 reg |= CURRENT_GATE_M2XCLK_DIV_4;
128 * This function set up the master clock (MCLK).
130 * Input: Frequency to be set.
133 * The maximum frequency the engine can run is 168MHz.
135 static void setMasterClock(unsigned int frequency)
137 unsigned int reg, divisor;
139 /* Cheok_0509: For SM750LE, the memory clock is fixed.
142 if (sm750_get_chip_type() == SM750LE)
146 /* Set the frequency to the maximum frequency
147 * that the SM750 engine can run, which is about 190 MHz.
149 if (frequency > MHz(190))
150 frequency = MHz(190);
152 /* Calculate the divisor */
153 divisor = DIV_ROUND_CLOSEST(get_mxclk_freq(), frequency);
155 /* Set the corresponding divisor in the register. */
156 reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK;
160 reg |= CURRENT_GATE_MCLK_DIV_3;
163 reg |= CURRENT_GATE_MCLK_DIV_4;
166 reg |= CURRENT_GATE_MCLK_DIV_6;
169 reg |= CURRENT_GATE_MCLK_DIV_8;
177 unsigned int ddk750_getVMSize(void)
182 /* sm750le only use 64 mb memory*/
183 if (sm750_get_chip_type() == SM750LE)
186 /* for 750,always use power mode0*/
187 reg = PEEK32(MODE0_GATE);
188 reg |= MODE0_GATE_GPIO;
189 POKE32(MODE0_GATE, reg);
191 /* get frame buffer size from GPIO */
192 reg = PEEK32(MISC_CTRL) & MISC_CTRL_LOCALMEM_SIZE_MASK;
194 case MISC_CTRL_LOCALMEM_SIZE_8M:
195 data = SZ_8M; break; /* 8 Mega byte */
196 case MISC_CTRL_LOCALMEM_SIZE_16M:
197 data = SZ_16M; break; /* 16 Mega byte */
198 case MISC_CTRL_LOCALMEM_SIZE_32M:
199 data = SZ_32M; break; /* 32 Mega byte */
200 case MISC_CTRL_LOCALMEM_SIZE_64M:
201 data = SZ_64M; break; /* 64 Mega byte */
209 int ddk750_initHw(initchip_param_t *pInitParam)
213 if (pInitParam->powerMode != 0)
214 pInitParam->powerMode = 0;
215 setPowerMode(pInitParam->powerMode);
217 /* Enable display power gate & LOCALMEM power gate*/
218 reg = PEEK32(CURRENT_GATE);
219 reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM);
222 if (sm750_get_chip_type() != SM750LE) {
223 /* set panel pll and graphic mode via mmio_88 */
224 reg = PEEK32(VGA_CONFIGURATION);
225 reg |= (VGA_CONFIGURATION_PLL | VGA_CONFIGURATION_MODE);
226 POKE32(VGA_CONFIGURATION, reg);
228 #if defined(__i386__) || defined(__x86_64__)
229 /* set graphic mode via IO method */
235 /* Set the Main Chip Clock */
236 setChipClock(MHz((unsigned int)pInitParam->chipClock));
238 /* Set up memory clock. */
239 setMemoryClock(MHz(pInitParam->memClock));
241 /* Set up master clock */
242 setMasterClock(MHz(pInitParam->masterClock));
245 /* Reset the memory controller.
246 * If the memory controller is not reset in SM750,
247 * the system might hang when sw accesses the memory.
248 * The memory should be resetted after changing the MXCLK.
250 if (pInitParam->resetMemory == 1) {
251 reg = PEEK32(MISC_CTRL);
252 reg &= ~MISC_CTRL_LOCALMEM_RESET;
253 POKE32(MISC_CTRL, reg);
255 reg |= MISC_CTRL_LOCALMEM_RESET;
256 POKE32(MISC_CTRL, reg);
259 if (pInitParam->setAllEngOff == 1) {
262 /* Disable Overlay, if a former application left it on */
263 reg = PEEK32(VIDEO_DISPLAY_CTRL);
264 reg &= ~DISPLAY_CTRL_PLANE;
265 POKE32(VIDEO_DISPLAY_CTRL, reg);
267 /* Disable video alpha, if a former application left it on */
268 reg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL);
269 reg &= ~DISPLAY_CTRL_PLANE;
270 POKE32(VIDEO_ALPHA_DISPLAY_CTRL, reg);
272 /* Disable alpha plane, if a former application left it on */
273 reg = PEEK32(ALPHA_DISPLAY_CTRL);
274 reg &= ~DISPLAY_CTRL_PLANE;
275 POKE32(ALPHA_DISPLAY_CTRL, reg);
277 /* Disable DMA Channel, if a former application left it on */
278 reg = PEEK32(DMA_ABORT_INTERRUPT);
279 reg |= DMA_ABORT_INTERRUPT_ABORT_1;
280 POKE32(DMA_ABORT_INTERRUPT, reg);
282 /* Disable DMA Power, if a former application left it on */
286 /* We can add more initialization as needed. */
292 * monk liu @ 4/6/2011:
293 * re-write the calculatePLL function of ddk750.
294 * the original version function does not use
295 * some mathematics tricks and shortcut
296 * when it doing the calculation of the best N,M,D combination
297 * I think this version gives a little upgrade in speed
299 * 750 pll clock formular:
300 * Request Clock = (Input Clock * M )/(N * X)
302 * Input Clock = 14318181 hz
308 unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
310 /* as sm750 register definition,
311 * N located in 2,15 and M located in 1,255
315 unsigned int RN, quo, rem, fl_quo;
316 unsigned int input, request;
317 unsigned int tmpClock, ret;
318 const int max_OD = 3;
321 if (sm750_get_chip_type() == SM750LE) {
322 /* SM750LE don't have
323 * programmable PLL and M/N values to work on.
324 * Just return the requested clock.
331 request = request_orig / 1000;
332 input = pll->inputFreq / 1000;
334 /* for MXCLK register,
335 * no POD provided, so need be treated differently
337 if (pll->clockType == MXCLK_PLL)
340 for (N = 15; N > 1; N--) {
341 /* RN will not exceed maximum long
342 * if @request <= 285 MHZ (for 32bit cpu)
346 rem = RN % input;/* rem always small than 14318181 */
347 fl_quo = (rem * 10000 / input);
349 for (d = max_d; d >= 0; d--) {
352 M += fl_quo * X / 10000;
354 M += (fl_quo * X % 10000) > 5000 ? 1 : 0;
355 if (M < 256 && M > 0) {
358 tmpClock = pll->inputFreq * M / N / X;
359 diff = abs(tmpClock - request_orig);
360 if (diff < mini_diff) {
365 pll->POD = d - max_OD;
366 pll->OD = d - pll->POD;
376 unsigned int formatPllReg(pll_value_t *pPLL)
378 #ifndef VALIDATION_CHIP
379 unsigned int POD = pPLL->POD;
381 unsigned int OD = pPLL->OD;
382 unsigned int M = pPLL->M;
383 unsigned int N = pPLL->N;
384 unsigned int reg = 0;
387 * Note that all PLL's have the same format. Here, we just use
388 * Panel PLL parameter to work out the bit fields in the
389 * register. On returning a 32 bit number, the value can be
390 * applied to any PLL in the calling function.
392 reg = PLL_CTRL_POWER |
393 #ifndef VALIDATION_CHIP
394 ((POD << PLL_CTRL_POD_SHIFT) & PLL_CTRL_POD_MASK) |
396 ((OD << PLL_CTRL_OD_SHIFT) & PLL_CTRL_OD_MASK) |
397 ((N << PLL_CTRL_N_SHIFT) & PLL_CTRL_N_MASK) |
398 ((M << PLL_CTRL_M_SHIFT) & PLL_CTRL_M_MASK);