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