1 /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
2 /*
3  * Copyright (C) STMicroelectronics 2022 - All Rights Reserved
4  */
5 
6 #ifndef CLK_STM32_CORE_H
7 #define CLK_STM32_CORE_H
8 
9 #include <drivers/clk.h>
10 
11 struct mux_cfg {
12 	uint16_t offset;
13 	uint8_t shift;
14 	uint8_t width;
15 	uint8_t ready;
16 };
17 
18 struct gate_cfg {
19 	uint16_t offset;
20 	uint8_t bit_idx;
21 	uint8_t set_clr;
22 };
23 
24 struct div_table_cfg {
25 	unsigned int val;
26 	unsigned int div;
27 };
28 
29 struct div_cfg {
30 	uint16_t offset;
31 	uint8_t shift;
32 	uint8_t width;
33 	uint8_t flags;
34 	uint8_t ready;
35 	const struct div_table_cfg *table;
36 };
37 
38 struct clk_stm32_priv {
39 	uintptr_t base;
40 	size_t nb_clk_refs;
41 	struct clk **clk_refs;
42 	const struct mux_cfg *muxes;
43 	const uint32_t nb_muxes;
44 	const struct gate_cfg *gates;
45 	const uint32_t nb_gates;
46 	const struct div_cfg *div;
47 	const uint32_t nb_div;
48 	bool (*is_critical)(struct clk *clk);
49 	void *pdata;
50 };
51 
52 struct clk_fixed_rate_cfg {
53 	unsigned long rate;
54 };
55 
56 struct fixed_factor_cfg {
57 	unsigned int mult;
58 	unsigned int div;
59 };
60 
61 struct clk_gate_cfg {
62 	uint32_t offset;
63 	uint8_t bit_idx;
64 };
65 
66 struct clk_stm32_mux_cfg {
67 	int mux_id;
68 };
69 
70 struct clk_stm32_gate_cfg {
71 	int gate_id;
72 };
73 
74 struct clk_stm32_div_cfg {
75 	int div_id;
76 };
77 
78 struct clk_stm32_composite_cfg {
79 	int gate_id;
80 	int div_id;
81 	int mux_id;
82 };
83 
84 struct clk_stm32_timer_cfg {
85 	uint32_t apbdiv;
86 	uint32_t timpre;
87 };
88 
89 struct clk_stm32_gate_ready_cfg {
90 	int gate_id;
91 	int gate_rdy_id;
92 };
93 
94 /* Define for divider clocks */
95 #define CLK_DIVIDER_ONE_BASED		BIT(0)
96 #define CLK_DIVIDER_POWER_OF_TWO	BIT(1)
97 #define CLK_DIVIDER_ALLOW_ZERO		BIT(2)
98 #define CLK_DIVIDER_HIWORD_MASK		BIT(3)
99 #define CLK_DIVIDER_ROUND_CLOSEST	BIT(4)
100 #define CLK_DIVIDER_READ_ONLY		BIT(5)
101 #define CLK_DIVIDER_MAX_AT_ZERO		BIT(6)
102 #define CLK_DIVIDER_BIG_ENDIAN		BIT(7)
103 
104 #define DIV_NO_RDY		UINT8_MAX
105 #define MUX_NO_RDY		UINT8_MAX
106 
107 #define MASK_WIDTH_SHIFT(_width, _shift) \
108 	GENMASK_32(((_width) + (_shift) - 1U), (_shift))
109 
110 /* Define for composite clocks */
111 #define NO_MUX		INT32_MAX
112 #define NO_DIV		INT32_MAX
113 #define NO_GATE		INT32_MAX
114 
115 void stm32_gate_enable(uint16_t gate_id);
116 void stm32_gate_disable(uint16_t gate_id);
117 bool stm32_gate_is_enabled(uint16_t gate_id);
118 TEE_Result stm32_gate_wait_ready(uint16_t gate_id, bool ready_on);
119 TEE_Result stm32_gate_rdy_enable(uint16_t gate_id);
120 TEE_Result stm32_gate_rdy_disable(uint16_t gate_id);
121 
122 size_t stm32_mux_get_parent(uint32_t mux_id);
123 TEE_Result stm32_mux_set_parent(uint16_t pid, uint8_t sel);
124 
125 TEE_Result stm32_div_set_rate(int div_id, unsigned long rate,
126 			      unsigned long prate);
127 
128 uint32_t stm32_div_get_value(int div_id);
129 TEE_Result stm32_div_set_value(uint32_t div_id, uint32_t value);
130 
131 int clk_stm32_parse_fdt_by_name(const void *fdt, int node, const char *name,
132 				uint32_t *tab, uint32_t *nb);
133 
134 unsigned long clk_stm32_divider_get_rate(struct clk *clk,
135 					 unsigned long parent_rate);
136 
137 TEE_Result clk_stm32_divider_set_rate(struct clk *clk,
138 				      unsigned long rate,
139 				      unsigned long parent_rate);
140 
141 size_t clk_stm32_composite_get_parent(struct clk *clk);
142 TEE_Result clk_stm32_composite_set_parent(struct clk *clk, size_t pidx);
143 unsigned long clk_stm32_composite_get_rate(struct clk *clk,
144 					   unsigned long parent_rate);
145 TEE_Result clk_stm32_composite_set_rate(struct clk *clk, unsigned long rate,
146 					unsigned long parent_rate);
147 TEE_Result clk_stm32_composite_gate_enable(struct clk *clk);
148 void clk_stm32_composite_gate_disable(struct clk *clk);
149 
150 TEE_Result clk_stm32_set_parent_by_index(struct clk *clk, size_t pidx);
151 
152 extern const struct clk_ops clk_fixed_factor_ops;
153 extern const struct clk_ops clk_fixed_clk_ops;
154 extern const struct clk_ops clk_stm32_gate_ops;
155 extern const struct clk_ops clk_stm32_gate_ready_ops;
156 extern const struct clk_ops clk_stm32_divider_ops;
157 extern const struct clk_ops clk_stm32_mux_ops;
158 extern const struct clk_ops clk_stm32_composite_ops;
159 
160 #define PARENT(x...) { x }
161 
162 #define STM32_FIXED_RATE(_name, _rate)\
163 	struct clk _name = {\
164 		.ops = &clk_fixed_clk_ops,\
165 		.priv = &(struct clk_fixed_rate_cfg) {\
166 			.rate = (_rate),\
167 		},\
168 		.name = #_name,\
169 		.flags = 0,\
170 		.num_parents = 0,\
171 	}
172 
173 #define STM32_FIXED_FACTOR(_name, _parent, _flags, _mult, _div)\
174 	struct clk _name = {\
175 		.ops = &clk_fixed_factor_ops,\
176 		.priv = &(struct fixed_factor_cfg) {\
177 			.mult = _mult,\
178 			.div = _div,\
179 		},\
180 		.name = #_name,\
181 		.flags = (_flags),\
182 		.num_parents = 1,\
183 		.parents = { (_parent) },\
184 	}
185 
186 #define STM32_GATE(_name, _parent, _flags, _gate_id)\
187 	struct clk _name = {\
188 		.ops = &clk_stm32_gate_ops,\
189 		.priv = &(struct clk_stm32_gate_cfg) {\
190 			.gate_id = _gate_id,\
191 		},\
192 		.name = #_name,\
193 		.flags = (_flags),\
194 		.num_parents = 1,\
195 		.parents = { (_parent) },\
196 	}
197 
198 #define STM32_DIVIDER(_name, _parent, _flags, _div_id)\
199 	struct clk _name = {\
200 		.ops = &clk_stm32_divider_ops,\
201 		.priv = &(struct clk_stm32_div_cfg) {\
202 			.div_id = (_div_id),\
203 		},\
204 		.name = #_name,\
205 		.flags = (_flags),\
206 		.num_parents = 1,\
207 		.parents = { (_parent) },\
208 	}
209 
210 #define STM32_MUX(_name, _nb_parents, _parents, _flags, _mux_id)\
211 	struct clk _name = {\
212 		.ops = &clk_stm32_mux_ops,\
213 		.priv = &(struct clk_stm32_mux_cfg) {\
214 			.mux_id = (_mux_id),\
215 		},\
216 		.name = #_name,\
217 		.flags = (_flags),\
218 		.num_parents = (_nb_parents),\
219 		.parents = _parents,\
220 	}
221 
222 #define STM32_GATE_READY(_name, _parent, _flags, _gate_id)\
223 	struct clk _name = {\
224 		.ops = &clk_stm32_gate_ready_ops,\
225 		.priv = &(struct clk_stm32_gate_cfg) {\
226 			.gate_id = _gate_id,\
227 		},\
228 		.name = #_name,\
229 		.flags = (_flags),\
230 		.num_parents = 1,\
231 		.parents = { _parent },\
232 	}
233 
234 #define STM32_COMPOSITE(_name, _nb_parents, _parents, _flags,\
235 			_gate_id, _div_id, _mux_id)\
236 	struct clk _name = {\
237 		.ops = &clk_stm32_composite_ops,\
238 		.priv = &(struct clk_stm32_composite_cfg) {\
239 			.gate_id = (_gate_id),\
240 			.div_id = (_div_id),\
241 			.mux_id = (_mux_id),\
242 		},\
243 		.name = #_name,\
244 		.flags = (_flags),\
245 		.num_parents = (_nb_parents),\
246 		.parents = _parents,\
247 	}
248 
249 struct clk_stm32_priv *clk_stm32_get_priv(void);
250 uintptr_t clk_stm32_get_rcc_base(void);
251 
252 TEE_Result clk_stm32_init(struct clk_stm32_priv *priv, uintptr_t base);
253 
254 void stm32mp_clk_provider_probe_final(const void *fdt, int node,
255 				      struct clk_stm32_priv *priv);
256 
257 #endif /* CLK_STM32_CORE_H */
258