jh71x0_clkc.h revision 1.1 1 /* $NetBSD: jh71x0_clkc.h,v 1.1 2024/07/27 07:09:50 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 struct jh71x0_clkc_clk *sc_clk;
65 size_t sc_nclks;
66 };
67
68 enum jh71x0_clkc_clktype {
69 JH71X0CLK_UNKNOWN,
70 JH71X0CLK_FIXED_FACTOR,
71 JH71X0CLK_GATE,
72 JH71X0CLK_DIV,
73 JH71X0CLK_FRACDIV,
74 JH71X0CLK_MUX,
75 JH71X0CLK_INV,
76 };
77
78 /*
79 * Fixed-factor clocks
80 */
81
82 struct jh71x0_clkc_fixed_factor {
83 const char * jcff_parent;
84 u_int jcff_div;
85 u_int jcff_mult;
86 };
87
88 u_int jh71x0_clkc_fixed_factor_get_rate(struct jh71x0_clkc_softc *,
89 struct jh71x0_clkc_clk *);
90 int jh71x0_clkc_fixed_factor_set_rate(struct jh71x0_clkc_softc *,
91 struct jh71x0_clkc_clk *, u_int);
92 const char *
93 jh71x0_clkc_fixed_factor_get_parent(struct jh71x0_clkc_softc *,
94 struct jh71x0_clkc_clk *);
95
96 extern struct jh71x0_clkc_clkops jh71x0_clkc_ffactor_ops;
97
98 #define JH71X0CLKC_FIXED_FACTOR(_id, _name, _parent, _div, _mult) \
99 [_id] = { \
100 .jcc_type = JH71X0CLK_FIXED_FACTOR, \
101 .jcc_clk.name = (_name), \
102 .jcc_ffactor.jcff_parent = (_parent), \
103 .jcc_ffactor.jcff_div = (_div), \
104 .jcc_ffactor.jcff_mult = (_mult), \
105 .jcc_ops = &jh71x0_clkc_ffactor_ops, \
106 }
107
108 /*
109 * Gate clocks
110 */
111
112 struct jh71x0_clkc_gate {
113 const char *jcg_parent;
114 };
115
116 int jh71x0_clkc_gate_enable(struct jh71x0_clkc_softc *,
117 struct jh71x0_clkc_clk *, int);
118 const char *
119 jh71x0_clkc_gate_get_parent(struct jh71x0_clkc_softc *,
120 struct jh71x0_clkc_clk *);
121
122 extern struct jh71x0_clkc_clkops jh71x0_clkc_gate_ops;
123
124 #define JH71X0CLKC_GATE(_id, _name, _pname) \
125 [_id] = { \
126 .jcc_type = JH71X0CLK_GATE, \
127 .jcc_clk = { \
128 .name = (_name), \
129 .flags = CLK_SET_RATE_PARENT, \
130 }, \
131 .jcc_reg = (_id) * sizeof(uint32_t), \
132 .jcc_gate.jcg_parent = (_pname), \
133 .jcc_ops = &jh71x0_clkc_gate_ops, \
134 }
135
136 /*
137 * Divider clocks
138 */
139
140 struct jh71x0_clkc_div {
141 bus_size_t jcd_reg;
142 const char * jcd_parent;
143 uint32_t jcd_maxdiv;
144 uint32_t jcd_flags;
145 #define JH71X0CLKC_DIV_GATE __BIT(0)
146 };
147
148 u_int jh71x0_clkc_div_get_rate(struct jh71x0_clkc_softc *,
149 struct jh71x0_clkc_clk *);
150 int jh71x0_clkc_div_set_rate(struct jh71x0_clkc_softc *,
151 struct jh71x0_clkc_clk *, u_int);
152 const char *
153 jh71x0_clkc_div_get_parent(struct jh71x0_clkc_softc *,
154 struct jh71x0_clkc_clk *);
155
156 extern struct jh71x0_clkc_clkops jh71x0_clkc_div_ops;
157
158 #define JH71X0CLKC_DIV_FLAGS(_id, _name, _maxdiv, _parent, _flags) \
159 [_id] = { \
160 .jcc_type = JH71X0CLK_DIV, \
161 .jcc_clk = { \
162 .name = (_name), \
163 }, \
164 .jcc_reg = (_id) * sizeof(uint32_t), \
165 .jcc_div = { \
166 .jcd_parent = (_parent), \
167 .jcd_maxdiv = (_maxdiv), \
168 .jcd_flags = (_flags), \
169 }, \
170 .jcc_ops = &jh71x0_clkc_div_ops, \
171 }
172
173 #define JH71X0CLKC_DIV(_id, _n, _m, _p) \
174 JH71X0CLKC_DIV_FLAGS((_id), (_n), (_m), (_p), 0)
175
176 #define JH71X0CLKC_GATEDIV(_id, _n, _m, _p) \
177 JH71X0CLKC_DIV_FLAGS((_id), (_n), (_m), (_p), JH71X0CLKC_DIV_GATE)
178
179 /*
180 * Fractional Divider clocks
181 */
182
183 struct jh71x0_clkc_fracdiv {
184 bus_size_t jcd_reg;
185 const char * jcd_parent;
186 uint32_t jcd_flags;
187 #define JH71X0CLKC_DIV_GATE __BIT(0)
188 };
189
190 u_int jh71x0_clkc_fracdiv_get_rate(struct jh71x0_clkc_softc *,
191 struct jh71x0_clkc_clk *);
192 int jh71x0_clkc_fracdiv_set_rate(struct jh71x0_clkc_softc *,
193 struct jh71x0_clkc_clk *, u_int);
194 const char *
195 jh71x0_clkc_fracdiv_get_parent(struct jh71x0_clkc_softc *,
196 struct jh71x0_clkc_clk *);
197
198 extern struct jh71x0_clkc_clkops jh71x0_clkc_fracdiv_ops;
199
200 #define JH71X0CLKC_FRACDIV(_id, _name, _parent) \
201 [_id] = { \
202 .jcc_type = JH71X0CLK_FRACDIV, \
203 .jcc_clk = { \
204 .name = (_name), \
205 }, \
206 .jcc_reg = (_id) * sizeof(uint32_t), \
207 .jcc_fracdiv = { \
208 .jcd_parent = (_parent), \
209 }, \
210 .jcc_ops = &jh71x0_clkc_fracdiv_ops, \
211 }
212
213
214 /*
215 * Mux clocks
216 */
217
218 struct jh71x0_clkc_mux {
219 size_t jcm_nparents;
220 const char ** jcm_parents;
221 };
222
223 int jh71x0_clkc_mux_set_parent(struct jh71x0_clkc_softc *,
224 struct jh71x0_clkc_clk *, const char *);
225 const char *
226 jh71x0_clkc_mux_get_parent(struct jh71x0_clkc_softc *,
227 struct jh71x0_clkc_clk *);
228
229 extern struct jh71x0_clkc_clkops jh71x0_clkc_mux_ops;
230
231 #define JH71X0CLKC_MUX_FLAGS(_id, _name, _parents, _cflags) \
232 [_id] = { \
233 .jcc_type = JH71X0CLK_MUX, \
234 .jcc_clk = { \
235 .name = (_name), \
236 .flags = (_cflags), \
237 }, \
238 .jcc_reg = (_id) * sizeof(uint32_t), \
239 .jcc_mux = { \
240 .jcm_parents = (_parents), \
241 .jcm_nparents = __arraycount(_parents), \
242 }, \
243 .jcc_ops = &jh71x0_clkc_mux_ops, \
244 }
245
246 #define JH71X0CLKC_MUX(_id, _n, _p) \
247 JH71X0CLKC_MUX_FLAGS((_id), (_n), (_p), 0)
248
249 struct jh71x0_clkc_inv {
250 const char * jci_parent;
251 };
252
253 const char *
254 jh71x0_clkc_inv_get_parent(struct jh71x0_clkc_softc *sc,
255 struct jh71x0_clkc_clk *jcc);
256
257 extern struct jh71x0_clkc_clkops jh71x0_clkc_inv_ops;
258
259 #define JH71X0CLKC_INV(_id, _name, _pname) \
260 [_id] = { \
261 .jcc_type = JH71X0CLK_INV, \
262 .jcc_clk = { \
263 .name = (_name), \
264 .flags = CLK_SET_RATE_PARENT, \
265 }, \
266 .jcc_reg = (_id) * sizeof(uint32_t), \
267 .jcc_inv.jci_parent = (_pname), \
268 .jcc_ops = &jh71x0_clkc_inv_ops, \
269 }
270
271
272 struct jh71x0_clkc_clkops {
273
274 int (*jcco_enable)(struct jh71x0_clkc_softc *,
275 struct jh71x0_clkc_clk *, int);
276 u_int (*jcco_getrate)(struct jh71x0_clkc_softc *,
277 struct jh71x0_clkc_clk *);
278 int (*jcco_setrate)(struct jh71x0_clkc_softc *,
279 struct jh71x0_clkc_clk *, u_int);
280 const char * (*jcco_getparent)(struct jh71x0_clkc_softc *,
281 struct jh71x0_clkc_clk *);
282 int (*jcco_setparent)(struct jh71x0_clkc_softc *,
283 struct jh71x0_clkc_clk *, const char *);
284 };
285
286
287 struct jh71x0_clkc_clk {
288 struct clk jcc_clk;
289 enum jh71x0_clkc_clktype jcc_type;
290 bus_size_t jcc_reg;
291 union {
292 struct jh71x0_clkc_gate jcc_gate;
293 struct jh71x0_clkc_div jcc_div;
294 struct jh71x0_clkc_fracdiv jcc_fracdiv;
295 struct jh71x0_clkc_fixed_factor jcc_ffactor;
296 struct jh71x0_clkc_mux jcc_mux;
297 struct jh71x0_clkc_inv jcc_inv;
298 };
299 struct jh71x0_clkc_clkops * jcc_ops;
300 };
301
302 extern const struct clk_funcs jh71x0_clkc_funcs;
303
304 #endif
305