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