1 // SPDX-License-Identifier: GPL-2.0-only
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>
11 #include <linux/bitfield.h>
12 #include <linux/clk-provider.h>
13 #include <linux/delay.h>
14 #include <linux/slab.h>
21 void __iomem
*pll_base
;
24 const struct visconti_pll_rate_table
*rate_table
;
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
)
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
,
78 const struct visconti_pll_rate_table
*rate_table
= pll
->rate_table
;
81 for (i
= 0; i
< pll
->rate_count
; i
++)
82 if (rate
== rate_table
[i
].rate
)
83 return &rate_table
[i
];
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
;
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
;
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
;
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
);
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
);
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
);
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
;
173 if (visconti_pll_is_enabled(hw
))
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
);
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
);
188 writel(reg
, pll
->pll_base
+ PLL_CTRL_REG
);
192 reg
= readl(pll
->pll_base
+ PLL_CTRL_REG
);
194 writel(reg
, pll
->pll_base
+ PLL_CTRL_REG
);
198 reg
= readl(pll
->pll_base
+ PLL_CTRL_REG
);
200 writel(reg
, pll
->pll_base
+ PLL_CTRL_REG
);
202 spin_unlock_irqrestore(pll
->lock
, flags
);
207 static void visconti_pll_disable(struct clk_hw
*hw
)
209 struct visconti_pll
*pll
= to_visconti_pll(hw
);
213 if (!visconti_pll_is_enabled(hw
))
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
);
222 writel(reg
, pll
->pll_base
+ PLL_CTRL_REG
);
224 reg
= readl(pll
->pll_base
+ PLL_CTRL_REG
);
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
,
242 const char *parent_name
,
244 const struct visconti_pll_rate_table
*rate_table
,
247 struct clk_init_data init
;
248 struct visconti_pll
*pll
;
249 struct clk_hw
*pll_hw_clk
;
253 pll
= kzalloc(sizeof(*pll
), GFP_KERNEL
);
255 return ERR_PTR(-ENOMEM
);
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; )
264 pll
->rate_count
= len
;
265 pll
->rate_table
= kmemdup_array(rate_table
,
266 pll
->rate_count
, sizeof(*pll
->rate_table
),
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
;
276 pll_hw_clk
= &pll
->hw
;
277 ret
= clk_hw_register(NULL
, &pll
->hw
);
279 pr_err("failed to register pll clock %s : %d\n", name
, ret
);
280 kfree(pll
->rate_table
);
282 pll_hw_clk
= ERR_PTR(ret
);
288 static void visconti_pll_add_lookup(struct visconti_pll_provider
*ctx
,
289 struct clk_hw
*hw_clk
,
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
,
303 for (idx
= 0; idx
< nr_plls
; idx
++, list
++) {
306 clk
= visconti_register_pll(ctx
,
313 pr_err("failed to register clock %s\n", list
->name
);
317 visconti_pll_add_lookup(ctx
, clk
, list
->id
);
321 struct visconti_pll_provider
* __init
visconti_init_pll(struct device_node
*np
,
323 unsigned long nr_plls
)
325 struct visconti_pll_provider
*ctx
;
328 ctx
= kzalloc(struct_size(ctx
, clk_data
.hws
, nr_plls
), GFP_KERNEL
);
330 return ERR_PTR(-ENOMEM
);
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
);