GNU Linux-libre 6.1.24-gnu
[releases.git] / drivers / clk / visconti / pll.c
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         const struct visconti_pll_rate_table *rate_table;
25         size_t rate_count;
26         struct visconti_pll_provider *ctx;
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 long visconti_pll_round_rate(struct clk_hw *hw,
104                                     unsigned long rate, unsigned long *prate)
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         /* 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;
114
115         /* return minimum supported value */
116         return rate_table[i - 1].rate;
117 }
118
119 static unsigned long visconti_pll_recalc_rate(struct clk_hw *hw,
120                                               unsigned long parent_rate)
121 {
122         struct visconti_pll *pll = to_visconti_pll(hw);
123         struct visconti_pll_rate_table rate_table;
124
125         memset(&rate_table, 0, sizeof(rate_table));
126         visconti_pll_get_params(pll, &rate_table);
127
128         return visconti_get_pll_rate_from_data(pll, &rate_table);
129 }
130
131 static int visconti_pll_set_params(struct visconti_pll *pll,
132                                    const struct visconti_pll_rate_table *rate_table)
133 {
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);
139
140         return 0;
141 }
142
143 static int visconti_pll_set_rate(struct clk_hw *hw, unsigned long rate,
144                             unsigned long parent_rate)
145 {
146         struct visconti_pll *pll = to_visconti_pll(hw);
147         const struct visconti_pll_rate_table *rate_table;
148
149         rate_table = visconti_get_pll_settings(pll, rate);
150         if (!rate_table)
151                 return -EINVAL;
152
153         return visconti_pll_set_params(pll, rate_table);
154 }
155
156 static int visconti_pll_is_enabled(struct clk_hw *hw)
157 {
158         struct visconti_pll *pll = to_visconti_pll(hw);
159         u32 reg;
160
161         reg = readl(pll->pll_base + PLL_CTRL_REG);
162
163         return (reg & PLL_PLLEN);
164 }
165
166 static int visconti_pll_enable(struct clk_hw *hw)
167 {
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;
172
173         if (visconti_pll_is_enabled(hw))
174                 return 0;
175
176         spin_lock_irqsave(pll->lock, flags);
177
178         writel(PLL_CONFIG_SEL, pll->pll_base + PLL_CONF_REG);
179
180         reg = readl(pll->pll_base + PLL_CTRL_REG);
181         reg |= PLL_BYPASS;
182         writel(reg, pll->pll_base + PLL_CTRL_REG);
183
184         visconti_pll_set_params(pll, &rate_table[0]);
185
186         reg = readl(pll->pll_base + PLL_CTRL_REG);
187         reg &= ~PLL_PLLEN;
188         writel(reg, pll->pll_base + PLL_CTRL_REG);
189
190         udelay(1);
191
192         reg = readl(pll->pll_base + PLL_CTRL_REG);
193         reg |= PLL_PLLEN;
194         writel(reg, pll->pll_base + PLL_CTRL_REG);
195
196         udelay(40);
197
198         reg = readl(pll->pll_base + PLL_CTRL_REG);
199         reg &= ~PLL_BYPASS;
200         writel(reg, pll->pll_base + PLL_CTRL_REG);
201
202         spin_unlock_irqrestore(pll->lock, flags);
203
204         return 0;
205 }
206
207 static void visconti_pll_disable(struct clk_hw *hw)
208 {
209         struct visconti_pll *pll = to_visconti_pll(hw);
210         unsigned long flags;
211         u32 reg;
212
213         if (!visconti_pll_is_enabled(hw))
214                 return;
215
216         spin_lock_irqsave(pll->lock, flags);
217
218         writel(PLL_CONFIG_SEL, pll->pll_base + PLL_CONF_REG);
219
220         reg = readl(pll->pll_base + PLL_CTRL_REG);
221         reg |= PLL_BYPASS;
222         writel(reg, pll->pll_base + PLL_CTRL_REG);
223
224         reg = readl(pll->pll_base + PLL_CTRL_REG);
225         reg &= ~PLL_PLLEN;
226         writel(reg, pll->pll_base + PLL_CTRL_REG);
227
228         spin_unlock_irqrestore(pll->lock, flags);
229 }
230
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,
238 };
239
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)
246 {
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;
252
253         pll = kzalloc(sizeof(*pll), GFP_KERNEL);
254         if (!pll)
255                 return ERR_PTR(-ENOMEM);
256
257         init.name = name;
258         init.flags = CLK_IGNORE_UNUSED;
259         init.parent_names = &parent_name;
260         init.num_parents = 1;
261
262         for (len = 0; rate_table[len].rate != 0; )
263                 len++;
264         pll->rate_count = len;
265         pll->rate_table = kmemdup(rate_table,
266                                   pll->rate_count * sizeof(struct visconti_pll_rate_table),
267                                   GFP_KERNEL);
268         WARN(!pll->rate_table, "%s: could not allocate rate table for %s\n", __func__, name);
269
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;
275
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);
283         }
284
285         return pll_hw_clk;
286 }
287
288 static void visconti_pll_add_lookup(struct visconti_pll_provider *ctx,
289                                     struct clk_hw *hw_clk,
290                                     unsigned int id)
291 {
292         if (id)
293                 ctx->clk_data.hws[id] = hw_clk;
294 }
295
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)
300 {
301         int idx;
302
303         for (idx = 0; idx < nr_plls; idx++, list++) {
304                 struct clk_hw *clk;
305
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;
315                 }
316
317                 visconti_pll_add_lookup(ctx, clk, list->id);
318         }
319 }
320
321 struct visconti_pll_provider * __init visconti_init_pll(struct device_node *np,
322                                                         void __iomem *base,
323                                                         unsigned long nr_plls)
324 {
325         struct visconti_pll_provider *ctx;
326         int i;
327
328         ctx = kzalloc(struct_size(ctx, clk_data.hws, nr_plls), GFP_KERNEL);
329         if (!ctx)
330                 return ERR_PTR(-ENOMEM);
331
332         for (i = 0; i < nr_plls; ++i)
333                 ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
334
335         ctx->node = np;
336         ctx->reg_base = base;
337         ctx->clk_data.num = nr_plls;
338
339         return ctx;
340 }