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