xref: /linux/drivers/clk/visconti/pll.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Toshiba Visconti PLL driver
4  *
5  * Copyright (c) 2021 TOSHIBA CORPORATION
6  * Copyright (c) 2021 Toshiba Electronic Devices & Storage Corporation
7  *
8  * Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
9  */
10 
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>
16 
17 #include "pll.h"
18 
19 struct visconti_pll {
20 	struct clk_hw	hw;
21 	void __iomem	*pll_base;
22 	spinlock_t	*lock;
23 	unsigned long flags;
24 	size_t rate_count;
25 	struct visconti_pll_provider *ctx;
26 	struct visconti_pll_rate_table rate_table[] __counted_by(rate_count);
27 };
28 
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
36 
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)
44 
45 #define PLL0_FRACMODE_DACEN	BIT(4)
46 #define PLL0_FRACMODE_DSMEN	BIT(0)
47 
48 #define PLL_CREATE_FRACMODE(table) (table->dacen << 4 | table->dsmen)
49 #define PLL_CREATE_OSTDIV(table) (table->postdiv2 << 4 | table->postdiv1)
50 
51 static inline struct visconti_pll *to_visconti_pll(struct clk_hw *hw)
52 {
53 	return container_of(hw, struct visconti_pll, hw);
54 }
55 
56 static void visconti_pll_get_params(struct visconti_pll *pll,
57 				    struct visconti_pll_rate_table *rate_table)
58 {
59 	u32 postdiv, val;
60 
61 	val = readl(pll->pll_base + PLL_FRACMODE_REG);
62 
63 	rate_table->dacen = FIELD_GET(PLL0_FRACMODE_DACEN, val);
64 	rate_table->dsmen = FIELD_GET(PLL0_FRACMODE_DSMEN, val);
65 
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;
69 
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;
73 }
74 
75 static const struct visconti_pll_rate_table *visconti_get_pll_settings(struct visconti_pll *pll,
76 								       unsigned long rate)
77 {
78 	const struct visconti_pll_rate_table *rate_table = pll->rate_table;
79 	int i;
80 
81 	for (i = 0; i < pll->rate_count; i++)
82 		if (rate == rate_table[i].rate)
83 			return &rate_table[i];
84 
85 	return NULL;
86 }
87 
88 static unsigned long visconti_get_pll_rate_from_data(struct visconti_pll *pll,
89 						     const struct visconti_pll_rate_table *rate)
90 {
91 	const struct visconti_pll_rate_table *rate_table = pll->rate_table;
92 	int i;
93 
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;
98 
99 	/* set default */
100 	return rate_table[0].rate;
101 }
102 
103 static int visconti_pll_determine_rate(struct clk_hw *hw,
104 				       struct clk_rate_request *req)
105 {
106 	struct visconti_pll *pll = to_visconti_pll(hw);
107 	const struct visconti_pll_rate_table *rate_table = pll->rate_table;
108 	int i;
109 
110 	/* Assuming rate_table is in descending order */
111 	for (i = 0; i < pll->rate_count; i++)
112 		if (req->rate >= rate_table[i].rate) {
113 			req->rate = rate_table[i].rate;
114 
115 			return 0;
116 		}
117 
118 	/* return minimum supported value */
119 	req->rate = rate_table[i - 1].rate;
120 
121 	return 0;
122 }
123 
124 static unsigned long visconti_pll_recalc_rate(struct clk_hw *hw,
125 					      unsigned long parent_rate)
126 {
127 	struct visconti_pll *pll = to_visconti_pll(hw);
128 	struct visconti_pll_rate_table rate_table;
129 
130 	memset(&rate_table, 0, sizeof(rate_table));
131 	visconti_pll_get_params(pll, &rate_table);
132 
133 	return visconti_get_pll_rate_from_data(pll, &rate_table);
134 }
135 
136 static int visconti_pll_set_params(struct visconti_pll *pll,
137 				   const struct visconti_pll_rate_table *rate_table)
138 {
139 	writel(PLL_CREATE_FRACMODE(rate_table), pll->pll_base + PLL_FRACMODE_REG);
140 	writel(PLL_CREATE_OSTDIV(rate_table), pll->pll_base + PLL_POSTDIV_REG);
141 	writel(rate_table->intin, pll->pll_base + PLL_INTIN_REG);
142 	writel(rate_table->fracin, pll->pll_base + PLL_FRACIN_REG);
143 	writel(rate_table->refdiv, pll->pll_base + PLL_REFDIV_REG);
144 
145 	return 0;
146 }
147 
148 static int visconti_pll_set_rate(struct clk_hw *hw, unsigned long rate,
149 			    unsigned long parent_rate)
150 {
151 	struct visconti_pll *pll = to_visconti_pll(hw);
152 	const struct visconti_pll_rate_table *rate_table;
153 
154 	rate_table = visconti_get_pll_settings(pll, rate);
155 	if (!rate_table)
156 		return -EINVAL;
157 
158 	return visconti_pll_set_params(pll, rate_table);
159 }
160 
161 static int visconti_pll_is_enabled(struct clk_hw *hw)
162 {
163 	struct visconti_pll *pll = to_visconti_pll(hw);
164 	u32 reg;
165 
166 	reg = readl(pll->pll_base + PLL_CTRL_REG);
167 
168 	return (reg & PLL_PLLEN);
169 }
170 
171 static int visconti_pll_enable(struct clk_hw *hw)
172 {
173 	struct visconti_pll *pll = to_visconti_pll(hw);
174 	const struct visconti_pll_rate_table *rate_table = pll->rate_table;
175 	unsigned long flags;
176 	u32 reg;
177 
178 	if (visconti_pll_is_enabled(hw))
179 		return 0;
180 
181 	spin_lock_irqsave(pll->lock, flags);
182 
183 	writel(PLL_CONFIG_SEL, pll->pll_base + PLL_CONF_REG);
184 
185 	reg = readl(pll->pll_base + PLL_CTRL_REG);
186 	reg |= PLL_BYPASS;
187 	writel(reg, pll->pll_base + PLL_CTRL_REG);
188 
189 	visconti_pll_set_params(pll, &rate_table[0]);
190 
191 	reg = readl(pll->pll_base + PLL_CTRL_REG);
192 	reg &= ~PLL_PLLEN;
193 	writel(reg, pll->pll_base + PLL_CTRL_REG);
194 
195 	udelay(1);
196 
197 	reg = readl(pll->pll_base + PLL_CTRL_REG);
198 	reg |= PLL_PLLEN;
199 	writel(reg, pll->pll_base + PLL_CTRL_REG);
200 
201 	udelay(40);
202 
203 	reg = readl(pll->pll_base + PLL_CTRL_REG);
204 	reg &= ~PLL_BYPASS;
205 	writel(reg, pll->pll_base + PLL_CTRL_REG);
206 
207 	spin_unlock_irqrestore(pll->lock, flags);
208 
209 	return 0;
210 }
211 
212 static void visconti_pll_disable(struct clk_hw *hw)
213 {
214 	struct visconti_pll *pll = to_visconti_pll(hw);
215 	unsigned long flags;
216 	u32 reg;
217 
218 	if (!visconti_pll_is_enabled(hw))
219 		return;
220 
221 	spin_lock_irqsave(pll->lock, flags);
222 
223 	writel(PLL_CONFIG_SEL, pll->pll_base + PLL_CONF_REG);
224 
225 	reg = readl(pll->pll_base + PLL_CTRL_REG);
226 	reg |= PLL_BYPASS;
227 	writel(reg, pll->pll_base + PLL_CTRL_REG);
228 
229 	reg = readl(pll->pll_base + PLL_CTRL_REG);
230 	reg &= ~PLL_PLLEN;
231 	writel(reg, pll->pll_base + PLL_CTRL_REG);
232 
233 	spin_unlock_irqrestore(pll->lock, flags);
234 }
235 
236 static const struct clk_ops visconti_pll_ops = {
237 	.enable = visconti_pll_enable,
238 	.disable = visconti_pll_disable,
239 	.is_enabled = visconti_pll_is_enabled,
240 	.determine_rate = visconti_pll_determine_rate,
241 	.recalc_rate = visconti_pll_recalc_rate,
242 	.set_rate = visconti_pll_set_rate,
243 };
244 
245 static struct clk_hw *visconti_register_pll(struct visconti_pll_provider *ctx,
246 					    const char *name,
247 					    const char *parent_name,
248 					    int offset,
249 					    const struct visconti_pll_rate_table *rate_table,
250 					    spinlock_t *lock)
251 {
252 	struct clk_init_data init = {};
253 	struct visconti_pll *pll;
254 	struct clk_hw *pll_hw_clk;
255 	size_t len;
256 	int ret;
257 
258 	init.name = name;
259 	init.flags = CLK_IGNORE_UNUSED;
260 	init.parent_names = &parent_name;
261 	init.num_parents = 1;
262 
263 	for (len = 0; rate_table[len].rate != 0; )
264 		len++;
265 
266 	pll = kzalloc_flex(*pll, rate_table, len);
267 	if (!pll)
268 		return ERR_PTR(-ENOMEM);
269 
270 	pll->rate_count = len;
271 	memcpy(pll->rate_table, rate_table, len * sizeof(*pll->rate_table));
272 
273 	init.ops = &visconti_pll_ops;
274 	pll->hw.init = &init;
275 	pll->pll_base = ctx->reg_base + offset;
276 	pll->lock = lock;
277 	pll->ctx = ctx;
278 
279 	pll_hw_clk = &pll->hw;
280 	ret = clk_hw_register(NULL, &pll->hw);
281 	if (ret) {
282 		pr_err("failed to register pll clock %s : %d\n", name, ret);
283 		kfree(pll);
284 		pll_hw_clk = ERR_PTR(ret);
285 	}
286 
287 	return pll_hw_clk;
288 }
289 
290 static void visconti_pll_add_lookup(struct visconti_pll_provider *ctx,
291 				    struct clk_hw *hw_clk,
292 				    unsigned int id)
293 {
294 	if (id)
295 		ctx->clk_data.hws[id] = hw_clk;
296 }
297 
298 void __init visconti_register_plls(struct visconti_pll_provider *ctx,
299 				   const struct visconti_pll_info *list,
300 				   unsigned int nr_plls,
301 				   spinlock_t *lock)
302 {
303 	int idx;
304 
305 	for (idx = 0; idx < nr_plls; idx++, list++) {
306 		struct clk_hw *clk;
307 
308 		clk = visconti_register_pll(ctx,
309 					    list->name,
310 					    list->parent,
311 					    list->base_reg,
312 					    list->rate_table,
313 					    lock);
314 		if (IS_ERR(clk)) {
315 			pr_err("failed to register clock %s\n", list->name);
316 			continue;
317 		}
318 
319 		visconti_pll_add_lookup(ctx, clk, list->id);
320 	}
321 }
322 
323 struct visconti_pll_provider * __init visconti_init_pll(struct device_node *np,
324 							void __iomem *base,
325 							unsigned long nr_plls)
326 {
327 	struct visconti_pll_provider *ctx;
328 	int i;
329 
330 	ctx = kzalloc_flex(*ctx, clk_data.hws, nr_plls);
331 	if (!ctx)
332 		return ERR_PTR(-ENOMEM);
333 
334 	ctx->node = np;
335 	ctx->reg_base = base;
336 	ctx->clk_data.num = nr_plls;
337 
338 	for (i = 0; i < nr_plls; ++i)
339 		ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
340 
341 	return ctx;
342 }
343