clk: rk3288: set BW 20 when GPLL is 297m for HDMI
[firefly-linux-kernel-4.4.55.git] / drivers / clk / rockchip / clk-pll.c
1 #include <linux/slab.h>
2 #include <asm/io.h>
3 #include <linux/rockchip/cpu.h>
4
5 #include "clk-ops.h"
6 #include "clk-pll.h"
7
8
9 static const struct pll_clk_set pll_com_table[] = {
10         _RK3188_PLL_SET_CLKS(1250000,   12,     625,    1),
11         _RK3188_PLL_SET_CLKS(1200000,   1,      50,     1),
12         _RK3188_PLL_SET_CLKS(1188000,   2,      99,     1),
13         _RK3188_PLL_SET_CLKS(891000,    8,      594,    2),
14         _RK3188_PLL_SET_CLKS(768000,    1,      64,     2),
15         _RK3188_PLL_SET_CLKS(594000,    2,      198,    4),
16         _RK3188_PLL_SET_CLKS(500000,    3,      250,    4),
17         _RK3188_PLL_SET_CLKS(408000,    1,      68,     4),
18         _RK3188_PLL_SET_CLKS(396000,    1,      66,     4),
19         _RK3188_PLL_SET_CLKS(384000,    2,      128,    4),
20         _RK3188_PLL_SET_CLKS(360000,    1,      60,     4),
21         _RK3188_PLL_SET_CLKS(300000,    1,      50,     4),
22         _RK3188_PLL_SET_CLKS(297000,    2,      198,    8),
23         _RK3188_PLL_SET_CLKS(148500,    2,      99,     8),
24         _RK3188_PLL_SET_CLKS(0,         0,      0,      0),
25 };
26
27 static const struct apll_clk_set rk3188_apll_table[] = {
28         //            (_mhz,    nr,     nf,     no,     _periph_div,    _aclk_div)
29         _RK3188_APLL_SET_CLKS(2208,     1,      92,     1,      8,      81),
30         _RK3188_APLL_SET_CLKS(2184,     1,      91,     1,      8,      81),
31         _RK3188_APLL_SET_CLKS(2160,     1,      90,     1,      8,      81),
32         _RK3188_APLL_SET_CLKS(2136,     1,      89,     1,      8,      81),
33         _RK3188_APLL_SET_CLKS(2112,     1,      88,     1,      8,      81),
34         _RK3188_APLL_SET_CLKS(2088,     1,      87,     1,      8,      81),
35         _RK3188_APLL_SET_CLKS(2064,     1,      86,     1,      8,      81),
36         _RK3188_APLL_SET_CLKS(2040,     1,      85,     1,      8,      81),
37         _RK3188_APLL_SET_CLKS(2016,     1,      84,     1,      8,      81),
38         _RK3188_APLL_SET_CLKS(1992,     1,      83,     1,      8,      81),
39         _RK3188_APLL_SET_CLKS(1968,     1,      82,     1,      8,      81),
40         _RK3188_APLL_SET_CLKS(1944,     1,      81,     1,      8,      81),
41         _RK3188_APLL_SET_CLKS(1920,     1,      80,     1,      8,      81),
42         _RK3188_APLL_SET_CLKS(1896,     1,      79,     1,      8,      81),
43         _RK3188_APLL_SET_CLKS(1872,     1,      78,     1,      8,      81),
44         _RK3188_APLL_SET_CLKS(1848,     1,      77,     1,      8,      81),
45         _RK3188_APLL_SET_CLKS(1824,     1,      76,     1,      8,      81),
46         _RK3188_APLL_SET_CLKS(1800,     1,      75,     1,      8,      81),
47         _RK3188_APLL_SET_CLKS(1776,     1,      74,     1,      8,      81),
48         _RK3188_APLL_SET_CLKS(1752,     1,      73,     1,      8,      81),
49         _RK3188_APLL_SET_CLKS(1728,     1,      72,     1,      8,      81),
50         _RK3188_APLL_SET_CLKS(1704,     1,      71,     1,      8,      81),
51         _RK3188_APLL_SET_CLKS(1680,     1,      70,     1,      8,      41),
52         _RK3188_APLL_SET_CLKS(1656,     1,      69,     1,      8,      41),
53         _RK3188_APLL_SET_CLKS(1632,     1,      68,     1,      8,      41),
54         _RK3188_APLL_SET_CLKS(1608,     1,      67,     1,      8,      41),
55         _RK3188_APLL_SET_CLKS(1560,     1,      65,     1,      8,      41),
56         _RK3188_APLL_SET_CLKS(1512,     1,      63,     1,      8,      41),
57         _RK3188_APLL_SET_CLKS(1488,     1,      62,     1,      8,      41),
58         _RK3188_APLL_SET_CLKS(1464,     1,      61,     1,      8,      41),
59         _RK3188_APLL_SET_CLKS(1440,     1,      60,     1,      8,      41),
60         _RK3188_APLL_SET_CLKS(1416,     1,      59,     1,      8,      41),
61         _RK3188_APLL_SET_CLKS(1392,     1,      58,     1,      8,      41),
62         _RK3188_APLL_SET_CLKS(1368,     1,      57,     1,      8,      41),
63         _RK3188_APLL_SET_CLKS(1344,     1,      56,     1,      8,      41),
64         _RK3188_APLL_SET_CLKS(1320,     1,      55,     1,      8,      41),
65         _RK3188_APLL_SET_CLKS(1296,     1,      54,     1,      8,      41),
66         _RK3188_APLL_SET_CLKS(1272,     1,      53,     1,      8,      41),
67         _RK3188_APLL_SET_CLKS(1248,     1,      52,     1,      8,      41),
68         _RK3188_APLL_SET_CLKS(1224,     1,      51,     1,      8,      41),
69         _RK3188_APLL_SET_CLKS(1200,     1,      50,     1,      8,      41),
70         _RK3188_APLL_SET_CLKS(1176,     1,      49,     1,      8,      41),
71         _RK3188_APLL_SET_CLKS(1128,     1,      47,     1,      8,      41),
72         _RK3188_APLL_SET_CLKS(1104,     1,      46,     1,      8,      41),
73         _RK3188_APLL_SET_CLKS(1008,     1,      84,     2,      8,      41),
74         _RK3188_APLL_SET_CLKS(912,      1,      76,     2,      8,      41),
75         _RK3188_APLL_SET_CLKS(888,      1,      74,     2,      8,      41),
76         _RK3188_APLL_SET_CLKS(816,      1,      68,     2,      8,      41),
77         _RK3188_APLL_SET_CLKS(792,      1,      66,     2,      8,      41),
78         _RK3188_APLL_SET_CLKS(696,      1,      58,     2,      8,      41),
79         _RK3188_APLL_SET_CLKS(600,      1,      50,     2,      4,      41),
80         _RK3188_APLL_SET_CLKS(552,      1,      92,     4,      4,      41),
81         _RK3188_APLL_SET_CLKS(504,      1,      84,     4,      4,      41),
82         _RK3188_APLL_SET_CLKS(408,      1,      68,     4,      4,      21),
83         _RK3188_APLL_SET_CLKS(312,      1,      52,     4,      2,      21),
84         _RK3188_APLL_SET_CLKS(252,      1,      84,     8,      2,      21),
85         _RK3188_APLL_SET_CLKS(216,      1,      72,     8,      2,      21),
86         _RK3188_APLL_SET_CLKS(126,      1,      84,     16,     2,      11),
87         _RK3188_APLL_SET_CLKS(48,       1,      32,     16,     2,      11),
88         _RK3188_APLL_SET_CLKS(0,        1,      32,     16,     2,      11),
89 };
90
91 static const struct apll_clk_set rk3288_apll_table[] = {
92         //                   (_mhz,     nr,     nf,     no,     l2ram,  m0,     mp,     atclk,  pclk_dbg)
93         _RK3288_APLL_SET_CLKS(2208,     1,      92,     1,      2,      2,      4,      4,      4),
94         _RK3288_APLL_SET_CLKS(2184,     1,      91,     1,      2,      2,      4,      4,      4),
95         _RK3288_APLL_SET_CLKS(2160,     1,      90,     1,      2,      2,      4,      4,      4),
96         _RK3288_APLL_SET_CLKS(2136,     1,      89,     1,      2,      2,      4,      4,      4),
97         _RK3288_APLL_SET_CLKS(2112,     1,      88,     1,      2,      2,      4,      4,      4),
98         _RK3288_APLL_SET_CLKS(2088,     1,      87,     1,      2,      2,      4,      4,      4),
99         _RK3288_APLL_SET_CLKS(2064,     1,      86,     1,      2,      2,      4,      4,      4),
100         _RK3288_APLL_SET_CLKS(2040,     1,      85,     1,      2,      2,      4,      4,      4),
101         _RK3288_APLL_SET_CLKS(2016,     1,      84,     1,      2,      2,      4,      4,      4),
102         _RK3288_APLL_SET_CLKS(1992,     1,      83,     1,      2,      2,      4,      4,      4),
103         _RK3288_APLL_SET_CLKS(1968,     1,      82,     1,      2,      2,      4,      4,      4),
104         _RK3288_APLL_SET_CLKS(1944,     1,      81,     1,      2,      2,      4,      4,      4),
105         _RK3288_APLL_SET_CLKS(1920,     1,      80,     1,      2,      2,      4,      4,      4),
106         _RK3288_APLL_SET_CLKS(1896,     1,      79,     1,      2,      2,      4,      4,      4),
107         _RK3288_APLL_SET_CLKS(1872,     1,      78,     1,      2,      2,      4,      4,      4),
108         _RK3288_APLL_SET_CLKS(1848,     1,      77,     1,      2,      2,      4,      4,      4),
109         _RK3288_APLL_SET_CLKS(1824,     1,      76,     1,      2,      2,      4,      4,      4),
110         _RK3288_APLL_SET_CLKS(1800,     1,      75,     1,      2,      2,      4,      4,      4),
111         _RK3288_APLL_SET_CLKS(1776,     1,      74,     1,      2,      2,      4,      4,      4),
112         _RK3288_APLL_SET_CLKS(1752,     1,      73,     1,      2,      2,      4,      4,      4),
113         _RK3288_APLL_SET_CLKS(1728,     1,      72,     1,      2,      2,      4,      4,      4),
114         _RK3288_APLL_SET_CLKS(1704,     1,      71,     1,      2,      2,      4,      4,      4),
115         _RK3288_APLL_SET_CLKS(1680,     1,      70,     1,      2,      2,      4,      4,      4),
116         _RK3288_APLL_SET_CLKS(1656,     1,      69,     1,      2,      2,      4,      4,      4),
117         _RK3288_APLL_SET_CLKS(1632,     1,      68,     1,      2,      2,      4,      4,      4),
118         _RK3288_APLL_SET_CLKS(1608,     1,      67,     1,      2,      2,      4,      4,      4),
119         _RK3288_APLL_SET_CLKS(1560,     1,      65,     1,      2,      2,      4,      4,      4),
120         _RK3288_APLL_SET_CLKS(1512,     1,      63,     1,      2,      2,      4,      4,      4),
121         _RK3288_APLL_SET_CLKS(1488,     1,      62,     1,      2,      2,      4,      4,      4),
122         _RK3288_APLL_SET_CLKS(1464,     1,      61,     1,      2,      2,      4,      4,      4),
123         _RK3288_APLL_SET_CLKS(1440,     1,      60,     1,      2,      2,      4,      4,      4),
124         _RK3288_APLL_SET_CLKS(1416,     1,      59,     1,      2,      2,      4,      4,      4),
125         _RK3288_APLL_SET_CLKS(1392,     1,      58,     1,      2,      2,      4,      4,      4),
126         _RK3288_APLL_SET_CLKS(1368,     1,      57,     1,      2,      2,      4,      4,      4),
127         _RK3288_APLL_SET_CLKS(1344,     1,      56,     1,      2,      2,      4,      4,      4),
128         _RK3288_APLL_SET_CLKS(1320,     1,      55,     1,      2,      2,      4,      4,      4),
129         _RK3288_APLL_SET_CLKS(1296,     1,      54,     1,      2,      2,      4,      4,      4),
130         _RK3288_APLL_SET_CLKS(1272,     1,      53,     1,      2,      2,      4,      4,      4),
131         _RK3288_APLL_SET_CLKS(1248,     1,      52,     1,      2,      2,      4,      4,      4),
132         _RK3288_APLL_SET_CLKS(1224,     1,      51,     1,      2,      2,      4,      4,      4),
133         _RK3288_APLL_SET_CLKS(1200,     1,      50,     1,      2,      2,      4,      4,      4),
134         _RK3288_APLL_SET_CLKS(1176,     1,      49,     1,      2,      2,      4,      4,      4),
135         _RK3288_APLL_SET_CLKS(1128,     1,      47,     1,      2,      2,      4,      4,      4),
136         _RK3288_APLL_SET_CLKS(1104,     1,      46,     1,      2,      2,      4,      4,      4),
137         _RK3288_APLL_SET_CLKS(1008,     1,      84,     2,      2,      2,      4,      4,      4),
138         _RK3288_APLL_SET_CLKS(912,      1,      76,     2,      2,      2,      4,      4,      4),
139         _RK3288_APLL_SET_CLKS(888,      1,      74,     2,      2,      2,      4,      4,      4),
140         _RK3288_APLL_SET_CLKS(816,      1,      68,     2,      2,      2,      4,      4,      4),
141         _RK3288_APLL_SET_CLKS(792,      1,      66,     2,      2,      2,      4,      4,      4),
142         _RK3288_APLL_SET_CLKS(696,      1,      58,     2,      2,      2,      4,      4,      4),
143         _RK3288_APLL_SET_CLKS(600,      1,      50,     2,      2,      2,      4,      4,      4),
144         _RK3288_APLL_SET_CLKS(552,      1,      92,     4,      2,      2,      4,      4,      4),
145         _RK3288_APLL_SET_CLKS(504,      1,      84,     4,      2,      2,      4,      4,      4),
146         _RK3288_APLL_SET_CLKS(408,      1,      68,     4,      2,      2,      4,      4,      4),
147         _RK3288_APLL_SET_CLKS(312,      1,      52,     4,      2,      2,      4,      4,      4),
148         _RK3288_APLL_SET_CLKS(252,      1,      84,     8,      2,      2,      4,      4,      4),
149         _RK3288_APLL_SET_CLKS(216,      1,      72,     8,      2,      2,      4,      4,      4),
150         _RK3288_APLL_SET_CLKS(126,      2,      84,     8,      2,      2,      4,      4,      4),
151         _RK3288_APLL_SET_CLKS(48,       2,      32,     8,      2,      2,      4,      4,      4),
152         _RK3288_APLL_SET_CLKS(0,        1,      32,     16,     2,      2,      4,      4,      4),
153 };
154
155 static void pll_wait_lock(struct clk_hw *hw)
156 {
157         struct clk_pll *pll = to_clk_pll(hw);
158         int delay = 24000000;
159
160
161         while (delay > 0) {
162                 if (grf_readl(pll->status_offset) & (1 << pll->status_shift))
163                         break;
164                 delay--;
165         }
166
167         if (delay == 0) {
168                 clk_err("pll %s: can't lock! status_shift=%u\n"
169                                 "pll_con0=%08x\npll_con1=%08x\n"
170                                 "pll_con2=%08x\npll_con3=%08x\n",
171                                 __clk_get_name(hw->clk),
172                                 pll->status_shift,
173                                 readl(pll->reg + RK3188_PLL_CON(0)),
174                                 readl(pll->reg + RK3188_PLL_CON(1)),
175                                 readl(pll->reg + RK3188_PLL_CON(2)),
176                                 readl(pll->reg + RK3188_PLL_CON(3)));
177
178                 while(1);
179         }
180 }
181
182 /* get rate that is most close to target */
183 static const struct apll_clk_set *apll_get_best_set(unsigned long rate,
184                 const struct apll_clk_set *table)
185 {
186         const struct apll_clk_set *ps, *pt;
187
188         ps = pt = table;
189         while (pt->rate) {
190                 if (pt->rate == rate) {
191                         ps = pt;
192                         break;
193                 }
194
195                 if ((pt->rate > rate || (rate - pt->rate < ps->rate - rate)))
196                         ps = pt;
197                 if (pt->rate < rate)
198                         break;
199                 pt++;
200         }
201
202         return ps;
203 }
204
205 /* get rate that is most close to target */
206 static const struct pll_clk_set *pll_com_get_best_set(unsigned long rate,
207                 const struct pll_clk_set *table)
208 {
209         const struct pll_clk_set *ps, *pt;
210
211         ps = pt = table;
212         while (pt->rate) {
213                 if (pt->rate == rate) {
214                         ps = pt;
215                         break;
216                 }
217
218                 if ((pt->rate > rate || (rate - pt->rate < ps->rate - rate)))
219                         ps = pt;
220                 if (pt->rate < rate)
221                         break;
222                 pt++;
223         }
224
225         return ps;
226 }
227
228 /* CLK_PLL_3188 type ops */
229 static unsigned long clk_pll_recalc_rate_3188(struct clk_hw *hw,
230                 unsigned long parent_rate)
231 {
232         struct clk_pll *pll = to_clk_pll(hw);
233         unsigned long rate;
234
235
236         if (_RK3188_PLL_MODE_IS_NORM(pll->mode_offset, pll->mode_shift)) {
237                 u32 pll_con0 = readl(pll->reg + RK3188_PLL_CON(0));
238                 u32 pll_con1 = readl(pll->reg + RK3188_PLL_CON(1));
239
240                 u64 rate64 = (u64)parent_rate * RK3188_PLL_NF(pll_con1);
241
242                 do_div(rate64, RK3188_PLL_NR(pll_con0));
243                 do_div(rate64, RK3188_PLL_NO(pll_con0));
244
245                 rate = rate64;
246         } else {
247                 /*FIXME*/
248                 rate = parent_rate;
249                 clk_debug("pll %s is in slow mode\n", __clk_get_name(hw->clk));
250         }
251
252         clk_debug("pll %s recalc rate =%lu\n", __clk_get_name(hw->clk), rate);
253
254         return rate;
255 }
256
257 static long clk_pll_round_rate_3188(struct clk_hw *hw, unsigned long rate,
258                 unsigned long *prate)
259 {
260         struct clk *parent = __clk_get_parent(hw->clk);
261
262         if (parent && (rate==__clk_get_rate(parent))) {
263                 clk_debug("pll %s round rate=%lu equal to parent rate\n",
264                                 __clk_get_name(hw->clk), rate);
265                 return rate;
266         }
267
268         return (pll_com_get_best_set(rate, pll_com_table)->rate);
269 }
270
271 static int _pll_clk_set_rate_3188(struct pll_clk_set *clk_set,
272                 struct clk_hw *hw)
273 {
274         struct clk_pll *pll = to_clk_pll(hw);
275         unsigned long flags = 0;
276
277
278         clk_debug("%s start!\n", __func__);
279
280         if(pll->lock)
281                 spin_lock_irqsave(pll->lock, flags);
282
283         //enter slowmode
284         cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
285         //pll power down
286         writel((0x1 << (16+1)) | (0x1<<1), pll->reg + RK3188_PLL_CON(3));
287         dsb();
288         dsb();
289         dsb();
290         dsb();
291         dsb();
292         dsb();
293         writel(clk_set->pllcon0, pll->reg + RK3188_PLL_CON(0));
294         writel(clk_set->pllcon1, pll->reg + RK3188_PLL_CON(1));
295
296         udelay(1);
297
298         //pll no power down
299         writel((0x1<<(16+1)), pll->reg + RK3188_PLL_CON(3));
300
301         pll_wait_lock(hw);
302
303         //return from slow
304         cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), pll->mode_offset);
305
306         if (pll->lock)
307                 spin_unlock_irqrestore(pll->lock, flags);
308
309         clk_debug("pll %s dump reg: con0=0x%08x, con1=0x%08x, mode=0x%08x\n",
310                         __clk_get_name(hw->clk),
311                         readl(pll->reg + RK3188_PLL_CON(0)),
312                         readl(pll->reg + RK3188_PLL_CON(1)),
313                         cru_readl(pll->mode_offset));
314
315         clk_debug("%s end!\n", __func__);
316
317         return 0;
318 }
319
320 static int clk_pll_set_rate_3188(struct clk_hw *hw, unsigned long rate,
321                 unsigned long parent_rate)
322 {
323         struct clk_pll *pll = to_clk_pll(hw);
324         struct pll_clk_set *clk_set = (struct pll_clk_set *)(pll_com_table);
325         int ret = 0;
326
327
328         if (rate == parent_rate) {
329                 clk_debug("pll %s set rate=%lu equal to parent rate\n",
330                                 __clk_get_name(hw->clk), rate);
331                 cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift),
332                                 pll->mode_offset);
333                 /* pll power down */
334                 writel((0x1 << (16+1)) | (0x1<<1), pll->reg + RK3188_PLL_CON(3));
335                 clk_debug("pll %s enter slow mode, set rate OK!\n",
336                                 __clk_get_name(hw->clk));
337                 return 0;
338         }
339
340         while(clk_set->rate) {
341                 if (clk_set->rate == rate) {
342                         break;
343                 }
344                 clk_set++;
345         }
346
347         if (clk_set->rate == rate) {
348                 ret = _pll_clk_set_rate_3188(clk_set, hw);
349                 clk_debug("pll %s set rate=%lu OK!\n", __clk_get_name(hw->clk),
350                                 rate);
351         } else {
352                 clk_err("pll %s is no corresponding rate=%lu\n",
353                                 __clk_get_name(hw->clk), rate);
354                 return -EINVAL;
355         }
356
357         return ret;
358 }
359
360 static const struct clk_ops clk_pll_ops_3188 = {
361         .recalc_rate = clk_pll_recalc_rate_3188,
362         .round_rate = clk_pll_round_rate_3188,
363         .set_rate = clk_pll_set_rate_3188,
364 };
365
366
367 /* CLK_PLL_3188_APLL type ops */
368 static unsigned long clk_pll_recalc_rate_3188_apll(struct clk_hw *hw,
369                 unsigned long parent_rate)
370 {
371         return clk_pll_recalc_rate_3188(hw, parent_rate);
372 }
373
374 static long clk_pll_round_rate_3188_apll(struct clk_hw *hw, unsigned long rate,
375                 unsigned long *prate)
376 {
377         struct clk *parent = __clk_get_parent(hw->clk);
378
379         if (parent && (rate==__clk_get_rate(parent))) {
380                 clk_debug("pll %s round rate=%lu equal to parent rate\n",
381                                 __clk_get_name(hw->clk), rate);
382                 return rate;
383         }
384
385         return (apll_get_best_set(rate, rk3188_apll_table)->rate);
386 }
387
388 /* 1: use, 0: no use */
389 #define RK3188_USE_ARM_GPLL     1
390
391 static int clk_pll_set_rate_3188_apll(struct clk_hw *hw, unsigned long rate,
392                 unsigned long parent_rate)
393 {
394         struct clk_pll *pll = to_clk_pll(hw);
395         struct clk *clk = hw->clk;
396         struct clk *arm_gpll = __clk_lookup("clk_arm_gpll");
397         unsigned long arm_gpll_rate;
398         const struct apll_clk_set *ps;
399         u32 old_aclk_div = 0, new_aclk_div = 0;
400         u32 temp_div;
401         unsigned long flags;
402         int sel_gpll = 0;
403
404
405         if (rate == parent_rate) {
406                 clk_debug("pll %s set rate=%lu equal to parent rate\n",
407                                 __clk_get_name(hw->clk), rate);
408                 cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift),
409                                 pll->mode_offset);
410                 /* pll power down */
411                 writel((0x1 << (16+1)) | (0x1<<1), pll->reg + RK3188_PLL_CON(3));
412                 clk_debug("pll %s enter slow mode, set rate OK!\n",
413                                 __clk_get_name(hw->clk));
414                 return 0;
415         }
416
417
418 #if !RK3188_USE_ARM_GPLL
419         goto CHANGE_APLL;
420 #endif
421
422         /* prepare arm_gpll before reparent clk_core to it */
423         if (!arm_gpll) {
424                 clk_err("clk arm_gpll is NULL!\n");
425                 goto CHANGE_APLL;
426         }
427
428         /* In rk3188, arm_gpll and cpu_gpll share a same gate,
429          * and aclk_cpu selects cpu_gpll as parent, thus this
430          * gate must keep enabled.
431          */
432 #if 0
433         if (clk_prepare(arm_gpll)) {
434                 clk_err("fail to prepare arm_gpll path\n");
435                 clk_unprepare(arm_gpll);
436                 goto CHANGE_APLL;
437         }
438
439         if (clk_enable(arm_gpll)) {
440                 clk_err("fail to enable arm_gpll path\n");
441                 clk_disable(arm_gpll);
442                 clk_unprepare(arm_gpll);
443                 goto CHANGE_APLL;
444         }
445 #endif
446
447         arm_gpll_rate = __clk_get_rate(arm_gpll);
448         temp_div = DIV_ROUND_UP(arm_gpll_rate, __clk_get_rate(clk));
449         temp_div = (temp_div == 0) ? 1 : temp_div;
450         if (temp_div > RK3188_CORE_CLK_MAX_DIV) {
451                 clk_debug("temp_div %d > max_div %d\n", temp_div,
452                                 RK3188_CORE_CLK_MAX_DIV);
453                 clk_debug("can't get rate %lu from arm_gpll rate %lu\n",
454                                 __clk_get_rate(clk), arm_gpll_rate);
455                 //clk_disable(arm_gpll);
456                 //clk_unprepare(arm_gpll);
457                 goto CHANGE_APLL;
458         }
459
460         local_irq_save(flags);
461
462         /* firstly set div, then select arm_gpll path */
463         cru_writel(RK3188_CORE_CLK_DIV_W_MSK|RK3188_CORE_CLK_DIV(temp_div),
464                         RK3188_CRU_CLKSELS_CON(0));
465         cru_writel(RK3188_CORE_SEL_PLL_W_MSK|RK3188_CORE_SEL_GPLL,
466                         RK3188_CRU_CLKSELS_CON(0));
467
468         sel_gpll = 1;
469         //loops_per_jiffy = CLK_LOOPS_RECALC(arm_gpll_rate) / temp_div;
470         smp_wmb();
471
472         local_irq_restore(flags);
473
474         clk_debug("temp select arm_gpll path, get rate %lu\n",
475                         arm_gpll_rate/temp_div);
476         clk_debug("from arm_gpll rate %lu, temp_div %d\n", arm_gpll_rate,
477                         temp_div);
478
479 CHANGE_APLL:
480         ps = apll_get_best_set(rate, rk3188_apll_table);
481         clk_debug("apll will set rate %lu\n", ps->rate);
482         clk_debug("table con:%08x,%08x,%08x, sel:%08x,%08x\n",
483                         ps->pllcon0, ps->pllcon1, ps->pllcon2,
484                         ps->clksel0, ps->clksel1);
485
486         local_irq_save(flags);
487
488         /* If core src don't select gpll, apll need to enter slow mode
489          * before power down
490          */
491         //FIXME
492         //if (!sel_gpll)
493         cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
494
495         /* PLL power down */
496         writel((0x1 << (16+1)) | (0x1<<1), pll->reg + RK3188_PLL_CON(3));
497         dsb();
498         dsb();
499         dsb();
500         dsb();
501         dsb();
502         dsb();
503         writel(ps->pllcon0, pll->reg + RK3188_PLL_CON(0));
504         writel(ps->pllcon1, pll->reg + RK3188_PLL_CON(1));
505
506         udelay(1);
507
508         /* PLL power up and wait for locked */
509         writel((0x1<<(16+1)), pll->reg + RK3188_PLL_CON(3));
510         pll_wait_lock(hw);
511
512         old_aclk_div = RK3188_GET_CORE_ACLK_VAL(cru_readl(RK3188_CRU_CLKSELS_CON(1)) &
513                         RK3188_CORE_ACLK_MSK);
514         new_aclk_div = RK3188_GET_CORE_ACLK_VAL(ps->clksel1 & RK3188_CORE_ACLK_MSK);
515
516         if (new_aclk_div >= old_aclk_div) {
517                 cru_writel(ps->clksel0, RK3188_CRU_CLKSELS_CON(0));
518                 cru_writel(ps->clksel1, RK3188_CRU_CLKSELS_CON(1));
519         }
520
521         /* PLL return from slow mode */
522         //FIXME
523         //if (!sel_gpll)
524         cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), pll->mode_offset);
525
526         /* reparent to apll, and set div to 1 */
527         if (sel_gpll) {
528                 cru_writel(RK3188_CORE_SEL_PLL_W_MSK|RK3188_CORE_SEL_APLL,
529                                 RK3188_CRU_CLKSELS_CON(0));
530                 cru_writel(RK3188_CORE_CLK_DIV_W_MSK|RK3188_CORE_CLK_DIV(1),
531                                 RK3188_CRU_CLKSELS_CON(0));
532         }
533
534         if (old_aclk_div > new_aclk_div) {
535                 cru_writel(ps->clksel0, RK3188_CRU_CLKSELS_CON(0));
536                 cru_writel(ps->clksel1, RK3188_CRU_CLKSELS_CON(1));
537         }
538
539         //loops_per_jiffy = ps->lpj;
540         smp_wmb();
541
542         local_irq_restore(flags);
543
544         if (sel_gpll) {
545                 sel_gpll = 0;
546                 //clk_disable(arm_gpll);
547                 //clk_unprepare(arm_gpll);
548         }
549
550         //clk_debug("apll set loops_per_jiffy =%lu\n", loops_per_jiffy);
551
552         clk_debug("apll set rate %lu, con(%x,%x,%x,%x), sel(%x,%x)\n",
553                         ps->rate,
554                         readl(pll->reg + RK3188_PLL_CON(0)),
555                         readl(pll->reg + RK3188_PLL_CON(1)),
556                         readl(pll->reg + RK3188_PLL_CON(2)),
557                         readl(pll->reg + RK3188_PLL_CON(3)),
558                         cru_readl(RK3188_CRU_CLKSELS_CON(0)),
559                         cru_readl(RK3188_CRU_CLKSELS_CON(1)));
560
561         return 0;
562 }
563
564 static const struct clk_ops clk_pll_ops_3188_apll = {
565         .recalc_rate = clk_pll_recalc_rate_3188_apll,
566         .round_rate = clk_pll_round_rate_3188_apll,
567         .set_rate = clk_pll_set_rate_3188_apll,
568 };
569
570
571 /* CLK_PLL_3188PLUS type ops */
572 static unsigned long clk_pll_recalc_rate_3188plus(struct clk_hw *hw,
573                 unsigned long parent_rate)
574 {
575         struct clk_pll *pll = to_clk_pll(hw);
576         unsigned long rate;
577
578
579         if (_RK3188_PLL_MODE_IS_NORM(pll->mode_offset, pll->mode_shift)) {
580                 u32 pll_con0 = readl(pll->reg + RK3188_PLL_CON(0));
581                 u32 pll_con1 = readl(pll->reg + RK3188_PLL_CON(1));
582
583                 u64 rate64 = (u64)parent_rate * RK3188PLUS_PLL_NF(pll_con1);
584
585                 do_div(rate64, RK3188PLUS_PLL_NR(pll_con0));
586                 do_div(rate64, RK3188PLUS_PLL_NO(pll_con0));
587
588                 rate = rate64;
589         } else {
590                 /*FIXME*/
591                 rate = parent_rate;
592                 clk_debug("pll %s is in slow mode\n", __clk_get_name(hw->clk));
593         }
594
595         clk_debug("pll %s recalc rate =%lu\n", __clk_get_name(hw->clk), rate);
596
597         return rate;
598 }
599
600 static long clk_pll_round_rate_3188plus(struct clk_hw *hw, unsigned long rate,
601                 unsigned long *prate)
602 {
603         return clk_pll_round_rate_3188(hw, rate, prate);
604 }
605
606 static int _pll_clk_set_rate_3188plus(struct pll_clk_set *clk_set,
607                 struct clk_hw *hw)
608 {
609         struct clk_pll *pll = to_clk_pll(hw);
610         unsigned long flags = 0;
611
612
613         clk_debug("%s start!\n", __func__);
614
615         if(pll->lock)
616                 spin_lock_irqsave(pll->lock, flags);
617
618         //enter slowmode
619         cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
620
621         //enter rest
622         writel(_RK3188PLUS_PLL_RESET_SET(1), pll->reg + RK3188_PLL_CON(3));
623
624         writel(clk_set->pllcon0, pll->reg + RK3188_PLL_CON(0));
625         writel(clk_set->pllcon1, pll->reg + RK3188_PLL_CON(1));
626         writel(clk_set->pllcon2, pll->reg + RK3188_PLL_CON(2));
627
628         udelay(5);
629
630         //return from rest
631         writel(_RK3188PLUS_PLL_RESET_SET(0), pll->reg + RK3188_PLL_CON(3));
632
633         //wating lock state
634         udelay(clk_set->rst_dly);
635
636         pll_wait_lock(hw);
637
638         //return from slow
639         cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), pll->mode_offset);
640
641         if (pll->lock)
642                 spin_unlock_irqrestore(pll->lock, flags);
643
644         clk_debug("pll %s dump reg: con0=0x%08x, con1=0x%08x, mode=0x%08x\n",
645                         __clk_get_name(hw->clk),
646                         readl(pll->reg + RK3188_PLL_CON(0)),
647                         readl(pll->reg + RK3188_PLL_CON(1)),
648                         cru_readl(pll->mode_offset));
649
650         clk_debug("%s end!\n", __func__);
651
652         return 0;
653 }
654
655 static int clk_pll_set_rate_3188plus(struct clk_hw *hw, unsigned long rate,
656                 unsigned long parent_rate)
657 {
658         //struct clk_pll *pll = to_clk_pll(hw);
659         struct pll_clk_set *clk_set = (struct pll_clk_set *)(pll_com_table);
660         int ret = 0;
661
662 #if 0
663         if (rate == parent_rate) {
664                 clk_debug("pll %s set rate=%lu equal to parent rate\n",
665                                 __clk_get_name(hw->clk), rate);
666                 cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift),
667                                 pll->mode_offset);
668                 /* pll power down */
669                 writel((0x1 << (16+1)) | (0x1<<1), pll->reg + RK3188_PLL_CON(3));
670                 clk_debug("pll %s enter slow mode, set rate OK!\n",
671                                 __clk_get_name(hw->clk));
672                 return 0;
673         }
674 #endif
675
676         while(clk_set->rate) {
677                 if (clk_set->rate == rate) {
678                         break;
679                 }
680                 clk_set++;
681         }
682
683         if (cpu_is_rk3288() && (rate == 297*MHZ)) {
684                 if((strncmp(__clk_get_name(hw->clk), "clk_gpll",
685                         strlen("clk_gpll")) == 0)) {
686
687                         printk("rk3288 set GPLL BW 20 for HDMI!\n");
688                         clk_set->pllcon2 = RK3188_PLL_CLK_BWADJ_SET(20);
689                 }
690         }
691
692         if (clk_set->rate == rate) {
693                 ret = _pll_clk_set_rate_3188plus(clk_set, hw);
694                 clk_debug("pll %s set rate=%lu OK!\n", __clk_get_name(hw->clk),
695                                 rate);
696         } else {
697                 clk_err("pll %s is no corresponding rate=%lu\n",
698                                 __clk_get_name(hw->clk), rate);
699                 return -EINVAL;
700         }
701
702         return ret;
703 }
704
705 static const struct clk_ops clk_pll_ops_3188plus = {
706         .recalc_rate = clk_pll_recalc_rate_3188plus,
707         .round_rate = clk_pll_round_rate_3188plus,
708         .set_rate = clk_pll_set_rate_3188plus,
709 };
710
711 /* CLK_PLL_3188PLUS_AUTO type ops */
712 #define PLL_FREF_MIN (269*KHZ)
713 #define PLL_FREF_MAX (2200*MHZ)
714
715 #define PLL_FVCO_MIN (440*MHZ)
716 #define PLL_FVCO_MAX (2200*MHZ)
717
718 #define PLL_FOUT_MIN (27500*KHZ) 
719 #define PLL_FOUT_MAX (2200*MHZ)
720
721 #define PLL_NF_MAX (4096)
722 #define PLL_NR_MAX (64)
723 #define PLL_NO_MAX (16)
724
725 static u32 clk_gcd(u32 numerator, u32 denominator)
726 {
727         u32 a, b;
728
729         if (!numerator || !denominator)
730                 return 0;
731         if (numerator > denominator) {
732                 a = numerator;
733                 b = denominator;
734         } else {
735                 a = denominator;
736                 b = numerator;
737         }
738         while (b != 0) {
739                 int r = b;
740                 b = a % b;
741                 a = r;
742         }
743
744         return a;
745 }
746
747 /* FIXME: calc using u64 */
748 static int pll_clk_get_best_set(unsigned long fin_hz, unsigned long fout_hz,
749                                 u32 *best_nr, u32 *best_nf, u32 *best_no)
750 {
751         u32 nr, nf, no, nonr;
752         u32 nr_out, nf_out, no_out;
753         u32 n;
754         u32 YFfenzi;
755         u32 YFfenmu;
756         u64 fref, fvco, fout;
757         u32 gcd_val = 0;
758
759
760         nr_out = PLL_NR_MAX + 1;
761         no_out = 0;
762
763 //      printk("pll_clk_get_set fin=%lu,fout=%lu\n", fin_hz, fout_hz);
764         if(!fin_hz || !fout_hz || fout_hz == fin_hz)
765                 return -EINVAL;
766         gcd_val = clk_gcd(fin_hz, fout_hz);
767
768 //      printk("gcd_val = %d\n",gcd_val);
769
770         YFfenzi = fout_hz / gcd_val;
771         YFfenmu = fin_hz / gcd_val;
772
773 //      printk("YFfenzi = %d, YFfenmu = %d\n",YFfenzi,YFfenmu);
774
775         for(n = 1;; n++) {
776                nf = YFfenzi * n;
777                nonr = YFfenmu * n;
778                if(nf > PLL_NF_MAX || nonr > (PLL_NO_MAX * PLL_NR_MAX))
779                        break;
780                for(no = 1; no <= PLL_NO_MAX; no++) {
781                        if(!(no == 1 || !(no % 2)))
782                                continue;
783
784                        if(nonr % no)
785                                continue;
786                        nr = nonr / no;
787
788                        if(nr > PLL_NR_MAX) //PLL_NR_MAX
789                                continue;
790
791                        fref = fin_hz / nr;
792                        if(fref < PLL_FREF_MIN || fref > PLL_FREF_MAX)
793                                continue;
794
795                        fvco = fref * nf;
796                        if(fvco < PLL_FVCO_MIN || fvco > PLL_FVCO_MAX)
797                                continue;
798                        fout = fvco / no;
799                        if(fout < PLL_FOUT_MIN || fout > PLL_FOUT_MAX)
800                                continue;
801
802                        /* output all available PLL settings */
803                        //printk("nr=%d,\tnf=%d,\tno=%d\n",nr,nf,no);
804                        //printk("_PLL_SET_CLKS(%lu,\t%d,\t%d,\t%d),\n",fout_hz/KHZ,nr,nf,no);
805
806                        /* select the best from all available PLL settings */
807                        if((nr < nr_out) || ((nr == nr_out)&&(no > no_out)))
808                        {
809                                nr_out = nr;
810                                nf_out = nf;
811                                no_out = no;
812                        }
813                }
814
815        }
816
817         /* output the best PLL setting */
818         if((nr_out <= PLL_NR_MAX) && (no_out > 0)){
819                 //printk("_PLL_SET_CLKS(%lu,\t%d,\t%d,\t%d),\n",fout_hz/KHZ,nr_out,nf_out,no_out);
820                 if(best_nr && best_nf && best_no){
821                         *best_nr = nr_out;
822                         *best_nf = nf_out;
823                         *best_no = no_out;
824                 }
825                 return 0;
826         } else {
827                 return -EINVAL;
828         }
829 }
830
831 static unsigned long clk_pll_recalc_rate_3188plus_auto(struct clk_hw *hw,
832                 unsigned long parent_rate)
833 {
834         return clk_pll_recalc_rate_3188plus(hw, parent_rate);
835 }
836
837 static long clk_pll_round_rate_3188plus_auto(struct clk_hw *hw, unsigned long rate,
838                 unsigned long *prate)
839 {
840         unsigned long best;
841
842         for(best=rate; best>0; best--){
843                 if(!pll_clk_get_best_set(*prate, best, NULL, NULL, NULL))
844                         return best;
845         }
846
847         return 0;
848 }
849
850 static int clk_pll_set_rate_3188plus_auto(struct clk_hw *hw, unsigned long rate,
851                 unsigned long parent_rate)
852 {
853         unsigned long best;
854         u32 nr,nf,no;
855         struct pll_clk_set clk_set;
856         int ret;
857
858
859         best = clk_pll_round_rate_3188plus_auto(hw, rate, &parent_rate);
860
861         if(!best)
862                 return -EINVAL;
863
864         pll_clk_get_best_set(parent_rate, best, &nr, &nf, &no);
865
866         /* prepare clk_set */
867         clk_set.rate = best;
868         clk_set.pllcon0 = RK3188_PLL_CLKR_SET(nr)|RK3188_PLL_CLKOD_SET(no), \
869         clk_set.pllcon1 = RK3188_PLL_CLKF_SET(nf),\
870         clk_set.pllcon2 = RK3188_PLL_CLK_BWADJ_SET(nf >> 1),\
871         clk_set.rst_dly = ((nr*500)/24+1),\
872
873         ret = _pll_clk_set_rate_3188plus(&clk_set, hw);
874         clk_debug("pll %s set rate=%lu OK!\n", __clk_get_name(hw->clk), best);
875
876         return ret;
877 }
878
879
880 static const struct clk_ops clk_pll_ops_3188plus_auto = {
881         .recalc_rate = clk_pll_recalc_rate_3188plus_auto,
882         .round_rate = clk_pll_round_rate_3188plus_auto,
883         .set_rate = clk_pll_set_rate_3188plus_auto,
884 };
885
886
887 /* CLK_PLL_3188PLUS_APLL type ops */
888 static unsigned long clk_pll_recalc_rate_3188plus_apll(struct clk_hw *hw,
889                 unsigned long parent_rate)
890 {
891         return clk_pll_recalc_rate_3188plus(hw, parent_rate);
892 }
893
894 static long clk_pll_round_rate_3188plus_apll(struct clk_hw *hw, unsigned long rate,
895                 unsigned long *prate)
896 {
897         return clk_pll_round_rate_3188_apll(hw, rate, prate);
898 }
899
900 /* 1: use, 0: no use */
901 #define RK3188PLUS_USE_ARM_GPLL 1
902
903 static int clk_pll_set_rate_3188plus_apll(struct clk_hw *hw, unsigned long rate,
904                 unsigned long parent_rate)
905 {
906         struct clk_pll *pll = to_clk_pll(hw);
907         struct clk *clk = hw->clk;
908         struct clk *arm_gpll = __clk_lookup("clk_arm_gpll");
909         unsigned long arm_gpll_rate;
910         const struct apll_clk_set *ps;
911         u32 old_aclk_div = 0, new_aclk_div = 0;
912         u32 temp_div;
913         unsigned long flags;
914         int sel_gpll = 0;
915
916 #if 0
917         if (rate == parent_rate) {
918                 clk_debug("pll %s set rate=%lu equal to parent rate\n",
919                                 __clk_get_name(hw->clk), rate);
920                 cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift),
921                                 pll->mode_offset);
922                 /* pll power down */
923                 writel((0x1 << (16+1)) | (0x1<<1), pll->reg + RK3188_PLL_CON(3));
924                 clk_debug("pll %s enter slow mode, set rate OK!\n",
925                                 __clk_get_name(hw->clk));
926                 return 0;
927         }
928 #endif
929
930
931 #if !RK3188PLUS_USE_ARM_GPLL
932         goto CHANGE_APLL;
933 #endif
934
935         /* prepare arm_gpll before reparent clk_core to it */
936         if (!arm_gpll) {
937                 clk_err("clk arm_gpll is NULL!\n");
938                 goto CHANGE_APLL;
939         }
940
941         /* In rk3188plus, arm_gpll and cpu_gpll share a same gate,
942          * and aclk_cpu selects cpu_gpll as parent, thus this
943          * gate must keep enabled.
944          */
945 #if 0
946         if (clk_prepare(arm_gpll)) {
947                 clk_err("fail to prepare arm_gpll path\n");
948                 clk_unprepare(arm_gpll);
949                 goto CHANGE_APLL;
950         }
951
952         if (clk_enable(arm_gpll)) {
953                 clk_err("fail to enable arm_gpll path\n");
954                 clk_disable(arm_gpll);
955                 clk_unprepare(arm_gpll);
956                 goto CHANGE_APLL;
957         }
958 #endif
959
960         arm_gpll_rate = __clk_get_rate(arm_gpll);
961         temp_div = DIV_ROUND_UP(arm_gpll_rate, __clk_get_rate(clk));
962         temp_div = (temp_div == 0) ? 1 : temp_div;
963         if (temp_div > RK3188_CORE_CLK_MAX_DIV) {
964                 clk_debug("temp_div %d > max_div %d\n", temp_div,
965                                 RK3188_CORE_CLK_MAX_DIV);
966                 clk_debug("can't get rate %lu from arm_gpll rate %lu\n",
967                                 __clk_get_rate(clk), arm_gpll_rate);
968                 //clk_disable(arm_gpll);
969                 //clk_unprepare(arm_gpll);
970                 goto CHANGE_APLL;
971         }
972
973         local_irq_save(flags);
974
975         /* firstly set div, then select arm_gpll path */
976         cru_writel(RK3188_CORE_CLK_DIV_W_MSK|RK3188_CORE_CLK_DIV(temp_div),
977                         RK3188_CRU_CLKSELS_CON(0));
978         cru_writel(RK3188_CORE_SEL_PLL_W_MSK|RK3188_CORE_SEL_GPLL,
979                         RK3188_CRU_CLKSELS_CON(0));
980
981         sel_gpll = 1;
982         //loops_per_jiffy = CLK_LOOPS_RECALC(arm_gpll_rate) / temp_div;
983         smp_wmb();
984
985         local_irq_restore(flags);
986
987         clk_debug("temp select arm_gpll path, get rate %lu\n",
988                         arm_gpll_rate/temp_div);
989         clk_debug("from arm_gpll rate %lu, temp_div %d\n", arm_gpll_rate,
990                         temp_div);
991
992 CHANGE_APLL:
993         ps = apll_get_best_set(rate, rk3188_apll_table);
994         clk_debug("apll will set rate %lu\n", ps->rate);
995         clk_debug("table con:%08x,%08x,%08x, sel:%08x,%08x\n",
996                         ps->pllcon0, ps->pllcon1, ps->pllcon2,
997                         ps->clksel0, ps->clksel1);
998
999         local_irq_save(flags);
1000
1001         /* If core src don't select gpll, apll need to enter slow mode
1002          * before reset
1003          */
1004         //FIXME
1005         //if (!sel_gpll)
1006         cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
1007
1008         /* PLL enter rest */
1009         writel(_RK3188PLUS_PLL_RESET_SET(1), pll->reg + RK3188_PLL_CON(3));
1010
1011         writel(ps->pllcon0, pll->reg + RK3188_PLL_CON(0));
1012         writel(ps->pllcon1, pll->reg + RK3188_PLL_CON(1));
1013         writel(ps->pllcon2, pll->reg + RK3188_PLL_CON(2));
1014
1015         udelay(5);
1016
1017         /* return from rest */
1018         writel(_RK3188PLUS_PLL_RESET_SET(0), pll->reg + RK3188_PLL_CON(3));
1019
1020         //wating lock state
1021         udelay(ps->rst_dly);
1022         pll_wait_lock(hw);
1023
1024         old_aclk_div = RK3188_GET_CORE_ACLK_VAL(cru_readl(RK3188_CRU_CLKSELS_CON(1)) &
1025                         RK3188_CORE_ACLK_MSK);
1026         new_aclk_div = RK3188_GET_CORE_ACLK_VAL(ps->clksel1 & RK3188_CORE_ACLK_MSK);
1027
1028         if (new_aclk_div >= old_aclk_div) {
1029                 cru_writel(ps->clksel0, RK3188_CRU_CLKSELS_CON(0));
1030                 cru_writel(ps->clksel1, RK3188_CRU_CLKSELS_CON(1));
1031         }
1032
1033         /* PLL return from slow mode */
1034         //FIXME
1035         //if (!sel_gpll)
1036         cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), pll->mode_offset);
1037
1038         /* reparent to apll, and set div to 1 */
1039         if (sel_gpll) {
1040                 cru_writel(RK3188_CORE_SEL_PLL_W_MSK|RK3188_CORE_SEL_APLL,
1041                                 RK3188_CRU_CLKSELS_CON(0));
1042                 cru_writel(RK3188_CORE_CLK_DIV_W_MSK|RK3188_CORE_CLK_DIV(1),
1043                                 RK3188_CRU_CLKSELS_CON(0));
1044         }
1045
1046         if (old_aclk_div > new_aclk_div) {
1047                 cru_writel(ps->clksel0, RK3188_CRU_CLKSELS_CON(0));
1048                 cru_writel(ps->clksel1, RK3188_CRU_CLKSELS_CON(1));
1049         }
1050
1051         //loops_per_jiffy = ps->lpj;
1052         smp_wmb();
1053
1054         local_irq_restore(flags);
1055
1056         if (sel_gpll) {
1057                 sel_gpll = 0;
1058                 //clk_disable(arm_gpll);
1059                 //clk_unprepare(arm_gpll);
1060         }
1061
1062         //clk_debug("apll set loops_per_jiffy =%lu\n", loops_per_jiffy);
1063
1064         clk_debug("apll set rate %lu, con(%x,%x,%x,%x), sel(%x,%x)\n",
1065                         ps->rate,
1066                         readl(pll->reg + RK3188_PLL_CON(0)),
1067                         readl(pll->reg + RK3188_PLL_CON(1)),
1068                         readl(pll->reg + RK3188_PLL_CON(2)),
1069                         readl(pll->reg + RK3188_PLL_CON(3)),
1070                         cru_readl(RK3188_CRU_CLKSELS_CON(0)),
1071                         cru_readl(RK3188_CRU_CLKSELS_CON(1)));
1072
1073         return 0;
1074 }
1075
1076 static const struct clk_ops clk_pll_ops_3188plus_apll = {
1077         .recalc_rate = clk_pll_recalc_rate_3188plus_apll,
1078         .round_rate = clk_pll_round_rate_3188plus_apll,
1079         .set_rate = clk_pll_set_rate_3188plus_apll,
1080 };
1081
1082 /* CLK_PLL_3288_APLL type ops */
1083 static unsigned long clk_pll_recalc_rate_3288_apll(struct clk_hw *hw,
1084                 unsigned long parent_rate)
1085 {
1086         return clk_pll_recalc_rate_3188plus(hw, parent_rate);
1087 }
1088
1089 static long clk_pll_round_rate_3288_apll(struct clk_hw *hw, unsigned long rate,
1090                 unsigned long *prate)
1091 {
1092         struct clk *parent = __clk_get_parent(hw->clk);
1093
1094         if (parent && (rate==__clk_get_rate(parent))) {
1095                 clk_debug("pll %s round rate=%lu equal to parent rate\n",
1096                                 __clk_get_name(hw->clk), rate);
1097                 return rate;
1098         }
1099
1100         return (apll_get_best_set(rate, rk3288_apll_table)->rate);
1101 }
1102
1103 /* 1: use, 0: no use */
1104 #define RK3288_USE_ARM_GPLL     1
1105
1106 static int clk_pll_set_rate_3288_apll(struct clk_hw *hw, unsigned long rate,
1107                 unsigned long parent_rate)
1108 {
1109         struct clk_pll *pll = to_clk_pll(hw);
1110         struct clk *clk = hw->clk;
1111         struct clk *arm_gpll = __clk_lookup("clk_arm_gpll");
1112         unsigned long arm_gpll_rate;
1113         const struct apll_clk_set *ps;
1114 //      u32 old_aclk_div = 0, new_aclk_div = 0;
1115         u32 temp_div;
1116         unsigned long flags;
1117         int sel_gpll = 0;
1118
1119
1120 #if 0
1121         if (rate == parent_rate) {
1122                 clk_debug("pll %s set rate=%lu equal to parent rate\n",
1123                                 __clk_get_name(hw->clk), rate);
1124                 cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift),
1125                                 pll->mode_offset);
1126                 /* pll power down */
1127                 writel((0x1 << (16+1)) | (0x1<<1), pll->reg + RK3188_PLL_CON(3));
1128                 clk_debug("pll %s enter slow mode, set rate OK!\n",
1129                                 __clk_get_name(hw->clk));
1130                 return 0;
1131         }
1132 #endif
1133
1134 #if !RK3288_USE_ARM_GPLL
1135         goto CHANGE_APLL;
1136 #endif
1137
1138         /* prepare arm_gpll before reparent clk_core to it */
1139         if (!arm_gpll) {
1140                 clk_err("clk arm_gpll is NULL!\n");
1141                 goto CHANGE_APLL;
1142         }
1143
1144         arm_gpll_rate = __clk_get_rate(arm_gpll);
1145         temp_div = DIV_ROUND_UP(arm_gpll_rate, __clk_get_rate(clk));
1146         temp_div = (temp_div == 0) ? 1 : temp_div;
1147         if (temp_div > RK3288_CORE_CLK_MAX_DIV) {
1148                 clk_debug("temp_div %d > max_div %d\n", temp_div,
1149                                 RK3288_CORE_CLK_MAX_DIV);
1150                 clk_debug("can't get rate %lu from arm_gpll rate %lu\n",
1151                                 __clk_get_rate(clk), arm_gpll_rate);
1152                 goto CHANGE_APLL;
1153         }
1154
1155 #if 1
1156         if (clk_prepare(arm_gpll)) {
1157                 clk_err("fail to prepare arm_gpll path\n");
1158                 clk_unprepare(arm_gpll);
1159                 goto CHANGE_APLL;
1160         }
1161
1162         if (clk_enable(arm_gpll)) {
1163                 clk_err("fail to enable arm_gpll path\n");
1164                 clk_disable(arm_gpll);
1165                 clk_unprepare(arm_gpll);
1166                 goto CHANGE_APLL;
1167         }
1168 #endif
1169
1170         local_irq_save(flags);
1171
1172         /* firstly set div, then select arm_gpll path */
1173         cru_writel(RK3288_CORE_CLK_DIV(temp_div), RK3288_CRU_CLKSELS_CON(0));
1174         cru_writel(RK3288_CORE_SEL_PLL_W_MSK|RK3288_CORE_SEL_GPLL,
1175                         RK3288_CRU_CLKSELS_CON(0));
1176
1177         sel_gpll = 1;
1178         //loops_per_jiffy = CLK_LOOPS_RECALC(arm_gpll_rate) / temp_div;
1179         smp_wmb();
1180
1181         local_irq_restore(flags);
1182
1183         clk_debug("temp select arm_gpll path, get rate %lu\n",
1184                         arm_gpll_rate/temp_div);
1185         clk_debug("from arm_gpll rate %lu, temp_div %d\n", arm_gpll_rate,
1186                         temp_div);
1187
1188 CHANGE_APLL:
1189         ps = apll_get_best_set(rate, rk3288_apll_table);
1190         clk_debug("apll will set rate %lu\n", ps->rate);
1191         clk_debug("table con:%08x,%08x,%08x, sel:%08x,%08x\n",
1192                         ps->pllcon0, ps->pllcon1, ps->pllcon2,
1193                         ps->clksel0, ps->clksel1);
1194
1195         local_irq_save(flags);
1196
1197         /* If core src don't select gpll, apll need to enter slow mode
1198          * before reset
1199          */
1200         //FIXME
1201         //if (!sel_gpll)
1202         cru_writel(_RK3188_PLL_MODE_SLOW_SET(pll->mode_shift), pll->mode_offset);
1203
1204         /* PLL enter rest */
1205         writel(_RK3188PLUS_PLL_RESET_SET(1), pll->reg + RK3188_PLL_CON(3));
1206
1207         writel(ps->pllcon0, pll->reg + RK3188_PLL_CON(0));
1208         writel(ps->pllcon1, pll->reg + RK3188_PLL_CON(1));
1209         writel(ps->pllcon2, pll->reg + RK3188_PLL_CON(2));
1210
1211         udelay(5);
1212
1213         /* return from rest */
1214         writel(_RK3188PLUS_PLL_RESET_SET(0), pll->reg + RK3188_PLL_CON(3));
1215
1216         //wating lock state
1217         udelay(ps->rst_dly);
1218         pll_wait_lock(hw);
1219
1220         if (rate >= __clk_get_rate(hw->clk)) {
1221                 cru_writel(ps->clksel0, RK3288_CRU_CLKSELS_CON(0));
1222                 cru_writel(ps->clksel1, RK3288_CRU_CLKSELS_CON(37));
1223         }
1224
1225         /* PLL return from slow mode */
1226         //FIXME
1227         //if (!sel_gpll)
1228         cru_writel(_RK3188_PLL_MODE_NORM_SET(pll->mode_shift), pll->mode_offset);
1229
1230         /* reparent to apll, and set div to 1 */
1231         if (sel_gpll) {
1232                 cru_writel(RK3288_CORE_SEL_PLL_W_MSK|RK3288_CORE_SEL_APLL,
1233                         RK3288_CRU_CLKSELS_CON(0));
1234                 cru_writel(RK3288_CORE_CLK_DIV(1), RK3288_CRU_CLKSELS_CON(0));
1235         }
1236
1237         if (rate < __clk_get_rate(hw->clk)) {
1238                 cru_writel(ps->clksel0, RK3288_CRU_CLKSELS_CON(0));
1239                 cru_writel(ps->clksel1, RK3288_CRU_CLKSELS_CON(37));
1240         }
1241
1242         //loops_per_jiffy = ps->lpj;
1243         smp_wmb();
1244
1245         local_irq_restore(flags);
1246
1247         if (sel_gpll) {
1248                 sel_gpll = 0;
1249                 clk_disable(arm_gpll);
1250                 clk_unprepare(arm_gpll);
1251         }
1252
1253         //clk_debug("apll set loops_per_jiffy =%lu\n", loops_per_jiffy);
1254
1255         clk_debug("apll set rate %lu, con(%x,%x,%x,%x), sel(%x,%x)\n",
1256                         ps->rate,
1257                         readl(pll->reg + RK3188_PLL_CON(0)),
1258                         readl(pll->reg + RK3188_PLL_CON(1)),
1259                         readl(pll->reg + RK3188_PLL_CON(2)),
1260                         readl(pll->reg + RK3188_PLL_CON(3)),
1261                         cru_readl(RK3288_CRU_CLKSELS_CON(0)),
1262                         cru_readl(RK3288_CRU_CLKSELS_CON(1)));
1263
1264         return 0;
1265 }
1266
1267
1268 static const struct clk_ops clk_pll_ops_3288_apll = {
1269         .recalc_rate = clk_pll_recalc_rate_3288_apll,
1270         .round_rate = clk_pll_round_rate_3288_apll,
1271         .set_rate = clk_pll_set_rate_3288_apll,
1272 };
1273
1274
1275
1276 const struct clk_ops *rk_get_pll_ops(u32 pll_flags)
1277 {
1278         switch (pll_flags) {
1279                 case CLK_PLL_3188:
1280                         return &clk_pll_ops_3188;
1281
1282                 case CLK_PLL_3188_APLL:
1283                         return &clk_pll_ops_3188_apll;
1284
1285                 case CLK_PLL_3188PLUS:
1286                         return &clk_pll_ops_3188plus;
1287
1288                 case CLK_PLL_3188PLUS_APLL:
1289                         return &clk_pll_ops_3188plus_apll;
1290
1291                 case CLK_PLL_3288_APLL:
1292                         return &clk_pll_ops_3288_apll;
1293
1294                 case CLK_PLL_3188PLUS_AUTO:
1295                         return &clk_pll_ops_3188plus_auto;
1296
1297                 default:
1298                         clk_err("%s: unknown pll_flags!\n", __func__);
1299                         return NULL;
1300         }
1301 }
1302
1303 struct clk *rk_clk_register_pll(struct device *dev, const char *name,
1304                 const char *parent_name, unsigned long flags, void __iomem *reg,
1305                 u32 width, u32 mode_offset, u8 mode_shift,
1306                 u32 status_offset, u8 status_shift, u32 pll_flags,
1307                 spinlock_t *lock)
1308 {
1309         struct clk_pll *pll;
1310         struct clk *clk;
1311         struct clk_init_data init;
1312
1313
1314         clk_debug("%s: pll name = %s, pll_flags = 0x%x, register start!\n",
1315                         __func__, name, pll_flags);
1316
1317         /* allocate the pll */
1318         pll = kzalloc(sizeof(struct clk_pll), GFP_KERNEL);
1319         if (!pll) {
1320                 clk_err("%s: could not allocate pll clk\n", __func__);
1321                 return ERR_PTR(-ENOMEM);
1322         }
1323
1324         init.name = name;
1325         init.flags = flags;
1326         init.parent_names = (parent_name ? &parent_name: NULL);
1327         init.num_parents = (parent_name ? 1 : 0);
1328         init.ops = rk_get_pll_ops(pll_flags);
1329
1330         /* struct clk_pll assignments */
1331         pll->reg = reg;
1332         pll->width = width;
1333         pll->mode_offset = mode_offset;
1334         pll->mode_shift = mode_shift;
1335         pll->status_offset = status_offset;
1336         pll->status_shift = status_shift;
1337         pll->flags = pll_flags;
1338         pll->lock = lock;
1339         pll->hw.init = &init;
1340
1341         /* register the clock */
1342         clk = clk_register(dev, &pll->hw);
1343
1344         if (IS_ERR(clk))
1345                 kfree(pll);
1346
1347         clk_debug("%s: pll name = %s, pll_flags = 0x%x, register finish!\n",
1348                         __func__, name, pll_flags);
1349
1350         return clk;
1351 }
1352