jh71x0_clkc.h revision 1.5 1 /* $NetBSD: jh71x0_clkc.h,v 1.5 2024/10/12 18:07:24 skrll Exp $ */
2
3 /*-
4 * Copyright (c) 2023 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Nick Hudson
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #ifndef _STARFIVE_JH71X0CLKC_H
33 #define _STARFIVE_JH71X0CLKC_H
34
35 #include <dev/clk/clk_backend.h>
36 #include <dev/fdt/syscon.h>
37
38 /*
39 * Each clock has a 32-bit register indexed from the register base with
40 * the following bit field definitions depending on type.
41 */
42
43 /* register fields */
44 #define JH71X0_CLK_ENABLE __BIT(31)
45 #define JH71X0_CLK_INVERT __BIT(30)
46 #define JH71X0_CLK_MUX_MASK __BITS(27, 24)
47 #define JH71X0_CLK_DIV_MASK __BITS(23, 0)
48 #define JH71X0_CLK_FRAC_MASK __BITS(15, 8)
49 #define JH71X0_CLK_INT_MASK __BITS(7, 0)
50
51 /* fractional divider min/max */
52 #define JH71X0_CLK_FRAC_MIN 100UL
53 #define JH71X0_CLK_FRAC_MAX (26600UL - 1)
54
55
56 struct jh71x0_clkc_clk;
57
58 struct jh71x0_clkc_softc {
59 device_t sc_dev;
60 bus_space_tag_t sc_bst;
61 bus_space_handle_t sc_bsh;
62 int sc_phandle;
63 struct clk_domain sc_clkdom;
64
65 struct jh71x0_clkc_clk *sc_clk;
66 size_t sc_nclks;
67
68 // JH7110 only
69 size_t sc_nrsts;
70 bus_size_t sc_reset_assert;
71 bus_size_t sc_reset_status;
72
73 kmutex_t sc_lock;
74 };
75
76 struct jh71x0_clkc_clk;
77
78 // MDIV
79
80 enum jh71x0_clkc_clktype {
81 JH71X0CLK_UNKNOWN,
82 JH71X0CLK_FIXED_FACTOR,
83 JH71X0CLK_GATE,
84 JH71X0CLK_DIV,
85 JH71X0CLK_FRACDIV,
86 JH71X0CLK_MUX,
87 JH71X0CLK_MUXDIV,
88 JH71X0CLK_INV,
89 };
90
91 /*
92 * Fixed-factor clocks
93 */
94
95 struct jh71x0_clkc_fixed_factor {
96 const char * jcff_parent;
97 u_int jcff_div;
98 u_int jcff_mult;
99 };
100
101 u_int jh71x0_clkc_fixed_factor_get_rate(struct jh71x0_clkc_softc *,
102 struct jh71x0_clkc_clk *);
103 int jh71x0_clkc_fixed_factor_set_rate(struct jh71x0_clkc_softc *,
104 struct jh71x0_clkc_clk *, u_int);
105 const char *
106 jh71x0_clkc_fixed_factor_get_parent(struct jh71x0_clkc_softc *,
107 struct jh71x0_clkc_clk *);
108
109 extern struct jh71x0_clkc_clkops jh71x0_clkc_ffactor_ops;
110
111 #define JH71X0CLKC_FIXED_FACTOR(_id, _name, _parent, _div, _mult) \
112 [_id] = { \
113 .jcc_type = JH71X0CLK_FIXED_FACTOR, \
114 .jcc_clk.name = (_name), \
115 .jcc_ffactor.jcff_parent = (_parent), \
116 .jcc_ffactor.jcff_div = (_div), \
117 .jcc_ffactor.jcff_mult = (_mult), \
118 .jcc_ops = &jh71x0_clkc_ffactor_ops, \
119 }
120
121 /*
122 * Gate clocks
123 */
124
125 struct jh71x0_clkc_gate {
126 const char *jcg_parent;
127 };
128
129 int jh71x0_clkc_gate_enable(struct jh71x0_clkc_softc *,
130 struct jh71x0_clkc_clk *, int);
131 const char *
132 jh71x0_clkc_gate_get_parent(struct jh71x0_clkc_softc *,
133 struct jh71x0_clkc_clk *);
134
135 extern struct jh71x0_clkc_clkops jh71x0_clkc_gate_ops;
136
137 #define JH71X0CLKC_GATE(_id, _name, _pname) \
138 [_id] = { \
139 .jcc_type = JH71X0CLK_GATE, \
140 .jcc_clk = { \
141 .name = (_name), \
142 .flags = CLK_SET_RATE_PARENT, \
143 }, \
144 .jcc_reg = (_id) * sizeof(uint32_t), \
145 .jcc_gate.jcg_parent = (_pname), \
146 .jcc_ops = &jh71x0_clkc_gate_ops, \
147 }
148
149 /*
150 * Divider clocks
151 */
152
153 struct jh71x0_clkc_div {
154 bus_size_t jcd_reg;
155 const char * jcd_parent;
156 uint32_t jcd_maxdiv;
157 uint32_t jcd_flags;
158 #define JH71X0CLKC_DIV_GATE __BIT(0)
159 };
160
161 u_int jh71x0_clkc_div_get_rate(struct jh71x0_clkc_softc *,
162 struct jh71x0_clkc_clk *);
163 int jh71x0_clkc_div_set_rate(struct jh71x0_clkc_softc *,
164 struct jh71x0_clkc_clk *, u_int);
165 const char *
166 jh71x0_clkc_div_get_parent(struct jh71x0_clkc_softc *,
167 struct jh71x0_clkc_clk *);
168
169 extern struct jh71x0_clkc_clkops jh71x0_clkc_div_ops;
170
171 #define JH71X0CLKC_DIV_FLAGS(_id, _name, _maxdiv, _parent, _flags) \
172 [_id] = { \
173 .jcc_type = JH71X0CLK_DIV, \
174 .jcc_clk = { \
175 .name = (_name), \
176 }, \
177 .jcc_reg = (_id) * sizeof(uint32_t), \
178 .jcc_div = { \
179 .jcd_parent = (_parent), \
180 .jcd_maxdiv = (_maxdiv), \
181 .jcd_flags = (_flags), \
182 }, \
183 .jcc_ops = &jh71x0_clkc_div_ops, \
184 }
185
186 #define JH71X0CLKC_DIV(_id, _n, _m, _p) \
187 JH71X0CLKC_DIV_FLAGS((_id), (_n), (_m), (_p), 0)
188
189 #define JH71X0CLKC_GATEDIV(_id, _n, _m, _p) \
190 JH71X0CLKC_DIV_FLAGS((_id), (_n), (_m), (_p), JH71X0CLKC_DIV_GATE)
191
192 /*
193 * Fractional Divider clocks
194 */
195
196 struct jh71x0_clkc_fracdiv {
197 bus_size_t jcd_reg;
198 const char * jcd_parent;
199 uint32_t jcd_flags;
200 #define JH71X0CLKC_DIV_GATE __BIT(0)
201 };
202
203 u_int jh71x0_clkc_fracdiv_get_rate(struct jh71x0_clkc_softc *,
204 struct jh71x0_clkc_clk *);
205 int jh71x0_clkc_fracdiv_set_rate(struct jh71x0_clkc_softc *,
206 struct jh71x0_clkc_clk *, u_int);
207 const char *
208 jh71x0_clkc_fracdiv_get_parent(struct jh71x0_clkc_softc *,
209 struct jh71x0_clkc_clk *);
210
211 extern struct jh71x0_clkc_clkops jh71x0_clkc_fracdiv_ops;
212
213 #define JH71X0CLKC_FRACDIV(_id, _name, _parent) \
214 [_id] = { \
215 .jcc_type = JH71X0CLK_FRACDIV, \
216 .jcc_clk = { \
217 .name = (_name), \
218 }, \
219 .jcc_reg = (_id) * sizeof(uint32_t), \
220 .jcc_fracdiv = { \
221 .jcd_parent = (_parent), \
222 }, \
223 .jcc_ops = &jh71x0_clkc_fracdiv_ops, \
224 }
225
226
227 /*
228 * Mux clocks
229 */
230
231 struct jh71x0_clkc_mux {
232 size_t jcm_nparents;
233 const char ** jcm_parents;
234 uint32_t jcm_flags;
235 #define JH71X0CLKC_MUX_GATE __BIT(0)
236 };
237
238 int jh71x0_clkc_mux_set_parent(struct jh71x0_clkc_softc *,
239 struct jh71x0_clkc_clk *, const char *);
240 const char *
241 jh71x0_clkc_mux_get_parent(struct jh71x0_clkc_softc *,
242 struct jh71x0_clkc_clk *);
243
244 extern struct jh71x0_clkc_clkops jh71x0_clkc_mux_ops;
245
246 #define JH71X0CLKC_MUX_FLAGSX2(_id, _name, _parents, _cflags, _mflags) \
247 [_id] = { \
248 .jcc_type = JH71X0CLK_MUX, \
249 .jcc_clk = { \
250 .name = (_name), \
251 .flags = (_cflags), \
252 }, \
253 .jcc_reg = (_id) * sizeof(uint32_t), \
254 .jcc_mux = { \
255 .jcm_parents = (_parents), \
256 .jcm_nparents = __arraycount(_parents), \
257 .jcm_flags = (_mflags), \
258 }, \
259 .jcc_ops = &jh71x0_clkc_mux_ops, \
260 }
261
262 #define JH71X0CLKC_MUX(_id, _n, _p) \
263 JH71X0CLKC_MUX_FLAGSX2((_id), (_n), (_p), 0, 0)
264
265 #define JH71X0CLKC_MUX_FLAGS(_id, _n, _p, _f) \
266 JH71X0CLKC_MUX_FLAGSX2((_id), (_n), (_p), (_f), 0)
267
268 #define JH71X0CLKC_MUXGATE(_id, _n, _p) \
269 JH71X0CLKC_MUX_FLAGSX2((_id), (_n), (_p), 0, JH71X0CLKC_MUX_GATE)
270
271 #define JH71X0CLKC_MUXGATE_FLAGS(_id, _n, _p, _f) \
272 JH71X0CLKC_MUX_FLAGSX2((_id), (_n), (_p), (_f), JH71X0CLKC_MUX_GATE)
273
274
275
276 /*
277 * Mux divider clocks
278 */
279
280 struct jh71x0_clkc_muxdiv {
281 size_t jcmd_nparents;
282 const char ** jcmd_parents;
283 uint32_t jcmd_maxdiv;
284 uint32_t jcmd_flags;
285 #define JH71X0CLKC_MUXDIV_GATE __BIT(0)
286 };
287
288 u_int jh71x0_clkc_muxdiv_get_rate(struct jh71x0_clkc_softc *,
289 struct jh71x0_clkc_clk *);
290 int jh71x0_clkc_muxdiv_set_rate(struct jh71x0_clkc_softc *,
291 struct jh71x0_clkc_clk *, u_int);
292
293 int jh71x0_clkc_muxdiv_set_parent(struct jh71x0_clkc_softc *,
294 struct jh71x0_clkc_clk *, const char *);
295 const char *
296 jh71x0_clkc_muxdiv_get_parent(struct jh71x0_clkc_softc *,
297 struct jh71x0_clkc_clk *);
298 extern struct jh71x0_clkc_clkops jh71x0_clkc_muxdiv_ops;
299
300 #define JH71X0CLKC_MUXDIV_FLAGSX2(_id, _name, _maxdiv, _parents, _cf, _mf) \
301 [_id] = { \
302 .jcc_type = JH71X0CLK_MUXDIV, \
303 .jcc_clk = { \
304 .name = (_name), \
305 .flags = (_cf), \
306 }, \
307 .jcc_reg = (_id) * sizeof(uint32_t), \
308 .jcc_muxdiv = { \
309 .jcmd_parents = (_parents), \
310 .jcmd_nparents = __arraycount(_parents), \
311 .jcmd_maxdiv = (_maxdiv), \
312 .jcmd_flags = (_mf), \
313 }, \
314 .jcc_ops = &jh71x0_clkc_muxdiv_ops, \
315 }
316
317 #define JH71X0CLKC_MUXDIV(_id, _n, _m, _p) \
318 JH71X0CLKC_MUXDIV_FLAGSX2((_id), (_n), (_m), (_p), 0, 0)
319
320 #define JH71X0CLKC_MUXDIV_FLAGS(_id, _n, _m, _p, _f) \
321 JH71X0CLKC_MUXDIV_FLAGSX2((_id), (_n), (_m), (_p), (_f), 0)
322
323 #define JH71X0CLKC_MUXDIVGATE(_id, _n, _m, _p) \
324 JH71X0CLKC_MUXDIV_FLAGSX2((_id), (_n), (_m), (_p), 0, JH71X0CLKC_MUX_GATE)
325
326 #define JH71X0CLKC_MUXDIVGATE_FLAGS(_id, _n, _m, _p, _f) \
327 JH71X0CLKC_MUXDIV_FLAGSX2((_id), (_n), (_m), (_p), (_f), JH71X0CLKC_MUX_GATE)
328
329
330 struct jh71x0_clkc_inv {
331 const char * jci_parent;
332 };
333
334 const char *
335 jh71x0_clkc_inv_get_parent(struct jh71x0_clkc_softc *sc,
336 struct jh71x0_clkc_clk *jcc);
337
338 extern struct jh71x0_clkc_clkops jh71x0_clkc_inv_ops;
339
340 #define JH71X0CLKC_INV(_id, _name, _pname) \
341 [_id] = { \
342 .jcc_type = JH71X0CLK_INV, \
343 .jcc_clk = { \
344 .name = (_name), \
345 .flags = CLK_SET_RATE_PARENT, \
346 }, \
347 .jcc_reg = (_id) * sizeof(uint32_t), \
348 .jcc_inv.jci_parent = (_pname), \
349 .jcc_ops = &jh71x0_clkc_inv_ops, \
350 }
351
352
353 struct jh71x0_clkc_clkops {
354
355 int (*jcco_enable)(struct jh71x0_clkc_softc *,
356 struct jh71x0_clkc_clk *, int);
357 u_int (*jcco_getrate)(struct jh71x0_clkc_softc *,
358 struct jh71x0_clkc_clk *);
359 int (*jcco_setrate)(struct jh71x0_clkc_softc *,
360 struct jh71x0_clkc_clk *, u_int);
361 const char * (*jcco_getparent)(struct jh71x0_clkc_softc *,
362 struct jh71x0_clkc_clk *);
363 int (*jcco_setparent)(struct jh71x0_clkc_softc *,
364 struct jh71x0_clkc_clk *, const char *);
365 };
366
367
368 struct jh71x0_clkc_clk {
369 struct clk jcc_clk;
370 enum jh71x0_clkc_clktype jcc_type;
371 bus_size_t jcc_reg;
372 union {
373 struct jh71x0_clkc_gate jcc_gate;
374 struct jh71x0_clkc_div jcc_div;
375 struct jh71x0_clkc_fracdiv jcc_fracdiv;
376 struct jh71x0_clkc_fixed_factor jcc_ffactor;
377 struct jh71x0_clkc_mux jcc_mux;
378 struct jh71x0_clkc_muxdiv jcc_muxdiv;
379 struct jh71x0_clkc_inv jcc_inv;
380 };
381 struct jh71x0_clkc_clkops * jcc_ops;
382 };
383
384 extern const struct clk_funcs jh71x0_clkc_funcs;
385
386 #endif
387