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