• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <linux/sizes.h>
2 
3 #include "ddk750_help.h"
4 #include "ddk750_reg.h"
5 #include "ddk750_chip.h"
6 #include "ddk750_power.h"
7 
getChipType(void)8 logical_chip_type_t getChipType(void)
9 {
10 	unsigned short physicalID;
11 	char physicalRev;
12 	logical_chip_type_t chip;
13 
14 	physicalID = devId750; /* either 0x718 or 0x750 */
15 	physicalRev = revId750;
16 
17 	if (physicalID == 0x718)
18 		chip = SM718;
19 	else if (physicalID == 0x750) {
20 		chip = SM750;
21 		/* SM750 and SM750LE are different in their revision ID only. */
22 		if (physicalRev == SM750LE_REVISION_ID)
23 			chip = SM750LE;
24 	} else
25 		chip = SM_UNKNOWN;
26 
27 	return chip;
28 }
29 
get_mxclk_freq(void)30 static unsigned int get_mxclk_freq(void)
31 {
32 	unsigned int pll_reg;
33 	unsigned int M, N, OD, POD;
34 
35 	if (getChipType() == SM750LE)
36 		return MHz(130);
37 
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);
43 
44 	return DEFAULT_INPUT_CLOCK * M / N / (1 << OD) / (1 << POD);
45 }
46 
47 /*
48  * This function set up the main chip clock.
49  *
50  * Input: Frequency to be set.
51  */
setChipClock(unsigned int frequency)52 static void setChipClock(unsigned int frequency)
53 {
54 	pll_value_t pll;
55 	unsigned int ulActualMxClk;
56 
57 	/* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
58 	if (getChipType() == SM750LE)
59 		return;
60 
61 	if (frequency) {
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 	}
78 }
79 
setMemoryClock(unsigned int frequency)80 static void setMemoryClock(unsigned int frequency)
81 {
82 	unsigned int ulReg, divisor;
83 
84 	/* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
85 	if (getChipType() == SM750LE)
86 		return;
87 
88 	if (frequency) {
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 */
95 		divisor = roundedDiv(get_mxclk_freq(), frequency);
96 
97 		/* Set the corresponding divisor in the register. */
98 		ulReg = PEEK32(CURRENT_GATE);
99 		switch (divisor) {
100 		default:
101 		case 1:
102 			ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_1);
103 			break;
104 		case 2:
105 			ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_2);
106 			break;
107 		case 3:
108 			ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_3);
109 			break;
110 		case 4:
111 			ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_4);
112 			break;
113 		}
114 
115 		setCurrentGate(ulReg);
116 	}
117 }
118 
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  */
setMasterClock(unsigned int frequency)127 static void setMasterClock(unsigned int frequency)
128 {
129 	unsigned int ulReg, divisor;
130 
131 	/* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
132 	if (getChipType() == SM750LE)
133 		return;
134 
135 	if (frequency) {
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 */
142 		divisor = roundedDiv(get_mxclk_freq(), frequency);
143 
144 		/* Set the corresponding divisor in the register. */
145 		ulReg = PEEK32(CURRENT_GATE);
146 		switch (divisor) {
147 		default:
148 		case 3:
149 			ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_3);
150 			break;
151 		case 4:
152 			ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_4);
153 			break;
154 		case 6:
155 			ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_6);
156 			break;
157 		case 8:
158 			ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_8);
159 			break;
160 		}
161 
162 		setCurrentGate(ulReg);
163 		}
164 }
165 
ddk750_getVMSize(void)166 unsigned int ddk750_getVMSize(void)
167 {
168 	unsigned int reg;
169 	unsigned int data;
170 
171 	/* sm750le only use 64 mb memory*/
172 	if (getChipType() == SM750LE)
173 		return SZ_64M;
174 
175 	/* for 750,always use power mode0*/
176 	reg = PEEK32(MODE0_GATE);
177 	reg = FIELD_SET(reg, MODE0_GATE, GPIO, ON);
178 	POKE32(MODE0_GATE, reg);
179 
180 	/* get frame buffer size from GPIO */
181 	reg = FIELD_GET(PEEK32(MISC_CTRL), MISC_CTRL, LOCALMEM_SIZE);
182 	switch (reg) {
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 */
191 	default:
192 		data = 0;
193 		break;
194 	}
195 	return data;
196 }
197 
ddk750_initHw(initchip_param_t * pInitParam)198 int ddk750_initHw(initchip_param_t *pInitParam)
199 {
200 	unsigned int ulReg;
201 
202 	if (pInitParam->powerMode != 0)
203 		pInitParam->powerMode = 0;
204 	setPowerMode(pInitParam->powerMode);
205 
206 	/* Enable display power gate & LOCALMEM power gate*/
207 	ulReg = PEEK32(CURRENT_GATE);
208 	ulReg = FIELD_SET(ulReg, CURRENT_GATE, DISPLAY, ON);
209 	ulReg = FIELD_SET(ulReg, CURRENT_GATE, LOCALMEM, ON);
210 	setCurrentGate(ulReg);
211 
212 	if (getChipType() != SM750LE) {
213 		/*	set panel pll and graphic mode via mmio_88 */
214 		ulReg = PEEK32(VGA_CONFIGURATION);
215 		ulReg = FIELD_SET(ulReg, VGA_CONFIGURATION, PLL, PANEL);
216 		ulReg = FIELD_SET(ulReg, VGA_CONFIGURATION, MODE, GRAPHIC);
217 		POKE32(VGA_CONFIGURATION, ulReg);
218 	} else {
219 #if defined(__i386__) || defined(__x86_64__)
220 		/* set graphic mode via IO method */
221 		outb_p(0x88, 0x3d4);
222 		outb_p(0x06, 0x3d5);
223 #endif
224 	}
225 
226 	/* Set the Main Chip Clock */
227 	setChipClock(MHz((unsigned int)pInitParam->chipClock));
228 
229 	/* Set up memory clock. */
230 	setMemoryClock(MHz(pInitParam->memClock));
231 
232 	/* Set up master clock */
233 	setMasterClock(MHz(pInitParam->masterClock));
234 
235 
236 	/* Reset the memory controller. If the memory controller is not reset in SM750,
237 	   the system might hang when sw accesses the memory.
238 	   The memory should be resetted after changing the MXCLK.
239 	 */
240 	if (pInitParam->resetMemory == 1) {
241 		ulReg = PEEK32(MISC_CTRL);
242 		ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, RESET);
243 		POKE32(MISC_CTRL, ulReg);
244 
245 		ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, NORMAL);
246 		POKE32(MISC_CTRL, ulReg);
247 	}
248 
249 	if (pInitParam->setAllEngOff == 1) {
250 		enable2DEngine(0);
251 
252 		/* Disable Overlay, if a former application left it on */
253 		ulReg = PEEK32(VIDEO_DISPLAY_CTRL);
254 		ulReg = FIELD_SET(ulReg, VIDEO_DISPLAY_CTRL, PLANE, DISABLE);
255 		POKE32(VIDEO_DISPLAY_CTRL, ulReg);
256 
257 		/* Disable video alpha, if a former application left it on */
258 		ulReg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL);
259 		ulReg = FIELD_SET(ulReg, VIDEO_ALPHA_DISPLAY_CTRL, PLANE, DISABLE);
260 		POKE32(VIDEO_ALPHA_DISPLAY_CTRL, ulReg);
261 
262 		/* Disable alpha plane, if a former application left it on */
263 		ulReg = PEEK32(ALPHA_DISPLAY_CTRL);
264 		ulReg = FIELD_SET(ulReg, ALPHA_DISPLAY_CTRL, PLANE, DISABLE);
265 		POKE32(ALPHA_DISPLAY_CTRL, ulReg);
266 
267 		/* Disable DMA Channel, if a former application left it on */
268 		ulReg = PEEK32(DMA_ABORT_INTERRUPT);
269 		ulReg = FIELD_SET(ulReg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT);
270 		POKE32(DMA_ABORT_INTERRUPT, ulReg);
271 
272 		/* Disable DMA Power, if a former application left it on */
273 		enableDMA(0);
274 	}
275 
276 	/* We can add more initialization as needed. */
277 
278 	return 0;
279 }
280 
281 /*
282 	monk liu @ 4/6/2011:
283 		   re-write the calculatePLL function of ddk750.
284 		   the original version function does not use some mathematics tricks and shortcut
285 		   when it doing the calculation of the best N,M,D combination
286 		   I think this version gives a little upgrade in speed
287 
288 	750 pll clock formular:
289 	Request Clock = (Input Clock * M )/(N * X)
290 
291 	Input Clock = 14318181 hz
292 	X = 2 power D
293 	D ={0,1,2,3,4,5,6}
294 	M = {1,...,255}
295 	N = {2,...,15}
296 */
calcPllValue(unsigned int request_orig,pll_value_t * pll)297 unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
298 {
299 	/* as sm750 register definition, N located in 2,15 and M located in 1,255	*/
300 	int N, M, X, d;
301 	int mini_diff;
302 	unsigned int RN, quo, rem, fl_quo;
303 	unsigned int input, request;
304 	unsigned int tmpClock, ret;
305 	const int max_OD = 3;
306 	int max_d;
307 
308 	if (getChipType() == SM750LE) {
309 		/* SM750LE don't have prgrammable PLL and M/N values to work on.
310 		Just return the requested clock. */
311 		return request_orig;
312 	}
313 
314 	ret = 0;
315 	mini_diff = ~0;
316 	request = request_orig / 1000;
317 	input = pll->inputFreq / 1000;
318 
319 	/* for MXCLK register , no POD provided, so need be treated differently	*/
320 	if (pll->clockType == MXCLK_PLL)
321 		max_d = 3;
322 
323 	for (N = 15; N > 1; N--) {
324 		/* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */
325 		RN = N * request;
326 		quo = RN / input;
327 		rem = RN % input;/* rem always small than 14318181 */
328 		fl_quo = (rem * 10000 / input);
329 
330 		for (d = max_d; d >= 0; d--) {
331 			X = (1 << d);
332 			M = quo * X;
333 			M += fl_quo * X / 10000;
334 			/* round step */
335 			M += (fl_quo * X % 10000) > 5000 ? 1 : 0;
336 			if (M < 256 && M > 0) {
337 				unsigned int diff;
338 
339 				tmpClock = pll->inputFreq * M / N / X;
340 				diff = absDiff(tmpClock, request_orig);
341 				if (diff < mini_diff) {
342 					pll->M = M;
343 					pll->N = N;
344 					pll->POD = 0;
345 					if (d > max_OD)
346 						pll->POD = d - max_OD;
347 					pll->OD = d - pll->POD;
348 					mini_diff = diff;
349 					ret = tmpClock;
350 				}
351 			}
352 		}
353 	}
354 	return ret;
355 }
356 
formatPllReg(pll_value_t * pPLL)357 unsigned int formatPllReg(pll_value_t *pPLL)
358 {
359 	unsigned int ulPllReg = 0;
360 
361     /* Note that all PLL's have the same format. Here, we just use Panel PLL parameter
362        to work out the bit fields in the register.
363        On returning a 32 bit number, the value can be applied to any PLL in the calling function.
364     */
365 	ulPllReg =
366 	FIELD_SET(0, PANEL_PLL_CTRL, BYPASS, OFF)
367 	| FIELD_SET(0, PANEL_PLL_CTRL, POWER,  ON)
368 	| FIELD_SET(0, PANEL_PLL_CTRL, INPUT,  OSC)
369 #ifndef VALIDATION_CHIP
370 	| FIELD_VALUE(0, PANEL_PLL_CTRL, POD,    pPLL->POD)
371 #endif
372 	| FIELD_VALUE(0, PANEL_PLL_CTRL, OD,     pPLL->OD)
373 	| FIELD_VALUE(0, PANEL_PLL_CTRL, N,      pPLL->N)
374 	| FIELD_VALUE(0, PANEL_PLL_CTRL, M,      pPLL->M);
375 
376 	return ulPllReg;
377 }
378 
379 
380