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 /* n / d + 1 / 2 = (2n + d) / 2d */
10 #define roundedDiv(num, denom)	((2 * (num) + (denom)) / (2 * (denom)))
11 #define MHz(x) ((x) * 1000000)
12 
13 logical_chip_type_t getChipType(void)
14 {
15 	unsigned short physicalID;
16 	char physicalRev;
17 	logical_chip_type_t chip;
18 
19 	physicalID = devId750; /* either 0x718 or 0x750 */
20 	physicalRev = revId750;
21 
22 	if (physicalID == 0x718)
23 		chip = SM718;
24 	else if (physicalID == 0x750) {
25 		chip = SM750;
26 		/* SM750 and SM750LE are different in their revision ID only. */
27 		if (physicalRev == SM750LE_REVISION_ID)
28 			chip = SM750LE;
29 	} else
30 		chip = SM_UNKNOWN;
31 
32 	return chip;
33 }
34 
35 static unsigned int get_mxclk_freq(void)
36 {
37 	unsigned int pll_reg;
38 	unsigned int M, N, OD, POD;
39 
40 	if (getChipType() == SM750LE)
41 		return MHz(130);
42 
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;
48 
49 	return DEFAULT_INPUT_CLOCK * M / N / (1 << OD) / (1 << POD);
50 }
51 
52 /*
53  * This function set up the main chip clock.
54  *
55  * Input: Frequency to be set.
56  */
57 static void setChipClock(unsigned int frequency)
58 {
59 	pll_value_t pll;
60 	unsigned int ulActualMxClk;
61 
62 	/* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
63 	if (getChipType() == SM750LE)
64 		return;
65 
66 	if (frequency) {
67 		/*
68 		* Set up PLL, a structure to hold the value to be set in clocks.
69 		*/
70 		pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */
71 		pll.clockType = MXCLK_PLL;
72 
73 		/*
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.
77 		*/
78 		ulActualMxClk = calcPllValue(frequency, &pll);
79 
80 		/* Master Clock Control: MXCLK_PLL */
81 		POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll));
82 	}
83 }
84 
85 static void setMemoryClock(unsigned int frequency)
86 {
87 	unsigned int reg, divisor;
88 
89 	/* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
90 	if (getChipType() == SM750LE)
91 		return;
92 
93 	if (frequency) {
94 		/* Set the frequency to the maximum frequency that the DDR Memory can take
95 		which is 336MHz. */
96 		if (frequency > MHz(336))
97 			frequency = MHz(336);
98 
99 		/* Calculate the divisor */
100 		divisor = roundedDiv(get_mxclk_freq(), frequency);
101 
102 		/* Set the corresponding divisor in the register. */
103 		reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK;
104 		switch (divisor) {
105 		default:
106 		case 1:
107 			reg |= CURRENT_GATE_M2XCLK_DIV_1;
108 			break;
109 		case 2:
110 			reg |= CURRENT_GATE_M2XCLK_DIV_2;
111 			break;
112 		case 3:
113 			reg |= CURRENT_GATE_M2XCLK_DIV_3;
114 			break;
115 		case 4:
116 			reg |= CURRENT_GATE_M2XCLK_DIV_4;
117 			break;
118 		}
119 
120 		setCurrentGate(reg);
121 	}
122 }
123 
124 /*
125  * This function set up the master clock (MCLK).
126  *
127  * Input: Frequency to be set.
128  *
129  * NOTE:
130  *      The maximum frequency the engine can run is 168MHz.
131  */
132 static void setMasterClock(unsigned int frequency)
133 {
134 	unsigned int reg, divisor;
135 
136 	/* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
137 	if (getChipType() == SM750LE)
138 		return;
139 
140 	if (frequency) {
141 		/* Set the frequency to the maximum frequency that the SM750 engine can
142 		run, which is about 190 MHz. */
143 		if (frequency > MHz(190))
144 			frequency = MHz(190);
145 
146 		/* Calculate the divisor */
147 		divisor = roundedDiv(get_mxclk_freq(), frequency);
148 
149 		/* Set the corresponding divisor in the register. */
150 		reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK;
151 		switch (divisor) {
152 		default:
153 		case 3:
154 			reg |= CURRENT_GATE_MCLK_DIV_3;
155 			break;
156 		case 4:
157 			reg |= CURRENT_GATE_MCLK_DIV_4;
158 			break;
159 		case 6:
160 			reg |= CURRENT_GATE_MCLK_DIV_6;
161 			break;
162 		case 8:
163 			reg |= CURRENT_GATE_MCLK_DIV_8;
164 			break;
165 		}
166 
167 		setCurrentGate(reg);
168 		}
169 }
170 
171 unsigned int ddk750_getVMSize(void)
172 {
173 	unsigned int reg;
174 	unsigned int data;
175 
176 	/* sm750le only use 64 mb memory*/
177 	if (getChipType() == SM750LE)
178 		return SZ_64M;
179 
180 	/* for 750,always use power mode0*/
181 	reg = PEEK32(MODE0_GATE);
182 	reg |= MODE0_GATE_GPIO;
183 	POKE32(MODE0_GATE, reg);
184 
185 	/* get frame buffer size from GPIO */
186 	reg = PEEK32(MISC_CTRL) & MISC_CTRL_LOCALMEM_SIZE_MASK;
187 	switch (reg) {
188 	case MISC_CTRL_LOCALMEM_SIZE_8M:
189 		data = SZ_8M;  break; /* 8  Mega byte */
190 	case MISC_CTRL_LOCALMEM_SIZE_16M:
191 		data = SZ_16M; break; /* 16 Mega byte */
192 	case MISC_CTRL_LOCALMEM_SIZE_32M:
193 		data = SZ_32M; break; /* 32 Mega byte */
194 	case MISC_CTRL_LOCALMEM_SIZE_64M:
195 		data = SZ_64M; break; /* 64 Mega byte */
196 	default:
197 		data = 0;
198 		break;
199 	}
200 	return data;
201 }
202 
203 int ddk750_initHw(initchip_param_t *pInitParam)
204 {
205 	unsigned int reg;
206 
207 	if (pInitParam->powerMode != 0)
208 		pInitParam->powerMode = 0;
209 	setPowerMode(pInitParam->powerMode);
210 
211 	/* Enable display power gate & LOCALMEM power gate*/
212 	reg = PEEK32(CURRENT_GATE);
213 	reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM);
214 	setCurrentGate(reg);
215 
216 	if (getChipType() != SM750LE) {
217 		/*	set panel pll and graphic mode via mmio_88 */
218 		reg = PEEK32(VGA_CONFIGURATION);
219 		reg |= (VGA_CONFIGURATION_PLL | VGA_CONFIGURATION_MODE);
220 		POKE32(VGA_CONFIGURATION, reg);
221 	} else {
222 #if defined(__i386__) || defined(__x86_64__)
223 		/* set graphic mode via IO method */
224 		outb_p(0x88, 0x3d4);
225 		outb_p(0x06, 0x3d5);
226 #endif
227 	}
228 
229 	/* Set the Main Chip Clock */
230 	setChipClock(MHz((unsigned int)pInitParam->chipClock));
231 
232 	/* Set up memory clock. */
233 	setMemoryClock(MHz(pInitParam->memClock));
234 
235 	/* Set up master clock */
236 	setMasterClock(MHz(pInitParam->masterClock));
237 
238 
239 	/* Reset the memory controller. If the memory controller is not reset in SM750,
240 	   the system might hang when sw accesses the memory.
241 	   The memory should be resetted after changing the MXCLK.
242 	 */
243 	if (pInitParam->resetMemory == 1) {
244 		reg = PEEK32(MISC_CTRL);
245 		reg &= ~MISC_CTRL_LOCALMEM_RESET;
246 		POKE32(MISC_CTRL, reg);
247 
248 		reg |= MISC_CTRL_LOCALMEM_RESET;
249 		POKE32(MISC_CTRL, reg);
250 	}
251 
252 	if (pInitParam->setAllEngOff == 1) {
253 		enable2DEngine(0);
254 
255 		/* Disable Overlay, if a former application left it on */
256 		reg = PEEK32(VIDEO_DISPLAY_CTRL);
257 		reg &= ~DISPLAY_CTRL_PLANE;
258 		POKE32(VIDEO_DISPLAY_CTRL, reg);
259 
260 		/* Disable video alpha, if a former application left it on */
261 		reg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL);
262 		reg &= ~DISPLAY_CTRL_PLANE;
263 		POKE32(VIDEO_ALPHA_DISPLAY_CTRL, reg);
264 
265 		/* Disable alpha plane, if a former application left it on */
266 		reg = PEEK32(ALPHA_DISPLAY_CTRL);
267 		reg &= ~DISPLAY_CTRL_PLANE;
268 		POKE32(ALPHA_DISPLAY_CTRL, reg);
269 
270 		/* Disable DMA Channel, if a former application left it on */
271 		reg = PEEK32(DMA_ABORT_INTERRUPT);
272 		reg |= DMA_ABORT_INTERRUPT_ABORT_1;
273 		POKE32(DMA_ABORT_INTERRUPT, reg);
274 
275 		/* Disable DMA Power, if a former application left it on */
276 		enableDMA(0);
277 	}
278 
279 	/* We can add more initialization as needed. */
280 
281 	return 0;
282 }
283 
284 /*
285 	monk liu @ 4/6/2011:
286 		   re-write the calculatePLL function of ddk750.
287 		   the original version function does not use some mathematics tricks and shortcut
288 		   when it doing the calculation of the best N,M,D combination
289 		   I think this version gives a little upgrade in speed
290 
291 	750 pll clock formular:
292 	Request Clock = (Input Clock * M )/(N * X)
293 
294 	Input Clock = 14318181 hz
295 	X = 2 power D
296 	D ={0,1,2,3,4,5,6}
297 	M = {1,...,255}
298 	N = {2,...,15}
299 */
300 unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
301 {
302 	/* as sm750 register definition, N located in 2,15 and M located in 1,255	*/
303 	int N, M, X, d;
304 	int mini_diff;
305 	unsigned int RN, quo, rem, fl_quo;
306 	unsigned int input, request;
307 	unsigned int tmpClock, ret;
308 	const int max_OD = 3;
309 	int max_d = 6;
310 
311 	if (getChipType() == SM750LE) {
312 		/* SM750LE don't have prgrammable PLL and M/N values to work on.
313 		Just return the requested clock. */
314 		return request_orig;
315 	}
316 
317 	ret = 0;
318 	mini_diff = ~0;
319 	request = request_orig / 1000;
320 	input = pll->inputFreq / 1000;
321 
322 	/* for MXCLK register , no POD provided, so need be treated differently	*/
323 	if (pll->clockType == MXCLK_PLL)
324 		max_d = 3;
325 
326 	for (N = 15; N > 1; N--) {
327 		/* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */
328 		RN = N * request;
329 		quo = RN / input;
330 		rem = RN % input;/* rem always small than 14318181 */
331 		fl_quo = (rem * 10000 / input);
332 
333 		for (d = max_d; d >= 0; d--) {
334 			X = (1 << d);
335 			M = quo * X;
336 			M += fl_quo * X / 10000;
337 			/* round step */
338 			M += (fl_quo * X % 10000) > 5000 ? 1 : 0;
339 			if (M < 256 && M > 0) {
340 				unsigned int diff;
341 
342 				tmpClock = pll->inputFreq * M / N / X;
343 				diff = abs(tmpClock - request_orig);
344 				if (diff < mini_diff) {
345 					pll->M = M;
346 					pll->N = N;
347 					pll->POD = 0;
348 					if (d > max_OD)
349 						pll->POD = d - max_OD;
350 					pll->OD = d - pll->POD;
351 					mini_diff = diff;
352 					ret = tmpClock;
353 				}
354 			}
355 		}
356 	}
357 	return ret;
358 }
359 
360 unsigned int formatPllReg(pll_value_t *pPLL)
361 {
362 #ifndef VALIDATION_CHIP
363 	unsigned int POD = pPLL->POD;
364 #endif
365 	unsigned int OD = pPLL->OD;
366 	unsigned int M = pPLL->M;
367 	unsigned int N = pPLL->N;
368 	unsigned int reg = 0;
369 
370 	/*
371 	 * Note that all PLL's have the same format. Here, we just use
372 	 * Panel PLL parameter to work out the bit fields in the
373 	 * register. On returning a 32 bit number, the value can be
374 	 * applied to any PLL in the calling function.
375 	 */
376 	reg = PLL_CTRL_POWER |
377 #ifndef VALIDATION_CHIP
378 		((POD << PLL_CTRL_POD_SHIFT) & PLL_CTRL_POD_MASK) |
379 #endif
380 		((OD << PLL_CTRL_OD_SHIFT) & PLL_CTRL_OD_MASK) |
381 		((N << PLL_CTRL_N_SHIFT) & PLL_CTRL_N_MASK) |
382 		((M << PLL_CTRL_M_SHIFT) & PLL_CTRL_M_MASK);
383 
384 	return reg;
385 }
386 
387 
388