• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <linux/kernel.h>
2 #include <linux/sizes.h>
3 
4 #include "ddk750_help.h"
5 #include "ddk750_reg.h"
6 #include "ddk750_chip.h"
7 #include "ddk750_power.h"
8 
9 #define MHz(x) ((x) * 1000000)
10 
sm750_get_chip_type(void)11 logical_chip_type_t sm750_get_chip_type(void)
12 {
13 	unsigned short physicalID;
14 	char physicalRev;
15 	logical_chip_type_t chip;
16 
17 	physicalID = devId750; /* either 0x718 or 0x750 */
18 	physicalRev = revId750;
19 
20 	if (physicalID == 0x718)
21 		chip = SM718;
22 	else if (physicalID == 0x750) {
23 		chip = SM750;
24 		/* SM750 and SM750LE are different in their revision ID only. */
25 		if (physicalRev == SM750LE_REVISION_ID)
26 			chip = SM750LE;
27 	} else
28 		chip = SM_UNKNOWN;
29 
30 	return chip;
31 }
32 
get_mxclk_freq(void)33 static unsigned int get_mxclk_freq(void)
34 {
35 	unsigned int pll_reg;
36 	unsigned int M, N, OD, POD;
37 
38 	if (sm750_get_chip_type() == SM750LE)
39 		return MHz(130);
40 
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;
46 
47 	return DEFAULT_INPUT_CLOCK * M / N / (1 << OD) / (1 << POD);
48 }
49 
50 /*
51  * This function set up the main chip clock.
52  *
53  * Input: Frequency to be set.
54  */
setChipClock(unsigned int frequency)55 static void setChipClock(unsigned int frequency)
56 {
57 	pll_value_t pll;
58 	unsigned int ulActualMxClk;
59 
60 	/* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
61 	if (sm750_get_chip_type() == SM750LE)
62 		return;
63 
64 	if (frequency) {
65 		/*
66 		* Set up PLL, a structure to hold the value to be set in clocks.
67 		*/
68 		pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */
69 		pll.clockType = MXCLK_PLL;
70 
71 		/*
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.
76 		*/
77 		ulActualMxClk = calcPllValue(frequency, &pll);
78 
79 		/* Master Clock Control: MXCLK_PLL */
80 		POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll));
81 	}
82 }
83 
setMemoryClock(unsigned int frequency)84 static void setMemoryClock(unsigned int frequency)
85 {
86 	unsigned int reg, divisor;
87 
88 	/* Cheok_0509: For SM750LE, the memory clock is fixed.
89 	 * Nothing to set.
90 	 */
91 	if (sm750_get_chip_type() == SM750LE)
92 		return;
93 
94 	if (frequency) {
95 		/*
96 		 * Set the frequency to the maximum frequency
97 		 * that the DDR Memory can take which is 336MHz.
98 		 */
99 		if (frequency > MHz(336))
100 			frequency = MHz(336);
101 
102 		/* Calculate the divisor */
103 		divisor = DIV_ROUND_CLOSEST(get_mxclk_freq(), frequency);
104 
105 		/* Set the corresponding divisor in the register. */
106 		reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK;
107 		switch (divisor) {
108 		default:
109 		case 1:
110 			reg |= CURRENT_GATE_M2XCLK_DIV_1;
111 			break;
112 		case 2:
113 			reg |= CURRENT_GATE_M2XCLK_DIV_2;
114 			break;
115 		case 3:
116 			reg |= CURRENT_GATE_M2XCLK_DIV_3;
117 			break;
118 		case 4:
119 			reg |= CURRENT_GATE_M2XCLK_DIV_4;
120 			break;
121 		}
122 
123 		setCurrentGate(reg);
124 	}
125 }
126 
127 /*
128  * This function set up the master clock (MCLK).
129  *
130  * Input: Frequency to be set.
131  *
132  * NOTE:
133  *      The maximum frequency the engine can run is 168MHz.
134  */
setMasterClock(unsigned int frequency)135 static void setMasterClock(unsigned int frequency)
136 {
137 	unsigned int reg, divisor;
138 
139 	/* Cheok_0509: For SM750LE, the memory clock is fixed.
140 	 * Nothing to set.
141 	 */
142 	if (sm750_get_chip_type() == SM750LE)
143 		return;
144 
145 	if (frequency) {
146 		/* Set the frequency to the maximum frequency
147 		 * that the SM750 engine can run, which is about 190 MHz.
148 		 */
149 		if (frequency > MHz(190))
150 			frequency = MHz(190);
151 
152 		/* Calculate the divisor */
153 		divisor = DIV_ROUND_CLOSEST(get_mxclk_freq(), frequency);
154 
155 		/* Set the corresponding divisor in the register. */
156 		reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK;
157 		switch (divisor) {
158 		default:
159 		case 3:
160 			reg |= CURRENT_GATE_MCLK_DIV_3;
161 			break;
162 		case 4:
163 			reg |= CURRENT_GATE_MCLK_DIV_4;
164 			break;
165 		case 6:
166 			reg |= CURRENT_GATE_MCLK_DIV_6;
167 			break;
168 		case 8:
169 			reg |= CURRENT_GATE_MCLK_DIV_8;
170 			break;
171 		}
172 
173 		setCurrentGate(reg);
174 		}
175 }
176 
ddk750_getVMSize(void)177 unsigned int ddk750_getVMSize(void)
178 {
179 	unsigned int reg;
180 	unsigned int data;
181 
182 	/* sm750le only use 64 mb memory*/
183 	if (sm750_get_chip_type() == SM750LE)
184 		return SZ_64M;
185 
186 	/* for 750,always use power mode0*/
187 	reg = PEEK32(MODE0_GATE);
188 	reg |= MODE0_GATE_GPIO;
189 	POKE32(MODE0_GATE, reg);
190 
191 	/* get frame buffer size from GPIO */
192 	reg = PEEK32(MISC_CTRL) & MISC_CTRL_LOCALMEM_SIZE_MASK;
193 	switch (reg) {
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 */
202 	default:
203 		data = 0;
204 		break;
205 	}
206 	return data;
207 }
208 
ddk750_initHw(initchip_param_t * pInitParam)209 int ddk750_initHw(initchip_param_t *pInitParam)
210 {
211 	unsigned int reg;
212 
213 	if (pInitParam->powerMode != 0)
214 		pInitParam->powerMode = 0;
215 	setPowerMode(pInitParam->powerMode);
216 
217 	/* Enable display power gate & LOCALMEM power gate*/
218 	reg = PEEK32(CURRENT_GATE);
219 	reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM);
220 	setCurrentGate(reg);
221 
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);
227 	} else {
228 #if defined(__i386__) || defined(__x86_64__)
229 		/* set graphic mode via IO method */
230 		outb_p(0x88, 0x3d4);
231 		outb_p(0x06, 0x3d5);
232 #endif
233 	}
234 
235 	/* Set the Main Chip Clock */
236 	setChipClock(MHz((unsigned int)pInitParam->chipClock));
237 
238 	/* Set up memory clock. */
239 	setMemoryClock(MHz(pInitParam->memClock));
240 
241 	/* Set up master clock */
242 	setMasterClock(MHz(pInitParam->masterClock));
243 
244 
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.
249 	 */
250 	if (pInitParam->resetMemory == 1) {
251 		reg = PEEK32(MISC_CTRL);
252 		reg &= ~MISC_CTRL_LOCALMEM_RESET;
253 		POKE32(MISC_CTRL, reg);
254 
255 		reg |= MISC_CTRL_LOCALMEM_RESET;
256 		POKE32(MISC_CTRL, reg);
257 	}
258 
259 	if (pInitParam->setAllEngOff == 1) {
260 		enable2DEngine(0);
261 
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);
266 
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);
271 
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);
276 
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);
281 
282 		/* Disable DMA Power, if a former application left it on */
283 		enableDMA(0);
284 	}
285 
286 	/* We can add more initialization as needed. */
287 
288 	return 0;
289 }
290 
291 /*
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
298  *
299  * 750 pll clock formular:
300  * Request Clock = (Input Clock * M )/(N * X)
301  *
302  * Input Clock = 14318181 hz
303  * X = 2 power D
304  * D ={0,1,2,3,4,5,6}
305  * M = {1,...,255}
306  * N = {2,...,15}
307  */
calcPllValue(unsigned int request_orig,pll_value_t * pll)308 unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
309 {
310 	/* as sm750 register definition,
311 	 * N located in 2,15 and M located in 1,255
312 	 */
313 	int N, M, X, d;
314 	int mini_diff;
315 	unsigned int RN, quo, rem, fl_quo;
316 	unsigned int input, request;
317 	unsigned int tmpClock, ret;
318 	const int max_OD = 3;
319 	int max_d = 6;
320 
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.
325 		 */
326 		return request_orig;
327 	}
328 
329 	ret = 0;
330 	mini_diff = ~0;
331 	request = request_orig / 1000;
332 	input = pll->inputFreq / 1000;
333 
334 	/* for MXCLK register,
335 	 * no POD provided, so need be treated differently
336 	 */
337 	if (pll->clockType == MXCLK_PLL)
338 		max_d = 3;
339 
340 	for (N = 15; N > 1; N--) {
341 		/* RN will not exceed maximum long
342 		 * if @request <= 285 MHZ (for 32bit cpu)
343 		 */
344 		RN = N * request;
345 		quo = RN / input;
346 		rem = RN % input;/* rem always small than 14318181 */
347 		fl_quo = (rem * 10000 / input);
348 
349 		for (d = max_d; d >= 0; d--) {
350 			X = BIT(d);
351 			M = quo * X;
352 			M += fl_quo * X / 10000;
353 			/* round step */
354 			M += (fl_quo * X % 10000) > 5000 ? 1 : 0;
355 			if (M < 256 && M > 0) {
356 				unsigned int diff;
357 
358 				tmpClock = pll->inputFreq * M / N / X;
359 				diff = abs(tmpClock - request_orig);
360 				if (diff < mini_diff) {
361 					pll->M = M;
362 					pll->N = N;
363 					pll->POD = 0;
364 					if (d > max_OD)
365 						pll->POD = d - max_OD;
366 					pll->OD = d - pll->POD;
367 					mini_diff = diff;
368 					ret = tmpClock;
369 				}
370 			}
371 		}
372 	}
373 	return ret;
374 }
375 
formatPllReg(pll_value_t * pPLL)376 unsigned int formatPllReg(pll_value_t *pPLL)
377 {
378 #ifndef VALIDATION_CHIP
379 	unsigned int POD = pPLL->POD;
380 #endif
381 	unsigned int OD = pPLL->OD;
382 	unsigned int M = pPLL->M;
383 	unsigned int N = pPLL->N;
384 	unsigned int reg = 0;
385 
386 	/*
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.
391 	 */
392 	reg = PLL_CTRL_POWER |
393 #ifndef VALIDATION_CHIP
394 		((POD << PLL_CTRL_POD_SHIFT) & PLL_CTRL_POD_MASK) |
395 #endif
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);
399 
400 	return reg;
401 }
402 
403 
404