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