1 #include <linux/sizes.h>
3 #include "ddk750_help.h"
4 #include "ddk750_reg.h"
5 #include "ddk750_chip.h"
6 #include "ddk750_power.h"
8 logical_chip_type_t getChipType(void)
10 unsigned short physicalID;
12 logical_chip_type_t chip;
14 physicalID = devId750; /* either 0x718 or 0x750 */
15 physicalRev = revId750;
17 if (physicalID == 0x718)
19 else if (physicalID == 0x750) {
21 /* SM750 and SM750LE are different in their revision ID only. */
22 if (physicalRev == SM750LE_REVISION_ID)
30 static unsigned int get_mxclk_freq(void)
33 unsigned int M, N, OD, POD;
35 if (getChipType() == SM750LE)
38 pll_reg = PEEK32(MXCLK_PLL_CTRL);
39 M = FIELD_GET(pll_reg, PANEL_PLL_CTRL, M);
40 N = FIELD_GET(pll_reg, PANEL_PLL_CTRL, N);
41 OD = FIELD_GET(pll_reg, PANEL_PLL_CTRL, OD);
42 POD = FIELD_GET(pll_reg, PANEL_PLL_CTRL, POD);
44 return DEFAULT_INPUT_CLOCK * M / N / (1 << OD) / (1 << POD);
48 * This function set up the main chip clock.
50 * Input: Frequency to be set.
52 static void setChipClock(unsigned int frequency)
55 unsigned int ulActualMxClk;
57 /* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
58 if (getChipType() == SM750LE)
63 * Set up PLL, a structure to hold the value to be set in clocks.
65 pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */
66 pll.clockType = MXCLK_PLL;
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.
73 ulActualMxClk = calcPllValue(frequency, &pll);
75 /* Master Clock Control: MXCLK_PLL */
76 POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll));
80 static void setMemoryClock(unsigned int frequency)
82 unsigned int reg, divisor;
84 /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
85 if (getChipType() == SM750LE)
89 /* Set the frequency to the maximum frequency that the DDR Memory can take
91 if (frequency > MHz(336))
94 /* Calculate the divisor */
95 divisor = roundedDiv(get_mxclk_freq(), frequency);
97 /* Set the corresponding divisor in the register. */
98 reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK;
102 reg |= CURRENT_GATE_M2XCLK_DIV_1;
105 reg |= CURRENT_GATE_M2XCLK_DIV_2;
108 reg |= CURRENT_GATE_M2XCLK_DIV_3;
111 reg |= CURRENT_GATE_M2XCLK_DIV_4;
120 * This function set up the master clock (MCLK).
122 * Input: Frequency to be set.
125 * The maximum frequency the engine can run is 168MHz.
127 static void setMasterClock(unsigned int frequency)
129 unsigned int reg, divisor;
131 /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
132 if (getChipType() == SM750LE)
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);
141 /* Calculate the divisor */
142 divisor = roundedDiv(get_mxclk_freq(), frequency);
144 /* Set the corresponding divisor in the register. */
145 reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK;
149 reg |= CURRENT_GATE_MCLK_DIV_3;
152 reg |= CURRENT_GATE_MCLK_DIV_4;
155 reg |= CURRENT_GATE_MCLK_DIV_6;
158 reg |= CURRENT_GATE_MCLK_DIV_8;
166 unsigned int ddk750_getVMSize(void)
171 /* sm750le only use 64 mb memory*/
172 if (getChipType() == SM750LE)
175 /* for 750,always use power mode0*/
176 reg = PEEK32(MODE0_GATE);
177 reg |= MODE0_GATE_GPIO;
178 POKE32(MODE0_GATE, reg);
180 /* get frame buffer size from GPIO */
181 reg = PEEK32(MISC_CTRL) & MISC_CTRL_LOCALMEM_SIZE_MASK;
183 case MISC_CTRL_LOCALMEM_SIZE_8M:
184 data = SZ_8M; break; /* 8 Mega byte */
185 case MISC_CTRL_LOCALMEM_SIZE_16M:
186 data = SZ_16M; break; /* 16 Mega byte */
187 case MISC_CTRL_LOCALMEM_SIZE_32M:
188 data = SZ_32M; break; /* 32 Mega byte */
189 case MISC_CTRL_LOCALMEM_SIZE_64M:
190 data = SZ_64M; break; /* 64 Mega byte */
198 int ddk750_initHw(initchip_param_t *pInitParam)
202 if (pInitParam->powerMode != 0)
203 pInitParam->powerMode = 0;
204 setPowerMode(pInitParam->powerMode);
206 /* Enable display power gate & LOCALMEM power gate*/
207 reg = PEEK32(CURRENT_GATE);
208 reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM);
211 if (getChipType() != SM750LE) {
212 /* set panel pll and graphic mode via mmio_88 */
213 reg = PEEK32(VGA_CONFIGURATION);
214 reg = FIELD_SET(reg, VGA_CONFIGURATION, PLL, PANEL);
215 reg = FIELD_SET(reg, VGA_CONFIGURATION, MODE, GRAPHIC);
216 POKE32(VGA_CONFIGURATION, reg);
218 #if defined(__i386__) || defined(__x86_64__)
219 /* set graphic mode via IO method */
225 /* Set the Main Chip Clock */
226 setChipClock(MHz((unsigned int)pInitParam->chipClock));
228 /* Set up memory clock. */
229 setMemoryClock(MHz(pInitParam->memClock));
231 /* Set up master clock */
232 setMasterClock(MHz(pInitParam->masterClock));
235 /* Reset the memory controller. If the memory controller is not reset in SM750,
236 the system might hang when sw accesses the memory.
237 The memory should be resetted after changing the MXCLK.
239 if (pInitParam->resetMemory == 1) {
240 reg = PEEK32(MISC_CTRL);
241 reg &= ~MISC_CTRL_LOCALMEM_RESET;
242 POKE32(MISC_CTRL, reg);
244 reg |= MISC_CTRL_LOCALMEM_RESET;
245 POKE32(MISC_CTRL, reg);
248 if (pInitParam->setAllEngOff == 1) {
251 /* Disable Overlay, if a former application left it on */
252 reg = PEEK32(VIDEO_DISPLAY_CTRL);
253 reg = FIELD_SET(reg, VIDEO_DISPLAY_CTRL, PLANE, DISABLE);
254 POKE32(VIDEO_DISPLAY_CTRL, reg);
256 /* Disable video alpha, if a former application left it on */
257 reg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL);
258 reg = FIELD_SET(reg, VIDEO_ALPHA_DISPLAY_CTRL, PLANE, DISABLE);
259 POKE32(VIDEO_ALPHA_DISPLAY_CTRL, reg);
261 /* Disable alpha plane, if a former application left it on */
262 reg = PEEK32(ALPHA_DISPLAY_CTRL);
263 reg = FIELD_SET(reg, ALPHA_DISPLAY_CTRL, PLANE, DISABLE);
264 POKE32(ALPHA_DISPLAY_CTRL, reg);
266 /* Disable DMA Channel, if a former application left it on */
267 reg = PEEK32(DMA_ABORT_INTERRUPT);
268 reg = FIELD_SET(reg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT);
269 POKE32(DMA_ABORT_INTERRUPT, reg);
271 /* Disable DMA Power, if a former application left it on */
275 /* We can add more initialization as needed. */
282 re-write the calculatePLL function of ddk750.
283 the original version function does not use some mathematics tricks and shortcut
284 when it doing the calculation of the best N,M,D combination
285 I think this version gives a little upgrade in speed
287 750 pll clock formular:
288 Request Clock = (Input Clock * M )/(N * X)
290 Input Clock = 14318181 hz
296 unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
298 /* as sm750 register definition, N located in 2,15 and M located in 1,255 */
301 unsigned int RN, quo, rem, fl_quo;
302 unsigned int input, request;
303 unsigned int tmpClock, ret;
304 const int max_OD = 3;
307 if (getChipType() == SM750LE) {
308 /* SM750LE don't have prgrammable PLL and M/N values to work on.
309 Just return the requested clock. */
315 request = request_orig / 1000;
316 input = pll->inputFreq / 1000;
318 /* for MXCLK register , no POD provided, so need be treated differently */
319 if (pll->clockType == MXCLK_PLL)
322 for (N = 15; N > 1; N--) {
323 /* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */
326 rem = RN % input;/* rem always small than 14318181 */
327 fl_quo = (rem * 10000 / input);
329 for (d = max_d; d >= 0; d--) {
332 M += fl_quo * X / 10000;
334 M += (fl_quo * X % 10000) > 5000 ? 1 : 0;
335 if (M < 256 && M > 0) {
338 tmpClock = pll->inputFreq * M / N / X;
339 diff = absDiff(tmpClock, request_orig);
340 if (diff < mini_diff) {
345 pll->POD = d - max_OD;
346 pll->OD = d - pll->POD;
356 unsigned int formatPllReg(pll_value_t *pPLL)
358 unsigned int reg = 0;
360 /* Note that all PLL's have the same format. Here, we just use Panel PLL parameter
361 to work out the bit fields in the register.
362 On returning a 32 bit number, the value can be applied to any PLL in the calling function.
365 FIELD_SET(0, PANEL_PLL_CTRL, BYPASS, OFF)
366 | FIELD_SET(0, PANEL_PLL_CTRL, POWER, ON)
367 | FIELD_SET(0, PANEL_PLL_CTRL, INPUT, OSC)
368 #ifndef VALIDATION_CHIP
369 | FIELD_VALUE(0, PANEL_PLL_CTRL, POD, pPLL->POD)
371 | FIELD_VALUE(0, PANEL_PLL_CTRL, OD, pPLL->OD)
372 | FIELD_VALUE(0, PANEL_PLL_CTRL, N, pPLL->N)
373 | FIELD_VALUE(0, PANEL_PLL_CTRL, M, pPLL->M);