1223534Shselasky// SPDX-License-Identifier: GPL-2.0
2223534Shselasky#include <linux/kernel.h>
3223534Shselasky#include <linux/sizes.h>
4223534Shselasky
5223534Shselasky#include "ddk750_reg.h"
6223534Shselasky#include "ddk750_chip.h"
7223534Shselasky#include "ddk750_power.h"
8223534Shselasky
9223534Shselasky#define MHz(x) ((x) * 1000000)
10223534Shselasky
11223534Shselaskystatic enum logical_chip_type chip;
12223534Shselasky
13223534Shselaskyenum logical_chip_type sm750_get_chip_type(void)
14223534Shselasky{
15223534Shselasky	return chip;
16223534Shselasky}
17223534Shselasky
18223534Shselaskyvoid sm750_set_chip_type(unsigned short dev_id, u8 rev_id)
19223534Shselasky{
20223534Shselasky	if (dev_id == 0x718) {
21223534Shselasky		chip = SM718;
22223534Shselasky	} else if (dev_id == 0x750) {
23223534Shselasky		chip = SM750;
24223534Shselasky		/* SM750 and SM750LE are different in their revision ID only. */
25223534Shselasky		if (rev_id == SM750LE_REVISION_ID) {
26223534Shselasky			chip = SM750LE;
27223534Shselasky			pr_info("found sm750le\n");
28223534Shselasky		}
29223534Shselasky	} else {
30223534Shselasky		chip = SM_UNKNOWN;
31223534Shselasky	}
32223534Shselasky}
33223534Shselasky
34static 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 */
56static 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
85static 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 */
137static 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
181unsigned 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
213int 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 */
312unsigned 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
385unsigned 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