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