blob: 3815d7c56fa4b7a9f4f81f94787a75d5788ffbe4 [file] [log] [blame]
Gabriel Fernandez1308d752020-03-11 11:30:34 +01001/*
Gabriel Fernandez56fd5232023-08-21 13:31:47 +02002 * Copyright (C) 2022-2024, STMicroelectronics - All Rights Reserved
Gabriel Fernandez1308d752020-03-11 11:30:34 +01003 *
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 {
Gabriel Fernandez56fd5232023-08-21 13:31:47 +020024 uint16_t val;
25 uint16_t div;
Gabriel Fernandez1308d752020-03-11 11:30:34 +010026};
27
28struct div_cfg {
Gabriel Fernandez56fd5232023-08-21 13:31:47 +020029 const struct clk_div_table *table;
Gabriel Fernandez1308d752020-03-11 11:30:34 +010030 uint16_t offset;
31 uint8_t shift;
32 uint8_t width;
33 uint8_t flags;
34 uint8_t bitrdy;
Gabriel Fernandez1308d752020-03-11 11:30:34 +010035};
36
37struct parent_cfg {
Gabriel Fernandez1308d752020-03-11 11:30:34 +010038 const uint16_t *id_parents;
39 struct mux_cfg *mux;
Gabriel Fernandez56fd5232023-08-21 13:31:47 +020040 uint8_t num_parents;
Gabriel Fernandez1308d752020-03-11 11:30:34 +010041};
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;
Gabriel Fernandez56fd5232023-08-21 13:31:47 +020059 uint8_t ops;
Gabriel Fernandez1308d752020-03-11 11:30:34 +010060 uint8_t flags;
61 void *clock_cfg;
Gabriel Fernandez1308d752020-03-11 11:30:34 +010062};
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;
Gabriel Fernandez56fd5232023-08-21 13:31:47 +020076 uint8_t *gate_refcounts;
Gabriel Fernandez1308d752020-03-11 11:30:34 +010077 void *pdata;
Gabriel Fernandez56fd5232023-08-21 13:31:47 +020078 const struct stm32_clk_ops **ops_array;
Gabriel Fernandez1308d752020-03-11 11:30:34 +010079};
80
81struct stm32_clk_bypass {
82 uint16_t offset;
83 uint8_t bit_byp;
84 uint8_t bit_digbyp;
85};
86
87struct stm32_clk_css {
88 uint16_t offset;
89 uint8_t bit_css;
90};
91
92struct stm32_clk_drive {
93 uint16_t offset;
94 uint8_t drv_shift;
95 uint8_t drv_width;
96 uint8_t drv_default;
97};
98
99struct clk_oscillator_data {
100 const char *name;
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100101 struct stm32_clk_bypass *bypass;
102 struct stm32_clk_css *css;
103 struct stm32_clk_drive *drive;
Gabriel Fernandez56fd5232023-08-21 13:31:47 +0200104 unsigned long frequency;
105 uint16_t id_clk;
106 uint16_t gate_id;
107 uint16_t gate_rdy_id;
108
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100109};
110
111struct clk_fixed_rate {
112 const char *name;
113 unsigned long fixed_rate;
114};
115
116struct clk_gate_cfg {
117 uint32_t offset;
118 uint8_t bit_idx;
119};
120
121/* CLOCK FLAGS */
122#define CLK_IS_CRITICAL BIT(0)
123#define CLK_IGNORE_UNUSED BIT(1)
124#define CLK_SET_RATE_PARENT BIT(2)
125
126#define CLK_DIVIDER_ONE_BASED BIT(0)
127#define CLK_DIVIDER_POWER_OF_TWO BIT(1)
128#define CLK_DIVIDER_ALLOW_ZERO BIT(2)
129#define CLK_DIVIDER_HIWORD_MASK BIT(3)
130#define CLK_DIVIDER_ROUND_CLOSEST BIT(4)
131#define CLK_DIVIDER_READ_ONLY BIT(5)
132#define CLK_DIVIDER_MAX_AT_ZERO BIT(6)
133#define CLK_DIVIDER_BIG_ENDIAN BIT(7)
134
135#define MUX_MAX_PARENTS U(0x8000)
136#define MUX_PARENT_MASK GENMASK(14, 0)
137#define MUX_FLAG U(0x8000)
138#define MUX(mux) ((mux) | MUX_FLAG)
139
140#define NO_GATE 0
141#define _NO_ID UINT16_MAX
142#define CLK_IS_ROOT UINT16_MAX
143#define MUX_NO_BIT_RDY UINT8_MAX
144#define DIV_NO_BIT_RDY UINT8_MAX
145
146#define MASK_WIDTH_SHIFT(_width, _shift) \
147 GENMASK(((_width) + (_shift) - 1U), (_shift))
148
Yann Gautier0d9413e2023-10-25 17:27:13 +0200149void clk_stm32_rcc_regs_lock(void);
150void clk_stm32_rcc_regs_unlock(void);
151
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100152int clk_stm32_init(struct stm32_clk_priv *priv, uintptr_t base);
153void clk_stm32_enable_critical_clocks(void);
154
155struct stm32_clk_priv *clk_stm32_get_priv(void);
156
157int clk_get_index(struct stm32_clk_priv *priv, unsigned long binding_id);
158const struct clk_stm32 *_clk_get(struct stm32_clk_priv *priv, int id);
159
160void clk_oscillator_set_bypass(struct stm32_clk_priv *priv, int id, bool digbyp, bool bypass);
161void clk_oscillator_set_drive(struct stm32_clk_priv *priv, int id, uint8_t lsedrv);
162void clk_oscillator_set_css(struct stm32_clk_priv *priv, int id, bool css);
163
164int _clk_stm32_gate_wait_ready(struct stm32_clk_priv *priv, uint16_t gate_id, bool ready_on);
165
166int clk_oscillator_wait_ready(struct stm32_clk_priv *priv, int id, bool ready_on);
167int clk_oscillator_wait_ready_on(struct stm32_clk_priv *priv, int id);
168int clk_oscillator_wait_ready_off(struct stm32_clk_priv *priv, int id);
169
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100170int clk_stm32_get_counter(unsigned long binding_id);
171
172void _clk_stm32_gate_disable(struct stm32_clk_priv *priv, uint16_t gate_id);
173int _clk_stm32_gate_enable(struct stm32_clk_priv *priv, uint16_t gate_id);
174
175int _clk_stm32_set_parent(struct stm32_clk_priv *priv, int id, int src_id);
176int _clk_stm32_set_parent_by_index(struct stm32_clk_priv *priv, int clk, int sel);
177
178int _clk_stm32_get_parent(struct stm32_clk_priv *priv, int id);
179int _clk_stm32_get_parent_by_index(struct stm32_clk_priv *priv, int clk_id, int idx);
180int _clk_stm32_get_parent_index(struct stm32_clk_priv *priv, int clk_id);
181
182unsigned long _clk_stm32_get_rate(struct stm32_clk_priv *priv, int id);
183unsigned long _clk_stm32_get_parent_rate(struct stm32_clk_priv *priv, int id);
184
185bool _stm32_clk_is_flags(struct stm32_clk_priv *priv, int id, uint8_t flag);
186
187int _clk_stm32_enable(struct stm32_clk_priv *priv, int id);
188void _clk_stm32_disable(struct stm32_clk_priv *priv, int id);
189
190int clk_stm32_enable_call_ops(struct stm32_clk_priv *priv, uint16_t id);
191void clk_stm32_disable_call_ops(struct stm32_clk_priv *priv, uint16_t id);
192
193bool _clk_stm32_is_enabled(struct stm32_clk_priv *priv, int id);
194
195int _clk_stm32_divider_set_rate(struct stm32_clk_priv *priv, int div_id,
196 unsigned long rate, unsigned long parent_rate);
197
198int clk_stm32_divider_set_rate(struct stm32_clk_priv *priv, int id, unsigned long rate,
199 unsigned long prate);
200
201unsigned long _clk_stm32_divider_recalc(struct stm32_clk_priv *priv,
202 int div_id,
203 unsigned long prate);
204
205unsigned long clk_stm32_divider_recalc(struct stm32_clk_priv *priv, int idx,
206 unsigned long prate);
207
208int clk_stm32_gate_enable(struct stm32_clk_priv *priv, int idx);
209void clk_stm32_gate_disable(struct stm32_clk_priv *priv, int idx);
210
211bool _clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int gate_id);
212bool clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int idx);
213
214uint32_t clk_stm32_div_get_value(struct stm32_clk_priv *priv, int div_id);
215int clk_stm32_set_div(struct stm32_clk_priv *priv, uint32_t div_id, uint32_t value);
216int clk_mux_set_parent(struct stm32_clk_priv *priv, uint16_t pid, uint8_t sel);
217int clk_mux_get_parent(struct stm32_clk_priv *priv, uint32_t mux_id);
218
219int stm32_clk_parse_fdt_by_name(void *fdt, int node, const char *name, uint32_t *tab, uint32_t *nb);
220
221#ifdef CFG_STM32_CLK_DEBUG
222void clk_stm32_display_clock_info(void);
223#endif
224
225struct clk_stm32_div_cfg {
Gabriel Fernandez56fd5232023-08-21 13:31:47 +0200226 uint8_t id;
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100227};
228
229#define STM32_DIV(idx, _binding, _parent, _flags, _div_id) \
230 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100231 .binding = (_binding),\
232 .parent = (_parent),\
233 .flags = (_flags),\
234 .clock_cfg = &(struct clk_stm32_div_cfg){\
235 .id = (_div_id),\
236 },\
Gabriel Fernandez56fd5232023-08-21 13:31:47 +0200237 .ops = STM32_DIVIDER_OPS,\
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100238 }
239
240struct clk_stm32_gate_cfg {
Gabriel Fernandez56fd5232023-08-21 13:31:47 +0200241 uint8_t id;
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100242};
243
244#define STM32_GATE(idx, _binding, _parent, _flags, _gate_id) \
245 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100246 .binding = (_binding),\
247 .parent = (_parent),\
248 .flags = (_flags),\
249 .clock_cfg = &(struct clk_stm32_gate_cfg){\
250 .id = (_gate_id),\
251 },\
Gabriel Fernandez56fd5232023-08-21 13:31:47 +0200252 .ops = STM32_GATE_OPS,\
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100253 }
254
255struct fixed_factor_cfg {
Gabriel Fernandez56fd5232023-08-21 13:31:47 +0200256 uint8_t mult;
257 uint8_t div;
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100258};
259
260unsigned long fixed_factor_recalc_rate(struct stm32_clk_priv *priv,
261 int _idx, unsigned long prate);
262
263#define FIXED_FACTOR(idx, _idx, _parent, _mult, _div) \
264 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100265 .binding = (_idx),\
266 .parent = (_parent),\
267 .clock_cfg = &(struct fixed_factor_cfg){\
268 .mult = (_mult),\
269 .div = (_div),\
270 },\
Gabriel Fernandez56fd5232023-08-21 13:31:47 +0200271 .ops = FIXED_FACTOR_OPS,\
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100272 }
273
274#define GATE(idx, _binding, _parent, _flags, _offset, _bit_idx) \
275 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100276 .binding = (_binding),\
277 .parent = (_parent),\
278 .flags = (_flags),\
279 .clock_cfg = &(struct clk_gate_cfg){\
280 .offset = (_offset),\
281 .bit_idx = (_bit_idx),\
282 },\
Gabriel Fernandez56fd5232023-08-21 13:31:47 +0200283 .ops = GATE_OPS,\
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100284 }
285
286#define STM32_MUX(idx, _binding, _mux_id, _flags) \
287 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100288 .binding = (_binding),\
289 .parent = (MUX(_mux_id)),\
290 .flags = (_flags),\
291 .clock_cfg = NULL,\
Gabriel Fernandez56fd5232023-08-21 13:31:47 +0200292 .ops = STM32_MUX_OPS\
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100293 }
294
295struct clk_timer_cfg {
296 uint32_t apbdiv;
297 uint32_t timpre;
298};
299
300#define CK_TIMER(idx, _idx, _parent, _flags, _apbdiv, _timpre) \
301 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100302 .binding = (_idx),\
303 .parent = (_parent),\
304 .flags = (CLK_SET_RATE_PARENT | (_flags)),\
305 .clock_cfg = &(struct clk_timer_cfg){\
306 .apbdiv = (_apbdiv),\
307 .timpre = (_timpre),\
308 },\
Gabriel Fernandez56fd5232023-08-21 13:31:47 +0200309 .ops = STM32_TIMER_OPS,\
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100310 }
311
312struct clk_stm32_fixed_rate_cfg {
313 unsigned long rate;
314};
315
316#define CLK_FIXED_RATE(idx, _binding, _rate) \
317 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100318 .binding = (_binding),\
319 .parent = (CLK_IS_ROOT),\
320 .clock_cfg = &(struct clk_stm32_fixed_rate_cfg){\
321 .rate = (_rate),\
322 },\
Gabriel Fernandez56fd5232023-08-21 13:31:47 +0200323 .ops = STM32_FIXED_RATE_OPS,\
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100324 }
325
326#define BYPASS(_offset, _bit_byp, _bit_digbyp) &(struct stm32_clk_bypass){\
327 .offset = (_offset),\
328 .bit_byp = (_bit_byp),\
329 .bit_digbyp = (_bit_digbyp),\
330}
331
332#define CSS(_offset, _bit_css) &(struct stm32_clk_css){\
333 .offset = (_offset),\
334 .bit_css = (_bit_css),\
335}
336
337#define DRIVE(_offset, _shift, _width, _default) &(struct stm32_clk_drive){\
338 .offset = (_offset),\
339 .drv_shift = (_shift),\
340 .drv_width = (_width),\
341 .drv_default = (_default),\
342}
343
344#define OSCILLATOR(idx_osc, _id, _name, _gate_id, _gate_rdy_id, _bypass, _css, _drive) \
345 [(idx_osc)] = (struct clk_oscillator_data){\
346 .name = (_name),\
347 .id_clk = (_id),\
348 .gate_id = (_gate_id),\
349 .gate_rdy_id = (_gate_rdy_id),\
350 .bypass = (_bypass),\
351 .css = (_css),\
352 .drive = (_drive),\
353 }
354
355struct clk_oscillator_data *clk_oscillator_get_data(struct stm32_clk_priv *priv, int id);
356
357void clk_stm32_osc_init(struct stm32_clk_priv *priv, int id);
358bool clk_stm32_osc_gate_is_enabled(struct stm32_clk_priv *priv, int id);
359int clk_stm32_osc_gate_enable(struct stm32_clk_priv *priv, int id);
360void clk_stm32_osc_gate_disable(struct stm32_clk_priv *priv, int id);
361
362struct stm32_osc_cfg {
Gabriel Fernandez56fd5232023-08-21 13:31:47 +0200363 uint8_t osc_id;
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100364};
365
366#define CLK_OSC(idx, _idx, _parent, _osc_id) \
367 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100368 .binding = (_idx),\
369 .parent = (_parent),\
370 .flags = CLK_IS_CRITICAL,\
371 .clock_cfg = &(struct stm32_osc_cfg){\
372 .osc_id = (_osc_id),\
373 },\
Gabriel Fernandez56fd5232023-08-21 13:31:47 +0200374 .ops = STM32_OSC_OPS,\
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100375 }
376
377#define CLK_OSC_FIXED(idx, _idx, _parent, _osc_id) \
378 [(idx)] = (struct clk_stm32){ \
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100379 .binding = (_idx),\
380 .parent = (_parent),\
381 .flags = CLK_IS_CRITICAL,\
382 .clock_cfg = &(struct stm32_osc_cfg){\
383 .osc_id = (_osc_id),\
384 },\
Gabriel Fernandez56fd5232023-08-21 13:31:47 +0200385 .ops = STM32_OSC_NOGATE_OPS,\
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100386 }
387
388extern const struct stm32_clk_ops clk_mux_ops;
389extern const struct stm32_clk_ops clk_stm32_divider_ops;
390extern const struct stm32_clk_ops clk_stm32_gate_ops;
391extern const struct stm32_clk_ops clk_fixed_factor_ops;
392extern const struct stm32_clk_ops clk_gate_ops;
393extern const struct stm32_clk_ops clk_timer_ops;
394extern const struct stm32_clk_ops clk_stm32_fixed_rate_ops;
395extern const struct stm32_clk_ops clk_stm32_osc_ops;
396extern const struct stm32_clk_ops clk_stm32_osc_nogate_ops;
397
Gabriel Fernandez56fd5232023-08-21 13:31:47 +0200398enum {
399 NO_OPS,
400 FIXED_FACTOR_OPS,
401 GATE_OPS,
402 STM32_MUX_OPS,
403 STM32_DIVIDER_OPS,
404 STM32_GATE_OPS,
405 STM32_TIMER_OPS,
406 STM32_FIXED_RATE_OPS,
407 STM32_OSC_OPS,
408 STM32_OSC_NOGATE_OPS,
409
410 STM32_LAST_OPS
411};
412
Gabriel Fernandez1308d752020-03-11 11:30:34 +0100413#endif /* CLK_STM32_CORE_H */