2 * Copyright 2014 Linaro Ltd.
3 * Copyright (C) 2014 ZTE Corporation.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
10 #include <linux/clk-provider.h>
11 #include <linux/err.h>
13 #include <linux/iopoll.h>
14 #include <linux/slab.h>
15 #include <linux/spinlock.h>
19 #define to_clk_zx_pll(_hw) container_of(_hw, struct clk_zx_pll, hw)
21 #define CFG0_CFG1_OFFSET 4
22 #define LOCK_FLAG BIT(30)
23 #define POWER_DOWN BIT(31)
25 static int rate_to_idx(struct clk_zx_pll *zx_pll, unsigned long rate)
27 const struct zx_pll_config *config = zx_pll->lookup_table;
30 for (i = 0; i < zx_pll->count; i++) {
31 if (config[i].rate > rate)
32 return i > 0 ? i - 1 : 0;
34 if (config[i].rate == rate)
41 static int hw_to_idx(struct clk_zx_pll *zx_pll)
43 const struct zx_pll_config *config = zx_pll->lookup_table;
47 hw_cfg0 = readl_relaxed(zx_pll->reg_base);
48 hw_cfg1 = readl_relaxed(zx_pll->reg_base + CFG0_CFG1_OFFSET);
50 /* For matching the value in lookup table */
51 hw_cfg0 &= ~LOCK_FLAG;
52 hw_cfg0 |= POWER_DOWN;
54 for (i = 0; i < zx_pll->count; i++) {
55 if (hw_cfg0 == config[i].cfg0 && hw_cfg1 == config[i].cfg1)
62 static unsigned long zx_pll_recalc_rate(struct clk_hw *hw,
63 unsigned long parent_rate)
65 struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
68 idx = hw_to_idx(zx_pll);
69 if (unlikely(idx == -EINVAL))
72 return zx_pll->lookup_table[idx].rate;
75 static long zx_pll_round_rate(struct clk_hw *hw, unsigned long rate,
78 struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
81 idx = rate_to_idx(zx_pll, rate);
83 return zx_pll->lookup_table[idx].rate;
86 static int zx_pll_set_rate(struct clk_hw *hw, unsigned long rate,
87 unsigned long parent_rate)
89 /* Assume current cpu is not running on current PLL */
90 struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
91 const struct zx_pll_config *config;
94 idx = rate_to_idx(zx_pll, rate);
95 config = &zx_pll->lookup_table[idx];
97 writel_relaxed(config->cfg0, zx_pll->reg_base);
98 writel_relaxed(config->cfg1, zx_pll->reg_base + CFG0_CFG1_OFFSET);
103 static int zx_pll_enable(struct clk_hw *hw)
105 struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
108 reg = readl_relaxed(zx_pll->reg_base);
109 writel_relaxed(reg & ~POWER_DOWN, zx_pll->reg_base);
111 return readl_relaxed_poll_timeout(zx_pll->reg_base, reg,
112 reg & LOCK_FLAG, 0, 100);
115 static void zx_pll_disable(struct clk_hw *hw)
117 struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
120 reg = readl_relaxed(zx_pll->reg_base);
121 writel_relaxed(reg | POWER_DOWN, zx_pll->reg_base);
124 static int zx_pll_is_enabled(struct clk_hw *hw)
126 struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
129 reg = readl_relaxed(zx_pll->reg_base);
131 return !(reg & POWER_DOWN);
134 static const struct clk_ops zx_pll_ops = {
135 .recalc_rate = zx_pll_recalc_rate,
136 .round_rate = zx_pll_round_rate,
137 .set_rate = zx_pll_set_rate,
138 .enable = zx_pll_enable,
139 .disable = zx_pll_disable,
140 .is_enabled = zx_pll_is_enabled,
143 struct clk *clk_register_zx_pll(const char *name, const char *parent_name,
144 unsigned long flags, void __iomem *reg_base,
145 const struct zx_pll_config *lookup_table, int count, spinlock_t *lock)
147 struct clk_zx_pll *zx_pll;
149 struct clk_init_data init;
151 zx_pll = kzalloc(sizeof(*zx_pll), GFP_KERNEL);
153 return ERR_PTR(-ENOMEM);
156 init.ops = &zx_pll_ops;
158 init.parent_names = parent_name ? &parent_name : NULL;
159 init.num_parents = parent_name ? 1 : 0;
161 zx_pll->reg_base = reg_base;
162 zx_pll->lookup_table = lookup_table;
163 zx_pll->count = count;
165 zx_pll->hw.init = &init;
167 clk = clk_register(NULL, &zx_pll->hw);