1 /* $NetBSD: rk_cru.h,v 1.8 2021/11/12 22:02:08 jmcneill 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 u_int refdiv; 56 u_int fbdiv; 57 u_int postdiv1; 58 u_int postdiv2; 59 u_int dsmpd; 60 u_int fracdiv; 61 }; 62 63 #define RK_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _fracdiv) \ 64 { \ 65 .rate = (_rate), \ 66 .refdiv = (_refdiv), \ 67 .fbdiv = (_fbdiv), \ 68 .postdiv1 = (_postdiv1), \ 69 .postdiv2 = (_postdiv2), \ 70 .dsmpd = (_dsmpd), \ 71 .fracdiv = (_fracdiv), \ 72 } 73 74 struct rk_cru_pll { 75 bus_size_t con_base; 76 bus_size_t mode_reg; 77 uint32_t mode_mask; 78 uint32_t lock_mask; 79 const struct rk_cru_pll_rate *rates; 80 u_int nrates; 81 const char **parents; 82 u_int nparents; 83 u_int flags; 84 #define RK_PLL_RK3288 0x01 85 }; 86 87 u_int rk_cru_pll_get_rate(struct rk_cru_softc *, struct rk_cru_clk *); 88 int rk_cru_pll_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int); 89 const char *rk_cru_pll_get_parent(struct rk_cru_softc *, struct rk_cru_clk *); 90 91 #define RK_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \ 92 { \ 93 .id = (_id), \ 94 .type = RK_CRU_PLL, \ 95 .base.name = (_name), \ 96 .base.flags = 0, \ 97 .u.pll.parents = (_parents), \ 98 .u.pll.nparents = __arraycount(_parents), \ 99 .u.pll.con_base = (_con_base), \ 100 .u.pll.mode_reg = (_mode_reg), \ 101 .u.pll.mode_mask = (_mode_mask), \ 102 .u.pll.lock_mask = (_lock_mask), \ 103 .u.pll.rates = (_rates), \ 104 .u.pll.nrates = __arraycount(_rates), \ 105 .u.pll.flags = 0, \ 106 .get_rate = rk_cru_pll_get_rate, \ 107 .set_rate = rk_cru_pll_set_rate, \ 108 .get_parent = rk_cru_pll_get_parent, \ 109 } 110 111 #define RK3288_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \ 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 = RK_PLL_RK3288, \ 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 /* ARM clocks */ 132 133 struct rk_cru_arm_rate { 134 u_int rate; 135 u_int div; 136 }; 137 138 #define RK_ARM_RATE(_rate, _div) \ 139 { \ 140 .rate = (_rate), \ 141 .div = (_div), \ 142 } 143 144 struct rk_cru_cpu_rate { 145 u_int rate; 146 u_int reg1, reg1_mask, reg1_val; 147 u_int reg2, reg2_mask, reg2_val; 148 }; 149 150 #define RK_CPU_RATE(_rate, _reg1, _reg1_mask, _reg1_val, _reg2, _reg2_mask, _reg2_val) \ 151 { \ 152 .rate = (_rate), \ 153 .reg1 = (_reg1), .reg1_mask = (_reg1_mask), .reg1_val = (_reg1_val), \ 154 .reg2 = (_reg2), .reg2_mask = (_reg2_mask), .reg2_val = (_reg2_val), \ 155 } 156 157 struct rk_cru_arm { 158 bus_size_t reg; 159 uint32_t mux_mask; 160 u_int mux_main; 161 u_int mux_alt; 162 uint32_t div_mask; 163 const char **parents; 164 u_int nparents; 165 const struct rk_cru_arm_rate *rates; 166 const struct rk_cru_cpu_rate *cpurates; 167 u_int nrates; 168 }; 169 170 u_int rk_cru_arm_get_rate(struct rk_cru_softc *, struct rk_cru_clk *); 171 int rk_cru_arm_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int); 172 int rk_cru_arm_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int); 173 const char *rk_cru_arm_get_parent(struct rk_cru_softc *, struct rk_cru_clk *); 174 int rk_cru_arm_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *); 175 176 #define RK_ARM(_id, _name, _parents, _reg, _mux_mask, _mux_main, _mux_alt, _div_mask, _rates) \ 177 { \ 178 .id = (_id), \ 179 .type = RK_CRU_ARM, \ 180 .base.name = (_name), \ 181 .base.flags = 0, \ 182 .u.arm.parents = (_parents), \ 183 .u.arm.nparents = __arraycount(_parents), \ 184 .u.arm.reg = (_reg), \ 185 .u.arm.mux_mask = (_mux_mask), \ 186 .u.arm.mux_main = (_mux_main), \ 187 .u.arm.mux_alt = (_mux_alt), \ 188 .u.arm.div_mask = (_div_mask), \ 189 .u.arm.rates = (_rates), \ 190 .u.arm.nrates = __arraycount(_rates), \ 191 .get_rate = rk_cru_arm_get_rate, \ 192 .set_rate = rk_cru_arm_set_rate, \ 193 .get_parent = rk_cru_arm_get_parent, \ 194 .set_parent = rk_cru_arm_set_parent, \ 195 } 196 197 #define RK_CPU(_id, _name, _parents, _reg, _mux_mask, _mux_main, _mux_alt, _div_mask, _cpurates) \ 198 { \ 199 .id = (_id), \ 200 .type = RK_CRU_ARM, \ 201 .base.name = (_name), \ 202 .base.flags = 0, \ 203 .u.arm.parents = (_parents), \ 204 .u.arm.nparents = __arraycount(_parents), \ 205 .u.arm.reg = (_reg), \ 206 .u.arm.mux_mask = (_mux_mask), \ 207 .u.arm.mux_main = (_mux_main), \ 208 .u.arm.mux_alt = (_mux_alt), \ 209 .u.arm.div_mask = (_div_mask), \ 210 .u.arm.cpurates = (_cpurates), \ 211 .u.arm.nrates = __arraycount(_cpurates), \ 212 .get_rate = rk_cru_arm_get_rate, \ 213 .set_rate = rk_cru_arm_set_rate, \ 214 .get_parent = rk_cru_arm_get_parent, \ 215 .set_parent = rk_cru_arm_set_parent, \ 216 } 217 218 /* Composite clocks */ 219 220 struct rk_cru_composite { 221 bus_size_t muxdiv_reg; 222 uint32_t mux_mask; 223 uint32_t div_mask; 224 bus_size_t gate_reg; 225 uint32_t gate_mask; 226 bus_size_t frac_reg; 227 const char **parents; 228 u_int nparents; 229 u_int flags; 230 #define RK_COMPOSITE_ROUND_DOWN 0x01 231 #define RK_COMPOSITE_SET_RATE_PARENT 0x02 232 #define RK_COMPOSITE_FRACDIV 0x04 233 #define RK_COMPOSITE_POW2 0x08 234 }; 235 236 int rk_cru_composite_enable(struct rk_cru_softc *, struct rk_cru_clk *, int); 237 u_int rk_cru_composite_get_rate(struct rk_cru_softc *, struct rk_cru_clk *); 238 int rk_cru_composite_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int); 239 const char *rk_cru_composite_get_parent(struct rk_cru_softc *, struct rk_cru_clk *); 240 int rk_cru_composite_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *); 241 242 #define _RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, _frac_reg, _flags) \ 243 { \ 244 .id = (_id), \ 245 .type = RK_CRU_COMPOSITE, \ 246 .base.name = (_name), \ 247 .base.flags = 0, \ 248 .u.composite.parents = (_parents), \ 249 .u.composite.nparents = __arraycount(_parents), \ 250 .u.composite.muxdiv_reg = (_muxdiv_reg), \ 251 .u.composite.mux_mask = (_mux_mask), \ 252 .u.composite.div_mask = (_div_mask), \ 253 .u.composite.gate_reg = (_gate_reg), \ 254 .u.composite.gate_mask = (_gate_mask), \ 255 .u.composite.frac_reg = (_frac_reg), \ 256 .u.composite.flags = (_flags), \ 257 .enable = rk_cru_composite_enable, \ 258 .get_rate = rk_cru_composite_get_rate, \ 259 .set_rate = rk_cru_composite_set_rate, \ 260 .get_parent = rk_cru_composite_get_parent, \ 261 .set_parent = rk_cru_composite_set_parent, \ 262 } 263 264 #define RK_COMPOSITE(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, _flags) \ 265 _RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, 0, _flags) 266 267 #define RK_COMPOSITE_NOMUX(_id, _name, _parent, _div_reg, _div_mask, _gate_reg, _gate_mask, _flags) \ 268 _RK_COMPOSITE_INIT(_id, _name, (const char *[]){ _parent }, _div_reg, 0, _div_mask, _gate_reg, _gate_mask, 0, _flags) 269 270 #define RK_COMPOSITE_NOGATE(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _flags) \ 271 _RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, 0, 0, 0, _flags) 272 273 #define RK_COMPOSITE_FRAC(_id, _name, _parent, _frac_reg, _flags) \ 274 _RK_COMPOSITE_INIT(_id, _name, (const char *[]){ _parent }, 0, 0, 0, 0, 0, _frac_reg, (_flags) | RK_COMPOSITE_FRACDIV) 275 276 #define RK_DIV(_id, _name, _parent, _div_reg, _div_mask, _flags) \ 277 _RK_COMPOSITE_INIT(_id, _name, (const char *[]){ _parent }, _div_reg, 0, _div_mask, 0, 0, 0, _flags) 278 279 /* Gate clocks */ 280 281 struct rk_cru_gate { 282 bus_size_t reg; 283 uint32_t mask; 284 const char *parent; 285 }; 286 287 int rk_cru_gate_enable(struct rk_cru_softc *, 288 struct rk_cru_clk *, int); 289 const char *rk_cru_gate_get_parent(struct rk_cru_softc *, 290 struct rk_cru_clk *); 291 292 #define RK_GATE(_id, _name, _pname, _reg, _bit) \ 293 { \ 294 .id = (_id), \ 295 .type = RK_CRU_GATE, \ 296 .base.name = (_name), \ 297 .base.flags = CLK_SET_RATE_PARENT, \ 298 .u.gate.parent = (_pname), \ 299 .u.gate.reg = (_reg), \ 300 .u.gate.mask = __BIT(_bit), \ 301 .enable = rk_cru_gate_enable, \ 302 .get_parent = rk_cru_gate_get_parent, \ 303 } 304 305 #define RK_SECURE_GATE(_id, _name, _pname) \ 306 { \ 307 .id = (_id), \ 308 .type = RK_CRU_GATE, \ 309 .base.name = (_name), \ 310 .u.gate.parent = (_pname), \ 311 .get_parent = rk_cru_gate_get_parent, \ 312 } 313 314 /* Mux clocks */ 315 316 struct rk_cru_mux { 317 bus_size_t reg; 318 uint32_t mask; 319 const char **parents; 320 u_int nparents; 321 u_int flags; 322 #define RK_MUX_GRF 0x01 323 }; 324 325 const char *rk_cru_mux_get_parent(struct rk_cru_softc *, struct rk_cru_clk *); 326 int rk_cru_mux_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *); 327 328 #define RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, _flags) \ 329 { \ 330 .id = (_id), \ 331 .type = RK_CRU_MUX, \ 332 .base.name = (_name), \ 333 .base.flags = CLK_SET_RATE_PARENT, \ 334 .u.mux.parents = (_parents), \ 335 .u.mux.nparents = __arraycount(_parents), \ 336 .u.mux.reg = (_reg), \ 337 .u.mux.mask = (_mask), \ 338 .u.mux.flags = (_flags), \ 339 .set_parent = rk_cru_mux_set_parent, \ 340 .get_parent = rk_cru_mux_get_parent, \ 341 } 342 #define RK_MUX(_id, _name, _parents, _reg, _mask) \ 343 RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, 0) 344 #define RK_MUXGRF(_id, _name, _parents, _reg, _mask) \ 345 RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, RK_MUX_GRF) 346 347 /* 348 * Rockchip clock definition 349 */ 350 351 struct rk_cru_clk { 352 struct clk base; 353 u_int id; 354 enum rk_cru_clktype type; 355 union { 356 struct rk_cru_pll pll; 357 struct rk_cru_arm arm; 358 struct rk_cru_composite composite; 359 struct rk_cru_gate gate; 360 struct rk_cru_mux mux; 361 } u; 362 363 int (*enable)(struct rk_cru_softc *, 364 struct rk_cru_clk *, int); 365 u_int (*get_rate)(struct rk_cru_softc *, 366 struct rk_cru_clk *); 367 int (*set_rate)(struct rk_cru_softc *, 368 struct rk_cru_clk *, u_int); 369 u_int (*round_rate)(struct rk_cru_softc *, 370 struct rk_cru_clk *, u_int); 371 const char * (*get_parent)(struct rk_cru_softc *, 372 struct rk_cru_clk *); 373 int (*set_parent)(struct rk_cru_softc *, 374 struct rk_cru_clk *, 375 const char *); 376 }; 377 378 /* 379 * Driver state 380 */ 381 382 struct rk_cru_softc { 383 device_t sc_dev; 384 int sc_phandle; 385 bus_space_tag_t sc_bst; 386 bus_space_handle_t sc_bsh; 387 struct syscon *sc_grf; 388 389 struct clk_domain sc_clkdom; 390 391 struct rk_cru_clk *sc_clks; 392 u_int sc_nclks; 393 394 bus_size_t sc_grf_soc_status; /* for PLL lock */ 395 bus_size_t sc_softrst_base; 396 }; 397 398 int rk_cru_attach(struct rk_cru_softc *); 399 struct rk_cru_clk *rk_cru_clock_find(struct rk_cru_softc *, 400 const char *); 401 void rk_cru_print(struct rk_cru_softc *); 402 403 #define CRU_READ(sc, reg) \ 404 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 405 #define CRU_WRITE(sc, reg, val) \ 406 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 407 408 #define HAS_GRF(sc) ((sc)->sc_grf != NULL) 409 410 #endif /* _ARM_RK_CRU_H */ 411