1 #include <linux/slab.h>
8 //static unsigned long lpj_gpll;
11 extern void __iomem *reg_start;
12 #define RK30_CRU_BASE (reg_start)
14 #define cru_readl(offset) readl(RK30_CRU_BASE + offset)
15 #define cru_writel(v, offset) do {writel(v, RK30_CRU_BASE + offset); dsb();} \
18 #define PLLS_IN_NORM(pll_id) (((cru_readl(CRU_MODE_CON)&PLL_MODE_MSK(pll_id))\
19 ==(PLL_MODE_NORM(pll_id)&PLL_MODE_MSK(pll_id)))\
20 &&!(cru_readl(PLL_CONS(pll_id,3))&PLL_BYPASS))
24 static const struct apll_clk_set apll_table[] = {
27 static const struct pll_clk_set pll_com_table[] = {
28 _PLL_SET_CLKS(1200000, 1, 50, 1),
29 _PLL_SET_CLKS(1188000, 2, 99, 1),
30 _PLL_SET_CLKS(891000, 8, 594, 2),
31 _PLL_SET_CLKS(768000, 1, 64, 2),
32 _PLL_SET_CLKS(594000, 2, 198, 4),
33 _PLL_SET_CLKS(408000, 1, 68, 4),
34 _PLL_SET_CLKS(384000, 2, 128, 4),
35 _PLL_SET_CLKS(360000, 1, 60, 4),
36 _PLL_SET_CLKS(300000, 1, 50, 4),
37 _PLL_SET_CLKS(297000, 2, 198, 8),
38 _PLL_SET_CLKS(148500, 2, 99, 8),
39 _PLL_SET_CLKS(0, 0, 0, 0),
43 static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
44 unsigned long parent_rate)
46 struct clk_pll *pll = to_clk_pll(hw);
50 if (PLLS_IN_NORM(pll_id)) {
51 u32 pll_con0 = cru_readl(PLL_CONS(pll_id, 0));
52 u32 pll_con1 = cru_readl(PLL_CONS(pll_id, 1));
54 u64 rate64 = (u64)parent_rate * PLL_NF(pll_con1);
56 do_div(rate64, PLL_NR(pll_con0));
57 do_div(rate64, PLL_NO(pll_con0));
62 clk_debug("pll id=%d by pass mode\n", pll_id);
65 clk_debug("pll id=%d, recalc rate =%lu\n", pll->id, rate);
71 /*get rate that is most close to target*/
72 static const struct pll_clk_set *pll_clk_get_best_set(unsigned long rate,
73 const struct pll_clk_set *table)
75 const struct pll_clk_set *ps, *pt;
79 if (pt->rate == rate) {
84 if ((pt->rate > rate || (rate - pt->rate < ps->rate - rate)))
94 static long clk_apll_round_rate(struct clk_hw *hw, unsigned long rate,
100 static long clk_pll_com_round_rate(struct clk_hw *hw, unsigned long rate,
101 unsigned long *prate)
103 return (pll_clk_get_best_set(rate, pll_com_table)->rate);
106 static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
107 unsigned long *prate)
109 struct clk_pll *pll = to_clk_pll(hw);
114 rate_out = clk_apll_round_rate(hw, rate, prate);
118 rate_out = clk_pll_com_round_rate(hw, rate, prate);
127 static int clk_apll_set_rate(struct clk_hw *hw, unsigned long rate,
128 unsigned long parent_rate)
133 static int clk_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
134 unsigned long parent_rate)
139 static int clk_gpll_set_rate(struct clk_hw *hw, unsigned long rate,
140 unsigned long parent_rate)
145 static int clk_pll_com_set_rate(struct clk_hw *hw, unsigned long rate,
146 unsigned long parent_rate)
151 static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
152 unsigned long parent_rate)
154 struct clk_pll *pll = to_clk_pll(hw);
159 ret = clk_apll_set_rate(hw, rate, parent_rate);
163 ret = clk_dpll_set_rate(hw, rate, parent_rate);
167 ret = clk_gpll_set_rate(hw, rate, parent_rate);
171 ret = clk_pll_com_set_rate(hw, rate, parent_rate);
179 const struct clk_ops clk_pll_ops = {
180 .recalc_rate = clk_pll_recalc_rate,
181 .round_rate = clk_pll_round_rate,
182 .set_rate = clk_pll_set_rate,
185 EXPORT_SYMBOL_GPL(clk_pll_ops);
188 struct clk *rk_clk_register_pll(struct device *dev, const char *name,
189 const char *parent_name, unsigned long flags, void __iomem *reg,
190 u32 width, u8 id, spinlock_t *lock)
194 struct clk_init_data init;
197 clk_debug("%s: pll name = %s, id = %d, register start!\n",__func__,name,id);
200 if(id >= END_PLL_ID){
201 clk_err("%s: PLL id = %d >= END_PLL_ID = %d\n", __func__,
203 return ERR_PTR(-EINVAL);
207 /* allocate the pll */
208 pll = kzalloc(sizeof(struct clk_pll), GFP_KERNEL);
210 clk_err("%s: could not allocate pll clk\n", __func__);
211 return ERR_PTR(-ENOMEM);
216 init.parent_names = (parent_name ? &parent_name: NULL);
217 init.num_parents = (parent_name ? 1 : 0);
218 init.ops = &clk_pll_ops;
220 /* struct clk_pll assignments */
225 pll->hw.init = &init;
227 /* register the clock */
228 clk = clk_register(dev, &pll->hw);
233 clk_debug("%s: pll name = %s, id = %d, register finish!\n",__func__,name,id);