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