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
11static enum logical_chip_type chip;
12
13enum logical_chip_type sm750_get_chip_type(void)
14{
15 return chip;
16}
17
18void 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
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(request: frequency, pll: &pll);
79
80 /* Master Clock Control: MXCLK_PLL */
81 poke32(MXCLK_PLL_CTRL, data: sm750_format_pll_reg(p_PLL: &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(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(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, data: 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(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(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, data: reg);
231 } else {
232#if defined(__i386__) || defined(__x86_64__)
233 /* set graphic mode via IO method */
234 outb_p(value: 0x88, port: 0x3d4);
235 outb_p(value: 0x06, port: 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, data: reg);
258
259 reg |= MISC_CTRL_LOCALMEM_RESET;
260 poke32(MISC_CTRL, data: reg);
261 }
262
263 if (p_init_param->set_all_eng_off == 1) {
264 sm750_enable_2d_engine(enable: 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, data: 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, data: 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, data: 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, data: reg);
285
286 /* Disable DMA Power, if a former application left it on */
287 sm750_enable_dma(enable: 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

source code of linux/drivers/staging/sm750fb/ddk750_chip.c