12 #define pr_fmt(fmt) "clk-vco-pll: " fmt
15 #include <linux/slab.h>
44 #define PLL_MODE_NORMAL 0
45 #define PLL_MODE_FRACTION 1
46 #define PLL_MODE_DITH_DSM 2
47 #define PLL_MODE_DITH_SSM 3
48 #define PLL_MODE_MASK 3
49 #define PLL_MODE_SHIFT 3
52 #define PLL_LOCK_SHIFT 0
53 #define PLL_LOCK_MASK 1
56 #define PLL_NORM_FDBK_M_MASK 0xFF
57 #define PLL_NORM_FDBK_M_SHIFT 24
58 #define PLL_DITH_FDBK_M_MASK 0xFFFF
59 #define PLL_DITH_FDBK_M_SHIFT 16
60 #define PLL_DIV_P_MASK 0x7
61 #define PLL_DIV_P_SHIFT 8
62 #define PLL_DIV_N_MASK 0xFF
63 #define PLL_DIV_N_SHIFT 0
65 #define to_clk_vco(_hw) container_of(_hw, struct clk_vco, hw)
66 #define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)
69 static unsigned long pll_calc_rate(
struct pll_rate_tbl *rtbl,
70 unsigned long prate,
int index,
unsigned long *pll_rate)
76 rate = (((2 * rate / 10000) * rtbl[index].
m) / (mode * rtbl[
index].
n));
79 *pll_rate = (rate / (1 << rtbl[
index].
p)) * 10000;
84 static long clk_pll_round_rate_index(
struct clk_hw *
hw,
unsigned long drate,
88 unsigned long prev_rate, vco_prev_rate,
rate = 0;
89 unsigned long vco_parent_rate =
93 pr_err(
"%s: prate is must for pll clk\n", __func__);
97 for (*index = 0; *index < pll->
vco->rtbl_cnt; (*index)++) {
99 vco_prev_rate = *
prate;
100 *prate = pll_calc_rate(pll->
vco->rtbl, vco_parent_rate, *index,
106 *prate = vco_prev_rate;
116 static long clk_pll_round_rate(
struct clk_hw *hw,
unsigned long drate,
117 unsigned long *prate)
121 return clk_pll_round_rate_index(hw, drate, prate, &unused);
124 static unsigned long clk_pll_recalc_rate(
struct clk_hw *hw,
unsigned long
128 unsigned long flags = 0;
137 spin_unlock_irqrestore(pll->
vco->lock, flags);
141 return parent_rate / (1 <<
p);
144 static int clk_pll_set_rate(
struct clk_hw *hw,
unsigned long drate,
149 unsigned long flags = 0,
val;
152 clk_pll_round_rate_index(hw, drate,
NULL, &i);
160 writel_relaxed(
val, pll->
vco->cfg_reg);
163 spin_unlock_irqrestore(pll->
vco->lock, flags);
168 static struct clk_ops clk_pll_ops = {
169 .recalc_rate = clk_pll_recalc_rate,
170 .round_rate = clk_pll_round_rate,
171 .set_rate = clk_pll_set_rate,
174 static inline unsigned long vco_calc_rate(
struct clk_hw *hw,
175 unsigned long prate,
int index)
179 return pll_calc_rate(vco->
rtbl, prate, index,
NULL);
182 static long clk_vco_round_rate(
struct clk_hw *hw,
unsigned long drate,
183 unsigned long *prate)
192 static unsigned long clk_vco_recalc_rate(
struct clk_hw *hw,
193 unsigned long parent_rate)
196 unsigned long flags = 0;
207 spin_unlock_irqrestore(vco->
lock, flags);
222 WARN(1,
"%s: denominator can't be zero\n", __func__);
226 return (((parent_rate / 10000) * num) /
den) * 10000;
230 static int clk_vco_set_rate(
struct clk_hw *hw,
unsigned long drate,
235 unsigned long flags = 0,
val;
264 spin_unlock_irqrestore(vco->
lock, flags);
269 static struct clk_ops clk_vco_ops = {
270 .recalc_rate = clk_vco_recalc_rate,
271 .round_rate = clk_vco_round_rate,
272 .set_rate = clk_vco_set_rate,
276 const char *vco_gate_name,
const char *parent_name,
280 struct clk **vco_gate_clk)
284 struct clk *vco_clk, *tpll_clk, *tvco_gate_clk;
285 struct clk_init_data vco_init, pll_init;
286 const char **vco_parent_name;
288 if (!vco_name || !pll_name || !parent_name || !mode_reg || !cfg_reg ||
289 !rtbl || !rtbl_cnt) {
290 pr_err(
"Invalid arguments passed");
296 pr_err(
"could not allocate vco clk\n");
302 pr_err(
"could not allocate pll clk\n");
312 vco->
hw.init = &vco_init;
315 pll->
hw.init = &pll_init;
319 parent_name, 0, mode_reg,
PLL_ENABLE, 0, lock);
320 if (IS_ERR_OR_NULL(tvco_gate_clk))
324 *vco_gate_clk = tvco_gate_clk;
325 vco_parent_name = &vco_gate_name;
327 vco_parent_name = &parent_name;
330 vco_init.
name = vco_name;
331 vco_init.ops = &clk_vco_ops;
332 vco_init.flags =
flags;
333 vco_init.parent_names = vco_parent_name;
334 vco_init.num_parents = 1;
336 pll_init.name = pll_name;
337 pll_init.ops = &clk_pll_ops;
338 pll_init.flags = CLK_SET_RATE_PARENT;
339 pll_init.parent_names = &vco_name;
340 pll_init.num_parents = 1;
343 if (IS_ERR_OR_NULL(vco_clk))
347 if (IS_ERR_OR_NULL(tpll_clk))
360 pr_err(
"Failed to register vco pll clock\n");