printf: Remove unused 'bprintf'
[drm/drm-misc.git] / drivers / clk / visconti / pll.c
blob3f929cf8dd2f71d5a57986b917c86fa4fc9e0ffd
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Toshiba Visconti PLL driver
5 * Copyright (c) 2021 TOSHIBA CORPORATION
6 * Copyright (c) 2021 Toshiba Electronic Devices & Storage Corporation
8 * Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
9 */
11 #include <linux/bitfield.h>
12 #include <linux/clk-provider.h>
13 #include <linux/delay.h>
14 #include <linux/slab.h>
15 #include <linux/io.h>
17 #include "pll.h"
19 struct visconti_pll {
20 struct clk_hw hw;
21 void __iomem *pll_base;
22 spinlock_t *lock;
23 unsigned long flags;
24 const struct visconti_pll_rate_table *rate_table;
25 size_t rate_count;
26 struct visconti_pll_provider *ctx;
29 #define PLL_CONF_REG 0x0000
30 #define PLL_CTRL_REG 0x0004
31 #define PLL_FRACMODE_REG 0x0010
32 #define PLL_INTIN_REG 0x0014
33 #define PLL_FRACIN_REG 0x0018
34 #define PLL_REFDIV_REG 0x001c
35 #define PLL_POSTDIV_REG 0x0020
37 #define PLL_CONFIG_SEL BIT(0)
38 #define PLL_PLLEN BIT(4)
39 #define PLL_BYPASS BIT(16)
40 #define PLL_INTIN_MASK GENMASK(11, 0)
41 #define PLL_FRACIN_MASK GENMASK(23, 0)
42 #define PLL_REFDIV_MASK GENMASK(5, 0)
43 #define PLL_POSTDIV_MASK GENMASK(2, 0)
45 #define PLL0_FRACMODE_DACEN BIT(4)
46 #define PLL0_FRACMODE_DSMEN BIT(0)
48 #define PLL_CREATE_FRACMODE(table) (table->dacen << 4 | table->dsmen)
49 #define PLL_CREATE_OSTDIV(table) (table->postdiv2 << 4 | table->postdiv1)
51 static inline struct visconti_pll *to_visconti_pll(struct clk_hw *hw)
53 return container_of(hw, struct visconti_pll, hw);
56 static void visconti_pll_get_params(struct visconti_pll *pll,
57 struct visconti_pll_rate_table *rate_table)
59 u32 postdiv, val;
61 val = readl(pll->pll_base + PLL_FRACMODE_REG);
63 rate_table->dacen = FIELD_GET(PLL0_FRACMODE_DACEN, val);
64 rate_table->dsmen = FIELD_GET(PLL0_FRACMODE_DSMEN, val);
66 rate_table->fracin = readl(pll->pll_base + PLL_FRACIN_REG) & PLL_FRACIN_MASK;
67 rate_table->intin = readl(pll->pll_base + PLL_INTIN_REG) & PLL_INTIN_MASK;
68 rate_table->refdiv = readl(pll->pll_base + PLL_REFDIV_REG) & PLL_REFDIV_MASK;
70 postdiv = readl(pll->pll_base + PLL_POSTDIV_REG);
71 rate_table->postdiv1 = postdiv & PLL_POSTDIV_MASK;
72 rate_table->postdiv2 = (postdiv >> 4) & PLL_POSTDIV_MASK;
75 static const struct visconti_pll_rate_table *visconti_get_pll_settings(struct visconti_pll *pll,
76 unsigned long rate)
78 const struct visconti_pll_rate_table *rate_table = pll->rate_table;
79 int i;
81 for (i = 0; i < pll->rate_count; i++)
82 if (rate == rate_table[i].rate)
83 return &rate_table[i];
85 return NULL;
88 static unsigned long visconti_get_pll_rate_from_data(struct visconti_pll *pll,
89 const struct visconti_pll_rate_table *rate)
91 const struct visconti_pll_rate_table *rate_table = pll->rate_table;
92 int i;
94 for (i = 0; i < pll->rate_count; i++)
95 if (memcmp(&rate_table[i].dacen, &rate->dacen,
96 sizeof(*rate) - sizeof(unsigned long)) == 0)
97 return rate_table[i].rate;
99 /* set default */
100 return rate_table[0].rate;
103 static long visconti_pll_round_rate(struct clk_hw *hw,
104 unsigned long rate, unsigned long *prate)
106 struct visconti_pll *pll = to_visconti_pll(hw);
107 const struct visconti_pll_rate_table *rate_table = pll->rate_table;
108 int i;
110 /* Assumming rate_table is in descending order */
111 for (i = 0; i < pll->rate_count; i++)
112 if (rate >= rate_table[i].rate)
113 return rate_table[i].rate;
115 /* return minimum supported value */
116 return rate_table[i - 1].rate;
119 static unsigned long visconti_pll_recalc_rate(struct clk_hw *hw,
120 unsigned long parent_rate)
122 struct visconti_pll *pll = to_visconti_pll(hw);
123 struct visconti_pll_rate_table rate_table;
125 memset(&rate_table, 0, sizeof(rate_table));
126 visconti_pll_get_params(pll, &rate_table);
128 return visconti_get_pll_rate_from_data(pll, &rate_table);
131 static int visconti_pll_set_params(struct visconti_pll *pll,
132 const struct visconti_pll_rate_table *rate_table)
134 writel(PLL_CREATE_FRACMODE(rate_table), pll->pll_base + PLL_FRACMODE_REG);
135 writel(PLL_CREATE_OSTDIV(rate_table), pll->pll_base + PLL_POSTDIV_REG);
136 writel(rate_table->intin, pll->pll_base + PLL_INTIN_REG);
137 writel(rate_table->fracin, pll->pll_base + PLL_FRACIN_REG);
138 writel(rate_table->refdiv, pll->pll_base + PLL_REFDIV_REG);
140 return 0;
143 static int visconti_pll_set_rate(struct clk_hw *hw, unsigned long rate,
144 unsigned long parent_rate)
146 struct visconti_pll *pll = to_visconti_pll(hw);
147 const struct visconti_pll_rate_table *rate_table;
149 rate_table = visconti_get_pll_settings(pll, rate);
150 if (!rate_table)
151 return -EINVAL;
153 return visconti_pll_set_params(pll, rate_table);
156 static int visconti_pll_is_enabled(struct clk_hw *hw)
158 struct visconti_pll *pll = to_visconti_pll(hw);
159 u32 reg;
161 reg = readl(pll->pll_base + PLL_CTRL_REG);
163 return (reg & PLL_PLLEN);
166 static int visconti_pll_enable(struct clk_hw *hw)
168 struct visconti_pll *pll = to_visconti_pll(hw);
169 const struct visconti_pll_rate_table *rate_table = pll->rate_table;
170 unsigned long flags;
171 u32 reg;
173 if (visconti_pll_is_enabled(hw))
174 return 0;
176 spin_lock_irqsave(pll->lock, flags);
178 writel(PLL_CONFIG_SEL, pll->pll_base + PLL_CONF_REG);
180 reg = readl(pll->pll_base + PLL_CTRL_REG);
181 reg |= PLL_BYPASS;
182 writel(reg, pll->pll_base + PLL_CTRL_REG);
184 visconti_pll_set_params(pll, &rate_table[0]);
186 reg = readl(pll->pll_base + PLL_CTRL_REG);
187 reg &= ~PLL_PLLEN;
188 writel(reg, pll->pll_base + PLL_CTRL_REG);
190 udelay(1);
192 reg = readl(pll->pll_base + PLL_CTRL_REG);
193 reg |= PLL_PLLEN;
194 writel(reg, pll->pll_base + PLL_CTRL_REG);
196 udelay(40);
198 reg = readl(pll->pll_base + PLL_CTRL_REG);
199 reg &= ~PLL_BYPASS;
200 writel(reg, pll->pll_base + PLL_CTRL_REG);
202 spin_unlock_irqrestore(pll->lock, flags);
204 return 0;
207 static void visconti_pll_disable(struct clk_hw *hw)
209 struct visconti_pll *pll = to_visconti_pll(hw);
210 unsigned long flags;
211 u32 reg;
213 if (!visconti_pll_is_enabled(hw))
214 return;
216 spin_lock_irqsave(pll->lock, flags);
218 writel(PLL_CONFIG_SEL, pll->pll_base + PLL_CONF_REG);
220 reg = readl(pll->pll_base + PLL_CTRL_REG);
221 reg |= PLL_BYPASS;
222 writel(reg, pll->pll_base + PLL_CTRL_REG);
224 reg = readl(pll->pll_base + PLL_CTRL_REG);
225 reg &= ~PLL_PLLEN;
226 writel(reg, pll->pll_base + PLL_CTRL_REG);
228 spin_unlock_irqrestore(pll->lock, flags);
231 static const struct clk_ops visconti_pll_ops = {
232 .enable = visconti_pll_enable,
233 .disable = visconti_pll_disable,
234 .is_enabled = visconti_pll_is_enabled,
235 .round_rate = visconti_pll_round_rate,
236 .recalc_rate = visconti_pll_recalc_rate,
237 .set_rate = visconti_pll_set_rate,
240 static struct clk_hw *visconti_register_pll(struct visconti_pll_provider *ctx,
241 const char *name,
242 const char *parent_name,
243 int offset,
244 const struct visconti_pll_rate_table *rate_table,
245 spinlock_t *lock)
247 struct clk_init_data init;
248 struct visconti_pll *pll;
249 struct clk_hw *pll_hw_clk;
250 size_t len;
251 int ret;
253 pll = kzalloc(sizeof(*pll), GFP_KERNEL);
254 if (!pll)
255 return ERR_PTR(-ENOMEM);
257 init.name = name;
258 init.flags = CLK_IGNORE_UNUSED;
259 init.parent_names = &parent_name;
260 init.num_parents = 1;
262 for (len = 0; rate_table[len].rate != 0; )
263 len++;
264 pll->rate_count = len;
265 pll->rate_table = kmemdup_array(rate_table,
266 pll->rate_count, sizeof(*pll->rate_table),
267 GFP_KERNEL);
268 WARN(!pll->rate_table, "%s: could not allocate rate table for %s\n", __func__, name);
270 init.ops = &visconti_pll_ops;
271 pll->hw.init = &init;
272 pll->pll_base = ctx->reg_base + offset;
273 pll->lock = lock;
274 pll->ctx = ctx;
276 pll_hw_clk = &pll->hw;
277 ret = clk_hw_register(NULL, &pll->hw);
278 if (ret) {
279 pr_err("failed to register pll clock %s : %d\n", name, ret);
280 kfree(pll->rate_table);
281 kfree(pll);
282 pll_hw_clk = ERR_PTR(ret);
285 return pll_hw_clk;
288 static void visconti_pll_add_lookup(struct visconti_pll_provider *ctx,
289 struct clk_hw *hw_clk,
290 unsigned int id)
292 if (id)
293 ctx->clk_data.hws[id] = hw_clk;
296 void __init visconti_register_plls(struct visconti_pll_provider *ctx,
297 const struct visconti_pll_info *list,
298 unsigned int nr_plls,
299 spinlock_t *lock)
301 int idx;
303 for (idx = 0; idx < nr_plls; idx++, list++) {
304 struct clk_hw *clk;
306 clk = visconti_register_pll(ctx,
307 list->name,
308 list->parent,
309 list->base_reg,
310 list->rate_table,
311 lock);
312 if (IS_ERR(clk)) {
313 pr_err("failed to register clock %s\n", list->name);
314 continue;
317 visconti_pll_add_lookup(ctx, clk, list->id);
321 struct visconti_pll_provider * __init visconti_init_pll(struct device_node *np,
322 void __iomem *base,
323 unsigned long nr_plls)
325 struct visconti_pll_provider *ctx;
326 int i;
328 ctx = kzalloc(struct_size(ctx, clk_data.hws, nr_plls), GFP_KERNEL);
329 if (!ctx)
330 return ERR_PTR(-ENOMEM);
332 ctx->node = np;
333 ctx->reg_base = base;
334 ctx->clk_data.num = nr_plls;
336 for (i = 0; i < nr_plls; ++i)
337 ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
339 return ctx;