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(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 | |
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(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(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, 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 | |
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(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 | */ |
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 | |