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
8logical_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
30static 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 */
52static 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
80static 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 */
127static 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
166unsigned 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
198int 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*/
297unsigned 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
357unsigned 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