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