1 /* $NetBSD: rk_cru.h,v 1.11 2022/08/23 05:39:06 ryo Exp $ */ 2 3 /*- 4 * Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #ifndef _ARM_RK_CRU_H 30 #define _ARM_RK_CRU_H 31 32 #include <dev/clk/clk_backend.h> 33 #include <dev/fdt/syscon.h> 34 35 struct rk_cru_softc; 36 struct rk_cru_clk; 37 38 /* 39 * Clocks 40 */ 41 42 enum rk_cru_clktype { 43 RK_CRU_UNKNOWN, 44 RK_CRU_PLL, 45 RK_CRU_ARM, 46 RK_CRU_COMPOSITE, 47 RK_CRU_GATE, 48 RK_CRU_MUX, 49 }; 50 51 /* PLL clocks */ 52 53 struct rk_cru_pll_rate { 54 u_int rate; 55 union { 56 struct { /* RK3328,3399 */ 57 u_int refdiv; 58 u_int fbdiv; 59 u_int postdiv1; 60 u_int postdiv2; 61 u_int dsmpd; 62 u_int fracdiv; 63 }; 64 struct { /* RK3588 */ 65 u_int p; 66 u_int m; 67 u_int s; 68 u_int k; 69 }; 70 }; 71 }; 72 73 #define RK_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _fracdiv) \ 74 { \ 75 .rate = (_rate), \ 76 .refdiv = (_refdiv), \ 77 .fbdiv = (_fbdiv), \ 78 .postdiv1 = (_postdiv1), \ 79 .postdiv2 = (_postdiv2), \ 80 .dsmpd = (_dsmpd), \ 81 .fracdiv = (_fracdiv), \ 82 } 83 84 #define RK3588_PLL_RATE(_rate, _p, _m, _s, _k) \ 85 { \ 86 .rate = (_rate), \ 87 .p = (_p), \ 88 .m = (_m), \ 89 .s = (_s), \ 90 .k = (_k), \ 91 } 92 93 struct rk_cru_pll { 94 bus_size_t con_base; 95 bus_size_t mode_reg; 96 uint32_t mode_mask; 97 uint32_t lock_mask; 98 const struct rk_cru_pll_rate *rates; 99 u_int nrates; 100 const char **parents; 101 u_int nparents; 102 u_int flags; 103 #define RK_PLL_RK3288 0x01 104 #define RK_PLL_RK3588 0x02 105 }; 106 107 u_int rk_cru_pll_get_rate(struct rk_cru_softc *, struct rk_cru_clk *); 108 int rk_cru_pll_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int); 109 const char *rk_cru_pll_get_parent(struct rk_cru_softc *, struct rk_cru_clk *); 110 111 #define RK_PLL_FLAGS(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates, _flags) \ 112 { \ 113 .id = (_id), \ 114 .type = RK_CRU_PLL, \ 115 .base.name = (_name), \ 116 .base.flags = 0, \ 117 .u.pll.parents = (_parents), \ 118 .u.pll.nparents = __arraycount(_parents), \ 119 .u.pll.con_base = (_con_base), \ 120 .u.pll.mode_reg = (_mode_reg), \ 121 .u.pll.mode_mask = (_mode_mask), \ 122 .u.pll.lock_mask = (_lock_mask), \ 123 .u.pll.rates = (_rates), \ 124 .u.pll.nrates = __arraycount(_rates), \ 125 .u.pll.flags = _flags, \ 126 .get_rate = rk_cru_pll_get_rate, \ 127 .set_rate = rk_cru_pll_set_rate, \ 128 .get_parent = rk_cru_pll_get_parent, \ 129 } 130 131 #define RK_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \ 132 RK_PLL_FLAGS(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates, 0) 133 134 #define RK3288_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \ 135 RK_PLL_FLAGS(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates, RK_PLL_RK3288) 136 137 #define RK3588_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \ 138 RK_PLL_FLAGS(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates, RK_PLL_RK3588) 139 140 /* ARM clocks */ 141 142 struct rk_cru_arm_rate { 143 u_int rate; 144 u_int div; 145 }; 146 147 #define RK_ARM_RATE(_rate, _div) \ 148 { \ 149 .rate = (_rate), \ 150 .div = (_div), \ 151 } 152 153 struct rk_regmaskval { 154 bus_size_t reg; 155 uint32_t mask; 156 uint32_t val; 157 }; 158 159 struct rk_cru_cpu_rate { 160 u_int rate; 161 struct rk_regmaskval divs[4]; 162 struct rk_regmaskval pre_muxs[3]; 163 struct rk_regmaskval post_muxs[3]; 164 }; 165 166 struct rk_regmask { 167 bus_size_t reg; 168 uint32_t mask; 169 }; 170 171 struct rk_cru_arm { 172 bus_size_t mux_reg; 173 uint32_t mux_mask; 174 u_int mux_main; 175 u_int mux_alt; 176 struct rk_regmask divs[4]; 177 const char **parents; 178 u_int nparents; 179 const struct rk_cru_arm_rate *rates; 180 const struct rk_cru_cpu_rate *cpurates; 181 u_int nrates; 182 }; 183 184 u_int rk_cru_arm_get_rate(struct rk_cru_softc *, struct rk_cru_clk *); 185 int rk_cru_arm_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int); 186 int rk_cru_arm_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int); 187 const char *rk_cru_arm_get_parent(struct rk_cru_softc *, struct rk_cru_clk *); 188 int rk_cru_arm_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *); 189 190 #define RK_ARM(_id, _name, _parents, _reg, _mux_mask, _mux_main, _mux_alt, _div_mask, _rates) \ 191 { \ 192 .id = (_id), \ 193 .type = RK_CRU_ARM, \ 194 .base.name = (_name), \ 195 .base.flags = 0, \ 196 .u.arm.parents = (_parents), \ 197 .u.arm.nparents = __arraycount(_parents), \ 198 .u.arm.mux_reg = (_reg), \ 199 .u.arm.mux_mask = (_mux_mask), \ 200 .u.arm.mux_main = (_mux_main), \ 201 .u.arm.mux_alt = (_mux_alt), \ 202 .u.arm.divs[0].reg = (_reg), \ 203 .u.arm.divs[0].mask = (_div_mask), \ 204 .u.arm.rates = (_rates), \ 205 .u.arm.nrates = __arraycount(_rates), \ 206 .get_rate = rk_cru_arm_get_rate, \ 207 .set_rate = rk_cru_arm_set_rate, \ 208 .get_parent = rk_cru_arm_get_parent, \ 209 .set_parent = rk_cru_arm_set_parent, \ 210 } 211 212 #define _RK_CPU_COMMON_INITIALIZER(_id, _name, _parents, \ 213 _mux_reg, _mux_mask, _mux_main, _mux_alt, _cpurates) \ 214 .id = (_id), \ 215 .type = RK_CRU_ARM, \ 216 .base.name = (_name), \ 217 .base.flags = 0, \ 218 .u.arm.parents = (_parents), \ 219 .u.arm.nparents = __arraycount(_parents), \ 220 .u.arm.mux_reg = (_mux_reg), \ 221 .u.arm.mux_mask = (_mux_mask), \ 222 .u.arm.mux_main = (_mux_main), \ 223 .u.arm.mux_alt = (_mux_alt), \ 224 .u.arm.cpurates = (_cpurates), \ 225 .u.arm.nrates = __arraycount(_cpurates), \ 226 .get_rate = rk_cru_arm_get_rate, \ 227 .set_rate = rk_cru_arm_set_rate, \ 228 .get_parent = rk_cru_arm_get_parent, \ 229 .set_parent = rk_cru_arm_set_parent 230 231 #define RK_CPU(_id, _name, _parents, _mux_reg, _mux_mask, _mux_main, _mux_alt, \ 232 _div_reg, _div_mask, _cpurates) \ 233 { \ 234 _RK_CPU_COMMON_INITIALIZER(_id, _name, _parents, \ 235 _mux_reg, _mux_mask, _mux_main, _mux_alt,_cpurates),\ 236 .u.arm.divs[0].reg = (_div_reg), \ 237 .u.arm.divs[0].mask = (_div_mask), \ 238 } 239 240 #define RK_CPU_CORE2(_id, _name, _parents, \ 241 _mux_reg, _mux_mask, _mux_main, _mux_alt, \ 242 _div0_reg, _div0_mask, \ 243 _div1_reg, _div1_mask, \ 244 _cpurates) \ 245 { \ 246 _RK_CPU_COMMON_INITIALIZER(_id, _name, _parents, \ 247 _mux_reg, _mux_mask, _mux_main, _mux_alt,_cpurates),\ 248 .u.arm.divs[0].reg = (_div0_reg), \ 249 .u.arm.divs[0].mask = (_div0_mask), \ 250 .u.arm.divs[1].reg = (_div1_reg), \ 251 .u.arm.divs[1].mask = (_div1_mask), \ 252 } 253 254 #define RK_CPU_CORE4(_id, _name, _parents, \ 255 _mux_reg, _mux_mask, _mux_main, _mux_alt, \ 256 _div0_reg, _div0_mask, \ 257 _div1_reg, _div1_mask, \ 258 _div2_reg, _div2_mask, \ 259 _div3_reg, _div3_mask, \ 260 _cpurates) \ 261 { \ 262 _RK_CPU_COMMON_INITIALIZER(_id, _name, _parents, \ 263 _mux_reg, _mux_mask, _mux_main, _mux_alt,_cpurates),\ 264 .u.arm.divs[0].reg = (_div0_reg), \ 265 .u.arm.divs[0].mask = (_div0_mask), \ 266 .u.arm.divs[1].reg = (_div1_reg), \ 267 .u.arm.divs[1].mask = (_div1_mask), \ 268 .u.arm.divs[2].reg = (_div2_reg), \ 269 .u.arm.divs[2].mask = (_div2_mask), \ 270 .u.arm.divs[3].reg = (_div3_reg), \ 271 .u.arm.divs[3].mask = (_div3_mask), \ 272 } 273 274 /* Composite clocks */ 275 276 struct rk_cru_composite { 277 bus_size_t muxdiv_reg; 278 uint32_t mux_mask; 279 uint32_t div_mask; 280 bus_size_t gate_reg; 281 uint32_t gate_mask; 282 bus_size_t frac_reg; 283 const char **parents; 284 u_int nparents; 285 u_int flags; 286 #define RK_COMPOSITE_ROUND_DOWN 0x01 287 #define RK_COMPOSITE_SET_RATE_PARENT 0x02 288 #define RK_COMPOSITE_FRACDIV 0x04 289 #define RK_COMPOSITE_POW2 0x08 290 #define RK_COMPOSITE_HALFDIV 0x10 291 }; 292 293 int rk_cru_composite_enable(struct rk_cru_softc *, struct rk_cru_clk *, int); 294 u_int rk_cru_composite_get_rate(struct rk_cru_softc *, struct rk_cru_clk *); 295 int rk_cru_composite_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int); 296 const char *rk_cru_composite_get_parent(struct rk_cru_softc *, struct rk_cru_clk *); 297 int rk_cru_composite_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *); 298 299 #define _RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, _frac_reg, _flags) \ 300 { \ 301 .id = (_id), \ 302 .type = RK_CRU_COMPOSITE, \ 303 .base.name = (_name), \ 304 .base.flags = 0, \ 305 .u.composite.parents = (_parents), \ 306 .u.composite.nparents = __arraycount(_parents), \ 307 .u.composite.muxdiv_reg = (_muxdiv_reg), \ 308 .u.composite.mux_mask = (_mux_mask), \ 309 .u.composite.div_mask = (_div_mask), \ 310 .u.composite.gate_reg = (_gate_reg), \ 311 .u.composite.gate_mask = (_gate_mask), \ 312 .u.composite.frac_reg = (_frac_reg), \ 313 .u.composite.flags = (_flags), \ 314 .enable = rk_cru_composite_enable, \ 315 .get_rate = rk_cru_composite_get_rate, \ 316 .set_rate = rk_cru_composite_set_rate, \ 317 .get_parent = rk_cru_composite_get_parent, \ 318 .set_parent = rk_cru_composite_set_parent, \ 319 } 320 321 #define RK_COMPOSITE(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, _flags) \ 322 _RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, 0, _flags) 323 324 #define RK_COMPOSITE_HALF(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, _flags) \ 325 _RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, 0, (_flags) | RK_COMPOSITE_HALFDIV) 326 327 #define RK_COMPOSITE_NOMUX(_id, _name, _parent, _div_reg, _div_mask, _gate_reg, _gate_mask, _flags) \ 328 _RK_COMPOSITE_INIT(_id, _name, (const char *[]){ _parent }, _div_reg, 0, _div_mask, _gate_reg, _gate_mask, 0, _flags) 329 330 #define RK_COMPOSITE_NODIV(_id, _name, _parents, _muxdiv_reg, _mux_mask, _gate_reg, _gate_mask, _flags) \ 331 _RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, 0, _gate_reg, _gate_mask, 0, _flags) 332 333 #define RK_COMPOSITE_NOGATE(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _flags) \ 334 _RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, 0, 0, 0, _flags) 335 336 #define RK_COMPOSITE_FRAC(_id, _name, _parent, _frac_reg, _flags) \ 337 _RK_COMPOSITE_INIT(_id, _name, (const char *[]){ _parent }, 0, 0, 0, 0, 0, _frac_reg, (_flags) | RK_COMPOSITE_FRACDIV) 338 339 #define RK_DIV(_id, _name, _parent, _div_reg, _div_mask, _flags) \ 340 _RK_COMPOSITE_INIT(_id, _name, (const char *[]){ _parent }, _div_reg, 0, _div_mask, 0, 0, 0, _flags) 341 342 /* Gate clocks */ 343 344 struct rk_cru_gate { 345 bus_size_t reg; 346 uint32_t mask; 347 const char *parent; 348 }; 349 350 int rk_cru_gate_enable(struct rk_cru_softc *, 351 struct rk_cru_clk *, int); 352 const char *rk_cru_gate_get_parent(struct rk_cru_softc *, 353 struct rk_cru_clk *); 354 355 #define RK_GATE(_id, _name, _pname, _reg, _bit) \ 356 { \ 357 .id = (_id), \ 358 .type = RK_CRU_GATE, \ 359 .base.name = (_name), \ 360 .base.flags = CLK_SET_RATE_PARENT, \ 361 .u.gate.parent = (_pname), \ 362 .u.gate.reg = (_reg), \ 363 .u.gate.mask = __BIT(_bit), \ 364 .enable = rk_cru_gate_enable, \ 365 .get_parent = rk_cru_gate_get_parent, \ 366 } 367 368 #define RK_SECURE_GATE(_id, _name, _pname) \ 369 { \ 370 .id = (_id), \ 371 .type = RK_CRU_GATE, \ 372 .base.name = (_name), \ 373 .u.gate.parent = (_pname), \ 374 .get_parent = rk_cru_gate_get_parent, \ 375 } 376 377 /* Mux clocks */ 378 379 struct rk_cru_mux { 380 bus_size_t reg; 381 uint32_t mask; 382 const char **parents; 383 u_int nparents; 384 u_int flags; 385 #define RK_MUX_GRF 0x01 386 }; 387 388 const char *rk_cru_mux_get_parent(struct rk_cru_softc *, struct rk_cru_clk *); 389 int rk_cru_mux_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *); 390 391 #define RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, _flags) \ 392 { \ 393 .id = (_id), \ 394 .type = RK_CRU_MUX, \ 395 .base.name = (_name), \ 396 .base.flags = CLK_SET_RATE_PARENT, \ 397 .u.mux.parents = (_parents), \ 398 .u.mux.nparents = __arraycount(_parents), \ 399 .u.mux.reg = (_reg), \ 400 .u.mux.mask = (_mask), \ 401 .u.mux.flags = (_flags), \ 402 .set_parent = rk_cru_mux_set_parent, \ 403 .get_parent = rk_cru_mux_get_parent, \ 404 } 405 #define RK_MUX(_id, _name, _parents, _reg, _mask) \ 406 RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, 0) 407 #define RK_MUXGRF(_id, _name, _parents, _reg, _mask) \ 408 RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, RK_MUX_GRF) 409 410 /* 411 * Rockchip clock definition 412 */ 413 414 struct rk_cru_clk { 415 struct clk base; 416 u_int id; 417 enum rk_cru_clktype type; 418 union { 419 struct rk_cru_pll pll; 420 struct rk_cru_arm arm; 421 struct rk_cru_composite composite; 422 struct rk_cru_gate gate; 423 struct rk_cru_mux mux; 424 } u; 425 426 int (*enable)(struct rk_cru_softc *, 427 struct rk_cru_clk *, int); 428 u_int (*get_rate)(struct rk_cru_softc *, 429 struct rk_cru_clk *); 430 int (*set_rate)(struct rk_cru_softc *, 431 struct rk_cru_clk *, u_int); 432 u_int (*round_rate)(struct rk_cru_softc *, 433 struct rk_cru_clk *, u_int); 434 const char * (*get_parent)(struct rk_cru_softc *, 435 struct rk_cru_clk *); 436 int (*set_parent)(struct rk_cru_softc *, 437 struct rk_cru_clk *, 438 const char *); 439 }; 440 441 /* 442 * Driver state 443 */ 444 445 struct rk_cru_softc { 446 device_t sc_dev; 447 int sc_phandle; 448 bus_space_tag_t sc_bst; 449 bus_space_handle_t sc_bsh; 450 struct syscon *sc_grf; 451 452 struct clk_domain sc_clkdom; 453 454 struct rk_cru_clk *sc_clks; 455 u_int sc_nclks; 456 457 bus_size_t sc_grf_soc_status; /* for PLL lock */ 458 bus_size_t sc_softrst_base; 459 }; 460 461 int rk_cru_attach(struct rk_cru_softc *); 462 struct rk_cru_clk *rk_cru_clock_find(struct rk_cru_softc *, 463 const char *); 464 void rk_cru_print(struct rk_cru_softc *); 465 466 #define CRU_READ(sc, reg) \ 467 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 468 #define CRU_WRITE(sc, reg, val) \ 469 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 470 471 #define HAS_GRF(sc) ((sc)->sc_grf != NULL) 472 473 #endif /* _ARM_RK_CRU_H */ 474