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