blob: cad07cc952e77cec74f7749b11e25e77e0ef77fd [file] [log] [blame]
Gabriel Fernandez3db088a2022-11-24 11:36:04 +01001// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
2/*
3 * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
4 * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics.
5 */
6
7#define LOG_CATEGORY UCLASS_CLK
8
Gabriel Fernandez3db088a2022-11-24 11:36:04 +01009#include <clk-uclass.h>
10#include <dm.h>
11#include <log.h>
12#include <asm/io.h>
13#include <dm/device_compat.h>
14#include <linux/clk-provider.h>
15#include "clk-stm32-core.h"
16
17int stm32_rcc_init(struct udevice *dev,
18 const struct stm32_clock_match_data *data)
19{
20 int i;
21 u8 *cpt;
22 struct stm32mp_rcc_priv *priv = dev_get_priv(dev);
23 fdt_addr_t base = dev_read_addr(dev->parent);
24 const struct clk_stm32_clock_data *clock_data = data->clock_data;
25
26 if (base == FDT_ADDR_T_NONE)
27 return -EINVAL;
28
29 priv->base = (void __iomem *)base;
30
31 /* allocate the counter of user for internal RCC gates, common for several user */
32 cpt = kzalloc(clock_data->num_gates, GFP_KERNEL);
33 if (!cpt)
34 return -ENOMEM;
35
36 priv->gate_cpt = cpt;
37
38 priv->data = clock_data;
39
40 for (i = 0; i < data->num_clocks; i++) {
41 const struct clock_config *cfg = &data->tab_clocks[i];
42 struct clk *clk = ERR_PTR(-ENOENT);
43
44 if (data->check_security && data->check_security(priv->base, cfg))
45 continue;
46
47 if (cfg->setup) {
48 clk = cfg->setup(dev, cfg);
49 clk->id = cfg->id;
50 } else {
51 dev_err(dev, "failed to register clock %s\n", cfg->name);
52 return -ENOENT;
53 }
54 }
55
56 return 0;
57}
58
59ulong clk_stm32_get_rate_by_name(const char *name)
60{
61 struct udevice *dev;
62
63 if (!uclass_get_device_by_name(UCLASS_CLK, name, &dev)) {
64 struct clk *clk = dev_get_clk_ptr(dev);
65
66 return clk_get_rate(clk);
67 }
68
69 return 0;
70}
71
72const struct clk_ops stm32_clk_ops = {
73 .enable = ccf_clk_enable,
74 .disable = ccf_clk_disable,
75 .get_rate = ccf_clk_get_rate,
76 .set_rate = ccf_clk_set_rate,
77};
78
79#define RCC_MP_ENCLRR_OFFSET 4
80
81static void clk_stm32_gate_set_state(void __iomem *base,
82 const struct clk_stm32_clock_data *data,
83 u8 *cpt, u16 gate_id, int enable)
84{
85 const struct stm32_gate_cfg *gate_cfg = &data->gates[gate_id];
86 void __iomem *addr = base + gate_cfg->reg_off;
87 u8 set_clr = gate_cfg->set_clr ? RCC_MP_ENCLRR_OFFSET : 0;
88
89 if (enable) {
90 if (cpt[gate_id]++ > 0)
91 return;
92
93 if (set_clr)
94 writel(BIT(gate_cfg->bit_idx), addr);
95 else
96 writel(readl(addr) | BIT(gate_cfg->bit_idx), addr);
97 } else {
98 if (--cpt[gate_id] > 0)
99 return;
100
101 if (set_clr)
102 writel(BIT(gate_cfg->bit_idx), addr + set_clr);
103 else
104 writel(readl(addr) & ~BIT(gate_cfg->bit_idx), addr);
105 }
106}
107
108static int clk_stm32_gate_enable(struct clk *clk)
109{
110 struct clk_stm32_gate *stm32_gate = to_clk_stm32_gate(clk);
111 struct stm32mp_rcc_priv *priv = stm32_gate->priv;
112
113 clk_stm32_gate_set_state(priv->base, priv->data, priv->gate_cpt,
114 stm32_gate->gate_id, 1);
115
116 return 0;
117}
118
119static int clk_stm32_gate_disable(struct clk *clk)
120{
121 struct clk_stm32_gate *stm32_gate = to_clk_stm32_gate(clk);
122 struct stm32mp_rcc_priv *priv = stm32_gate->priv;
123
124 clk_stm32_gate_set_state(priv->base, priv->data, priv->gate_cpt,
125 stm32_gate->gate_id, 0);
126
127 return 0;
128}
129
130static const struct clk_ops clk_stm32_gate_ops = {
131 .enable = clk_stm32_gate_enable,
132 .disable = clk_stm32_gate_disable,
133 .get_rate = clk_generic_get_rate,
134};
135
136#define UBOOT_DM_CLK_STM32_GATE "clk_stm32_gate"
137
138U_BOOT_DRIVER(clk_stm32_gate) = {
139 .name = UBOOT_DM_CLK_STM32_GATE,
140 .id = UCLASS_CLK,
141 .ops = &clk_stm32_gate_ops,
142};
143
144struct clk *clk_stm32_gate_register(struct udevice *dev,
145 const struct clock_config *cfg)
146{
147 struct stm32mp_rcc_priv *priv = dev_get_priv(dev);
148 struct stm32_clk_gate_cfg *clk_cfg = cfg->clock_cfg;
149 struct clk_stm32_gate *stm32_gate;
150 struct clk *clk;
151 int ret;
152
153 stm32_gate = kzalloc(sizeof(*stm32_gate), GFP_KERNEL);
154 if (!stm32_gate)
155 return ERR_PTR(-ENOMEM);
156
157 stm32_gate->priv = priv;
158 stm32_gate->gate_id = clk_cfg->gate_id;
159
160 clk = &stm32_gate->clk;
161 clk->flags = cfg->flags;
162
163 ret = clk_register(clk, UBOOT_DM_CLK_STM32_GATE,
164 cfg->name, cfg->parent_name);
165 if (ret) {
166 kfree(stm32_gate);
167 return ERR_PTR(ret);
168 }
169
170 return clk;
171}
172
173struct clk *
174clk_stm32_register_composite(struct udevice *dev,
175 const struct clock_config *cfg)
176{
177 struct stm32_clk_composite_cfg *composite = cfg->clock_cfg;
178 const char *const *parent_names;
179 int num_parents;
180 struct clk *clk = ERR_PTR(-ENOMEM);
181 struct clk_mux *mux = NULL;
182 struct clk_stm32_gate *gate = NULL;
183 struct clk_divider *div = NULL;
184 struct clk *mux_clk = NULL;
185 const struct clk_ops *mux_ops = NULL;
186 struct clk *gate_clk = NULL;
187 const struct clk_ops *gate_ops = NULL;
188 struct clk *div_clk = NULL;
189 const struct clk_ops *div_ops = NULL;
190 struct stm32mp_rcc_priv *priv = dev_get_priv(dev);
191 const struct clk_stm32_clock_data *data = priv->data;
192
193 if (composite->mux_id != NO_STM32_MUX) {
194 const struct stm32_mux_cfg *mux_cfg;
195
196 mux = kzalloc(sizeof(*mux), GFP_KERNEL);
197 if (!mux)
198 goto fail;
199
200 mux_cfg = &data->muxes[composite->mux_id];
201
202 mux->reg = priv->base + mux_cfg->reg_off;
203 mux->shift = mux_cfg->shift;
204 mux->mask = BIT(mux_cfg->width) - 1;
205 mux->num_parents = mux_cfg->num_parents;
206 mux->flags = 0;
207 mux->parent_names = mux_cfg->parent_names;
208
209 mux_clk = &mux->clk;
210 mux_ops = &clk_mux_ops;
211
212 parent_names = mux_cfg->parent_names;
213 num_parents = mux_cfg->num_parents;
214 } else {
215 parent_names = &cfg->parent_name;
216 num_parents = 1;
217 }
218
219 if (composite->div_id != NO_STM32_DIV) {
220 const struct stm32_div_cfg *div_cfg;
221
222 div = kzalloc(sizeof(*div), GFP_KERNEL);
223 if (!div)
224 goto fail;
225
226 div_cfg = &data->dividers[composite->div_id];
227
228 div->reg = priv->base + div_cfg->reg_off;
229 div->shift = div_cfg->shift;
230 div->width = div_cfg->width;
231 div->width = div_cfg->width;
232 div->flags = div_cfg->div_flags;
233 div->table = div_cfg->table;
234
235 div_clk = &div->clk;
236 div_ops = &clk_divider_ops;
237 }
238
239 if (composite->gate_id != NO_STM32_GATE) {
240 gate = kzalloc(sizeof(*gate), GFP_KERNEL);
241 if (!gate)
242 goto fail;
243
244 gate->priv = priv;
245 gate->gate_id = composite->gate_id;
246
247 gate_clk = &gate->clk;
248 gate_ops = &clk_stm32_gate_ops;
249 }
250
251 clk = clk_register_composite(NULL, cfg->name,
252 parent_names, num_parents,
253 mux_clk, mux_ops,
254 div_clk, div_ops,
255 gate_clk, gate_ops,
256 cfg->flags);
257 if (IS_ERR(clk))
258 goto fail;
259
260 return clk;
261
262fail:
263 kfree(gate);
264 kfree(div);
265 kfree(mux);
266 return ERR_CAST(clk);
267}