jh71x0_clkc.h revision 1.2 1 /* $NetBSD: jh71x0_clkc.h,v 1.2 2024/08/19 07:33:56 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
74 struct jh71x0_clkc_clk;
75
76 // MDIV
77
78 enum jh71x0_clkc_clktype {
79 JH71X0CLK_UNKNOWN,
80 JH71X0CLK_FIXED_FACTOR,
81 JH71X0CLK_GATE,
82 JH71X0CLK_DIV,
83 JH71X0CLK_FRACDIV,
84 JH71X0CLK_MUX,
85 JH71X0CLK_MUXDIV,
86 JH71X0CLK_INV,
87 };
88
89 /*
90 * Fixed-factor clocks
91 */
92
93 struct jh71x0_clkc_fixed_factor {
94 const char * jcff_parent;
95 u_int jcff_div;
96 u_int jcff_mult;
97 };
98
99 u_int jh71x0_clkc_fixed_factor_get_rate(struct jh71x0_clkc_softc *,
100 struct jh71x0_clkc_clk *);
101 int jh71x0_clkc_fixed_factor_set_rate(struct jh71x0_clkc_softc *,
102 struct jh71x0_clkc_clk *, u_int);
103 const char *
104 jh71x0_clkc_fixed_factor_get_parent(struct jh71x0_clkc_softc *,
105 struct jh71x0_clkc_clk *);
106
107 extern struct jh71x0_clkc_clkops jh71x0_clkc_ffactor_ops;
108
109 #define JH71X0CLKC_FIXED_FACTOR(_id, _name, _parent, _div, _mult) \
110 [_id] = { \
111 .jcc_type = JH71X0CLK_FIXED_FACTOR, \
112 .jcc_clk.name = (_name), \
113 .jcc_ffactor.jcff_parent = (_parent), \
114 .jcc_ffactor.jcff_div = (_div), \
115 .jcc_ffactor.jcff_mult = (_mult), \
116 .jcc_ops = &jh71x0_clkc_ffactor_ops, \
117 }
118
119 /*
120 * Gate clocks
121 */
122
123 struct jh71x0_clkc_gate {
124 const char *jcg_parent;
125 };
126
127 int jh71x0_clkc_gate_enable(struct jh71x0_clkc_softc *,
128 struct jh71x0_clkc_clk *, int);
129 const char *
130 jh71x0_clkc_gate_get_parent(struct jh71x0_clkc_softc *,
131 struct jh71x0_clkc_clk *);
132
133 extern struct jh71x0_clkc_clkops jh71x0_clkc_gate_ops;
134
135 #define JH71X0CLKC_GATE(_id, _name, _pname) \
136 [_id] = { \
137 .jcc_type = JH71X0CLK_GATE, \
138 .jcc_clk = { \
139 .name = (_name), \
140 .flags = CLK_SET_RATE_PARENT, \
141 }, \
142 .jcc_reg = (_id) * sizeof(uint32_t), \
143 .jcc_gate.jcg_parent = (_pname), \
144 .jcc_ops = &jh71x0_clkc_gate_ops, \
145 }
146
147 /*
148 * Divider clocks
149 */
150
151 struct jh71x0_clkc_div {
152 bus_size_t jcd_reg;
153 const char * jcd_parent;
154 uint32_t jcd_maxdiv;
155 uint32_t jcd_flags;
156 #define JH71X0CLKC_DIV_GATE __BIT(0)
157 };
158
159 u_int jh71x0_clkc_div_get_rate(struct jh71x0_clkc_softc *,
160 struct jh71x0_clkc_clk *);
161 int jh71x0_clkc_div_set_rate(struct jh71x0_clkc_softc *,
162 struct jh71x0_clkc_clk *, u_int);
163 const char *
164 jh71x0_clkc_div_get_parent(struct jh71x0_clkc_softc *,
165 struct jh71x0_clkc_clk *);
166
167 extern struct jh71x0_clkc_clkops jh71x0_clkc_div_ops;
168
169 #define JH71X0CLKC_DIV_FLAGS(_id, _name, _maxdiv, _parent, _flags) \
170 [_id] = { \
171 .jcc_type = JH71X0CLK_DIV, \
172 .jcc_clk = { \
173 .name = (_name), \
174 }, \
175 .jcc_reg = (_id) * sizeof(uint32_t), \
176 .jcc_div = { \
177 .jcd_parent = (_parent), \
178 .jcd_maxdiv = (_maxdiv), \
179 .jcd_flags = (_flags), \
180 }, \
181 .jcc_ops = &jh71x0_clkc_div_ops, \
182 }
183
184 #define JH71X0CLKC_DIV(_id, _n, _m, _p) \
185 JH71X0CLKC_DIV_FLAGS((_id), (_n), (_m), (_p), 0)
186
187 #define JH71X0CLKC_GATEDIV(_id, _n, _m, _p) \
188 JH71X0CLKC_DIV_FLAGS((_id), (_n), (_m), (_p), JH71X0CLKC_DIV_GATE)
189
190 /*
191 * Fractional Divider clocks
192 */
193
194 struct jh71x0_clkc_fracdiv {
195 bus_size_t jcd_reg;
196 const char * jcd_parent;
197 uint32_t jcd_flags;
198 #define JH71X0CLKC_DIV_GATE __BIT(0)
199 };
200
201 u_int jh71x0_clkc_fracdiv_get_rate(struct jh71x0_clkc_softc *,
202 struct jh71x0_clkc_clk *);
203 int jh71x0_clkc_fracdiv_set_rate(struct jh71x0_clkc_softc *,
204 struct jh71x0_clkc_clk *, u_int);
205 const char *
206 jh71x0_clkc_fracdiv_get_parent(struct jh71x0_clkc_softc *,
207 struct jh71x0_clkc_clk *);
208
209 extern struct jh71x0_clkc_clkops jh71x0_clkc_fracdiv_ops;
210
211 #define JH71X0CLKC_FRACDIV(_id, _name, _parent) \
212 [_id] = { \
213 .jcc_type = JH71X0CLK_FRACDIV, \
214 .jcc_clk = { \
215 .name = (_name), \
216 }, \
217 .jcc_reg = (_id) * sizeof(uint32_t), \
218 .jcc_fracdiv = { \
219 .jcd_parent = (_parent), \
220 }, \
221 .jcc_ops = &jh71x0_clkc_fracdiv_ops, \
222 }
223
224
225 /*
226 * Mux clocks
227 */
228
229 struct jh71x0_clkc_mux {
230 size_t jcm_nparents;
231 const char ** jcm_parents;
232 uint32_t jcm_flags;
233 #define JH71X0CLKC_MUX_GATE __BIT(0)
234 };
235
236 int jh71x0_clkc_mux_set_parent(struct jh71x0_clkc_softc *,
237 struct jh71x0_clkc_clk *, const char *);
238 const char *
239 jh71x0_clkc_mux_get_parent(struct jh71x0_clkc_softc *,
240 struct jh71x0_clkc_clk *);
241
242 extern struct jh71x0_clkc_clkops jh71x0_clkc_mux_ops;
243
244 #define JH71X0CLKC_MUX_FLAGSX2(_id, _name, _parents, _cflags, _mflags) \
245 [_id] = { \
246 .jcc_type = JH71X0CLK_MUX, \
247 .jcc_clk = { \
248 .name = (_name), \
249 .flags = (_cflags), \
250 }, \
251 .jcc_reg = (_id) * sizeof(uint32_t), \
252 .jcc_mux = { \
253 .jcm_parents = (_parents), \
254 .jcm_nparents = __arraycount(_parents), \
255 .jcm_flags = (_mflags), \
256 }, \
257 .jcc_ops = &jh71x0_clkc_mux_ops, \
258 }
259
260 #define JH71X0CLKC_MUX(_id, _n, _p) \
261 JH71X0CLKC_MUX_FLAGSX2((_id), (_n), (_p), 0, 0)
262
263 #define JH71X0CLKC_MUX_FLAGS(_id, _n, _p, _f) \
264 JH71X0CLKC_MUX_FLAGSX2((_id), (_n), (_p), (_f), 0)
265
266 #define JH71X0CLKC_MUXGATE(_id, _n, _p) \
267 JH71X0CLKC_MUX_FLAGSX2((_id), (_n), (_p), 0, JH71X0CLKC_MUX_GATE)
268
269 #define JH71X0CLKC_MUXGATE_FLAGS(_id, _n, _p, _f) \
270 JH71X0CLKC_MUX_FLAGSX2((_id), (_n), (_p), (_f), JH71X0CLKC_MUX_GATE)
271
272
273
274 /*
275 * Mux divider clocks
276 */
277
278 struct jh71x0_clkc_muxdiv {
279 size_t jcmd_nparents;
280 const char ** jcmd_parents;
281 uint32_t jcmd_maxdiv;
282 uint32_t jcmd_flags;
283 #define JH71X0CLKC_MUXDIV_GATE __BIT(0)
284 };
285
286 u_int jh71x0_clkc_muxdiv_get_rate(struct jh71x0_clkc_softc *,
287 struct jh71x0_clkc_clk *);
288 int jh71x0_clkc_muxdiv_set_rate(struct jh71x0_clkc_softc *,
289 struct jh71x0_clkc_clk *, u_int);
290
291 int jh71x0_clkc_muxdiv_set_parent(struct jh71x0_clkc_softc *,
292 struct jh71x0_clkc_clk *, const char *);
293 const char *
294 jh71x0_clkc_muxdiv_get_parent(struct jh71x0_clkc_softc *,
295 struct jh71x0_clkc_clk *);
296 extern struct jh71x0_clkc_clkops jh71x0_clkc_muxdiv_ops;
297
298 #define JH71X0CLKC_MUXDIV_FLAGSX2(_id, _name, _maxdiv, _parents, _cf, _mf) \
299 [_id] = { \
300 .jcc_type = JH71X0CLK_MUXDIV, \
301 .jcc_clk = { \
302 .name = (_name), \
303 .flags = (_cf), \
304 }, \
305 .jcc_reg = (_id) * sizeof(uint32_t), \
306 .jcc_muxdiv = { \
307 .jcmd_parents = (_parents), \
308 .jcmd_nparents = __arraycount(_parents), \
309 .jcmd_maxdiv = (_maxdiv), \
310 .jcmd_flags = (_mf), \
311 }, \
312 .jcc_ops = &jh71x0_clkc_muxdiv_ops, \
313 }
314
315 #define JH71X0CLKC_MUXDIV(_id, _n, _m, _p) \
316 JH71X0CLKC_MUXDIV_FLAGSX2((_id), (_n), (_m), (_p), 0, 0)
317
318 #define JH71X0CLKC_MUXDIV_FLAGS(_id, _n, _m, _p, _f) \
319 JH71X0CLKC_MUXDIV_FLAGSX2((_id), (_n), (_m), (_p), (_f), 0)
320
321 #define JH71X0CLKC_MUXDIVGATE(_id, _n, _m, _p) \
322 JH71X0CLKC_MUXDIV_FLAGSX2((_id), (_n), (_m), (_p), 0, JH71X0CLKC_MUX_GATE)
323
324 #define JH71X0CLKC_MUXDIVGATE_FLAGS(_id, _n, _m, _p, _f) \
325 JH71X0CLKC_MUXDIV_FLAGSX2((_id), (_n), (_m), (_p), (_f), JH71X0CLKC_MUX_GATE)
326
327
328 struct jh71x0_clkc_inv {
329 const char * jci_parent;
330 };
331
332 const char *
333 jh71x0_clkc_inv_get_parent(struct jh71x0_clkc_softc *sc,
334 struct jh71x0_clkc_clk *jcc);
335
336 extern struct jh71x0_clkc_clkops jh71x0_clkc_inv_ops;
337
338 #define JH71X0CLKC_INV(_id, _name, _pname) \
339 [_id] = { \
340 .jcc_type = JH71X0CLK_INV, \
341 .jcc_clk = { \
342 .name = (_name), \
343 .flags = CLK_SET_RATE_PARENT, \
344 }, \
345 .jcc_reg = (_id) * sizeof(uint32_t), \
346 .jcc_inv.jci_parent = (_pname), \
347 .jcc_ops = &jh71x0_clkc_inv_ops, \
348 }
349
350
351 struct jh71x0_clkc_clkops {
352
353 int (*jcco_enable)(struct jh71x0_clkc_softc *,
354 struct jh71x0_clkc_clk *, int);
355 u_int (*jcco_getrate)(struct jh71x0_clkc_softc *,
356 struct jh71x0_clkc_clk *);
357 int (*jcco_setrate)(struct jh71x0_clkc_softc *,
358 struct jh71x0_clkc_clk *, u_int);
359 const char * (*jcco_getparent)(struct jh71x0_clkc_softc *,
360 struct jh71x0_clkc_clk *);
361 int (*jcco_setparent)(struct jh71x0_clkc_softc *,
362 struct jh71x0_clkc_clk *, const char *);
363 };
364
365
366 struct jh71x0_clkc_clk {
367 struct clk jcc_clk;
368 enum jh71x0_clkc_clktype jcc_type;
369 bus_size_t jcc_reg;
370 union {
371 struct jh71x0_clkc_gate jcc_gate;
372 struct jh71x0_clkc_div jcc_div;
373 struct jh71x0_clkc_fracdiv jcc_fracdiv;
374 struct jh71x0_clkc_fixed_factor jcc_ffactor;
375 struct jh71x0_clkc_mux jcc_mux;
376 struct jh71x0_clkc_muxdiv jcc_muxdiv;
377 struct jh71x0_clkc_inv jcc_inv;
378 };
379 struct jh71x0_clkc_clkops * jcc_ops;
380 };
381
382 extern const struct clk_funcs jh71x0_clkc_funcs;
383
384 #endif
385