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