blob: 8bfb5134f44b174524c6db704c1de8b1f19856c0 [file] [log] [blame]
Gabriel Fernandez1308d752020-03-11 11:30:34 +01001/*
2 * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
3 *
4 * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
5 */
6
7#ifndef CLK_STM32_CORE_H
8#define CLK_STM32_CORE_H
9
10struct mux_cfg {
11 uint16_t offset;
12 uint8_t shift;
13 uint8_t width;
14 uint8_t bitrdy;
15};
16
17struct gate_cfg {
18 uint16_t offset;
19 uint8_t bit_idx;
20 uint8_t set_clr;
21};
22
23struct clk_div_table {
24 unsigned int val;
25 unsigned int div;
26};
27
28struct div_cfg {
29 uint16_t offset;
30 uint8_t shift;
31 uint8_t width;
32 uint8_t flags;
33 uint8_t bitrdy;
34 const struct clk_div_table *table;
35};
36
37struct parent_cfg {
38 uint8_t num_parents;
39 const uint16_t *id_parents;
40 struct mux_cfg *mux;
41};
42
43struct stm32_clk_priv;
44
45struct stm32_clk_ops {
46 unsigned long (*recalc_rate)(struct stm32_clk_priv *priv, int id, unsigned long rate);
47 int (*get_parent)(struct stm32_clk_priv *priv, int id);
48 int (*set_rate)(struct stm32_clk_priv *priv, int id, unsigned long rate,
49 unsigned long prate);
50 int (*enable)(struct stm32_clk_priv *priv, int id);
51 void (*disable)(struct stm32_clk_priv *priv, int id);
52 bool (*is_enabled)(struct stm32_clk_priv *priv, int id);
53 void (*init)(struct stm32_clk_priv *priv, int id);
54};
55
56struct clk_stm32 {
Gabriel Fernandez1308d752020-03-11 11:30:34 +010057 uint16_t binding;
58 uint16_t parent;
59 uint8_t flags;
60 void *clock_cfg;
61 const struct stm32_clk_ops *ops;
62};
63
64struct stm32_clk_priv {
65 uintptr_t base;
66 const uint32_t num;
67 const struct clk_stm32 *clks;
68 const struct parent_cfg *parents;
69 const uint32_t nb_parents;
70 const struct gate_cfg *gates;
71 const uint32_t nb_gates;
72 const struct div_cfg *div;
73 const uint32_t nb_div;
74 struct clk_oscillator_data *osci_data;
75 const uint32_t nb_osci_data;
76 uint32_t *gate_refcounts;
77 void *pdata;
78};
79
80struct stm32_clk_bypass {
81 uint16_t offset;
82 uint8_t bit_byp;
83 uint8_t bit_digbyp;
84};
85
86struct stm32_clk_css {
87 uint16_t offset;
88 uint8_t bit_css;
89};
90
91struct stm32_clk_drive {
92 uint16_t offset;
93 uint8_t drv_shift;
94 uint8_t drv_width;
95 uint8_t drv_default;
96};
97
98struct clk_oscillator_data {
99 const char *name;
100 uint16_t id_clk;
101 unsigned long frequency;
102 uint16_t gate_id;
103 uint16_t gate_rdy_id;
104 struct stm32_clk_bypass *bypass;
105 struct stm32_clk_css *css;
106 struct stm32_clk_drive *drive;
107};
108
109struct clk_fixed_rate {
110 const char *name;
111 unsigned long fixed_rate;
112};
113
114struct clk_gate_cfg {
115 uint32_t offset;
116 uint8_t bit_idx;
117};
118
119/* CLOCK FLAGS */
120#define CLK_IS_CRITICAL BIT(0)
121#define CLK_IGNORE_UNUSED BIT(1)
122#define CLK_SET_RATE_PARENT BIT(2)
123
124#define CLK_DIVIDER_ONE_BASED BIT(0)
125#define CLK_DIVIDER_POWER_OF_TWO BIT(1)
126#define CLK_DIVIDER_ALLOW_ZERO BIT(2)
127#define CLK_DIVIDER_HIWORD_MASK BIT(3)
128#define CLK_DIVIDER_ROUND_CLOSEST BIT(4)
129#define CLK_DIVIDER_READ_ONLY BIT(5)
130#define CLK_DIVIDER_MAX_AT_ZERO BIT(6)
131#define CLK_DIVIDER_BIG_ENDIAN BIT(7)
132
133#define MUX_MAX_PARENTS U(0x8000)
134#define MUX_PARENT_MASK GENMASK(14, 0)
135#define MUX_FLAG U(0x8000)
136#define MUX(mux) ((mux) | MUX_FLAG)
137
138#define NO_GATE 0
139#define _NO_ID UINT16_MAX
140#define CLK_IS_ROOT UINT16_MAX
141#define MUX_NO_BIT_RDY UINT8_MAX
142#define DIV_NO_BIT_RDY UINT8_MAX
143
144#define MASK_WIDTH_SHIFT(_width, _shift) \
145 GENMASK(((_width) + (_shift) - 1U), (_shift))
146
147int clk_stm32_init(struct stm32_clk_priv *priv, uintptr_t base);
148void clk_stm32_enable_critical_clocks(void);
149
150struct stm32_clk_priv *clk_stm32_get_priv(void);
151
152int clk_get_index(struct stm32_clk_priv *priv, unsigned long binding_id);
153const struct clk_stm32 *_clk_get(struct stm32_clk_priv *priv, int id);
154
155void clk_oscillator_set_bypass(struct stm32_clk_priv *priv, int id, bool digbyp, bool bypass);
156void clk_oscillator_set_drive(struct stm32_clk_priv *priv, int id, uint8_t lsedrv);
157void clk_oscillator_set_css(struct stm32_clk_priv *priv, int id, bool css);
158
159int _clk_stm32_gate_wait_ready(struct stm32_clk_priv *priv, uint16_t gate_id, bool ready_on);
160
161int clk_oscillator_wait_ready(struct stm32_clk_priv *priv, int id, bool ready_on);
162int clk_oscillator_wait_ready_on(struct stm32_clk_priv *priv, int id);
163int clk_oscillator_wait_ready_off(struct stm32_clk_priv *priv, int id);
164
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100165int clk_stm32_get_counter(unsigned long binding_id);
166
167void _clk_stm32_gate_disable(struct stm32_clk_priv *priv, uint16_t gate_id);
168int _clk_stm32_gate_enable(struct stm32_clk_priv *priv, uint16_t gate_id);
169
170int _clk_stm32_set_parent(struct stm32_clk_priv *priv, int id, int src_id);
171int _clk_stm32_set_parent_by_index(struct stm32_clk_priv *priv, int clk, int sel);
172
173int _clk_stm32_get_parent(struct stm32_clk_priv *priv, int id);
174int _clk_stm32_get_parent_by_index(struct stm32_clk_priv *priv, int clk_id, int idx);
175int _clk_stm32_get_parent_index(struct stm32_clk_priv *priv, int clk_id);
176
177unsigned long _clk_stm32_get_rate(struct stm32_clk_priv *priv, int id);
178unsigned long _clk_stm32_get_parent_rate(struct stm32_clk_priv *priv, int id);
179
180bool _stm32_clk_is_flags(struct stm32_clk_priv *priv, int id, uint8_t flag);
181
182int _clk_stm32_enable(struct stm32_clk_priv *priv, int id);
183void _clk_stm32_disable(struct stm32_clk_priv *priv, int id);
184
185int clk_stm32_enable_call_ops(struct stm32_clk_priv *priv, uint16_t id);
186void clk_stm32_disable_call_ops(struct stm32_clk_priv *priv, uint16_t id);
187
188bool _clk_stm32_is_enabled(struct stm32_clk_priv *priv, int id);
189
190int _clk_stm32_divider_set_rate(struct stm32_clk_priv *priv, int div_id,
191 unsigned long rate, unsigned long parent_rate);
192
193int clk_stm32_divider_set_rate(struct stm32_clk_priv *priv, int id, unsigned long rate,
194 unsigned long prate);
195
196unsigned long _clk_stm32_divider_recalc(struct stm32_clk_priv *priv,
197 int div_id,
198 unsigned long prate);
199
200unsigned long clk_stm32_divider_recalc(struct stm32_clk_priv *priv, int idx,
201 unsigned long prate);
202
203int clk_stm32_gate_enable(struct stm32_clk_priv *priv, int idx);
204void clk_stm32_gate_disable(struct stm32_clk_priv *priv, int idx);
205
206bool _clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int gate_id);
207bool clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int idx);
208
209uint32_t clk_stm32_div_get_value(struct stm32_clk_priv *priv, int div_id);
210int clk_stm32_set_div(struct stm32_clk_priv *priv, uint32_t div_id, uint32_t value);
211int clk_mux_set_parent(struct stm32_clk_priv *priv, uint16_t pid, uint8_t sel);
212int clk_mux_get_parent(struct stm32_clk_priv *priv, uint32_t mux_id);
213
214int stm32_clk_parse_fdt_by_name(void *fdt, int node, const char *name, uint32_t *tab, uint32_t *nb);
215
216#ifdef CFG_STM32_CLK_DEBUG
217void clk_stm32_display_clock_info(void);
218#endif
219
220struct clk_stm32_div_cfg {
221 int id;
222};
223
224#define STM32_DIV(idx, _binding, _parent, _flags, _div_id) \
225 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100226 .binding = (_binding),\
227 .parent = (_parent),\
228 .flags = (_flags),\
229 .clock_cfg = &(struct clk_stm32_div_cfg){\
230 .id = (_div_id),\
231 },\
232 .ops = &clk_stm32_divider_ops,\
233 }
234
235struct clk_stm32_gate_cfg {
236 int id;
237};
238
239#define STM32_GATE(idx, _binding, _parent, _flags, _gate_id) \
240 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100241 .binding = (_binding),\
242 .parent = (_parent),\
243 .flags = (_flags),\
244 .clock_cfg = &(struct clk_stm32_gate_cfg){\
245 .id = (_gate_id),\
246 },\
247 .ops = &clk_stm32_gate_ops,\
248 }
249
250struct fixed_factor_cfg {
251 unsigned int mult;
252 unsigned int div;
253};
254
255unsigned long fixed_factor_recalc_rate(struct stm32_clk_priv *priv,
256 int _idx, unsigned long prate);
257
258#define FIXED_FACTOR(idx, _idx, _parent, _mult, _div) \
259 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100260 .binding = (_idx),\
261 .parent = (_parent),\
262 .clock_cfg = &(struct fixed_factor_cfg){\
263 .mult = (_mult),\
264 .div = (_div),\
265 },\
266 .ops = &clk_fixed_factor_ops,\
267 }
268
269#define GATE(idx, _binding, _parent, _flags, _offset, _bit_idx) \
270 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100271 .binding = (_binding),\
272 .parent = (_parent),\
273 .flags = (_flags),\
274 .clock_cfg = &(struct clk_gate_cfg){\
275 .offset = (_offset),\
276 .bit_idx = (_bit_idx),\
277 },\
278 .ops = &clk_gate_ops,\
279 }
280
281#define STM32_MUX(idx, _binding, _mux_id, _flags) \
282 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100283 .binding = (_binding),\
284 .parent = (MUX(_mux_id)),\
285 .flags = (_flags),\
286 .clock_cfg = NULL,\
287 .ops = (&clk_mux_ops),\
288 }
289
290struct clk_timer_cfg {
291 uint32_t apbdiv;
292 uint32_t timpre;
293};
294
295#define CK_TIMER(idx, _idx, _parent, _flags, _apbdiv, _timpre) \
296 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100297 .binding = (_idx),\
298 .parent = (_parent),\
299 .flags = (CLK_SET_RATE_PARENT | (_flags)),\
300 .clock_cfg = &(struct clk_timer_cfg){\
301 .apbdiv = (_apbdiv),\
302 .timpre = (_timpre),\
303 },\
304 .ops = &clk_timer_ops,\
305 }
306
307struct clk_stm32_fixed_rate_cfg {
308 unsigned long rate;
309};
310
311#define CLK_FIXED_RATE(idx, _binding, _rate) \
312 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100313 .binding = (_binding),\
314 .parent = (CLK_IS_ROOT),\
315 .clock_cfg = &(struct clk_stm32_fixed_rate_cfg){\
316 .rate = (_rate),\
317 },\
318 .ops = &clk_stm32_fixed_rate_ops,\
319 }
320
321#define BYPASS(_offset, _bit_byp, _bit_digbyp) &(struct stm32_clk_bypass){\
322 .offset = (_offset),\
323 .bit_byp = (_bit_byp),\
324 .bit_digbyp = (_bit_digbyp),\
325}
326
327#define CSS(_offset, _bit_css) &(struct stm32_clk_css){\
328 .offset = (_offset),\
329 .bit_css = (_bit_css),\
330}
331
332#define DRIVE(_offset, _shift, _width, _default) &(struct stm32_clk_drive){\
333 .offset = (_offset),\
334 .drv_shift = (_shift),\
335 .drv_width = (_width),\
336 .drv_default = (_default),\
337}
338
339#define OSCILLATOR(idx_osc, _id, _name, _gate_id, _gate_rdy_id, _bypass, _css, _drive) \
340 [(idx_osc)] = (struct clk_oscillator_data){\
341 .name = (_name),\
342 .id_clk = (_id),\
343 .gate_id = (_gate_id),\
344 .gate_rdy_id = (_gate_rdy_id),\
345 .bypass = (_bypass),\
346 .css = (_css),\
347 .drive = (_drive),\
348 }
349
350struct clk_oscillator_data *clk_oscillator_get_data(struct stm32_clk_priv *priv, int id);
351
352void clk_stm32_osc_init(struct stm32_clk_priv *priv, int id);
353bool clk_stm32_osc_gate_is_enabled(struct stm32_clk_priv *priv, int id);
354int clk_stm32_osc_gate_enable(struct stm32_clk_priv *priv, int id);
355void clk_stm32_osc_gate_disable(struct stm32_clk_priv *priv, int id);
356
357struct stm32_osc_cfg {
358 int osc_id;
359};
360
361#define CLK_OSC(idx, _idx, _parent, _osc_id) \
362 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100363 .binding = (_idx),\
364 .parent = (_parent),\
365 .flags = CLK_IS_CRITICAL,\
366 .clock_cfg = &(struct stm32_osc_cfg){\
367 .osc_id = (_osc_id),\
368 },\
369 .ops = &clk_stm32_osc_ops,\
370 }
371
372#define CLK_OSC_FIXED(idx, _idx, _parent, _osc_id) \
373 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100374 .binding = (_idx),\
375 .parent = (_parent),\
376 .flags = CLK_IS_CRITICAL,\
377 .clock_cfg = &(struct stm32_osc_cfg){\
378 .osc_id = (_osc_id),\
379 },\
380 .ops = &clk_stm32_osc_nogate_ops,\
381 }
382
383extern const struct stm32_clk_ops clk_mux_ops;
384extern const struct stm32_clk_ops clk_stm32_divider_ops;
385extern const struct stm32_clk_ops clk_stm32_gate_ops;
386extern const struct stm32_clk_ops clk_fixed_factor_ops;
387extern const struct stm32_clk_ops clk_gate_ops;
388extern const struct stm32_clk_ops clk_timer_ops;
389extern const struct stm32_clk_ops clk_stm32_fixed_rate_ops;
390extern const struct stm32_clk_ops clk_stm32_osc_ops;
391extern const struct stm32_clk_ops clk_stm32_osc_nogate_ops;
392
393#endif /* CLK_STM32_CORE_H */