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