1 /* $OpenBSD: rkclock.c,v 1.91 2024/11/24 22:19:59 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2017, 2018 Mark Kettenis <kettenis@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/sysctl.h> 21 #include <sys/device.h> 22 23 #include <machine/intr.h> 24 #include <machine/bus.h> 25 #include <machine/fdt.h> 26 27 #include <dev/ofw/openfirm.h> 28 #include <dev/ofw/ofw_clock.h> 29 #include <dev/ofw/ofw_misc.h> 30 #include <dev/ofw/fdt.h> 31 32 /* RK3288 registers */ 33 #define RK3288_CRU_APLL_CON(i) (0x0000 + (i) * 4) 34 #define RK3288_CRU_CPLL_CON(i) (0x0020 + (i) * 4) 35 #define RK3288_CRU_GPLL_CON(i) (0x0030 + (i) * 4) 36 #define RK3288_CRU_NPLL_CON(i) (0x0040 + (i) * 4) 37 #define RK3288_CRU_PLL_CLKR_MASK (0x3f << 8) 38 #define RK3288_CRU_PLL_CLKR_SHIFT 8 39 #define RK3288_CRU_PLL_CLKOD_MASK (0xf << 0) 40 #define RK3288_CRU_PLL_CLKOD_SHIFT 0 41 #define RK3288_CRU_PLL_CLKF_MASK (0x1fff << 0) 42 #define RK3288_CRU_PLL_CLKF_SHIFT 0 43 #define RK3288_CRU_PLL_RESET (1 << 5) 44 #define RK3288_CRU_MODE_CON 0x0050 45 #define RK3288_CRU_MODE_PLL_WORK_MODE_MASK 0x3 46 #define RK3288_CRU_MODE_PLL_WORK_MODE_SLOW 0x0 47 #define RK3288_CRU_MODE_PLL_WORK_MODE_NORMAL 0x1 48 #define RK3288_CRU_CLKSEL_CON(i) (0x0060 + (i) * 4) 49 #define RK3288_CRU_SOFTRST_CON(i) (0x01b8 + (i) * 4) 50 51 /* RK3308 registers */ 52 #define RK3308_CRU_APLL_CON(i) (0x0000 + (i) * 4) 53 #define RK3308_CRU_DPLL_CON(i) (0x0020 + (i) * 4) 54 #define RK3308_CRU_VPLL0_CON(i) (0x0040 + (i) * 4) 55 #define RK3308_CRU_VPLL1_CON(i) (0x0060 + (i) * 4) 56 #define RK3308_CRU_PLL_POSTDIV1_MASK (0x7 << 12) 57 #define RK3308_CRU_PLL_POSTDIV1_SHIFT 12 58 #define RK3308_CRU_PLL_FBDIV_MASK (0xfff << 0) 59 #define RK3308_CRU_PLL_FBDIV_SHIFT 0 60 #define RK3308_CRU_PLL_DSMPD (1 << 12) 61 #define RK3308_CRU_PLL_PLL_LOCK (1 << 10) 62 #define RK3308_CRU_PLL_POSTDIV2_MASK (0x7 << 6) 63 #define RK3308_CRU_PLL_POSTDIV2_SHIFT 6 64 #define RK3308_CRU_PLL_REFDIV_MASK (0x3f << 0) 65 #define RK3308_CRU_PLL_REFDIV_SHIFT 0 66 #define RK3308_CRU_PLL_FRACDIV_MASK (0xffffff << 0) 67 #define RK3308_CRU_PLL_FRACDIV_SHIFT 0 68 #define RK3308_CRU_CRU_MODE 0x00a0 69 #define RK3308_CRU_CRU_MODE_MASK 0x3 70 #define RK3308_CRU_CRU_MODE_SLOW 0x0 71 #define RK3308_CRU_CRU_MODE_NORMAL 0x1 72 #define RK3308_CRU_CRU_MODE_DEEP 0x2 73 #define RK3308_CRU_CLKSEL_CON(i) (0x0100 + (i) * 4) 74 #define RK3308_CRU_ACLK_CORE_DIV_CON_MASK (0x07 << 12) 75 #define RK3308_CRU_ACLK_CORE_DIV_CON_SHIFT 12 76 #define RK3308_CRU_CLK_CORE_DBG_DIV_CON_MASK (0x0f << 8) 77 #define RK3308_CRU_CLK_CORE_DBG_DIV_CON_SHIFT 8 78 #define RK3308_CRU_CORE_CLK_PLL_SEL_MASK (0x03 << 6) 79 #define RK3308_CRU_CORE_CLK_PLL_SEL_SHIFT 6 80 #define RK3308_CRU_CLK_CORE_DIV_CON_MASK (0x0f << 0) 81 #define RK3308_CRU_CLK_CORE_DIV_CON_SHIFT 0 82 #define RK3308_CRU_CLKGATE_CON(i) (0x0300 + (i) * 4) 83 #define RK3308_CRU_SOFTRST_CON(i) (0x0400 + (i) * 4) 84 85 /* RK3328 registers */ 86 #define RK3328_CRU_APLL_CON(i) (0x0000 + (i) * 4) 87 #define RK3328_CRU_DPLL_CON(i) (0x0020 + (i) * 4) 88 #define RK3328_CRU_CPLL_CON(i) (0x0040 + (i) * 4) 89 #define RK3328_CRU_GPLL_CON(i) (0x0060 + (i) * 4) 90 #define RK3328_CRU_NPLL_CON(i) (0x00a0 + (i) * 4) 91 #define RK3328_CRU_PLL_POSTDIV1_MASK (0x7 << 12) 92 #define RK3328_CRU_PLL_POSTDIV1_SHIFT 12 93 #define RK3328_CRU_PLL_FBDIV_MASK (0xfff << 0) 94 #define RK3328_CRU_PLL_FBDIV_SHIFT 0 95 #define RK3328_CRU_PLL_DSMPD (1 << 12) 96 #define RK3328_CRU_PLL_PLL_LOCK (1 << 10) 97 #define RK3328_CRU_PLL_POSTDIV2_MASK (0x7 << 6) 98 #define RK3328_CRU_PLL_POSTDIV2_SHIFT 6 99 #define RK3328_CRU_PLL_REFDIV_MASK (0x3f << 0) 100 #define RK3328_CRU_PLL_REFDIV_SHIFT 0 101 #define RK3328_CRU_PLL_FRACDIV_MASK (0xffffff << 0) 102 #define RK3328_CRU_PLL_FRACDIV_SHIFT 0 103 #define RK3328_CRU_CRU_MODE 0x0080 104 #define RK3328_CRU_CRU_MODE_MASK 0x1 105 #define RK3328_CRU_CRU_MODE_SLOW 0x0 106 #define RK3328_CRU_CRU_MODE_NORMAL 0x1 107 #define RK3328_CRU_CLKSEL_CON(i) (0x0100 + (i) * 4) 108 #define RK3328_CRU_CORE_CLK_PLL_SEL_MASK (0x3 << 6) 109 #define RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT 6 110 #define RK3328_CRU_CLK_CORE_DIV_CON_MASK (0x1f << 0) 111 #define RK3328_CRU_CLK_CORE_DIV_CON_SHIFT 0 112 #define RK3328_CRU_ACLK_CORE_DIV_CON_MASK (0x7 << 4) 113 #define RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT 4 114 #define RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK (0xf << 0) 115 #define RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT 0 116 #define RK3328_CRU_VOP_DCLK_SRC_SEL_MASK (0x1 << 1) 117 #define RK3328_CRU_VOP_DCLK_SRC_SEL_SHIFT 1 118 #define RK3328_CRU_CLKGATE_CON(i) (0x0200 + (i) * 4) 119 #define RK3328_CRU_SOFTRST_CON(i) (0x0300 + (i) * 4) 120 121 #define RK3328_GRF_SOC_CON4 0x0410 122 #define RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN (1 << 14) 123 #define RK3328_GRF_MAC_CON1 0x0904 124 #define RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL (1 << 10) 125 126 /* RK3399 registers */ 127 #define RK3399_CRU_LPLL_CON(i) (0x0000 + (i) * 4) 128 #define RK3399_CRU_BPLL_CON(i) (0x0020 + (i) * 4) 129 #define RK3399_CRU_DPLL_CON(i) (0x0020 + (i) * 4) 130 #define RK3399_CRU_CPLL_CON(i) (0x0060 + (i) * 4) 131 #define RK3399_CRU_GPLL_CON(i) (0x0080 + (i) * 4) 132 #define RK3399_CRU_NPLL_CON(i) (0x00a0 + (i) * 4) 133 #define RK3399_CRU_VPLL_CON(i) (0x00c0 + (i) * 4) 134 #define RK3399_CRU_PLL_FBDIV_MASK (0xfff << 0) 135 #define RK3399_CRU_PLL_FBDIV_SHIFT 0 136 #define RK3399_CRU_PLL_POSTDIV2_MASK (0x7 << 12) 137 #define RK3399_CRU_PLL_POSTDIV2_SHIFT 12 138 #define RK3399_CRU_PLL_POSTDIV1_MASK (0x7 << 8) 139 #define RK3399_CRU_PLL_POSTDIV1_SHIFT 8 140 #define RK3399_CRU_PLL_REFDIV_MASK (0x3f << 0) 141 #define RK3399_CRU_PLL_REFDIV_SHIFT 0 142 #define RK3399_CRU_PLL_PLL_WORK_MODE_MASK (0x3 << 8) 143 #define RK3399_CRU_PLL_PLL_WORK_MODE_SLOW (0x0 << 8) 144 #define RK3399_CRU_PLL_PLL_WORK_MODE_NORMAL (0x1 << 8) 145 #define RK3399_CRU_PLL_PLL_WORK_MODE_DEEP_SLOW (0x2 << 8) 146 #define RK3399_CRU_PLL_PLL_LOCK (1U << 31) 147 #define RK3399_CRU_CLKSEL_CON(i) (0x0100 + (i) * 4) 148 #define RK3399_CRU_ACLKM_CORE_DIV_CON_MASK (0x1f << 8) 149 #define RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT 8 150 #define RK3399_CRU_CORE_PLL_SEL_MASK (0x3 << 6) 151 #define RK3399_CRU_CORE_PLL_SEL_APLL (0x0 << 6) 152 #define RK3399_CRU_CORE_PLL_SEL_BPLL (0x1 << 6) 153 #define RK3399_CRU_CORE_PLL_SEL_DPLL (0x2 << 6) 154 #define RK3399_CRU_CORE_PLL_SEL_GPLL (0x3 << 6) 155 #define RK3399_CRU_CORE_PLL_SEL_SHIFT 6 156 #define RK3399_CRU_CLK_CORE_DIV_CON_MASK (0x1f << 0) 157 #define RK3399_CRU_CLK_CORE_DIV_CON_SHIFT 0 158 #define RK3399_CRU_PCLK_DBG_DIV_CON_MASK (0x1f << 8) 159 #define RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT 8 160 #define RK3399_CRU_ATCLK_CORE_DIV_CON_MASK (0x1f << 0) 161 #define RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT 0 162 #define RK3399_CRU_CLK_SD_PLL_SEL_MASK (0x7 << 8) 163 #define RK3399_CRU_CLK_SD_PLL_SEL_SHIFT 8 164 #define RK3399_CRU_CLK_SD_DIV_CON_MASK (0x7f << 0) 165 #define RK3399_CRU_CLK_SD_DIV_CON_SHIFT 0 166 #define RK3399_CRU_CLKGATE_CON(i) (0x0300 + (i) * 4) 167 #define RK3399_CRU_SOFTRST_CON(i) (0x0400 + (i) * 4) 168 #define RK3399_CRU_SDMMC_CON(i) (0x0580 + (i) * 4) 169 170 #define RK3399_PMUCRU_PPLL_CON(i) (0x0000 + (i) * 4) 171 #define RK3399_PMUCRU_CLKSEL_CON(i) (0x0080 + (i) * 4) 172 173 /* RK3568 registers */ 174 #define RK3568_CRU_APLL_CON(i) (0x0000 + (i) * 4) 175 #define RK3568_CRU_DPLL_CON(i) (0x0020 + (i) * 4) 176 #define RK3568_CRU_GPLL_CON(i) (0x0040 + (i) * 4) 177 #define RK3568_CRU_CPLL_CON(i) (0x0060 + (i) * 4) 178 #define RK3568_CRU_NPLL_CON(i) (0x0080 + (i) * 4) 179 #define RK3568_CRU_VPLL_CON(i) (0x00a0 + (i) * 4) 180 #define RK3568_CRU_MODE_CON 0x00c0 181 #define RK3568_CRU_CLKSEL_CON(i) (0x0100 + (i) * 4) 182 #define RK3568_CRU_GATE_CON(i) (0x0300 + (i) * 4) 183 #define RK3568_CRU_SOFTRST_CON(i) (0x0400 + (i) * 4) 184 185 #define RK3568_PMUCRU_PPLL_CON(i) (0x0000 + (i) * 4) 186 #define RK3568_PMUCRU_HPLL_CON(i) (0x0040 + (i) * 4) 187 #define RK3568_PMUCRU_MODE_CON 0x0080 188 #define RK3568_PMUCRU_CLKSEL_CON(i) (0x0100 + (i) * 4) 189 #define RK3568_PMUCRU_GATE_CON(i) (0x0180 + (i) * 4) 190 191 /* RK3588 registers */ 192 #define RK3588_CRU_AUPLL_CON(i) (0x00180 + (i) * 4) 193 #define RK3588_CRU_CPLL_CON(i) (0x001a0 + (i) * 4) 194 #define RK3588_CRU_GPLL_CON(i) (0x001c0 + (i) * 4) 195 #define RK3588_CRU_NPLL_CON(i) (0x001e0 + (i) * 4) 196 #define RK3588_CRU_PLL_M_MASK (0x3ff << 0) 197 #define RK3588_CRU_PLL_M_SHIFT 0 198 #define RK3588_CRU_PLL_RESETB (1 << 13) 199 #define RK3588_CRU_PLL_S_MASK (0x7 << 6) 200 #define RK3588_CRU_PLL_S_SHIFT 6 201 #define RK3588_CRU_PLL_P_MASK (0x3f << 0) 202 #define RK3588_CRU_PLL_P_SHIFT 0 203 #define RK3588_CRU_PLL_K_MASK (0xffff << 0) 204 #define RK3588_CRU_PLL_K_SHIFT 0 205 #define RK3588_CRU_PLL_PLL_LOCK (1 << 15) 206 #define RK3588_CRU_MODE_CON 0x00280 207 #define RK3588_CRU_MODE_MASK 0x3 208 #define RK3588_CRU_MODE_SLOW 0x0 209 #define RK3588_CRU_MODE_NORMAL 0x1 210 211 #define RK3588_CRU_CLKSEL_CON(i) (0x00300 + (i) * 4) 212 #define RK3588_CRU_GATE_CON(i) (0x00800 + (i) * 4) 213 #define RK3588_CRU_SOFTRST_CON(i) (0x00a00 + (i) * 4) 214 215 #define RK3588_PHPTOPCRU_PPLL_CON(i) (0x08200 + (i) * 4) 216 #define RK3588_PHPTOPCRU_SOFTRST_CON(i) (0x08a00 + (i) * 4) 217 #define RK3588_PMUCRU_CLKSEL_CON(i) (0x30300 + (i) * 4) 218 219 #include "rkclock_clocks.h" 220 221 struct rkclock { 222 uint16_t idx; 223 uint32_t reg; 224 uint16_t sel_mask; 225 uint16_t div_mask; 226 uint16_t parents[8]; 227 uint32_t flags; 228 }; 229 230 #define SEL(l, f) (((1 << (l - f + 1)) - 1) << f) 231 #define DIV(l, f) SEL(l, f) 232 233 #define FIXED_PARENT (1 << 0) 234 #define SET_PARENT (1 << 1) 235 236 #define HREAD4(sc, reg) \ 237 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 238 #define HWRITE4(sc, reg, val) \ 239 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 240 #define HSET4(sc, reg, bits) \ 241 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) 242 #define HCLR4(sc, reg, bits) \ 243 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) 244 245 struct rkclock_softc { 246 struct device sc_dev; 247 bus_space_tag_t sc_iot; 248 bus_space_handle_t sc_ioh; 249 struct regmap *sc_grf; 250 251 uint32_t sc_phandle; 252 const struct rkclock *sc_clocks; 253 254 struct clock_device sc_cd; 255 struct reset_device sc_rd; 256 }; 257 258 int rkclock_match(struct device *, void *, void *); 259 void rkclock_attach(struct device *, struct device *, void *); 260 261 const struct cfattach rkclock_ca = { 262 sizeof (struct rkclock_softc), rkclock_match, rkclock_attach 263 }; 264 265 struct cfdriver rkclock_cd = { 266 NULL, "rkclock", DV_DULL 267 }; 268 269 void rk3288_init(struct rkclock_softc *); 270 uint32_t rk3288_get_frequency(void *, uint32_t *); 271 int rk3288_set_frequency(void *, uint32_t *, uint32_t); 272 void rk3288_enable(void *, uint32_t *, int); 273 void rk3288_reset(void *, uint32_t *, int); 274 275 void rk3308_init(struct rkclock_softc *); 276 uint32_t rk3308_get_frequency(void *, uint32_t *); 277 int rk3308_set_frequency(void *, uint32_t *, uint32_t); 278 int rk3308_set_parent(void *, uint32_t *, uint32_t *); 279 void rk3308_enable(void *, uint32_t *, int); 280 void rk3308_reset(void *, uint32_t *, int); 281 282 void rk3328_init(struct rkclock_softc *); 283 uint32_t rk3328_get_frequency(void *, uint32_t *); 284 int rk3328_set_frequency(void *, uint32_t *, uint32_t); 285 int rk3328_set_parent(void *, uint32_t *, uint32_t *); 286 void rk3328_enable(void *, uint32_t *, int); 287 void rk3328_reset(void *, uint32_t *, int); 288 289 void rk3399_init(struct rkclock_softc *); 290 uint32_t rk3399_get_frequency(void *, uint32_t *); 291 int rk3399_set_frequency(void *, uint32_t *, uint32_t); 292 int rk3399_set_parent(void *, uint32_t *, uint32_t *); 293 void rk3399_enable(void *, uint32_t *, int); 294 void rk3399_reset(void *, uint32_t *, int); 295 296 void rk3399_pmu_init(struct rkclock_softc *); 297 uint32_t rk3399_pmu_get_frequency(void *, uint32_t *); 298 int rk3399_pmu_set_frequency(void *, uint32_t *, uint32_t); 299 void rk3399_pmu_enable(void *, uint32_t *, int); 300 void rk3399_pmu_reset(void *, uint32_t *, int); 301 302 void rk3568_init(struct rkclock_softc *); 303 uint32_t rk3568_get_frequency(void *, uint32_t *); 304 int rk3568_set_frequency(void *, uint32_t *, uint32_t); 305 int rk3568_set_parent(void *, uint32_t *, uint32_t *); 306 void rk3568_enable(void *, uint32_t *, int); 307 void rk3568_reset(void *, uint32_t *, int); 308 309 void rk3568_pmu_init(struct rkclock_softc *); 310 uint32_t rk3568_pmu_get_frequency(void *, uint32_t *); 311 int rk3568_pmu_set_frequency(void *, uint32_t *, uint32_t); 312 void rk3568_pmu_enable(void *, uint32_t *, int); 313 void rk3568_pmu_reset(void *, uint32_t *, int); 314 315 void rk3588_init(struct rkclock_softc *); 316 uint32_t rk3588_get_frequency(void *, uint32_t *); 317 int rk3588_set_frequency(void *, uint32_t *, uint32_t); 318 void rk3588_enable(void *, uint32_t *, int); 319 void rk3588_reset(void *, uint32_t *, int); 320 321 struct rkclock_compat { 322 const char *compat; 323 const char *name; 324 int assign; 325 void (*init)(struct rkclock_softc *); 326 void (*enable)(void *, uint32_t *, int); 327 uint32_t (*get_frequency)(void *, uint32_t *); 328 int (*set_frequency)(void *, uint32_t *, uint32_t); 329 int (*set_parent)(void *, uint32_t *, uint32_t *); 330 void (*reset)(void *, uint32_t *, int); 331 }; 332 333 const struct rkclock_compat rkclock_compat[] = { 334 { 335 "rockchip,rk3288-cru", NULL, 0, rk3288_init, 336 rk3288_enable, rk3288_get_frequency, 337 rk3288_set_frequency, NULL, 338 rk3288_reset 339 }, 340 { 341 "rockchip,rk3308-cru", NULL, 1, rk3308_init, 342 rk3308_enable, rk3308_get_frequency, 343 rk3308_set_frequency, rk3308_set_parent, 344 rk3308_reset 345 }, 346 { 347 "rockchip,rk3328-cru", NULL, 1, rk3328_init, 348 rk3328_enable, rk3328_get_frequency, 349 rk3328_set_frequency, rk3328_set_parent, 350 rk3328_reset 351 }, 352 { 353 "rockchip,rk3399-cru", NULL, 1, rk3399_init, 354 rk3399_enable, rk3399_get_frequency, 355 rk3399_set_frequency, rk3399_set_parent, 356 rk3399_reset 357 }, 358 { 359 "rockchip,rk3399-pmucru", NULL, 1, rk3399_pmu_init, 360 rk3399_pmu_enable, rk3399_pmu_get_frequency, 361 rk3399_pmu_set_frequency, NULL, 362 rk3399_pmu_reset 363 }, 364 { 365 "rockchip,rk3568-cru", "CRU", 1, rk3568_init, 366 rk3568_enable, rk3568_get_frequency, 367 rk3568_set_frequency, rk3568_set_parent, 368 rk3568_reset 369 }, 370 { 371 "rockchip,rk3568-pmucru", "PMUCRU", 1, rk3568_pmu_init, 372 rk3568_pmu_enable, rk3568_pmu_get_frequency, 373 rk3568_pmu_set_frequency, NULL, 374 rk3568_pmu_reset 375 }, 376 { 377 "rockchip,rk3588-cru", NULL, 1, rk3588_init, 378 rk3588_enable, rk3588_get_frequency, 379 rk3588_set_frequency, NULL, 380 rk3588_reset 381 }, 382 }; 383 384 int 385 rkclock_match(struct device *parent, void *match, void *aux) 386 { 387 struct fdt_attach_args *faa = aux; 388 int i; 389 390 for (i = 0; i < nitems(rkclock_compat); i++) { 391 if (OF_is_compatible(faa->fa_node, rkclock_compat[i].compat)) 392 return 10; 393 } 394 395 return 0; 396 } 397 398 void 399 rkclock_attach(struct device *parent, struct device *self, void *aux) 400 { 401 struct rkclock_softc *sc = (struct rkclock_softc *)self; 402 struct fdt_attach_args *faa = aux; 403 uint32_t grf; 404 int i; 405 406 if (faa->fa_nreg < 1) { 407 printf(": no registers\n"); 408 return; 409 } 410 411 sc->sc_iot = faa->fa_iot; 412 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 413 faa->fa_reg[0].size, 0, &sc->sc_ioh)) { 414 printf(": can't map registers\n"); 415 return; 416 } 417 418 grf = OF_getpropint(faa->fa_node, "rockchip,grf", 0); 419 sc->sc_grf = regmap_byphandle(grf); 420 421 sc->sc_phandle = OF_getpropint(faa->fa_node, "phandle", 0); 422 423 for (i = 0; i < nitems(rkclock_compat); i++) { 424 if (OF_is_compatible(faa->fa_node, rkclock_compat[i].compat)) { 425 break; 426 } 427 } 428 KASSERT(i < nitems(rkclock_compat)); 429 430 if (rkclock_compat[i].name != NULL) 431 printf(": %s", rkclock_compat[i].name); 432 433 printf("\n"); 434 435 if (rkclock_compat[i].init) 436 rkclock_compat[i].init(sc); 437 438 sc->sc_cd.cd_node = faa->fa_node; 439 sc->sc_cd.cd_cookie = sc; 440 sc->sc_cd.cd_enable = rkclock_compat[i].enable; 441 sc->sc_cd.cd_get_frequency = rkclock_compat[i].get_frequency; 442 sc->sc_cd.cd_set_frequency = rkclock_compat[i].set_frequency; 443 sc->sc_cd.cd_set_parent = rkclock_compat[i].set_parent; 444 clock_register(&sc->sc_cd); 445 446 sc->sc_rd.rd_node = faa->fa_node; 447 sc->sc_rd.rd_cookie = sc; 448 sc->sc_rd.rd_reset = rkclock_compat[i].reset; 449 reset_register(&sc->sc_rd); 450 451 if (rkclock_compat[i].assign) 452 clock_set_assigned(faa->fa_node); 453 } 454 455 const struct rkclock * 456 rkclock_lookup(struct rkclock_softc *sc, uint32_t idx) 457 { 458 const struct rkclock *clk; 459 460 for (clk = sc->sc_clocks; clk->idx; clk++) { 461 if (clk->idx == idx) 462 return clk; 463 } 464 465 return NULL; 466 } 467 468 uint32_t 469 rkclock_external_frequency(const char *name) 470 { 471 char buf[64] = {}; 472 int len, node; 473 474 /* 475 * Hunt through the device tree to find a fixed-rate clock 476 * that has the requested clock output signal name. This may 477 * be too simple. 478 */ 479 node = OF_peer(0); 480 for (node = OF_child(node); node != 0; node = OF_peer(node)) { 481 len = OF_getproplen(node, "clock-output-names"); 482 if (len <= 0 || len > sizeof(buf)) 483 continue; 484 OF_getprop(node, "clock-output-names", buf, sizeof(buf)); 485 if (strcmp(buf, name) != 0) 486 continue; 487 if (OF_is_compatible(node, "fixed-clock")) 488 return OF_getpropint(node, "clock-frequency", 0); 489 } 490 491 return 0; 492 } 493 494 uint32_t 495 rkclock_div_con(struct rkclock_softc *sc, const struct rkclock *clk, 496 uint32_t mux, uint32_t freq) 497 { 498 uint32_t parent_freq, div, div_con, max_div_con; 499 uint32_t idx = clk->parents[mux]; 500 501 /* Derive maximum value from mask. */ 502 max_div_con = clk->div_mask >> (ffs(clk->div_mask) - 1); 503 504 parent_freq = sc->sc_cd.cd_get_frequency(sc, &idx); 505 div = (parent_freq + freq - 1) / freq; 506 div_con = (div > 0 ? div - 1 : 0); 507 return (div_con < max_div_con) ? div_con : max_div_con; 508 } 509 510 uint32_t 511 rkclock_freq(struct rkclock_softc *sc, const struct rkclock *clk, 512 uint32_t mux, uint32_t freq) 513 { 514 uint32_t parent_freq, div_con; 515 uint32_t idx = clk->parents[mux]; 516 517 parent_freq = sc->sc_cd.cd_get_frequency(sc, &idx); 518 div_con = rkclock_div_con(sc, clk, mux, freq); 519 return parent_freq / (div_con + 1); 520 } 521 522 uint32_t 523 rkclock_get_frequency(struct rkclock_softc *sc, uint32_t idx) 524 { 525 const struct rkclock *clk; 526 uint32_t reg, mux, div_con; 527 int shift; 528 529 clk = rkclock_lookup(sc, idx); 530 if (clk == NULL) { 531 printf("%s(%s, %u)\n", __func__, sc->sc_dev.dv_xname, idx); 532 return 0; 533 } 534 535 reg = HREAD4(sc, clk->reg); 536 shift = ffs(clk->sel_mask) - 1; 537 if (shift == -1) 538 mux = 0; 539 else 540 mux = (reg & clk->sel_mask) >> shift; 541 shift = ffs(clk->div_mask) - 1; 542 if (shift == -1) 543 div_con = 0; 544 else 545 div_con = (reg & clk->div_mask) >> shift; 546 547 if (clk->parents[mux] == 0) { 548 printf("%s: parent 0x%08x\n", __func__, idx); 549 return 0; 550 } 551 idx = clk->parents[mux]; 552 return sc->sc_cd.cd_get_frequency(sc, &idx) / (div_con + 1); 553 } 554 555 int 556 rkclock_set_frequency(struct rkclock_softc *sc, uint32_t idx, uint32_t freq) 557 { 558 const struct rkclock *clk; 559 uint32_t reg, mux, div_con; 560 uint32_t best_freq, best_mux, f; 561 uint32_t parent; 562 int sel_shift, div_shift, i; 563 564 clk = rkclock_lookup(sc, idx); 565 if (clk == NULL) { 566 printf("%s(%s, %u, %u)\n", __func__, sc->sc_dev.dv_xname, 567 idx, freq); 568 return -1; 569 } 570 571 reg = HREAD4(sc, clk->reg); 572 sel_shift = ffs(clk->sel_mask) - 1; 573 if (sel_shift == -1) 574 mux = sel_shift = 0; 575 else 576 mux = (reg & clk->sel_mask) >> sel_shift; 577 578 if (clk->parents[mux] == 0) { 579 printf("%s(%s, %u, %u) parent\n", __func__, 580 sc->sc_dev.dv_xname, idx, freq); 581 return 0; 582 } 583 584 if (clk->flags & SET_PARENT) { 585 parent = clk->parents[mux]; 586 sc->sc_cd.cd_set_frequency(sc, &parent, freq); 587 if (clk->div_mask == 0) 588 return 0; 589 } 590 591 /* 592 * If there is no divider, pick the parent with the frequency 593 * closest to the target frequency. 594 */ 595 if (clk->div_mask == 0) { 596 /* 597 * Start out with the current parent. This prevents 598 * unnecessary switching to a different parent. 599 */ 600 parent = clk->parents[mux]; 601 best_freq = sc->sc_cd.cd_get_frequency(sc, &parent); 602 best_mux = mux; 603 604 for (i = 0; i < nitems(clk->parents); i++) { 605 if (clk->parents[i] == 0) 606 continue; 607 parent = clk->parents[i]; 608 f = sc->sc_cd.cd_get_frequency(sc, &parent); 609 if ((best_freq > freq && f < best_freq) || 610 (f > best_freq && f <= freq)) { 611 best_freq = f; 612 best_mux = i; 613 } 614 } 615 616 HWRITE4(sc, clk->reg, 617 clk->sel_mask << 16 | best_mux << sel_shift); 618 return 0; 619 } 620 621 /* 622 * Start out with the current parent. This prevents 623 * unnecessary switching to a different parent. 624 */ 625 best_freq = rkclock_freq(sc, clk, mux, freq); 626 best_mux = mux; 627 628 /* 629 * Find the parent that allows configuration of a frequency 630 * closest to the target frequency. 631 */ 632 if ((clk->flags & FIXED_PARENT) == 0) { 633 for (i = 0; i < nitems(clk->parents); i++) { 634 if (clk->parents[i] == 0) 635 continue; 636 f = rkclock_freq(sc, clk, i, freq); 637 if ((best_freq > freq && f < best_freq) || 638 (f > best_freq && f <= freq)) { 639 best_freq = f; 640 best_mux = i; 641 } 642 } 643 } 644 645 div_con = rkclock_div_con(sc, clk, best_mux, freq); 646 div_shift = ffs(clk->div_mask) - 1; 647 HWRITE4(sc, clk->reg, 648 clk->sel_mask << 16 | best_mux << sel_shift | 649 clk->div_mask << 16 | div_con << div_shift); 650 return 0; 651 } 652 653 int 654 rkclock_set_parent(struct rkclock_softc *sc, uint32_t idx, uint32_t parent) 655 { 656 const struct rkclock *clk; 657 uint32_t mux; 658 int shift; 659 660 clk = rkclock_lookup(sc, idx); 661 if (clk == NULL || clk->sel_mask == 0) { 662 printf("%s: 0x%08x\n", __func__, idx); 663 return -1; 664 } 665 666 for (mux = 0; mux < nitems(clk->parents); mux++) { 667 if (clk->parents[mux] == parent) 668 break; 669 } 670 if (mux == nitems(clk->parents) || parent == 0) { 671 printf("%s: 0x%08x parent 0x%08x\n", __func__, idx, parent); 672 return -1; 673 } 674 675 shift = ffs(clk->sel_mask) - 1; 676 HWRITE4(sc, clk->reg, clk->sel_mask << 16 | mux << shift); 677 return 0; 678 } 679 680 /* 681 * Rockchip RK3288 682 */ 683 684 const struct rkclock rk3288_clocks[] = { 685 { 686 RK3288_CLK_SDMMC, RK3288_CRU_CLKSEL_CON(11), 687 SEL(7, 6), DIV(5, 0), 688 { RK3288_PLL_CPLL, RK3288_PLL_GPLL, RK3288_XIN24M } 689 } 690 }; 691 692 void 693 rk3288_init(struct rkclock_softc *sc) 694 { 695 int node; 696 697 /* 698 * Since the hardware comes up with a really conservative CPU 699 * clock frequency, and U-Boot doesn't set it to a more 700 * reasonable default, try to do so here. These defaults were 701 * chosen assuming that the CPU voltage is at least 1.1 V. 702 * Only do this on the Tinker-RK3288 for now where this is 703 * likely to be true given the default voltages for the 704 * regulators on that board. 705 */ 706 node = OF_finddevice("/"); 707 if (OF_is_compatible(node, "rockchip,rk3288-tinker")) { 708 uint32_t idx; 709 710 /* Run at 1.2 GHz. */ 711 idx = RK3288_ARMCLK; 712 rk3288_set_frequency(sc, &idx, 1200000000); 713 } 714 715 sc->sc_clocks = rk3288_clocks; 716 } 717 718 uint32_t 719 rk3288_get_pll(struct rkclock_softc *sc, bus_size_t base) 720 { 721 uint32_t clkod, clkr, clkf; 722 uint32_t reg; 723 724 reg = HREAD4(sc, base); 725 clkod = (reg & RK3288_CRU_PLL_CLKOD_MASK) >> 726 RK3288_CRU_PLL_CLKOD_SHIFT; 727 clkr = (reg & RK3288_CRU_PLL_CLKR_MASK) >> 728 RK3288_CRU_PLL_CLKR_SHIFT; 729 reg = HREAD4(sc, base + 4); 730 clkf = (reg & RK3288_CRU_PLL_CLKF_MASK) >> 731 RK3288_CRU_PLL_CLKF_SHIFT; 732 return 24000000ULL * (clkf + 1) / (clkr + 1) / (clkod + 1); 733 } 734 735 int 736 rk3288_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq) 737 { 738 int shift = 4 * (base / RK3288_CRU_CPLL_CON(0)); 739 uint32_t no, nr, nf; 740 741 /* 742 * It is not clear whether all combinations of the clock 743 * dividers result in a stable clock. Therefore this function 744 * only supports a limited set of PLL clock rates. For now 745 * this set covers all the CPU frequencies supported by the 746 * Linux kernel. 747 */ 748 switch (freq) { 749 case 1800000000: 750 case 1704000000: 751 case 1608000000: 752 case 1512000000: 753 case 1488000000: 754 case 1416000000: 755 case 1200000000: 756 nr = no = 1; 757 break; 758 case 1008000000: 759 case 816000000: 760 case 696000000: 761 case 600000000: 762 nr = 1; no = 2; 763 break; 764 case 408000000: 765 case 312000000: 766 nr = 1; no = 4; 767 break; 768 case 216000000: 769 case 126000000: 770 nr = 1; no = 8; 771 break; 772 default: 773 printf("%s: %u Hz\n", __func__, freq); 774 return -1; 775 } 776 777 /* Calculate feedback divider. */ 778 nf = freq * nr * no / 24000000; 779 780 /* 781 * Select slow mode to guarantee a stable clock while we're 782 * adjusting the PLL. 783 */ 784 HWRITE4(sc, RK3288_CRU_MODE_CON, 785 (RK3288_CRU_MODE_PLL_WORK_MODE_MASK << 16 | 786 RK3288_CRU_MODE_PLL_WORK_MODE_SLOW) << shift); 787 788 /* Assert reset. */ 789 HWRITE4(sc, base + 0x000c, 790 RK3288_CRU_PLL_RESET << 16 | RK3288_CRU_PLL_RESET); 791 792 /* Set PLL rate. */ 793 HWRITE4(sc, base + 0x0000, 794 RK3288_CRU_PLL_CLKR_MASK << 16 | 795 (nr - 1) << RK3288_CRU_PLL_CLKR_SHIFT | 796 RK3288_CRU_PLL_CLKOD_MASK << 16 | 797 (no - 1) << RK3288_CRU_PLL_CLKOD_SHIFT); 798 HWRITE4(sc, base + 0x0004, 799 RK3288_CRU_PLL_CLKF_MASK << 16 | 800 (nf - 1) << RK3288_CRU_PLL_CLKF_SHIFT); 801 802 /* Deassert reset and wait. */ 803 HWRITE4(sc, base + 0x000c, 804 RK3288_CRU_PLL_RESET << 16); 805 delay((nr * 500 / 24) + 1); 806 807 /* Switch back to normal mode. */ 808 HWRITE4(sc, RK3288_CRU_MODE_CON, 809 (RK3288_CRU_MODE_PLL_WORK_MODE_MASK << 16 | 810 RK3288_CRU_MODE_PLL_WORK_MODE_NORMAL) << shift); 811 812 return 0; 813 } 814 815 uint32_t 816 rk3288_get_frequency(void *cookie, uint32_t *cells) 817 { 818 struct rkclock_softc *sc = cookie; 819 uint32_t idx = cells[0]; 820 uint32_t reg, mux, div_con, aclk_div_con; 821 822 switch (idx) { 823 case RK3288_PLL_APLL: 824 return rk3288_get_pll(sc, RK3288_CRU_APLL_CON(0)); 825 case RK3288_PLL_CPLL: 826 return rk3288_get_pll(sc, RK3288_CRU_CPLL_CON(0)); 827 case RK3288_PLL_GPLL: 828 return rk3288_get_pll(sc, RK3288_CRU_GPLL_CON(0)); 829 case RK3288_PLL_NPLL: 830 return rk3288_get_pll(sc, RK3288_CRU_NPLL_CON(0)); 831 case RK3288_ARMCLK: 832 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(0)); 833 mux = (reg >> 15) & 0x1; 834 div_con = (reg >> 8) & 0x1f; 835 idx = (mux == 0) ? RK3288_PLL_APLL : RK3288_PLL_GPLL; 836 return rk3288_get_frequency(sc, &idx) / (div_con + 1); 837 case RK3288_XIN24M: 838 return 24000000; 839 case RK3288_CLK_UART0: 840 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(13)); 841 mux = (reg >> 8) & 0x3; 842 div_con = reg & 0x7f; 843 if (mux == 2) 844 return 24000000 / (div_con + 1); 845 break; 846 case RK3288_CLK_UART1: 847 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(14)); 848 mux = (reg >> 8) & 0x3; 849 div_con = reg & 0x7f; 850 if (mux == 2) 851 return 24000000 / (div_con + 1); 852 break; 853 case RK3288_CLK_UART2: 854 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(15)); 855 mux = (reg >> 8) & 0x3; 856 div_con = reg & 0x7f; 857 if (mux == 2) 858 return 24000000 / (div_con + 1); 859 break; 860 case RK3288_CLK_UART3: 861 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(16)); 862 mux = (reg >> 8) & 0x3; 863 div_con = reg & 0x7f; 864 if (mux == 2) 865 return 24000000 / (div_con + 1); 866 break; 867 case RK3288_CLK_UART4: 868 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(3)); 869 mux = (reg >> 8) & 0x3; 870 div_con = reg & 0x7f; 871 if (mux == 2) 872 return 24000000 / (div_con + 1); 873 break; 874 case RK3288_CLK_MAC: 875 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(21)); 876 if (reg & 0x10) 877 return 125000000; 878 mux = (reg >> 0) & 0x3; 879 div_con = (reg >> 8) & 0x1f; 880 switch (mux) { 881 case 0: 882 idx = RK3288_PLL_NPLL; 883 break; 884 case 1: 885 idx = RK3288_PLL_CPLL; 886 break; 887 case 2: 888 idx = RK3288_PLL_GPLL; 889 break; 890 default: 891 return 0; 892 } 893 return rk3288_get_frequency(sc, &idx) / (div_con + 1); 894 case RK3288_PCLK_I2C0: 895 case RK3288_PCLK_I2C2: 896 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(1)); 897 mux = (reg >> 15) & 0x1; 898 /* pd_bus_pclk_div_con */ 899 div_con = (reg >> 12) & 0x7; 900 if (mux == 1) 901 idx = RK3288_PLL_GPLL; 902 else 903 idx = RK3288_PLL_CPLL; 904 return rk3288_get_frequency(sc, &idx) / (div_con + 1); 905 case RK3288_PCLK_I2C1: 906 case RK3288_PCLK_I2C3: 907 case RK3288_PCLK_I2C4: 908 case RK3288_PCLK_I2C5: 909 reg = HREAD4(sc, RK3288_CRU_CLKSEL_CON(10)); 910 mux = (reg >> 15) & 0x1; 911 /* peri_pclk_div_con */ 912 div_con = (reg >> 12) & 0x3; 913 /* peri_aclk_div_con */ 914 aclk_div_con = reg & 0xf; 915 if (mux == 1) 916 idx = RK3288_PLL_GPLL; 917 else 918 idx = RK3288_PLL_CPLL; 919 return (rk3288_get_frequency(sc, &idx) / (aclk_div_con + 1)) >> 920 div_con; 921 default: 922 break; 923 } 924 925 return rkclock_get_frequency(sc, idx); 926 } 927 928 int 929 rk3288_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 930 { 931 struct rkclock_softc *sc = cookie; 932 uint32_t idx = cells[0]; 933 int error; 934 935 switch (idx) { 936 case RK3288_PLL_APLL: 937 return rk3288_set_pll(sc, RK3288_CRU_APLL_CON(0), freq); 938 case RK3288_ARMCLK: 939 idx = RK3288_PLL_APLL; 940 error = rk3288_set_frequency(sc, &idx, freq); 941 if (error == 0) { 942 HWRITE4(sc, RK3288_CRU_CLKSEL_CON(0), 943 ((1 << 15) | (0x1f << 8)) << 16); 944 } 945 return error; 946 default: 947 break; 948 } 949 950 return rkclock_set_frequency(sc, idx, freq); 951 } 952 953 void 954 rk3288_enable(void *cookie, uint32_t *cells, int on) 955 { 956 uint32_t idx = cells[0]; 957 958 switch (idx) { 959 case RK3288_CLK_SDMMC: 960 case RK3288_CLK_TSADC: 961 case RK3288_CLK_UART0: 962 case RK3288_CLK_UART1: 963 case RK3288_CLK_UART2: 964 case RK3288_CLK_UART3: 965 case RK3288_CLK_UART4: 966 case RK3288_CLK_MAC_RX: 967 case RK3288_CLK_MAC_TX: 968 case RK3288_CLK_SDMMC_DRV: 969 case RK3288_CLK_SDMMC_SAMPLE: 970 case RK3288_CLK_MAC: 971 case RK3288_ACLK_GMAC: 972 case RK3288_PCLK_GMAC: 973 case RK3288_PCLK_I2C0: 974 case RK3288_PCLK_I2C1: 975 case RK3288_PCLK_I2C2: 976 case RK3288_PCLK_I2C3: 977 case RK3288_PCLK_I2C4: 978 case RK3288_PCLK_I2C5: 979 case RK3288_PCLK_TSADC: 980 case RK3288_HCLK_HOST0: 981 case RK3288_HCLK_SDMMC: 982 /* Enabled by default. */ 983 break; 984 default: 985 printf("%s: 0x%08x\n", __func__, idx); 986 break; 987 } 988 } 989 990 void 991 rk3288_reset(void *cookie, uint32_t *cells, int on) 992 { 993 struct rkclock_softc *sc = cookie; 994 uint32_t idx = cells[0]; 995 uint32_t mask = (1 << (idx % 16)); 996 997 HWRITE4(sc, RK3288_CRU_SOFTRST_CON(idx / 16), 998 mask << 16 | (on ? mask : 0)); 999 } 1000 1001 /* 1002 * Rockchip RK3308 1003 */ 1004 1005 const struct rkclock rk3308_clocks[] = { 1006 { 1007 RK3308_CLK_RTC32K, RK3308_CRU_CLKSEL_CON(2), 1008 SEL(10, 9), 0, 1009 { RK3308_PLL_VPLL0, RK3308_PLL_VPLL1 } 1010 }, 1011 { 1012 RK3308_CLK_UART0, RK3308_CRU_CLKSEL_CON(10), 1013 SEL(15, 13), DIV(4, 0), 1014 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 1015 RK3308_USB480M, RK3308_XIN24M } 1016 }, 1017 { 1018 RK3308_CLK_UART1, RK3308_CRU_CLKSEL_CON(13), 1019 SEL(15, 13), DIV(4, 0), 1020 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 1021 RK3308_USB480M, RK3308_XIN24M } 1022 }, 1023 { 1024 RK3308_CLK_UART2, RK3308_CRU_CLKSEL_CON(16), 1025 SEL(15, 13), DIV(4, 0), 1026 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 1027 RK3308_USB480M, RK3308_XIN24M } 1028 }, 1029 { 1030 RK3308_CLK_UART3, RK3308_CRU_CLKSEL_CON(19), 1031 SEL(15, 13), DIV(4, 0), 1032 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 1033 RK3308_USB480M, RK3308_XIN24M } 1034 }, 1035 { 1036 RK3308_CLK_UART4, RK3308_CRU_CLKSEL_CON(22), 1037 SEL(15, 13), DIV(4, 0), 1038 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 1039 RK3308_USB480M, RK3308_XIN24M } 1040 }, 1041 { 1042 RK3308_CLK_PWM0, RK3308_CRU_CLKSEL_CON(29), 1043 SEL(15, 14), DIV(6, 0), 1044 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_XIN24M } 1045 }, 1046 { 1047 RK3308_CLK_SPI0, RK3308_CRU_CLKSEL_CON(30), 1048 SEL(15, 14), DIV(6, 0), 1049 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_XIN24M } 1050 }, 1051 { 1052 RK3308_CLK_SPI1, RK3308_CRU_CLKSEL_CON(31), 1053 SEL(15, 14), DIV(6, 0), 1054 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_XIN24M } 1055 }, 1056 { 1057 RK3308_CLK_SPI2, RK3308_CRU_CLKSEL_CON(32), 1058 SEL(15, 14), DIV(6, 0), 1059 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_XIN24M } 1060 }, 1061 { 1062 RK3308_CLK_TSADC, RK3308_CRU_CLKSEL_CON(33), 1063 0, DIV(10, 0), 1064 { RK3308_XIN24M } 1065 }, 1066 { 1067 RK3308_CLK_SARADC, RK3308_CRU_CLKSEL_CON(34), 1068 0, DIV(10, 0), 1069 { RK3308_XIN24M } 1070 }, 1071 { 1072 RK3308_CLK_CRYPTO, RK3308_CRU_CLKSEL_CON(7), 1073 SEL(7, 6), DIV(4, 0), 1074 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 0 } 1075 }, 1076 { 1077 RK3308_CLK_CRYPTO_APK, RK3308_CRU_CLKSEL_CON(7), 1078 SEL(15, 14), DIV(12, 8), 1079 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 0 } 1080 }, 1081 { 1082 RK3308_CLK_SDMMC, RK3308_CRU_CLKSEL_CON(39), 1083 SEL(9, 8), DIV(7, 0), 1084 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 1085 RK3308_XIN24M } 1086 }, 1087 { 1088 RK3308_CLK_SDIO, RK3308_CRU_CLKSEL_CON(40), 1089 SEL(9, 8), DIV(7, 0), 1090 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 1091 RK3308_XIN24M } 1092 }, 1093 { 1094 RK3308_CLK_EMMC, RK3308_CRU_CLKSEL_CON(41), 1095 SEL(9, 8), DIV(7, 0), 1096 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 1097 RK3308_XIN24M } 1098 }, 1099 { 1100 RK3308_CLK_MAC_SRC, RK3308_CRU_CLKSEL_CON(43), 1101 SEL(7, 6), DIV(4, 0), 1102 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 0 } 1103 }, 1104 { 1105 RK3308_CLK_MAC, RK3308_CRU_CLKSEL_CON(43), 1106 SEL(14, 13), 0, 1107 { RK3308_CLK_MAC_SRC, 0 }, 1108 SET_PARENT 1109 }, 1110 { 1111 RK3308_ACLK_PERI_SRC, RK3308_CRU_CLKSEL_CON(36), 1112 SEL(7, 6), 0, 1113 { RK3308_PLL_DPLL, RK3308_PLL_VPLL0, RK3308_PLL_VPLL1, 0 } 1114 }, 1115 { 1116 RK3308_PCLK_PERI, RK3308_CRU_CLKSEL_CON(37), 1117 0, DIV(12, 8), 1118 { RK3308_ACLK_PERI_SRC } 1119 }, 1120 { 1121 RK3308_PCLK_MAC, 0, 0, 0, 1122 { RK3308_PCLK_PERI } 1123 }, 1124 1125 { 1126 /* Sentinel */ 1127 } 1128 }; 1129 1130 void 1131 rk3308_init(struct rkclock_softc *sc) 1132 { 1133 int i; 1134 1135 /* The code below assumes all clocks are enabled. Check this!. */ 1136 for (i = 0; i <= 14; i++) { 1137 if (HREAD4(sc, RK3308_CRU_CLKGATE_CON(i)) != 0x00000000) { 1138 printf("CRU_CLKGATE_CON%d: 0x%08x\n", i, 1139 HREAD4(sc, RK3308_CRU_CLKGATE_CON(i))); 1140 } 1141 } 1142 sc->sc_clocks = rk3308_clocks; 1143 } 1144 1145 uint32_t 1146 rk3308_armclk_parent(uint32_t mux) 1147 { 1148 switch (mux) { 1149 case 0: 1150 return RK3308_PLL_APLL; 1151 case 1: 1152 return RK3308_PLL_VPLL0; 1153 case 2: 1154 return RK3308_PLL_VPLL1; 1155 } 1156 1157 return 0; 1158 } 1159 1160 uint32_t 1161 rk3308_get_armclk(struct rkclock_softc *sc) 1162 { 1163 uint32_t reg, mux, div_con; 1164 uint32_t idx; 1165 1166 reg = HREAD4(sc, RK3308_CRU_CLKSEL_CON(0)); 1167 mux = (reg & RK3308_CRU_CORE_CLK_PLL_SEL_MASK) >> 1168 RK3308_CRU_CORE_CLK_PLL_SEL_SHIFT; 1169 div_con = (reg & RK3308_CRU_CLK_CORE_DIV_CON_MASK) >> 1170 RK3308_CRU_CLK_CORE_DIV_CON_SHIFT; 1171 idx = rk3308_armclk_parent(mux); 1172 1173 return rk3308_get_frequency(sc, &idx) / (div_con + 1); 1174 } 1175 1176 int 1177 rk3308_set_armclk(struct rkclock_softc *sc, uint32_t freq) 1178 { 1179 uint32_t reg, mux; 1180 uint32_t old_freq, div; 1181 uint32_t idx; 1182 1183 old_freq = rk3308_get_armclk(sc); 1184 if (freq == old_freq) 1185 return 0; 1186 1187 reg = HREAD4(sc, RK3308_CRU_CLKSEL_CON(0)); 1188 mux = (reg & RK3308_CRU_CORE_CLK_PLL_SEL_MASK) >> 1189 RK3308_CRU_CORE_CLK_PLL_SEL_SHIFT; 1190 1191 /* Keep the pclk_dbg clock at or below 300 MHz. */ 1192 div = 1; 1193 while (freq / (div + 1) > 300000000) 1194 div++; 1195 /* and make sure we use an odd divider. */ 1196 if ((div % 2) == 0) 1197 div++; 1198 1199 /* When ramping up, set clock dividers first. */ 1200 if (freq > old_freq) { 1201 HWRITE4(sc, RK3308_CRU_CLKSEL_CON(0), 1202 RK3308_CRU_CLK_CORE_DIV_CON_MASK << 16 | 1203 0 << RK3308_CRU_CLK_CORE_DIV_CON_SHIFT | 1204 RK3308_CRU_ACLK_CORE_DIV_CON_MASK << 16 | 1205 1 << RK3308_CRU_ACLK_CORE_DIV_CON_SHIFT | 1206 RK3308_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 | 1207 div << RK3308_CRU_CLK_CORE_DBG_DIV_CON_SHIFT); 1208 } 1209 1210 /* We always use VPLL1 and force the switch below if needed. */ 1211 idx = RK3308_PLL_VPLL1; 1212 rk3308_set_frequency(sc, &idx, freq); 1213 1214 /* When ramping down, set clock dividers last. */ 1215 if (freq < old_freq || mux != 2) { 1216 HWRITE4(sc, RK3308_CRU_CLKSEL_CON(0), 1217 RK3308_CRU_CORE_CLK_PLL_SEL_MASK << 16 | 1218 2 << RK3308_CRU_CORE_CLK_PLL_SEL_SHIFT | 1219 RK3308_CRU_CLK_CORE_DIV_CON_MASK << 16 | 1220 0 << RK3308_CRU_CLK_CORE_DIV_CON_SHIFT | 1221 RK3308_CRU_ACLK_CORE_DIV_CON_MASK << 16 | 1222 1 << RK3308_CRU_ACLK_CORE_DIV_CON_SHIFT | 1223 RK3308_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 | 1224 div << RK3308_CRU_CLK_CORE_DBG_DIV_CON_SHIFT); 1225 } 1226 1227 return 0; 1228 } 1229 1230 uint32_t 1231 rk3308_get_pll(struct rkclock_softc *sc, bus_size_t base) 1232 { 1233 uint32_t fbdiv, postdiv1, postdiv2, refdiv; 1234 uint32_t dsmpd, fracdiv; 1235 uint64_t frac = 0; 1236 uint32_t reg; 1237 1238 reg = HREAD4(sc, base + 0x0000); 1239 postdiv1 = (reg & RK3308_CRU_PLL_POSTDIV1_MASK) >> 1240 RK3308_CRU_PLL_POSTDIV1_SHIFT; 1241 fbdiv = (reg & RK3308_CRU_PLL_FBDIV_MASK) >> 1242 RK3308_CRU_PLL_FBDIV_SHIFT; 1243 reg = HREAD4(sc, base + 0x0004); 1244 dsmpd = (reg & RK3308_CRU_PLL_DSMPD); 1245 postdiv2 = (reg & RK3308_CRU_PLL_POSTDIV2_MASK) >> 1246 RK3308_CRU_PLL_POSTDIV2_SHIFT; 1247 refdiv = (reg & RK3308_CRU_PLL_REFDIV_MASK) >> 1248 RK3308_CRU_PLL_REFDIV_SHIFT; 1249 reg = HREAD4(sc, base + 0x0008); 1250 fracdiv = (reg & RK3308_CRU_PLL_FRACDIV_MASK) >> 1251 RK3308_CRU_PLL_FRACDIV_SHIFT; 1252 1253 if (dsmpd == 0) 1254 frac = (24000000ULL * fracdiv / refdiv) >> 24; 1255 return ((24000000ULL * fbdiv / refdiv) + frac) / postdiv1 / postdiv2; 1256 } 1257 1258 int 1259 rk3308_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq) 1260 { 1261 uint32_t fbdiv, postdiv1, postdiv2, refdiv; 1262 int mode_shift = -1; 1263 1264 switch (base) { 1265 case RK3308_CRU_APLL_CON(0): 1266 mode_shift = 0; 1267 break; 1268 case RK3308_CRU_DPLL_CON(0): 1269 mode_shift = 2; 1270 break; 1271 case RK3308_CRU_VPLL0_CON(0): 1272 mode_shift = 4; 1273 break; 1274 case RK3308_CRU_VPLL1_CON(0): 1275 mode_shift = 6; 1276 break; 1277 } 1278 KASSERT(mode_shift != -1); 1279 1280 /* 1281 * It is not clear whether all combinations of the clock 1282 * dividers result in a stable clock. Therefore this function 1283 * only supports a limited set of PLL clock rates. For now 1284 * this set covers all the CPU frequencies supported by the 1285 * Linux kernel. 1286 */ 1287 switch (freq) { 1288 case 1608000000U: 1289 case 1584000000U: 1290 case 1560000000U: 1291 case 1536000000U: 1292 case 1512000000U: 1293 case 1488000000U: 1294 case 1464000000U: 1295 case 1440000000U: 1296 case 1416000000U: 1297 case 1392000000U: 1298 case 1368000000U: 1299 case 1344000000U: 1300 case 1320000000U: 1301 case 1296000000U: 1302 case 1272000000U: 1303 case 1248000000U: 1304 case 1200000000U: 1305 case 1104000000U: 1306 postdiv1 = postdiv2 = refdiv = 1; 1307 break; 1308 case 1188000000U: 1309 refdiv = 2; postdiv1 = postdiv2 = 1; 1310 break; 1311 case 1100000000U: 1312 refdiv = 12; postdiv1 = postdiv2 = 1; 1313 break; 1314 case 1000000000U: 1315 refdiv = 6; postdiv1 = postdiv2 = 1; 1316 break; 1317 case 1008000000U: 1318 case 984000000U: 1319 case 960000000U: 1320 case 936000000U: 1321 case 912000000U: 1322 case 888000000U: 1323 case 864000000U: 1324 case 840000000U: 1325 case 816000000U: 1326 case 696000000U: 1327 case 624000000U: 1328 postdiv1 = 2; postdiv2 = refdiv = 1; 1329 break; 1330 case 900000000U: 1331 refdiv = 4; postdiv1 = 2; postdiv2 = 1; 1332 break; 1333 case 800000000U: 1334 case 700000000U: 1335 case 500000000U: 1336 refdiv = 6; postdiv1 = 2; postdiv2 = 1; 1337 break; 1338 case 600000000U: 1339 case 504000000U: 1340 postdiv1 = 3; postdiv2 = refdiv = 1; 1341 break; 1342 case 594000000U: 1343 refdiv = 2; postdiv1 = 2; postdiv2 = 1; 1344 break; 1345 case 408000000U: 1346 case 312000000U: 1347 postdiv1 = postdiv2 = 2; refdiv = 1; 1348 break; 1349 case 216000000U: 1350 postdiv1 = 4; postdiv2 = 2; refdiv = 1; 1351 break; 1352 case 96000000U: 1353 postdiv1 = postdiv2 = 4; refdiv = 1; 1354 break; 1355 default: 1356 printf("%s: %u Hz\n", __func__, freq); 1357 return -1; 1358 } 1359 1360 /* Calculate feedback divider. */ 1361 fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000; 1362 1363 /* 1364 * Select slow mode to guarantee a stable clock while we're 1365 * adjusting the PLL. 1366 */ 1367 HWRITE4(sc, RK3308_CRU_CRU_MODE, 1368 (RK3308_CRU_CRU_MODE_MASK << 16 | 1369 RK3308_CRU_CRU_MODE_SLOW) << mode_shift); 1370 1371 /* Set PLL rate. */ 1372 HWRITE4(sc, base + 0x0000, 1373 RK3308_CRU_PLL_POSTDIV1_MASK << 16 | 1374 postdiv1 << RK3308_CRU_PLL_POSTDIV1_SHIFT | 1375 RK3308_CRU_PLL_FBDIV_MASK << 16 | 1376 fbdiv << RK3308_CRU_PLL_FBDIV_SHIFT); 1377 HWRITE4(sc, base + 0x0004, 1378 RK3308_CRU_PLL_DSMPD << 16 | RK3308_CRU_PLL_DSMPD | 1379 RK3308_CRU_PLL_POSTDIV2_MASK << 16 | 1380 postdiv2 << RK3308_CRU_PLL_POSTDIV2_SHIFT | 1381 RK3308_CRU_PLL_REFDIV_MASK << 16 | 1382 refdiv << RK3308_CRU_PLL_REFDIV_SHIFT); 1383 1384 /* Wait for PLL to stabilize. */ 1385 while ((HREAD4(sc, base + 0x0004) & RK3308_CRU_PLL_PLL_LOCK) == 0) 1386 delay(10); 1387 1388 /* Switch back to normal mode. */ 1389 HWRITE4(sc, RK3308_CRU_CRU_MODE, 1390 (RK3308_CRU_CRU_MODE_MASK << 16 | 1391 RK3308_CRU_CRU_MODE_NORMAL) << mode_shift); 1392 1393 return 0; 1394 } 1395 1396 uint32_t 1397 rk3308_get_rtc32k(struct rkclock_softc *sc) 1398 { 1399 uint32_t reg, mux, pll, div_con; 1400 1401 reg = HREAD4(sc, RK3308_CRU_CLKSEL_CON(2)); 1402 mux = (reg & 0x300) >> 8; 1403 if (mux != 3) { 1404 printf("%s: RTC32K not using clk_32k_div\n", __func__); 1405 return 0; 1406 } 1407 1408 if ((reg >> 10) & 1) 1409 pll = RK3308_PLL_VPLL1; 1410 else 1411 pll = RK3308_PLL_VPLL0; 1412 1413 div_con = HREAD4(sc, RK3308_CRU_CLKSEL_CON(4)) & 0xffff; 1414 return rk3308_get_frequency(sc, &pll) / (div_con + 1); 1415 } 1416 1417 int 1418 rk3308_set_rtc32k(struct rkclock_softc *sc, uint32_t freq) 1419 { 1420 const struct rkclock *clk; 1421 uint32_t vpll0_freq, vpll1_freq, mux, div_con; 1422 1423 clk = rkclock_lookup(sc, RK3308_CLK_RTC32K); 1424 vpll0_freq = rkclock_freq(sc, clk, 0, freq); 1425 vpll1_freq = rkclock_freq(sc, clk, 1, freq); 1426 mux = 0; 1427 freq = vpll0_freq; 1428 1429 if ((vpll1_freq > vpll0_freq && vpll1_freq <= freq) || 1430 (vpll1_freq < vpll0_freq && vpll1_freq >= freq)) { 1431 mux = 1; 1432 freq = vpll1_freq; 1433 } 1434 1435 div_con = rkclock_div_con(sc, clk, mux, freq); 1436 HWRITE4(sc, RK3308_CRU_CLKSEL_CON(2), 1 << 26 | (mux << 10)); 1437 HWRITE4(sc, RK3308_CRU_CLKSEL_CON(4), 0xffff0000 | div_con); 1438 return 0; 1439 } 1440 1441 uint32_t 1442 rk3308_get_frequency(void *cookie, uint32_t *cells) 1443 { 1444 struct rkclock_softc *sc = cookie; 1445 uint32_t idx = cells[0]; 1446 1447 switch (idx) { 1448 case RK3308_PLL_APLL: 1449 return rk3308_get_pll(sc, RK3308_CRU_APLL_CON(0)); 1450 case RK3308_PLL_DPLL: 1451 return rk3308_get_pll(sc, RK3308_CRU_DPLL_CON(0)); 1452 case RK3308_PLL_VPLL0: 1453 return rk3308_get_pll(sc, RK3308_CRU_VPLL0_CON(0)); 1454 case RK3308_PLL_VPLL1: 1455 return rk3308_get_pll(sc, RK3308_CRU_VPLL1_CON(0)); 1456 case RK3308_ARMCLK: 1457 return rk3308_get_armclk(sc); 1458 case RK3308_XIN24M: 1459 return 24000000; 1460 case RK3308_CLK_RTC32K: 1461 return rk3308_get_rtc32k(sc); 1462 1463 /* 1464 * XXX The USB480M clock is external. Returning zero here will cause 1465 * it to be ignored for reparenting purposes. 1466 */ 1467 case RK3308_USB480M: 1468 return 0; 1469 default: 1470 break; 1471 } 1472 1473 return rkclock_get_frequency(sc, idx); 1474 } 1475 1476 int 1477 rk3308_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 1478 { 1479 struct rkclock_softc *sc = cookie; 1480 uint32_t idx = cells[0]; 1481 1482 switch (idx) { 1483 case RK3308_PLL_APLL: 1484 return rk3308_set_pll(sc, RK3308_CRU_APLL_CON(0), freq); 1485 case RK3308_PLL_DPLL: 1486 return rk3308_set_pll(sc, RK3308_CRU_DPLL_CON(0), freq); 1487 case RK3308_PLL_VPLL0: 1488 return rk3308_set_pll(sc, RK3308_CRU_VPLL0_CON(0), freq); 1489 case RK3308_PLL_VPLL1: 1490 return rk3308_set_pll(sc, RK3308_CRU_VPLL1_CON(0), freq); 1491 case RK3308_ARMCLK: 1492 return rk3308_set_armclk(sc, freq); 1493 case RK3308_CLK_RTC32K: 1494 return rk3308_set_rtc32k(sc, freq); 1495 default: 1496 break; 1497 } 1498 1499 return rkclock_set_frequency(sc, idx, freq); 1500 } 1501 1502 1503 int 1504 rk3308_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells) 1505 { 1506 struct rkclock_softc *sc = cookie; 1507 1508 if (pcells[0] != sc->sc_phandle) 1509 return -1; 1510 1511 return rkclock_set_parent(sc, cells[0], pcells[1]); 1512 } 1513 1514 void 1515 rk3308_enable(void *cookie, uint32_t *cells, int on) 1516 { 1517 uint32_t idx = cells[0]; 1518 1519 /* 1520 * All clocks are enabled by default, so there is nothing for 1521 * us to do until we start disabling clocks. 1522 */ 1523 if (!on) 1524 printf("%s: 0x%08x\n", __func__, idx); 1525 } 1526 1527 void 1528 rk3308_reset(void *cookie, uint32_t *cells, int on) 1529 { 1530 struct rkclock_softc *sc = cookie; 1531 uint32_t idx = cells[0]; 1532 uint32_t mask = (1 << (idx % 16)); 1533 1534 HWRITE4(sc, RK3308_CRU_SOFTRST_CON(idx / 16), 1535 mask << 16 | (on ? mask : 0)); 1536 } 1537 1538 1539 /* 1540 * Rockchip RK3328 1541 */ 1542 1543 const struct rkclock rk3328_clocks[] = { 1544 { 1545 RK3328_CLK_RTC32K, RK3328_CRU_CLKSEL_CON(38), 1546 SEL(15, 14), DIV(13, 0), 1547 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M } 1548 }, 1549 { 1550 RK3328_CLK_SPI, RK3328_CRU_CLKSEL_CON(24), 1551 SEL(7, 7), DIV(6, 0), 1552 { RK3328_PLL_CPLL, RK3328_PLL_GPLL } 1553 }, 1554 { 1555 RK3328_CLK_SDMMC, RK3328_CRU_CLKSEL_CON(30), 1556 SEL(9, 8), DIV(7, 0), 1557 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M, 1558 RK3328_USB480M } 1559 }, 1560 { 1561 RK3328_CLK_SDIO, RK3328_CRU_CLKSEL_CON(31), 1562 SEL(9, 8), DIV(7, 0), 1563 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M, 1564 RK3328_USB480M } 1565 }, 1566 { 1567 RK3328_CLK_EMMC, RK3328_CRU_CLKSEL_CON(32), 1568 SEL(9, 8), DIV(7, 0), 1569 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_XIN24M, 1570 RK3328_USB480M } 1571 }, 1572 { 1573 RK3328_CLK_TSADC, RK3328_CRU_CLKSEL_CON(22), 1574 0, DIV(9, 0), 1575 { RK3328_CLK_24M } 1576 }, 1577 { 1578 RK3328_CLK_UART0, RK3328_CRU_CLKSEL_CON(14), 1579 SEL(9, 8), 0, 1580 { 0, 0, RK3328_XIN24M, RK3328_XIN24M } 1581 }, 1582 { 1583 RK3328_CLK_UART1, RK3328_CRU_CLKSEL_CON(16), 1584 SEL(9, 8), 0, 1585 { 0, 0, RK3328_XIN24M, RK3328_XIN24M } 1586 }, 1587 { 1588 RK3328_CLK_UART2, RK3328_CRU_CLKSEL_CON(18), 1589 SEL(9, 8), 0, 1590 { 0, 0, RK3328_XIN24M, RK3328_XIN24M } 1591 }, 1592 { 1593 RK3328_CLK_WIFI, RK3328_CRU_CLKSEL_CON(52), 1594 SEL(7, 6), DIV(5, 0), 1595 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_USB480M } 1596 }, 1597 { 1598 RK3328_CLK_I2C0, RK3328_CRU_CLKSEL_CON(34), 1599 SEL(7, 7), DIV(6, 0), 1600 { RK3328_PLL_CPLL, RK3328_PLL_GPLL } 1601 }, 1602 { 1603 RK3328_CLK_I2C1, RK3328_CRU_CLKSEL_CON(34), 1604 SEL(15, 15), DIV(14, 8), 1605 { RK3328_PLL_CPLL, RK3328_PLL_GPLL } 1606 }, 1607 { 1608 RK3328_CLK_I2C2, RK3328_CRU_CLKSEL_CON(35), 1609 SEL(7, 7), DIV(6, 0), 1610 { RK3328_PLL_CPLL, RK3328_PLL_GPLL } 1611 }, 1612 { 1613 RK3328_CLK_I2C3, RK3328_CRU_CLKSEL_CON(35), 1614 SEL(15, 15), DIV(14, 8), 1615 { RK3328_PLL_CPLL, RK3328_PLL_GPLL } 1616 }, 1617 { 1618 RK3328_CLK_CRYPTO, RK3328_CRU_CLKSEL_CON(20), 1619 SEL(7, 7), DIV(4, 0), 1620 { RK3328_PLL_CPLL, RK3328_PLL_GPLL } 1621 }, 1622 { 1623 RK3328_CLK_PDM, RK3328_CRU_CLKSEL_CON(20), 1624 SEL(15, 14), DIV(12, 8), 1625 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_PLL_APLL }, 1626 FIXED_PARENT | SET_PARENT 1627 }, 1628 { 1629 RK3328_CLK_VDEC_CABAC, RK3328_CRU_CLKSEL_CON(48), 1630 SEL(15, 14), DIV(12, 8), 1631 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY, 1632 RK3328_USB480M } 1633 }, 1634 { 1635 RK3328_CLK_VDEC_CORE, RK3328_CRU_CLKSEL_CON(49), 1636 SEL(7, 6), DIV(4, 0), 1637 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY, 1638 RK3328_USB480M } 1639 }, 1640 { 1641 RK3328_CLK_VENC_DSP, RK3328_CRU_CLKSEL_CON(52), 1642 SEL(15, 14), DIV(12, 8), 1643 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY, 1644 RK3328_USB480M } 1645 }, 1646 { 1647 RK3328_CLK_VENC_CORE, RK3328_CRU_CLKSEL_CON(51), 1648 SEL(15, 14), DIV(12, 8), 1649 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY, 1650 RK3328_USB480M } 1651 }, 1652 { 1653 RK3328_CLK_TSP, RK3328_CRU_CLKSEL_CON(21), 1654 SEL(15, 15), DIV(12, 8), 1655 { RK3328_PLL_CPLL, RK3328_PLL_GPLL } 1656 }, 1657 { 1658 RK3328_CLK_MAC2IO_SRC, RK3328_CRU_CLKSEL_CON(27), 1659 SEL(7, 7), DIV(4, 0), 1660 { RK3328_PLL_CPLL, RK3328_PLL_GPLL } 1661 }, 1662 { 1663 RK3328_DCLK_LCDC, RK3328_CRU_CLKSEL_CON(40), 1664 SEL(1, 1), 0, 1665 { RK3328_HDMIPHY, RK3328_DCLK_LCDC_SRC } 1666 }, 1667 { 1668 RK3328_ACLK_VOP_PRE, RK3328_CRU_CLKSEL_CON(39), 1669 SEL(7, 6), DIV(4, 0), 1670 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY, 1671 RK3328_USB480M } 1672 }, 1673 { 1674 RK3328_ACLK_RGA_PRE, RK3328_CRU_CLKSEL_CON(36), 1675 SEL(15, 14), DIV(12, 8), 1676 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY, 1677 RK3328_USB480M } 1678 }, 1679 { 1680 RK3328_ACLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(0), 1681 SEL(14, 13), DIV(12, 8), 1682 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY } 1683 }, 1684 { 1685 RK3328_ACLK_PERI_PRE, RK3328_CRU_CLKSEL_CON(28), 1686 SEL(7, 6), DIV(4, 0), 1687 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY } 1688 }, 1689 { 1690 RK3328_ACLK_RKVDEC_PRE, RK3328_CRU_CLKSEL_CON(48), 1691 SEL(7, 6), DIV(4, 0), 1692 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY, 1693 RK3328_USB480M } 1694 }, 1695 { 1696 RK3328_ACLK_RKVENC, RK3328_CRU_CLKSEL_CON(51), 1697 SEL(7, 6), DIV(4, 0), 1698 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY, 1699 RK3328_USB480M } 1700 }, 1701 { 1702 RK3328_ACLK_VPU_PRE, RK3328_CRU_CLKSEL_CON(50), 1703 SEL(7, 6), DIV(4, 0), 1704 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY, 1705 RK3328_USB480M } 1706 }, 1707 { 1708 RK3328_ACLK_VIO_PRE, RK3328_CRU_CLKSEL_CON(37), 1709 SEL(7, 6), DIV(4, 0), 1710 { RK3328_PLL_CPLL, RK3328_PLL_GPLL, RK3328_HDMIPHY, 1711 RK3328_USB480M } 1712 }, 1713 { 1714 RK3328_PCLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(1), 1715 0, DIV(14, 12), 1716 { RK3328_ACLK_BUS_PRE } 1717 }, 1718 { 1719 RK3328_HCLK_BUS_PRE, RK3328_CRU_CLKSEL_CON(1), 1720 0, DIV(9, 8), 1721 { RK3328_ACLK_BUS_PRE } 1722 }, 1723 { 1724 RK3328_PCLK_PERI, RK3328_CRU_CLKSEL_CON(29), 1725 0, DIV(6, 4), 1726 { RK3328_ACLK_PERI_PRE } 1727 }, 1728 { 1729 RK3328_HCLK_PERI, RK3328_CRU_CLKSEL_CON(29), 1730 0, DIV(1, 0), 1731 { RK3328_ACLK_PERI_PRE } 1732 }, 1733 { 1734 RK3328_CLK_24M, RK3328_CRU_CLKSEL_CON(2), 1735 0, DIV(12, 8), 1736 { RK3328_XIN24M } 1737 }, 1738 { 1739 /* Sentinel */ 1740 } 1741 }; 1742 1743 void 1744 rk3328_init(struct rkclock_softc *sc) 1745 { 1746 int i; 1747 1748 /* The code below assumes all clocks are enabled. Check this!. */ 1749 for (i = 0; i <= 28; i++) { 1750 if (HREAD4(sc, RK3328_CRU_CLKGATE_CON(i)) != 0x00000000) { 1751 printf("CRU_CLKGATE_CON%d: 0x%08x\n", i, 1752 HREAD4(sc, RK3328_CRU_CLKGATE_CON(i))); 1753 } 1754 } 1755 1756 sc->sc_clocks = rk3328_clocks; 1757 } 1758 1759 uint32_t 1760 rk3328_armclk_parent(uint32_t mux) 1761 { 1762 switch (mux) { 1763 case 0: 1764 return RK3328_PLL_APLL; 1765 case 1: 1766 return RK3328_PLL_GPLL; 1767 case 2: 1768 return RK3328_PLL_DPLL; 1769 case 3: 1770 return RK3328_PLL_NPLL; 1771 } 1772 1773 return 0; 1774 } 1775 1776 uint32_t 1777 rk3328_get_armclk(struct rkclock_softc *sc) 1778 { 1779 uint32_t reg, mux, div_con; 1780 uint32_t idx; 1781 1782 reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(0)); 1783 mux = (reg & RK3328_CRU_CORE_CLK_PLL_SEL_MASK) >> 1784 RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT; 1785 div_con = (reg & RK3328_CRU_CLK_CORE_DIV_CON_MASK) >> 1786 RK3328_CRU_CLK_CORE_DIV_CON_SHIFT; 1787 idx = rk3328_armclk_parent(mux); 1788 1789 return rk3328_get_frequency(sc, &idx) / (div_con + 1); 1790 } 1791 1792 int 1793 rk3328_set_armclk(struct rkclock_softc *sc, uint32_t freq) 1794 { 1795 uint32_t reg, mux; 1796 uint32_t old_freq, div; 1797 uint32_t idx; 1798 1799 old_freq = rk3328_get_armclk(sc); 1800 if (freq == old_freq) 1801 return 0; 1802 1803 reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(0)); 1804 mux = (reg & RK3328_CRU_CORE_CLK_PLL_SEL_MASK) >> 1805 RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT; 1806 1807 /* Keep the pclk_dbg clock at or below 300 MHz. */ 1808 div = 1; 1809 while (freq / (div + 1) > 300000000) 1810 div++; 1811 /* and make sure we use an odd divider. */ 1812 if ((div % 2) == 0) 1813 div++; 1814 1815 /* When ramping up, set clock dividers first. */ 1816 if (freq > old_freq) { 1817 HWRITE4(sc, RK3328_CRU_CLKSEL_CON(0), 1818 RK3328_CRU_CLK_CORE_DIV_CON_MASK << 16 | 1819 0 << RK3328_CRU_CLK_CORE_DIV_CON_SHIFT); 1820 HWRITE4(sc, RK3328_CRU_CLKSEL_CON(1), 1821 RK3328_CRU_ACLK_CORE_DIV_CON_MASK << 16 | 1822 1 << RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT | 1823 RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 | 1824 div << RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT); 1825 } 1826 1827 /* We always use NPLL and force the switch below if needed. */ 1828 idx = RK3328_PLL_NPLL; 1829 rk3328_set_frequency(sc, &idx, freq); 1830 1831 /* When ramping down, set clock dividers last. */ 1832 if (freq < old_freq || mux != 3) { 1833 HWRITE4(sc, RK3328_CRU_CLKSEL_CON(0), 1834 RK3328_CRU_CORE_CLK_PLL_SEL_MASK << 16 | 1835 3 << RK3328_CRU_CORE_CLK_PLL_SEL_SHIFT | 1836 RK3328_CRU_CLK_CORE_DIV_CON_MASK << 16 | 1837 0 << RK3328_CRU_CLK_CORE_DIV_CON_SHIFT); 1838 HWRITE4(sc, RK3328_CRU_CLKSEL_CON(1), 1839 RK3328_CRU_ACLK_CORE_DIV_CON_MASK << 16 | 1840 1 << RK3328_CRU_ACLK_CORE_DIV_CON_SHIFT | 1841 RK3328_CRU_CLK_CORE_DBG_DIV_CON_MASK << 16 | 1842 div << RK3328_CRU_CLK_CORE_DBG_DIV_CON_SHIFT); 1843 } 1844 1845 return 0; 1846 } 1847 1848 uint32_t 1849 rk3328_get_pll(struct rkclock_softc *sc, bus_size_t base) 1850 { 1851 uint32_t fbdiv, postdiv1, postdiv2, refdiv; 1852 uint32_t dsmpd, fracdiv; 1853 uint64_t frac = 0; 1854 uint32_t reg; 1855 1856 reg = HREAD4(sc, base + 0x0000); 1857 postdiv1 = (reg & RK3328_CRU_PLL_POSTDIV1_MASK) >> 1858 RK3328_CRU_PLL_POSTDIV1_SHIFT; 1859 fbdiv = (reg & RK3328_CRU_PLL_FBDIV_MASK) >> 1860 RK3328_CRU_PLL_FBDIV_SHIFT; 1861 reg = HREAD4(sc, base + 0x0004); 1862 dsmpd = (reg & RK3328_CRU_PLL_DSMPD); 1863 postdiv2 = (reg & RK3328_CRU_PLL_POSTDIV2_MASK) >> 1864 RK3328_CRU_PLL_POSTDIV2_SHIFT; 1865 refdiv = (reg & RK3328_CRU_PLL_REFDIV_MASK) >> 1866 RK3328_CRU_PLL_REFDIV_SHIFT; 1867 reg = HREAD4(sc, base + 0x0008); 1868 fracdiv = (reg & RK3328_CRU_PLL_FRACDIV_MASK) >> 1869 RK3328_CRU_PLL_FRACDIV_SHIFT; 1870 1871 if (dsmpd == 0) 1872 frac = (24000000ULL * fracdiv / refdiv) >> 24; 1873 return ((24000000ULL * fbdiv / refdiv) + frac) / postdiv1 / postdiv2; 1874 } 1875 1876 int 1877 rk3328_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq) 1878 { 1879 uint32_t fbdiv, postdiv1, postdiv2, refdiv; 1880 int mode_shift = -1; 1881 1882 switch (base) { 1883 case RK3328_CRU_APLL_CON(0): 1884 mode_shift = 0; 1885 break; 1886 case RK3328_CRU_DPLL_CON(0): 1887 mode_shift = 4; 1888 break; 1889 case RK3328_CRU_CPLL_CON(0): 1890 mode_shift = 8; 1891 break; 1892 case RK3328_CRU_GPLL_CON(0): 1893 mode_shift = 12; 1894 break; 1895 case RK3328_CRU_NPLL_CON(0): 1896 mode_shift = 1; 1897 break; 1898 } 1899 KASSERT(mode_shift != -1); 1900 1901 /* 1902 * It is not clear whether all combinations of the clock 1903 * dividers result in a stable clock. Therefore this function 1904 * only supports a limited set of PLL clock rates. For now 1905 * this set covers all the CPU frequencies supported by the 1906 * Linux kernel. 1907 */ 1908 switch (freq) { 1909 case 1800000000U: 1910 case 1704000000U: 1911 case 1608000000U: 1912 case 1512000000U: 1913 case 1488000000U: 1914 case 1416000000U: 1915 case 1392000000U: 1916 case 1296000000U: 1917 case 1200000000U: 1918 case 1104000000U: 1919 postdiv1 = postdiv2 = refdiv = 1; 1920 break; 1921 case 1008000000U: 1922 case 912000000U: 1923 case 816000000U: 1924 case 696000000U: 1925 postdiv1 = 2; postdiv2 = refdiv = 1; 1926 break; 1927 case 600000000U: 1928 postdiv1 = 3; postdiv2 = refdiv = 1; 1929 break; 1930 case 408000000U: 1931 case 312000000U: 1932 postdiv1 = postdiv2 = 2; refdiv = 1; 1933 break; 1934 case 216000000U: 1935 postdiv1 = 4; postdiv2 = 2; refdiv = 1; 1936 break; 1937 case 96000000U: 1938 postdiv1 = postdiv2 = 4; refdiv = 1; 1939 break; 1940 default: 1941 printf("%s: %u Hz\n", __func__, freq); 1942 return -1; 1943 } 1944 1945 /* Calculate feedback divider. */ 1946 fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000; 1947 1948 /* 1949 * Select slow mode to guarantee a stable clock while we're 1950 * adjusting the PLL. 1951 */ 1952 HWRITE4(sc, RK3328_CRU_CRU_MODE, 1953 (RK3328_CRU_CRU_MODE_MASK << 16 | 1954 RK3328_CRU_CRU_MODE_SLOW) << mode_shift); 1955 1956 /* Set PLL rate. */ 1957 HWRITE4(sc, base + 0x0000, 1958 RK3328_CRU_PLL_POSTDIV1_MASK << 16 | 1959 postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT | 1960 RK3328_CRU_PLL_FBDIV_MASK << 16 | 1961 fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT); 1962 HWRITE4(sc, base + 0x0004, 1963 RK3328_CRU_PLL_DSMPD << 16 | RK3328_CRU_PLL_DSMPD | 1964 RK3328_CRU_PLL_POSTDIV2_MASK << 16 | 1965 postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT | 1966 RK3328_CRU_PLL_REFDIV_MASK << 16 | 1967 refdiv << RK3328_CRU_PLL_REFDIV_SHIFT); 1968 1969 /* Wait for PLL to stabilize. */ 1970 while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0) 1971 delay(10); 1972 1973 /* Switch back to normal mode. */ 1974 HWRITE4(sc, RK3328_CRU_CRU_MODE, 1975 (RK3328_CRU_CRU_MODE_MASK << 16 | 1976 RK3328_CRU_CRU_MODE_NORMAL) << mode_shift); 1977 1978 return 0; 1979 } 1980 1981 int 1982 rk3328_set_frac_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq) 1983 { 1984 uint32_t fbdiv, postdiv1, postdiv2, refdiv, fracdiv; 1985 int mode_shift = -1; 1986 uint32_t reg; 1987 1988 switch (base) { 1989 case RK3328_CRU_APLL_CON(0): 1990 mode_shift = 0; 1991 break; 1992 case RK3328_CRU_DPLL_CON(0): 1993 mode_shift = 4; 1994 break; 1995 case RK3328_CRU_CPLL_CON(0): 1996 mode_shift = 8; 1997 break; 1998 case RK3328_CRU_GPLL_CON(0): 1999 mode_shift = 12; 2000 break; 2001 case RK3328_CRU_NPLL_CON(0): 2002 mode_shift = 1; 2003 break; 2004 } 2005 KASSERT(mode_shift != -1); 2006 2007 /* 2008 * It is not clear whether all combinations of the clock 2009 * dividers result in a stable clock. Therefore this function 2010 * only supports a limited set of PLL clock rates. This set 2011 * set covers all the fractional PLL frequencies supported by 2012 * the Linux kernel. 2013 */ 2014 switch (freq) { 2015 case 1016064000U: 2016 postdiv1 = postdiv2 = 1; refdiv = 3; fracdiv = 134217; 2017 break; 2018 case 983040000U: 2019 postdiv1 = postdiv2 = 1; refdiv = 24; fracdiv = 671088; 2020 break; 2021 case 491520000U: 2022 postdiv1 = 2; postdiv2 = 1; refdiv = 24; fracdiv = 671088; 2023 break; 2024 case 61440000U: 2025 postdiv1 = 7; postdiv2 = 2; refdiv = 6; fracdiv = 671088; 2026 break; 2027 case 56448000U: 2028 postdiv1 = postdiv2 = 4; refdiv = 12; fracdiv = 9797894; 2029 break; 2030 case 40960000U: 2031 postdiv1 = 4; postdiv2 = 5; refdiv = 12; fracdiv = 10066239; 2032 break; 2033 default: 2034 printf("%s: %u Hz\n", __func__, freq); 2035 return -1; 2036 } 2037 2038 /* Calculate feedback divider. */ 2039 fbdiv = (uint64_t)freq * postdiv1 * postdiv2 * refdiv / 24000000; 2040 2041 /* 2042 * Select slow mode to guarantee a stable clock while we're 2043 * adjusting the PLL. 2044 */ 2045 HWRITE4(sc, RK3328_CRU_CRU_MODE, 2046 (RK3328_CRU_CRU_MODE_MASK << 16 | 2047 RK3328_CRU_CRU_MODE_SLOW) << mode_shift); 2048 2049 /* Set PLL rate. */ 2050 HWRITE4(sc, base + 0x0000, 2051 RK3328_CRU_PLL_POSTDIV1_MASK << 16 | 2052 postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT | 2053 RK3328_CRU_PLL_FBDIV_MASK << 16 | 2054 fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT); 2055 HWRITE4(sc, base + 0x0004, 2056 RK3328_CRU_PLL_DSMPD << 16 | 2057 RK3328_CRU_PLL_POSTDIV2_MASK << 16 | 2058 postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT | 2059 RK3328_CRU_PLL_REFDIV_MASK << 16 | 2060 refdiv << RK3328_CRU_PLL_REFDIV_SHIFT); 2061 reg = HREAD4(sc, base + 0x0008); 2062 reg &= ~RK3328_CRU_PLL_FRACDIV_MASK; 2063 reg |= fracdiv << RK3328_CRU_PLL_FRACDIV_SHIFT; 2064 HWRITE4(sc, base + 0x0008, reg); 2065 2066 /* Wait for PLL to stabilize. */ 2067 while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0) 2068 delay(10); 2069 2070 /* Switch back to normal mode. */ 2071 HWRITE4(sc, RK3328_CRU_CRU_MODE, 2072 (RK3328_CRU_CRU_MODE_MASK << 16 | 2073 RK3328_CRU_CRU_MODE_NORMAL) << mode_shift); 2074 2075 return 0; 2076 } 2077 2078 uint32_t 2079 rk3328_get_frequency(void *cookie, uint32_t *cells) 2080 { 2081 struct rkclock_softc *sc = cookie; 2082 uint32_t idx = cells[0]; 2083 uint32_t reg; 2084 2085 switch (idx) { 2086 case RK3328_PLL_APLL: 2087 return rk3328_get_pll(sc, RK3328_CRU_APLL_CON(0)); 2088 case RK3328_PLL_DPLL: 2089 return rk3328_get_pll(sc, RK3328_CRU_DPLL_CON(0)); 2090 case RK3328_PLL_CPLL: 2091 return rk3328_get_pll(sc, RK3328_CRU_CPLL_CON(0)); 2092 case RK3328_PLL_GPLL: 2093 return rk3328_get_pll(sc, RK3328_CRU_GPLL_CON(0)); 2094 case RK3328_PLL_NPLL: 2095 return rk3328_get_pll(sc, RK3328_CRU_NPLL_CON(0)); 2096 case RK3328_ARMCLK: 2097 return rk3328_get_armclk(sc); 2098 case RK3328_XIN24M: 2099 return 24000000; 2100 case RK3328_GMAC_CLKIN: 2101 return 125000000; 2102 /* 2103 * XXX The HDMIPHY and USB480M clocks are external. Returning 2104 * zero here will cause them to be ignored for reparenting 2105 * purposes. 2106 */ 2107 case RK3328_HDMIPHY: 2108 return 0; 2109 case RK3328_USB480M: 2110 return 0; 2111 case RK3328_CLK_MAC2IO: 2112 reg = regmap_read_4(sc->sc_grf, RK3328_GRF_MAC_CON1); 2113 if (reg & RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL) 2114 idx = RK3328_GMAC_CLKIN; 2115 else 2116 idx = RK3328_CLK_MAC2IO_SRC; 2117 return rk3328_get_frequency(sc, &idx); 2118 default: 2119 break; 2120 } 2121 2122 return rkclock_get_frequency(sc, idx); 2123 } 2124 2125 int 2126 rk3328_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 2127 { 2128 struct rkclock_softc *sc = cookie; 2129 uint32_t idx = cells[0]; 2130 uint32_t reg, mux; 2131 2132 switch (idx) { 2133 case RK3328_PLL_APLL: 2134 return rk3328_set_frac_pll(sc, RK3328_CRU_APLL_CON(0), freq); 2135 case RK3328_PLL_DPLL: 2136 return rk3328_set_pll(sc, RK3328_CRU_DPLL_CON(0), freq); 2137 case RK3328_PLL_CPLL: 2138 return rk3328_set_pll(sc, RK3328_CRU_CPLL_CON(0), freq); 2139 case RK3328_PLL_GPLL: 2140 return rk3328_set_frac_pll(sc, RK3328_CRU_GPLL_CON(0), freq); 2141 case RK3328_PLL_NPLL: 2142 return rk3328_set_pll(sc, RK3328_CRU_NPLL_CON(0), freq); 2143 case RK3328_ARMCLK: 2144 return rk3328_set_armclk(sc, freq); 2145 case RK3328_CLK_UART0: 2146 case RK3328_CLK_UART1: 2147 case RK3328_CLK_UART2: 2148 if (freq == rk3328_get_frequency(sc, &idx)) 2149 return 0; 2150 break; 2151 case RK3328_DCLK_LCDC: 2152 reg = HREAD4(sc, RK3328_CRU_CLKSEL_CON(40)); 2153 mux = (reg & RK3328_CRU_VOP_DCLK_SRC_SEL_MASK) >> 2154 RK3328_CRU_VOP_DCLK_SRC_SEL_SHIFT; 2155 idx = (mux == 0) ? RK3328_HDMIPHY : RK3328_DCLK_LCDC_SRC; 2156 return rk3328_set_frequency(sc, &idx, freq); 2157 case RK3328_HCLK_CRYPTO_SLV: 2158 idx = RK3328_HCLK_BUS_PRE; 2159 return rk3328_set_frequency(sc, &idx, freq); 2160 default: 2161 break; 2162 } 2163 2164 return rkclock_set_frequency(sc, idx, freq); 2165 } 2166 2167 int 2168 rk3328_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells) 2169 { 2170 struct rkclock_softc *sc = cookie; 2171 uint32_t idx = cells[0]; 2172 uint32_t parent; 2173 2174 if (pcells[0] == sc->sc_phandle) 2175 parent = pcells[1]; 2176 else { 2177 char name[32]; 2178 int node; 2179 2180 node = OF_getnodebyphandle(pcells[0]); 2181 if (node == 0) 2182 return -1; 2183 name[0] = 0; 2184 OF_getprop(node, "clock-output-names", name, sizeof(name)); 2185 name[sizeof(name) - 1] = 0; 2186 if (strcmp(name, "xin24m") == 0) 2187 parent = RK3328_XIN24M; 2188 else if (strcmp(name, "gmac_clkin") == 0) 2189 parent = RK3328_GMAC_CLKIN; 2190 else 2191 return -1; 2192 } 2193 2194 switch (idx) { 2195 case RK3328_CLK_MAC2IO: 2196 if (parent == RK3328_GMAC_CLKIN) { 2197 regmap_write_4(sc->sc_grf, RK3328_GRF_MAC_CON1, 2198 RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL << 16 | 2199 RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL); 2200 } else { 2201 regmap_write_4(sc->sc_grf, RK3328_GRF_MAC_CON1, 2202 RK3328_GRF_GMAC2IO_RMII_EXTCLK_SEL << 16); 2203 } 2204 return 0; 2205 case RK3328_CLK_MAC2IO_EXT: 2206 if (parent == RK3328_GMAC_CLKIN) { 2207 regmap_write_4(sc->sc_grf, RK3328_GRF_SOC_CON4, 2208 RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN << 16 | 2209 RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN); 2210 } else { 2211 regmap_write_4(sc->sc_grf, RK3328_GRF_SOC_CON4, 2212 RK3328_GRF_GMAC2IO_MAC_CLK_OUTPUT_EN << 16); 2213 } 2214 return 0; 2215 } 2216 2217 return rkclock_set_parent(sc, idx, parent); 2218 } 2219 2220 void 2221 rk3328_enable(void *cookie, uint32_t *cells, int on) 2222 { 2223 uint32_t idx = cells[0]; 2224 2225 /* 2226 * All clocks are enabled by default, so there is nothing for 2227 * us to do until we start disabling clocks. 2228 */ 2229 if (!on) 2230 printf("%s: 0x%08x\n", __func__, idx); 2231 } 2232 2233 void 2234 rk3328_reset(void *cookie, uint32_t *cells, int on) 2235 { 2236 struct rkclock_softc *sc = cookie; 2237 uint32_t idx = cells[0]; 2238 uint32_t mask = (1 << (idx % 16)); 2239 2240 HWRITE4(sc, RK3328_CRU_SOFTRST_CON(idx / 16), 2241 mask << 16 | (on ? mask : 0)); 2242 } 2243 2244 /* 2245 * Rockchip RK3399 2246 */ 2247 2248 const struct rkclock rk3399_clocks[] = { 2249 { 2250 RK3399_CLK_I2C1, RK3399_CRU_CLKSEL_CON(61), 2251 SEL(7, 7), DIV(6, 0), 2252 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2253 }, 2254 { 2255 RK3399_CLK_I2C2, RK3399_CRU_CLKSEL_CON(62), 2256 SEL(7, 7), DIV(6, 0), 2257 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2258 }, 2259 { 2260 RK3399_CLK_I2C3, RK3399_CRU_CLKSEL_CON(63), 2261 SEL(7, 7), DIV(6, 0), 2262 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2263 }, 2264 { 2265 RK3399_CLK_I2C5, RK3399_CRU_CLKSEL_CON(61), 2266 SEL(15, 15), DIV(14, 8), 2267 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2268 }, 2269 { 2270 RK3399_CLK_I2C6, RK3399_CRU_CLKSEL_CON(62), 2271 SEL(15, 15), DIV(14, 8), 2272 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2273 }, 2274 { 2275 RK3399_CLK_I2C7, RK3399_CRU_CLKSEL_CON(63), 2276 SEL(15, 15), DIV(14, 8), 2277 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2278 }, 2279 { 2280 RK3399_CLK_SPI0, RK3399_CRU_CLKSEL_CON(59), 2281 SEL(7, 7), DIV(6, 0), 2282 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2283 }, 2284 { 2285 RK3399_CLK_SPI1, RK3399_CRU_CLKSEL_CON(59), 2286 SEL(15, 15), DIV(14, 8), 2287 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2288 }, 2289 { 2290 RK3399_CLK_SPI2, RK3399_CRU_CLKSEL_CON(60), 2291 SEL(7, 7), DIV(6, 0), 2292 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2293 }, 2294 { 2295 RK3399_CLK_SPI4, RK3399_CRU_CLKSEL_CON(60), 2296 SEL(15, 15), DIV(14, 8), 2297 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2298 }, 2299 { 2300 RK3399_CLK_SPI5, RK3399_CRU_CLKSEL_CON(58), 2301 SEL(15, 15), DIV(14, 8), 2302 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2303 }, 2304 { 2305 RK3399_CLK_SDMMC, RK3399_CRU_CLKSEL_CON(16), 2306 SEL(10, 8), DIV(6, 0), 2307 { RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL, 2308 /* RK3399_PLL_PPLL */ 0, /* RK3399_USB_480M */ 0, 2309 RK3399_XIN24M } 2310 }, 2311 { 2312 RK3399_CLK_SDIO, RK3399_CRU_CLKSEL_CON(15), 2313 SEL(10, 8), DIV(6, 0), 2314 { RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL, 2315 /* RK3399_PLL_PPLL */ 0, /* RK3399_USB_480M */ 0, 2316 RK3399_XIN24M } 2317 }, 2318 { 2319 RK3399_CLK_EMMC, RK3399_CRU_CLKSEL_CON(22), 2320 SEL(10, 8), DIV(6, 0), 2321 { RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL, 2322 /* RK3399_USB_480M */ 0, RK3399_XIN24M } 2323 }, 2324 { 2325 RK3399_CLK_TSADC, RK3399_CRU_CLKSEL_CON(27), 2326 SEL(15, 15), DIV(9, 0), 2327 { RK3399_XIN24M, RK3399_CLK_32K } 2328 }, 2329 { 2330 RK3399_CLK_UART0, RK3399_CRU_CLKSEL_CON(33), 2331 SEL(9, 8), 0, 2332 { 0, 0, RK3399_XIN24M } 2333 }, 2334 { 2335 RK3399_CLK_UART1, RK3399_CRU_CLKSEL_CON(34), 2336 SEL(9, 8), 0, 2337 { 0, 0, RK3399_XIN24M } 2338 }, 2339 { 2340 RK3399_CLK_UART2, RK3399_CRU_CLKSEL_CON(35), 2341 SEL(9, 8), 0, 2342 { 0, 0, RK3399_XIN24M } 2343 }, 2344 { 2345 RK3399_CLK_UART3, RK3399_CRU_CLKSEL_CON(36), 2346 SEL(9, 8), 0, 2347 { 0, 0, RK3399_XIN24M } 2348 }, 2349 { 2350 RK3399_CLK_I2S0_8CH, RK3399_CRU_CLKSEL_CON(28), 2351 SEL(9, 8), 0, 2352 { RK3399_CLK_I2S0_DIV, RK3399_CLK_I2S0_FRAC, 0, RK3399_XIN12M }, 2353 SET_PARENT 2354 }, 2355 { 2356 RK3399_CLK_I2S1_8CH, RK3399_CRU_CLKSEL_CON(29), 2357 SEL(9, 8), 0, 2358 { RK3399_CLK_I2S1_DIV, RK3399_CLK_I2S1_FRAC, 0, RK3399_XIN12M }, 2359 SET_PARENT 2360 }, 2361 { 2362 RK3399_CLK_I2S2_8CH, RK3399_CRU_CLKSEL_CON(30), 2363 SEL(9, 8), 0, 2364 { RK3399_CLK_I2S2_DIV, RK3399_CLK_I2S2_FRAC, 0, RK3399_XIN12M }, 2365 SET_PARENT 2366 }, 2367 { 2368 RK3399_CLK_I2S_8CH_OUT, RK3399_CRU_CLKSEL_CON(31), 2369 SEL(2, 2), 0, 2370 { RK3399_CLK_I2SOUT_SRC, RK3399_XIN12M }, 2371 SET_PARENT 2372 }, 2373 { 2374 RK3399_CLK_MAC, RK3399_CRU_CLKSEL_CON(20), 2375 SEL(15, 14), DIV(12, 8), 2376 { RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL } 2377 }, 2378 { 2379 RK3399_CLK_UPHY0_TCPDCORE, RK3399_CRU_CLKSEL_CON(64), 2380 SEL(7, 6), DIV(4, 0), 2381 { RK3399_XIN24M, RK3399_CLK_32K, RK3399_PLL_CPLL, 2382 RK3399_PLL_GPLL } 2383 }, 2384 { 2385 RK3399_CLK_UPHY1_TCPDCORE, RK3399_CRU_CLKSEL_CON(65), 2386 SEL(7, 6), DIV(4, 0), 2387 { RK3399_XIN24M, RK3399_CLK_32K, RK3399_PLL_CPLL, 2388 RK3399_PLL_GPLL } 2389 }, 2390 { 2391 RK3399_CLK_PCIEPHY_REF, RK3399_CRU_CLKSEL_CON(18), 2392 SEL(10, 10), 0, 2393 { RK3399_XIN24M, RK3399_CLK_PCIEPHY_REF100M }, 2394 SET_PARENT 2395 }, 2396 { 2397 RK3399_CLK_PCIEPHY_REF100M, RK3399_CRU_CLKSEL_CON(18), 2398 0, DIV(15, 11), 2399 { RK3399_PLL_NPLL } 2400 }, 2401 { 2402 RK3399_DCLK_VOP0, RK3399_CRU_CLKSEL_CON(49), 2403 SEL(11, 11), 0, 2404 { RK3399_DCLK_VOP0_DIV, RK3399_DCLK_VOP0_FRAC }, 2405 SET_PARENT 2406 }, 2407 { 2408 RK3399_DCLK_VOP1, RK3399_CRU_CLKSEL_CON(50), 2409 SEL(11, 11), 0, 2410 { RK3399_DCLK_VOP1_DIV, RK3399_DCLK_VOP1_FRAC }, 2411 SET_PARENT 2412 }, 2413 { 2414 RK3399_DCLK_VOP0_DIV, RK3399_CRU_CLKSEL_CON(49), 2415 SEL(9, 8), DIV(7, 0), 2416 { RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2417 }, 2418 { 2419 RK3399_DCLK_VOP1_DIV, RK3399_CRU_CLKSEL_CON(50), 2420 SEL(9, 8), DIV(7, 0), 2421 { RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2422 }, 2423 { 2424 RK3399_ACLK_PERIPH, RK3399_CRU_CLKSEL_CON(14), 2425 SEL(7, 7), DIV(4, 0), 2426 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2427 }, 2428 { 2429 RK3399_ACLK_PERILP0, RK3399_CRU_CLKSEL_CON(23), 2430 SEL(7, 7), DIV(4, 0), 2431 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2432 }, 2433 { 2434 RK3399_ACLK_VIO, RK3399_CRU_CLKSEL_CON(42), 2435 SEL(7, 6), DIV(4, 0), 2436 { RK3399_PLL_CPLL, RK3399_PLL_GPLL, /* RK3399_PLL_PPLL */ } 2437 }, 2438 { 2439 RK3399_ACLK_CCI, RK3399_CRU_CLKSEL_CON(5), 2440 SEL(7, 6), DIV(4, 0), 2441 { RK3399_PLL_CPLL, RK3399_PLL_GPLL, RK3399_PLL_NPLL, 2442 RK3399_PLL_VPLL } 2443 }, 2444 { 2445 RK3399_ACLK_VOP0, RK3399_CRU_CLKSEL_CON(47), 2446 SEL(7, 6), DIV(4, 0), 2447 { RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL, 2448 RK3399_PLL_NPLL } 2449 }, 2450 { 2451 RK3399_ACLK_VOP1, RK3399_CRU_CLKSEL_CON(48), 2452 SEL(7, 6), DIV(4, 0), 2453 { RK3399_PLL_VPLL, RK3399_PLL_CPLL, RK3399_PLL_GPLL, 2454 RK3399_PLL_NPLL } 2455 }, 2456 { 2457 RK3399_ACLK_HDCP, RK3399_CRU_CLKSEL_CON(42), 2458 SEL(15, 14), DIV(12, 8), 2459 { RK3399_PLL_CPLL, RK3399_PLL_GPLL, /* RK3399_PLL_PPLL */ } 2460 }, 2461 { 2462 RK3399_ACLK_GIC_PRE, RK3399_CRU_CLKSEL_CON(56), 2463 SEL(15, 15), DIV(12, 8), 2464 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2465 }, 2466 { 2467 RK3399_PCLK_PERIPH, RK3399_CRU_CLKSEL_CON(14), 2468 0, DIV(14, 12), 2469 { RK3399_ACLK_PERIPH } 2470 }, 2471 { 2472 RK3399_PCLK_PERILP0, RK3399_CRU_CLKSEL_CON(23), 2473 0, DIV(14, 12), 2474 { RK3399_ACLK_PERILP0 } 2475 }, 2476 { 2477 RK3399_PCLK_PERILP1, RK3399_CRU_CLKSEL_CON(25), 2478 0, DIV(10, 8), 2479 { RK3399_HCLK_PERILP1 } 2480 }, 2481 { 2482 RK3399_PCLK_DDR, RK3399_CRU_CLKSEL_CON(6), 2483 SEL(15, 15), DIV(12, 8), 2484 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2485 }, 2486 { 2487 RK3399_PCLK_WDT, RK3399_CRU_CLKSEL_CON(57), 2488 0, DIV(4, 0), 2489 { RK3399_PLL_GPLL } 2490 }, 2491 { 2492 RK3399_HCLK_PERIPH, RK3399_CRU_CLKSEL_CON(14), 2493 0, DIV(9, 8), 2494 { RK3399_ACLK_PERIPH } 2495 }, 2496 { 2497 RK3399_HCLK_PERILP0, RK3399_CRU_CLKSEL_CON(23), 2498 0, DIV(9, 8), 2499 { RK3399_ACLK_PERILP0 } 2500 }, 2501 { 2502 RK3399_HCLK_PERILP1, RK3399_CRU_CLKSEL_CON(25), 2503 SEL(7, 7), DIV(4, 0), 2504 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2505 }, 2506 { 2507 RK3399_HCLK_SDMMC, RK3399_CRU_CLKSEL_CON(13), 2508 SEL(15, 15), DIV(12, 8), 2509 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2510 }, 2511 { 2512 RK3399_HCLK_VOP0, RK3399_CRU_CLKSEL_CON(47), 2513 0, DIV(12, 8), 2514 { RK3399_ACLK_VOP0 } 2515 }, 2516 { 2517 RK3399_HCLK_VOP1, RK3399_CRU_CLKSEL_CON(48), 2518 0, DIV(12, 8), 2519 { RK3399_ACLK_VOP1 } 2520 }, 2521 { 2522 RK3399_CLK_I2S0_DIV, RK3399_CRU_CLKSEL_CON(28), 2523 SEL(7, 7), DIV(6, 0), 2524 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2525 }, 2526 { 2527 RK3399_CLK_I2S1_DIV, RK3399_CRU_CLKSEL_CON(29), 2528 SEL(7, 7), DIV(6, 0), 2529 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2530 }, 2531 { 2532 RK3399_CLK_I2S2_DIV, RK3399_CRU_CLKSEL_CON(30), 2533 SEL(7, 7), DIV(6, 0), 2534 { RK3399_PLL_CPLL, RK3399_PLL_GPLL } 2535 }, 2536 { 2537 RK3399_CLK_I2SOUT_SRC, RK3399_CRU_CLKSEL_CON(31), 2538 SEL(1, 0), 0, 2539 { RK3399_CLK_I2S0_8CH, RK3399_CLK_I2S1_8CH, 2540 RK3399_CLK_I2S2_8CH }, 2541 SET_PARENT 2542 }, 2543 { 2544 /* Sentinel */ 2545 } 2546 }; 2547 2548 /* Some of our parent clocks live in the PMUCRU. */ 2549 struct rkclock_softc *rk3399_pmucru_sc; 2550 2551 void 2552 rk3399_init(struct rkclock_softc *sc) 2553 { 2554 int i; 2555 2556 /* PMUCRU instance should attach before us. */ 2557 KASSERT(rk3399_pmucru_sc != NULL); 2558 2559 /* 2560 * The U-Boot shipped on the Theobroma Systems RK3399-Q7 2561 * module is buggy and sets the parent of the clock for the 2562 * "big" cluster to LPLL. Undo that mistake here such that 2563 * the clocks of both clusters are independent. 2564 */ 2565 HWRITE4(sc, RK3399_CRU_CLKSEL_CON(2), 2566 RK3399_CRU_CORE_PLL_SEL_MASK << 16 | 2567 RK3399_CRU_CORE_PLL_SEL_BPLL); 2568 2569 /* The code below assumes all clocks are enabled. Check this!. */ 2570 for (i = 0; i <= 34; i++) { 2571 if (HREAD4(sc, RK3399_CRU_CLKGATE_CON(i)) != 0x00000000) { 2572 printf("CRU_CLKGATE_CON%d: 0x%08x\n", i, 2573 HREAD4(sc, RK3399_CRU_CLKGATE_CON(i))); 2574 } 2575 } 2576 2577 sc->sc_clocks = rk3399_clocks; 2578 } 2579 2580 uint32_t 2581 rk3399_get_pll(struct rkclock_softc *sc, bus_size_t base) 2582 { 2583 uint32_t fbdiv, postdiv1, postdiv2, refdiv; 2584 uint32_t pll_work_mode; 2585 uint32_t reg; 2586 2587 reg = HREAD4(sc, base + 0x000c); 2588 pll_work_mode = reg & RK3399_CRU_PLL_PLL_WORK_MODE_MASK; 2589 if (pll_work_mode == RK3399_CRU_PLL_PLL_WORK_MODE_SLOW) 2590 return 24000000; 2591 if (pll_work_mode == RK3399_CRU_PLL_PLL_WORK_MODE_DEEP_SLOW) 2592 return 32768; 2593 2594 reg = HREAD4(sc, base + 0x0000); 2595 fbdiv = (reg & RK3399_CRU_PLL_FBDIV_MASK) >> 2596 RK3399_CRU_PLL_FBDIV_SHIFT; 2597 reg = HREAD4(sc, base + 0x0004); 2598 postdiv2 = (reg & RK3399_CRU_PLL_POSTDIV2_MASK) >> 2599 RK3399_CRU_PLL_POSTDIV2_SHIFT; 2600 postdiv1 = (reg & RK3399_CRU_PLL_POSTDIV1_MASK) >> 2601 RK3399_CRU_PLL_POSTDIV1_SHIFT; 2602 refdiv = (reg & RK3399_CRU_PLL_REFDIV_MASK) >> 2603 RK3399_CRU_PLL_REFDIV_SHIFT; 2604 return 24000000ULL * fbdiv / refdiv / postdiv1 / postdiv2; 2605 } 2606 2607 int 2608 rk3399_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq) 2609 { 2610 uint32_t fbdiv, postdiv1, postdiv2, refdiv; 2611 2612 /* 2613 * It is not clear whether all combinations of the clock 2614 * dividers result in a stable clock. Therefore this function 2615 * only supports a limited set of PLL clock rates. For now 2616 * this set covers all the CPU frequencies supported by the 2617 * Linux kernel. 2618 */ 2619 switch (freq) { 2620 case 2208000000U: 2621 case 2184000000U: 2622 case 2088000000U: 2623 case 2040000000U: 2624 case 2016000000U: 2625 case 1992000000U: 2626 case 1896000000U: 2627 case 1800000000U: 2628 case 1704000000U: 2629 case 1608000000U: 2630 case 1512000000U: 2631 case 1488000000U: 2632 case 1416000000U: 2633 case 1200000000U: 2634 postdiv1 = postdiv2 = refdiv = 1; 2635 break; 2636 case 1008000000U: 2637 case 816000000U: 2638 case 696000000U: 2639 postdiv1 = 2; postdiv2 = refdiv = 1; 2640 break; 2641 case 676000000U: 2642 postdiv1 = 2; postdiv2 = 1; refdiv = 3; 2643 break; 2644 case 1000000000U: 2645 case 800000000U: 2646 case 600000000U: 2647 postdiv1 = 3; postdiv2 = refdiv = 1; 2648 break; 2649 case 594000000U: 2650 postdiv1 = 4; postdiv2 = refdiv = 1; 2651 break; 2652 case 408000000U: 2653 postdiv1 = postdiv2 = 2; refdiv = 1; 2654 break; 2655 case 297000000U: 2656 case 216000000U: 2657 postdiv1 = 4; postdiv2 = 2; refdiv = 1; 2658 break; 2659 case 148500000U: 2660 case 96000000U: 2661 postdiv1 = postdiv2 = 4; refdiv = 1; 2662 break; 2663 case 74250000U: 2664 postdiv1 = postdiv2 = 4; refdiv = 2; 2665 break; 2666 case 65000000U: 2667 case 54000000U: 2668 case 27000000U: 2669 postdiv1 = 6; postdiv2 = 4; refdiv = 1; 2670 break; 2671 default: 2672 printf("%s: %d Hz\n", __func__, freq); 2673 return -1; 2674 } 2675 2676 /* Calculate feedback divider. */ 2677 fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000; 2678 2679 /* 2680 * Select slow mode to guarantee a stable clock while we're 2681 * adjusting the PLL. 2682 */ 2683 HWRITE4(sc, base + 0x000c, 2684 RK3399_CRU_PLL_PLL_WORK_MODE_MASK << 16 | 2685 RK3399_CRU_PLL_PLL_WORK_MODE_SLOW); 2686 2687 /* Set PLL rate. */ 2688 HWRITE4(sc, base + 0x0000, 2689 RK3399_CRU_PLL_FBDIV_MASK << 16 | 2690 fbdiv << RK3399_CRU_PLL_FBDIV_SHIFT); 2691 HWRITE4(sc, base + 0x0004, 2692 RK3399_CRU_PLL_POSTDIV2_MASK << 16 | 2693 postdiv2 << RK3399_CRU_PLL_POSTDIV2_SHIFT | 2694 RK3399_CRU_PLL_POSTDIV1_MASK << 16 | 2695 postdiv1 << RK3399_CRU_PLL_POSTDIV1_SHIFT | 2696 RK3399_CRU_PLL_REFDIV_MASK << 16 | 2697 refdiv << RK3399_CRU_PLL_REFDIV_SHIFT); 2698 2699 /* Wait for PLL to stabilize. */ 2700 while ((HREAD4(sc, base + 0x0008) & RK3399_CRU_PLL_PLL_LOCK) == 0) 2701 delay(10); 2702 2703 /* Switch back to normal mode. */ 2704 HWRITE4(sc, base + 0x000c, 2705 RK3399_CRU_PLL_PLL_WORK_MODE_MASK << 16 | 2706 RK3399_CRU_PLL_PLL_WORK_MODE_NORMAL); 2707 2708 return 0; 2709 } 2710 2711 uint32_t 2712 rk3399_armclk_parent(uint32_t mux) 2713 { 2714 switch (mux) { 2715 case 0: 2716 return RK3399_PLL_ALPLL; 2717 case 1: 2718 return RK3399_PLL_ABPLL; 2719 case 2: 2720 return RK3399_PLL_DPLL; 2721 case 3: 2722 return RK3399_PLL_GPLL; 2723 } 2724 2725 return 0; 2726 } 2727 2728 uint32_t 2729 rk3399_get_armclk(struct rkclock_softc *sc, bus_size_t clksel) 2730 { 2731 uint32_t reg, mux, div_con; 2732 uint32_t idx; 2733 2734 reg = HREAD4(sc, clksel); 2735 mux = (reg & RK3399_CRU_CORE_PLL_SEL_MASK) >> 2736 RK3399_CRU_CORE_PLL_SEL_SHIFT; 2737 div_con = (reg & RK3399_CRU_CLK_CORE_DIV_CON_MASK) >> 2738 RK3399_CRU_CLK_CORE_DIV_CON_SHIFT; 2739 idx = rk3399_armclk_parent(mux); 2740 2741 return rk3399_get_frequency(sc, &idx) / (div_con + 1); 2742 } 2743 2744 int 2745 rk3399_set_armclk(struct rkclock_softc *sc, bus_size_t clksel, uint32_t freq) 2746 { 2747 uint32_t reg, mux; 2748 uint32_t old_freq, div; 2749 uint32_t idx; 2750 2751 old_freq = rk3399_get_armclk(sc, clksel); 2752 if (freq == old_freq) 2753 return 0; 2754 2755 reg = HREAD4(sc, clksel); 2756 mux = (reg & RK3399_CRU_CORE_PLL_SEL_MASK) >> 2757 RK3399_CRU_CORE_PLL_SEL_SHIFT; 2758 idx = rk3399_armclk_parent(mux); 2759 2760 /* Keep the atclk_core and pclk_dbg clocks at or below 200 MHz. */ 2761 div = 1; 2762 while (freq / (div + 1) > 200000000) 2763 div++; 2764 2765 /* When ramping up, set clock dividers first. */ 2766 if (freq > old_freq) { 2767 HWRITE4(sc, clksel, 2768 RK3399_CRU_CLK_CORE_DIV_CON_MASK << 16 | 2769 0 << RK3399_CRU_CLK_CORE_DIV_CON_SHIFT | 2770 RK3399_CRU_ACLKM_CORE_DIV_CON_MASK << 16 | 2771 1 << RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT); 2772 HWRITE4(sc, clksel + 0x0004, 2773 RK3399_CRU_PCLK_DBG_DIV_CON_MASK << 16 | 2774 div << RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT | 2775 RK3399_CRU_ATCLK_CORE_DIV_CON_MASK << 16 | 2776 div << RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT); 2777 } 2778 2779 rk3399_set_frequency(sc, &idx, freq); 2780 2781 /* When ramping down, set clock dividers last. */ 2782 if (freq < old_freq) { 2783 HWRITE4(sc, clksel, 2784 RK3399_CRU_CLK_CORE_DIV_CON_MASK << 16 | 2785 0 << RK3399_CRU_CLK_CORE_DIV_CON_SHIFT | 2786 RK3399_CRU_ACLKM_CORE_DIV_CON_MASK << 16 | 2787 1 << RK3399_CRU_ACLKM_CORE_DIV_CON_SHIFT); 2788 HWRITE4(sc, clksel + 0x0004, 2789 RK3399_CRU_PCLK_DBG_DIV_CON_MASK << 16 | 2790 div << RK3399_CRU_PCLK_DBG_DIV_CON_SHIFT | 2791 RK3399_CRU_ATCLK_CORE_DIV_CON_MASK << 16 | 2792 div << RK3399_CRU_ATCLK_CORE_DIV_CON_SHIFT); 2793 } 2794 2795 return 0; 2796 } 2797 2798 uint32_t 2799 rk3399_get_frac(struct rkclock_softc *sc, uint32_t parent, bus_size_t base) 2800 { 2801 uint32_t parent_freq, frac; 2802 uint16_t n, d; 2803 2804 frac = HREAD4(sc, base); 2805 n = frac >> 16; 2806 d = frac & 0xffff; 2807 if (n == 0 || d == 0) 2808 n = d = 1; 2809 parent_freq = sc->sc_cd.cd_get_frequency(sc, &parent); 2810 return ((uint64_t)parent_freq * n) / d; 2811 } 2812 2813 int 2814 rk3399_set_frac(struct rkclock_softc *sc, uint32_t parent, bus_size_t base, 2815 uint32_t freq) 2816 { 2817 uint32_t n, d; 2818 uint32_t p0, p1, p2; 2819 uint32_t q0, q1, q2; 2820 uint32_t a, tmp; 2821 2822 n = freq; 2823 d = sc->sc_cd.cd_get_frequency(sc, &parent); 2824 2825 /* 2826 * The denominator needs to be at least 20 times the numerator 2827 * for a stable clock. 2828 */ 2829 if (n == 0 || d == 0 || d < 20 * n) 2830 return -1; 2831 2832 /* 2833 * This is a simplified implementation of the algorithm to 2834 * calculate the best rational approximation using continued 2835 * fractions. 2836 */ 2837 2838 p0 = q1 = 0; 2839 p1 = q0 = 1; 2840 2841 while (d != 0) { 2842 /* 2843 * Calculate next coefficient in the continued 2844 * fraction and keep track of the remainder. 2845 */ 2846 tmp = d; 2847 a = n / d; 2848 d = n % d; 2849 n = tmp; 2850 2851 /* 2852 * Calculate next approximation in the series based on 2853 * the current coefficient. 2854 */ 2855 p2 = p0 + a * p1; 2856 q2 = q0 + a * q1; 2857 2858 /* 2859 * Terminate if we reached the maximum allowed 2860 * denominator. 2861 */ 2862 if (q2 > 0xffff) 2863 break; 2864 2865 p0 = p1; p1 = p2; 2866 q0 = q1; q1 = q2; 2867 } 2868 2869 HWRITE4(sc, base, p1 << 16 | q1); 2870 return 0; 2871 } 2872 2873 uint32_t 2874 rk3399_get_frequency(void *cookie, uint32_t *cells) 2875 { 2876 struct rkclock_softc *sc = cookie; 2877 uint32_t idx = cells[0]; 2878 2879 switch (idx) { 2880 case RK3399_PLL_ALPLL: 2881 return rk3399_get_pll(sc, RK3399_CRU_LPLL_CON(0)); 2882 case RK3399_PLL_ABPLL: 2883 return rk3399_get_pll(sc, RK3399_CRU_BPLL_CON(0)); 2884 case RK3399_PLL_DPLL: 2885 return rk3399_get_pll(sc, RK3399_CRU_DPLL_CON(0)); 2886 case RK3399_PLL_CPLL: 2887 return rk3399_get_pll(sc, RK3399_CRU_CPLL_CON(0)); 2888 case RK3399_PLL_GPLL: 2889 return rk3399_get_pll(sc, RK3399_CRU_GPLL_CON(0)); 2890 case RK3399_PLL_NPLL: 2891 return rk3399_get_pll(sc, RK3399_CRU_NPLL_CON(0)); 2892 case RK3399_PLL_VPLL: 2893 return rk3399_get_pll(sc, RK3399_CRU_VPLL_CON(0)); 2894 case RK3399_ARMCLKL: 2895 return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(0)); 2896 case RK3399_ARMCLKB: 2897 return rk3399_get_armclk(sc, RK3399_CRU_CLKSEL_CON(2)); 2898 case RK3399_XIN24M: 2899 return 24000000; 2900 case RK3399_CLK_32K: 2901 return 32768; 2902 case RK3399_XIN12M: 2903 return 12000000; 2904 case RK3399_CLK_I2S0_FRAC: 2905 return rk3399_get_frac(sc, RK3399_CLK_I2S0_DIV, 2906 RK3399_CRU_CLKSEL_CON(96)); 2907 case RK3399_CLK_I2S1_FRAC: 2908 return rk3399_get_frac(sc, RK3399_CLK_I2S1_DIV, 2909 RK3399_CRU_CLKSEL_CON(97)); 2910 case RK3399_CLK_I2S2_FRAC: 2911 return rk3399_get_frac(sc, RK3399_CLK_I2S2_DIV, 2912 RK3399_CRU_CLKSEL_CON(98)); 2913 default: 2914 break; 2915 } 2916 2917 return rkclock_get_frequency(sc, idx); 2918 } 2919 2920 int 2921 rk3399_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 2922 { 2923 struct rkclock_softc *sc = cookie; 2924 uint32_t idx = cells[0]; 2925 2926 switch (idx) { 2927 case RK3399_PLL_ALPLL: 2928 return rk3399_set_pll(sc, RK3399_CRU_LPLL_CON(0), freq); 2929 case RK3399_PLL_ABPLL: 2930 return rk3399_set_pll(sc, RK3399_CRU_BPLL_CON(0), freq); 2931 case RK3399_PLL_CPLL: 2932 return rk3399_set_pll(sc, RK3399_CRU_CPLL_CON(0), freq); 2933 case RK3399_PLL_GPLL: 2934 return rk3399_set_pll(sc, RK3399_CRU_GPLL_CON(0), freq); 2935 case RK3399_PLL_NPLL: 2936 return rk3399_set_pll(sc, RK3399_CRU_NPLL_CON(0), freq); 2937 case RK3399_PLL_VPLL: 2938 return rk3399_set_pll(sc, RK3399_CRU_VPLL_CON(0), freq); 2939 case RK3399_ARMCLKL: 2940 return rk3399_set_armclk(sc, RK3399_CRU_CLKSEL_CON(0), freq); 2941 case RK3399_ARMCLKB: 2942 return rk3399_set_armclk(sc, RK3399_CRU_CLKSEL_CON(2), freq); 2943 case RK3399_CLK_I2S0_8CH: 2944 rkclock_set_parent(sc, idx, RK3399_CLK_I2S0_FRAC); 2945 return rkclock_set_frequency(sc, idx, freq); 2946 case RK3399_CLK_I2S1_8CH: 2947 rkclock_set_parent(sc, idx, RK3399_CLK_I2S1_FRAC); 2948 return rkclock_set_frequency(sc, idx, freq); 2949 case RK3399_CLK_I2S2_8CH: 2950 rkclock_set_parent(sc, idx, RK3399_CLK_I2S2_FRAC); 2951 return rkclock_set_frequency(sc, idx, freq); 2952 case RK3399_XIN12M: 2953 if (freq / (1000 * 1000) != 12) 2954 return -1; 2955 return 0; 2956 case RK3399_CLK_I2S0_FRAC: 2957 return rk3399_set_frac(sc, RK3399_CLK_I2S0_DIV, 2958 RK3399_CRU_CLKSEL_CON(96), freq); 2959 case RK3399_CLK_I2S1_FRAC: 2960 return rk3399_set_frac(sc, RK3399_CLK_I2S1_DIV, 2961 RK3399_CRU_CLKSEL_CON(97), freq); 2962 case RK3399_CLK_I2S2_FRAC: 2963 return rk3399_set_frac(sc, RK3399_CLK_I2S2_DIV, 2964 RK3399_CRU_CLKSEL_CON(98), freq); 2965 default: 2966 break; 2967 } 2968 2969 return rkclock_set_frequency(sc, idx, freq); 2970 } 2971 2972 2973 int 2974 rk3399_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells) 2975 { 2976 struct rkclock_softc *sc = cookie; 2977 2978 if (pcells[0] != sc->sc_phandle) 2979 return -1; 2980 2981 return rkclock_set_parent(sc, cells[0], pcells[1]); 2982 } 2983 2984 void 2985 rk3399_enable(void *cookie, uint32_t *cells, int on) 2986 { 2987 struct rkclock_softc *sc = cookie; 2988 uint32_t idx = cells[0]; 2989 2990 /* 2991 * All clocks are enabled upon hardware reset, but on some boards the 2992 * firmware will disable some of them. Handle those here. 2993 */ 2994 if (!on) { 2995 printf("%s: 0x%08x\n", __func__, idx); 2996 return; 2997 } 2998 2999 switch (idx) { 3000 case RK3399_CLK_USB2PHY0_REF: 3001 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(6), (1 << 5) << 16); 3002 break; 3003 case RK3399_CLK_USB2PHY1_REF: 3004 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(6), (1 << 6) << 16); 3005 break; 3006 case RK3399_CLK_UPHY0_TCPDPHY_REF: 3007 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(13), (1 << 4) << 16); 3008 break; 3009 case RK3399_CLK_UPHY0_TCPDCORE: 3010 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(13), (1 << 5) << 16); 3011 break; 3012 case RK3399_CLK_UPHY1_TCPDPHY_REF: 3013 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(13), (1 << 6) << 16); 3014 break; 3015 case RK3399_CLK_UPHY1_TCPDCORE: 3016 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(13), (1 << 7) << 16); 3017 break; 3018 case RK3399_ACLK_GMAC: 3019 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(32), (1 << 0) << 16); 3020 break; 3021 case RK3399_PCLK_GMAC: 3022 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(32), (1 << 2) << 16); 3023 break; 3024 case RK3399_CLK_MAC: 3025 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(5), (1 << 5) << 16); 3026 break; 3027 case RK3399_CLK_MAC_RX: 3028 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(5), (1 << 8) << 16); 3029 break; 3030 case RK3399_CLK_MAC_TX: 3031 HWRITE4(sc, RK3399_CRU_CLKGATE_CON(5), (1 << 9) << 16); 3032 break; 3033 } 3034 } 3035 3036 void 3037 rk3399_reset(void *cookie, uint32_t *cells, int on) 3038 { 3039 struct rkclock_softc *sc = cookie; 3040 uint32_t idx = cells[0]; 3041 uint32_t mask = (1 << (idx % 16)); 3042 3043 HWRITE4(sc, RK3399_CRU_SOFTRST_CON(idx / 16), 3044 mask << 16 | (on ? mask : 0)); 3045 } 3046 3047 /* PMUCRU */ 3048 3049 const struct rkclock rk3399_pmu_clocks[] = { 3050 { 3051 RK3399_CLK_I2C0, RK3399_PMUCRU_CLKSEL_CON(2), 3052 0, DIV(6, 0), 3053 { RK3399_PLL_PPLL } 3054 }, 3055 { 3056 RK3399_CLK_I2C4, RK3399_PMUCRU_CLKSEL_CON(3), 3057 0, DIV(6, 0), 3058 { RK3399_PLL_PPLL } 3059 }, 3060 { 3061 RK3399_CLK_I2C8, RK3399_PMUCRU_CLKSEL_CON(2), 3062 0, DIV(14, 8), 3063 { RK3399_PLL_PPLL } 3064 }, 3065 { 3066 RK3399_PCLK_RKPWM, RK3399_PMUCRU_CLKSEL_CON(0), 3067 0, DIV(6, 0), 3068 { RK3399_PLL_PPLL } 3069 }, 3070 { 3071 /* Sentinel */ 3072 } 3073 }; 3074 3075 void 3076 rk3399_pmu_init(struct rkclock_softc *sc) 3077 { 3078 sc->sc_clocks = rk3399_pmu_clocks; 3079 rk3399_pmucru_sc = sc; 3080 } 3081 3082 uint32_t 3083 rk3399_pmu_get_frequency(void *cookie, uint32_t *cells) 3084 { 3085 struct rkclock_softc *sc = cookie; 3086 uint32_t idx = cells[0]; 3087 3088 switch (idx) { 3089 case RK3399_PLL_PPLL: 3090 return rk3399_get_pll(sc, RK3399_PMUCRU_PPLL_CON(0)); 3091 default: 3092 break; 3093 } 3094 3095 return rkclock_get_frequency(sc, idx); 3096 } 3097 3098 int 3099 rk3399_pmu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 3100 { 3101 struct rkclock_softc *sc = cookie; 3102 uint32_t idx = cells[0]; 3103 3104 switch (idx) { 3105 case RK3399_PLL_PPLL: 3106 return rk3399_set_pll(sc, RK3399_PMUCRU_PPLL_CON(0), freq); 3107 default: 3108 break; 3109 } 3110 3111 return rkclock_set_frequency(sc, idx, freq); 3112 } 3113 3114 void 3115 rk3399_pmu_enable(void *cookie, uint32_t *cells, int on) 3116 { 3117 uint32_t idx = cells[0]; 3118 3119 switch (idx) { 3120 case RK3399_CLK_I2C0: 3121 case RK3399_CLK_I2C4: 3122 case RK3399_CLK_I2C8: 3123 case RK3399_PCLK_I2C0: 3124 case RK3399_PCLK_I2C4: 3125 case RK3399_PCLK_I2C8: 3126 case RK3399_PCLK_RKPWM: 3127 /* Enabled by default. */ 3128 break; 3129 default: 3130 printf("%s: 0x%08x\n", __func__, idx); 3131 break; 3132 } 3133 } 3134 3135 void 3136 rk3399_pmu_reset(void *cookie, uint32_t *cells, int on) 3137 { 3138 uint32_t idx = cells[0]; 3139 3140 printf("%s: 0x%08x\n", __func__, idx); 3141 } 3142 3143 /* 3144 * Rockchip RK3568 3145 */ 3146 3147 const struct rkclock rk3568_clocks[] = { 3148 { 3149 RK3568_BCLK_EMMC, RK3568_CRU_CLKSEL_CON(28), 3150 SEL(9, 8), 0, 3151 { RK3568_GPLL_200M, RK3568_GPLL_150M, RK3568_CPLL_125M } 3152 }, 3153 { 3154 RK3568_CCLK_EMMC, RK3568_CRU_CLKSEL_CON(28), 3155 SEL(14, 12), 0, 3156 { RK3568_XIN24M, RK3568_GPLL_200M, RK3568_GPLL_150M, 3157 RK3568_CPLL_100M, RK3568_CPLL_50M, RK3568_CLK_OSC0_DIV_375K } 3158 }, 3159 { 3160 RK3568_TCLK_EMMC, 0, 0, 0, 3161 { RK3568_XIN24M } 3162 }, 3163 3164 { 3165 RK3568_ACLK_PHP, RK3568_CRU_CLKSEL_CON(30), 3166 SEL(1, 0), 0, 3167 { RK3568_GPLL_300M, RK3568_GPLL_200M, 3168 RK3568_GPLL_100M, RK3568_XIN24M } 3169 }, 3170 { 3171 RK3568_PCLK_PHP, RK3568_CRU_CLKSEL_CON(30), 3172 0, DIV(7, 4), 3173 { RK3568_ACLK_PHP } 3174 }, 3175 { 3176 RK3568_CLK_SDMMC0, RK3568_CRU_CLKSEL_CON(30), 3177 SEL(10, 8), 0, 3178 { RK3568_XIN24M, RK3568_GPLL_400M, RK3568_GPLL_300M, 3179 RK3568_CPLL_100M, RK3568_CPLL_50M, RK3568_CLK_OSC0_DIV_750K } 3180 }, 3181 { 3182 RK3568_CLK_SDMMC1, RK3568_CRU_CLKSEL_CON(30), 3183 SEL(14, 12), 0, 3184 { RK3568_XIN24M, RK3568_GPLL_400M, RK3568_GPLL_300M, 3185 RK3568_CPLL_100M, RK3568_CPLL_50M, RK3568_CLK_OSC0_DIV_750K } 3186 }, 3187 { 3188 RK3568_CLK_SDMMC2, RK3568_CRU_CLKSEL_CON(32), 3189 SEL(10, 8), 0, 3190 { RK3568_XIN24M, RK3568_GPLL_400M, RK3568_GPLL_300M, 3191 RK3568_CPLL_100M, RK3568_CPLL_50M, RK3568_CLK_OSC0_DIV_750K } 3192 }, 3193 { 3194 RK3568_ACLK_GMAC0, 0, 0, 0, 3195 { RK3568_ACLK_PHP } 3196 }, 3197 { 3198 RK3568_PCLK_GMAC0, 0, 0, 0, 3199 { RK3568_PCLK_PHP } 3200 }, 3201 { 3202 RK3568_CLK_MAC0_2TOP, RK3568_CRU_CLKSEL_CON(31), 3203 SEL(9, 8), 0, 3204 { RK3568_CPLL_125M, RK3568_CPLL_50M, 3205 RK3568_CPLL_25M, RK3568_XIN24M } 3206 }, 3207 { 3208 RK3568_CLK_MAC0_REFOUT, 0, 0, 0, 3209 { RK3568_CLK_MAC0_2TOP } 3210 }, 3211 { 3212 RK3568_CLK_GMAC0_PTP_REF, RK3568_CRU_CLKSEL_CON(31), 3213 SEL(13, 12), 0, 3214 { RK3568_CPLL_62P5M, RK3568_GPLL_100M, 3215 RK3568_CPLL_50M, RK3568_XIN24M } 3216 }, 3217 { 3218 RK3568_ACLK_USB, RK3568_CRU_CLKSEL_CON(32), 3219 SEL(1, 0), 0, 3220 { RK3568_GPLL_300M, RK3568_GPLL_200M, 3221 RK3568_GPLL_100M, RK3568_XIN24M } 3222 }, 3223 { 3224 RK3568_PCLK_USB, RK3568_CRU_CLKSEL_CON(32), 3225 0, DIV(7, 4), 3226 { RK3568_ACLK_USB } 3227 }, 3228 { 3229 RK3568_ACLK_GMAC1, 0, 0, 0, 3230 { RK3568_ACLK_USB } 3231 }, 3232 { 3233 RK3568_PCLK_GMAC1, 0, 0, 0, 3234 { RK3568_PCLK_USB } 3235 }, 3236 { 3237 RK3568_CLK_MAC1_2TOP, RK3568_CRU_CLKSEL_CON(33), 3238 SEL(9, 8), 0, 3239 { RK3568_CPLL_125M, RK3568_CPLL_50M, 3240 RK3568_CPLL_25M, RK3568_XIN24M } 3241 }, 3242 { 3243 RK3568_CLK_MAC1_REFOUT, 0, 0, 0, 3244 { RK3568_CLK_MAC1_2TOP } 3245 }, 3246 { 3247 RK3568_CLK_GMAC1_PTP_REF, RK3568_CRU_CLKSEL_CON(33), 3248 SEL(13, 12), 0, 3249 { RK3568_CPLL_62P5M, RK3568_GPLL_100M, 3250 RK3568_CPLL_50M, RK3568_XIN24M } 3251 }, 3252 { 3253 RK3568_CLK_TSADC_TSEN, RK3568_CRU_CLKSEL_CON(51), 3254 SEL(5, 4), DIV(2, 0), 3255 { RK3568_XIN24M, RK3568_GPLL_100M, RK3568_CPLL_100M } 3256 }, 3257 { 3258 RK3568_CLK_TSADC, RK3568_CRU_CLKSEL_CON(51), 3259 0, DIV(14, 8), 3260 { RK3568_CLK_TSADC_TSEN } 3261 }, 3262 { 3263 RK3568_SCLK_UART1, RK3568_CRU_CLKSEL_CON(52), 3264 SEL(13, 12), 0, 3265 { 0, 0, RK3568_XIN24M } 3266 }, 3267 { 3268 RK3568_SCLK_UART2, RK3568_CRU_CLKSEL_CON(54), 3269 SEL(13, 12), 0, 3270 { 0, 0, RK3568_XIN24M } 3271 }, 3272 { 3273 RK3568_SCLK_UART3, RK3568_CRU_CLKSEL_CON(56), 3274 SEL(13, 12), 0, 3275 { 0, 0, RK3568_XIN24M } 3276 }, 3277 { 3278 RK3568_SCLK_UART4, RK3568_CRU_CLKSEL_CON(58), 3279 SEL(13, 12), 0, 3280 { 0, 0, RK3568_XIN24M } 3281 }, 3282 { 3283 RK3568_SCLK_UART5, RK3568_CRU_CLKSEL_CON(60), 3284 SEL(13, 12), 0, 3285 { 0, 0, RK3568_XIN24M } 3286 }, 3287 { 3288 RK3568_SCLK_UART6, RK3568_CRU_CLKSEL_CON(62), 3289 SEL(13, 12), 0, 3290 { 0, 0, RK3568_XIN24M } 3291 }, 3292 { 3293 RK3568_SCLK_UART7, RK3568_CRU_CLKSEL_CON(64), 3294 SEL(13, 12), 0, 3295 { 0, 0, RK3568_XIN24M } 3296 }, 3297 { 3298 RK3568_SCLK_UART8, RK3568_CRU_CLKSEL_CON(66), 3299 SEL(13, 12), 0, 3300 { 0, 0, RK3568_XIN24M } 3301 }, 3302 { 3303 RK3568_SCLK_UART9, RK3568_CRU_CLKSEL_CON(68), 3304 SEL(13, 12), 0, 3305 { 0, 0, RK3568_XIN24M } 3306 }, 3307 { 3308 RK3568_CLK_I2C, RK3568_CRU_CLKSEL_CON(71), 3309 SEL(9, 8), 0, 3310 { 0, 0, RK3568_XIN24M } 3311 }, 3312 { 3313 RK3568_CLK_I2C1, 0, 0, 0, 3314 { RK3568_CLK_I2C } 3315 }, 3316 { 3317 RK3568_CLK_I2C2, 0, 0, 0, 3318 { RK3568_CLK_I2C } 3319 }, 3320 { 3321 RK3568_CLK_I2C3, 0, 0, 0, 3322 { RK3568_CLK_I2C } 3323 }, 3324 { 3325 RK3568_CLK_I2C4, 0, 0, 0, 3326 { RK3568_CLK_I2C } 3327 }, 3328 { 3329 RK3568_CLK_I2C5, 0, 0, 0, 3330 { RK3568_CLK_I2C } 3331 }, 3332 { 3333 RK3568_CLK_SPI0, RK3568_CRU_CLKSEL_CON(72), 3334 SEL(1, 0), 0, 3335 { RK3568_GPLL_200M, RK3568_XIN24M, RK3568_CPLL_100M } 3336 }, 3337 { 3338 RK3568_CLK_SPI1, RK3568_CRU_CLKSEL_CON(72), 3339 SEL(3, 2), 0, 3340 { RK3568_GPLL_200M, RK3568_XIN24M, RK3568_CPLL_100M } 3341 }, 3342 { 3343 RK3568_CLK_SPI2, RK3568_CRU_CLKSEL_CON(72), 3344 SEL(5, 4), 0, 3345 { RK3568_GPLL_200M, RK3568_XIN24M, RK3568_CPLL_100M } 3346 }, 3347 { 3348 RK3568_CLK_SPI3, RK3568_CRU_CLKSEL_CON(72), 3349 SEL(7, 6), 0, 3350 { RK3568_GPLL_200M, RK3568_XIN24M, RK3568_CPLL_100M } 3351 }, 3352 { 3353 RK3568_SCLK_GMAC0, RK3568_CRU_CLKSEL_CON(31), 3354 SEL(2, 2), 0, 3355 { RK3568_CLK_MAC0_2TOP, RK3568_GMAC0_CLKIN } 3356 }, 3357 { 3358 RK3568_SCLK_GMAC0_RGMII_SPEED, RK3568_CRU_CLKSEL_CON(31), 3359 SEL(5, 4), 0, 3360 { RK3568_SCLK_GMAC0, RK3568_SCLK_GMAC0, 3361 RK3568_SCLK_GMAC0_DIV_50, RK3568_SCLK_GMAC0_DIV_5 } 3362 }, 3363 { 3364 RK3568_SCLK_GMAC0_RMII_SPEED, RK3568_CRU_CLKSEL_CON(31), 3365 SEL(3, 3), 0, 3366 { RK3568_SCLK_GMAC0_DIV_20, RK3568_SCLK_GMAC0_DIV_2 } 3367 }, 3368 { 3369 RK3568_SCLK_GMAC0_RX_TX, RK3568_CRU_CLKSEL_CON(31), 3370 SEL(1, 0), 0, 3371 { RK3568_SCLK_GMAC0_RGMII_SPEED, RK3568_SCLK_GMAC0_RMII_SPEED } 3372 }, 3373 { 3374 RK3568_SCLK_GMAC1, RK3568_CRU_CLKSEL_CON(33), 3375 SEL(2, 2), 0, 3376 { RK3568_CLK_MAC1_2TOP, RK3568_GMAC1_CLKIN } 3377 }, 3378 { 3379 RK3568_SCLK_GMAC1_RGMII_SPEED, RK3568_CRU_CLKSEL_CON(33), 3380 SEL(5, 4), 0, 3381 { RK3568_SCLK_GMAC1, RK3568_SCLK_GMAC1, 3382 RK3568_SCLK_GMAC1_DIV_50, RK3568_SCLK_GMAC1_DIV_5 } 3383 }, 3384 { 3385 RK3568_SCLK_GMAC1_RMII_SPEED, RK3568_CRU_CLKSEL_CON(33), 3386 SEL(3, 3), 0, 3387 { RK3568_SCLK_GMAC1_DIV_20, RK3568_SCLK_GMAC1_DIV_2 } 3388 }, 3389 { 3390 RK3568_SCLK_GMAC1_RX_TX, RK3568_CRU_CLKSEL_CON(33), 3391 SEL(1, 0), 0, 3392 { RK3568_SCLK_GMAC1_RGMII_SPEED, RK3568_SCLK_GMAC1_RMII_SPEED } 3393 }, 3394 { 3395 RK3568_CPLL_125M, RK3568_CRU_CLKSEL_CON(80), 3396 0, DIV(4, 0), 3397 { RK3568_PLL_CPLL } 3398 }, 3399 { 3400 RK3568_CPLL_62P5M, RK3568_CRU_CLKSEL_CON(80), 3401 0, DIV(12, 8), 3402 { RK3568_PLL_CPLL } 3403 }, 3404 { 3405 RK3568_CPLL_50M, RK3568_CRU_CLKSEL_CON(81), 3406 0, DIV(4, 0), 3407 { RK3568_PLL_CPLL } 3408 }, 3409 { 3410 RK3568_CPLL_25M, RK3568_CRU_CLKSEL_CON(81), 3411 0, DIV(13, 8), 3412 { RK3568_PLL_CPLL } 3413 }, 3414 { 3415 RK3568_CPLL_100M, RK3568_CRU_CLKSEL_CON(82), 3416 0, DIV(4, 0), 3417 { RK3568_PLL_CPLL } 3418 }, 3419 { 3420 RK3568_GPLL_400M, RK3568_CRU_CLKSEL_CON(75), 3421 0, DIV(4, 0), 3422 { RK3568_PLL_GPLL } 3423 }, 3424 { 3425 RK3568_GPLL_300M, RK3568_CRU_CLKSEL_CON(75), 3426 0, DIV(12, 8), 3427 { RK3568_PLL_GPLL } 3428 }, 3429 { 3430 RK3568_GPLL_200M, RK3568_CRU_CLKSEL_CON(76), 3431 0, DIV(4, 0), 3432 { RK3568_PLL_GPLL } 3433 }, 3434 { 3435 RK3568_GPLL_150M, RK3568_CRU_CLKSEL_CON(76), 3436 0, DIV(12, 5), 3437 { RK3568_PLL_GPLL } 3438 }, 3439 { 3440 RK3568_GPLL_100M, RK3568_CRU_CLKSEL_CON(77), 3441 0, DIV(4, 0), 3442 { RK3568_PLL_GPLL } 3443 }, 3444 { 3445 RK3568_CLK_OSC0_DIV_750K, RK3568_CRU_CLKSEL_CON(82), 3446 0, DIV(13, 8), 3447 { RK3568_XIN24M } 3448 }, 3449 { 3450 /* Sentinel */ 3451 } 3452 }; 3453 3454 void 3455 rk3568_init(struct rkclock_softc *sc) 3456 { 3457 int i; 3458 3459 /* The code below assumes all clocks are enabled. Check this!. */ 3460 for (i = 0; i <= 35; i++) { 3461 if (HREAD4(sc, RK3568_CRU_GATE_CON(i)) != 0x00000000) { 3462 printf("CRU_GATE_CON%d: 0x%08x\n", i, 3463 HREAD4(sc, RK3568_CRU_GATE_CON(i))); 3464 } 3465 } 3466 3467 sc->sc_clocks = rk3568_clocks; 3468 } 3469 3470 int 3471 rk3568_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq) 3472 { 3473 uint32_t fbdiv, postdiv1, postdiv2, refdiv; 3474 int mode_shift = -1; 3475 3476 switch (base) { 3477 case RK3568_CRU_APLL_CON(0): 3478 mode_shift = 0; 3479 break; 3480 case RK3568_CRU_DPLL_CON(0): 3481 mode_shift = 2; 3482 break; 3483 case RK3568_CRU_CPLL_CON(0): 3484 mode_shift = 4; 3485 break; 3486 case RK3568_CRU_GPLL_CON(0): 3487 mode_shift = 6; 3488 break; 3489 case RK3568_CRU_NPLL_CON(0): 3490 mode_shift = 10; 3491 break; 3492 case RK3568_CRU_VPLL_CON(0): 3493 mode_shift = 12; 3494 break; 3495 } 3496 KASSERT(mode_shift != -1); 3497 3498 /* 3499 * It is not clear whether all combinations of the clock 3500 * dividers result in a stable clock. Therefore this function 3501 * only supports a limited set of PLL clock rates. 3502 */ 3503 switch (freq) { 3504 case 1200000000U: 3505 postdiv1 = 2; postdiv2 = refdiv = 1; 3506 break; 3507 default: 3508 printf("%s: %u Hz\n", __func__, freq); 3509 return -1; 3510 } 3511 3512 /* Calculate feedback divider. */ 3513 fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000; 3514 3515 /* 3516 * Select slow mode to guarantee a stable clock while we're 3517 * adjusting the PLL. 3518 */ 3519 HWRITE4(sc, RK3568_CRU_MODE_CON, 3520 (RK3328_CRU_CRU_MODE_MASK << 16 | 3521 RK3328_CRU_CRU_MODE_SLOW) << mode_shift); 3522 3523 /* Set PLL rate. */ 3524 HWRITE4(sc, base + 0x0000, 3525 RK3328_CRU_PLL_POSTDIV1_MASK << 16 | 3526 postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT | 3527 RK3328_CRU_PLL_FBDIV_MASK << 16 | 3528 fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT); 3529 HWRITE4(sc, base + 0x0004, 3530 RK3328_CRU_PLL_DSMPD << 16 | RK3328_CRU_PLL_DSMPD | 3531 RK3328_CRU_PLL_POSTDIV2_MASK << 16 | 3532 postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT | 3533 RK3328_CRU_PLL_REFDIV_MASK << 16 | 3534 refdiv << RK3328_CRU_PLL_REFDIV_SHIFT); 3535 3536 /* Wait for PLL to stabilize. */ 3537 while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0) 3538 delay(10); 3539 3540 /* Switch back to normal mode. */ 3541 HWRITE4(sc, RK3568_CRU_MODE_CON, 3542 (RK3328_CRU_CRU_MODE_MASK << 16 | 3543 RK3328_CRU_CRU_MODE_NORMAL) << mode_shift); 3544 3545 return 0; 3546 } 3547 3548 uint32_t 3549 rk3568_get_frequency(void *cookie, uint32_t *cells) 3550 { 3551 struct rkclock_softc *sc = cookie; 3552 uint32_t idx = cells[0]; 3553 3554 switch (idx) { 3555 case RK3568_PLL_APLL: 3556 return rk3328_get_pll(sc, RK3568_CRU_APLL_CON(0)); 3557 case RK3568_PLL_DPLL: 3558 return rk3328_get_pll(sc, RK3568_CRU_DPLL_CON(0)); 3559 case RK3568_PLL_CPLL: 3560 return rk3328_get_pll(sc, RK3568_CRU_CPLL_CON(0)); 3561 case RK3568_PLL_GPLL: 3562 return rk3328_get_pll(sc, RK3568_CRU_GPLL_CON(0)); 3563 case RK3568_PLL_NPLL: 3564 return rk3328_get_pll(sc, RK3568_CRU_NPLL_CON(0)); 3565 case RK3568_PLL_VPLL: 3566 return rk3328_get_pll(sc, RK3568_CRU_VPLL_CON(0)); 3567 case RK3568_SCLK_GMAC0_DIV_50: 3568 idx = RK3568_SCLK_GMAC0; 3569 return rk3568_get_frequency(sc, &idx) / 50; 3570 case RK3568_SCLK_GMAC0_DIV_5: 3571 idx = RK3568_SCLK_GMAC0; 3572 return rk3568_get_frequency(sc, &idx) / 5; 3573 case RK3568_SCLK_GMAC0_DIV_20: 3574 idx = RK3568_SCLK_GMAC0; 3575 return rk3568_get_frequency(sc, &idx) / 20; 3576 case RK3568_SCLK_GMAC0_DIV_2: 3577 idx = RK3568_SCLK_GMAC0; 3578 return rk3568_get_frequency(sc, &idx) / 2; 3579 case RK3568_SCLK_GMAC1_DIV_50: 3580 idx = RK3568_SCLK_GMAC1; 3581 return rk3568_get_frequency(sc, &idx) / 50; 3582 case RK3568_SCLK_GMAC1_DIV_5: 3583 idx = RK3568_SCLK_GMAC1; 3584 return rk3568_get_frequency(sc, &idx) / 5; 3585 case RK3568_SCLK_GMAC1_DIV_20: 3586 idx = RK3568_SCLK_GMAC1; 3587 return rk3568_get_frequency(sc, &idx) / 20; 3588 case RK3568_SCLK_GMAC1_DIV_2: 3589 idx = RK3568_SCLK_GMAC1; 3590 return rk3568_get_frequency(sc, &idx) / 2; 3591 case RK3568_CLK_OSC0_DIV_375K: 3592 idx = RK3568_CLK_OSC0_DIV_750K; 3593 return rk3568_get_frequency(sc, &idx) / 2; 3594 case RK3568_GMAC0_CLKIN: 3595 return rkclock_external_frequency("gmac0_clkin"); 3596 case RK3568_GMAC1_CLKIN: 3597 return rkclock_external_frequency("gmac1_clkin"); 3598 case RK3568_XIN24M: 3599 return 24000000; 3600 default: 3601 break; 3602 } 3603 3604 return rkclock_get_frequency(sc, idx); 3605 } 3606 3607 int 3608 rk3568_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 3609 { 3610 struct rkclock_softc *sc = cookie; 3611 uint32_t idx = cells[0]; 3612 3613 switch (idx) { 3614 case RK3568_PLL_GPLL: 3615 return rk3568_set_pll(sc, RK3568_CRU_GPLL_CON(0), freq); 3616 default: 3617 break; 3618 } 3619 3620 return rkclock_set_frequency(sc, idx, freq); 3621 } 3622 3623 int 3624 rk3568_set_parent(void *cookie, uint32_t *cells, uint32_t *pcells) 3625 { 3626 struct rkclock_softc *sc = cookie; 3627 char buf[64] = {}; 3628 int len, node; 3629 3630 if (pcells[0] != sc->sc_phandle) { 3631 node = OF_getnodebyphandle(pcells[0]); 3632 if (node == 0) 3633 return -1; 3634 len = OF_getproplen(node, "clock-output-names"); 3635 if (len <= 0 || len > sizeof(buf)) 3636 return -1; 3637 OF_getprop(node, "clock-output-names", buf, sizeof(buf)); 3638 3639 if (strcmp(buf, "gmac0_clkin") == 0) { 3640 return rkclock_set_parent(sc, cells[0], 3641 RK3568_GMAC0_CLKIN); 3642 } 3643 if (strcmp(buf, "gmac1_clkin") == 0) { 3644 return rkclock_set_parent(sc, cells[0], 3645 RK3568_GMAC1_CLKIN); 3646 } 3647 3648 printf("%s: 0x%08x 0x%08x\n", __func__, cells[0], pcells[0]); 3649 return -1; 3650 } 3651 3652 return rkclock_set_parent(sc, cells[0], pcells[1]); 3653 } 3654 3655 void 3656 rk3568_enable(void *cookie, uint32_t *cells, int on) 3657 { 3658 uint32_t idx = cells[0]; 3659 3660 /* All clocks are enabled upon hardware reset. */ 3661 if (!on) { 3662 printf("%s: 0x%08x\n", __func__, idx); 3663 return; 3664 } 3665 } 3666 3667 void 3668 rk3568_reset(void *cookie, uint32_t *cells, int on) 3669 { 3670 struct rkclock_softc *sc = cookie; 3671 uint32_t idx = cells[0]; 3672 uint32_t mask = (1 << (idx % 16)); 3673 3674 HWRITE4(sc, RK3568_CRU_SOFTRST_CON(idx / 16), 3675 mask << 16 | (on ? mask : 0)); 3676 } 3677 3678 /* PMUCRU */ 3679 3680 const struct rkclock rk3568_pmu_clocks[] = { 3681 { 3682 RK3568_CLK_RTC_32K, RK3568_PMUCRU_CLKSEL_CON(0), 3683 SEL(7, 6), 0, 3684 { 0, RK3568_XIN32K, RK3568_CLK_RTC32K_FRAC }, 3685 SET_PARENT 3686 }, 3687 { 3688 RK3568_CLK_I2C0, RK3568_PMUCRU_CLKSEL_CON(3), 3689 0, DIV(15, 7), 3690 { RK3568_CLK_PDPMU } 3691 }, 3692 { 3693 RK3568_SCLK_UART0, RK3568_PMUCRU_CLKSEL_CON(4), 3694 SEL(11, 10), 0, 3695 { 0, 0, RK3568_XIN24M } 3696 }, 3697 { 3698 RK3568_CLK_PCIEPHY0_OSC0, 0, 0, 0, 3699 { RK3568_XIN24M } 3700 }, 3701 { 3702 RK3568_CLK_PCIEPHY0_DIV, RK3568_PMUCRU_CLKSEL_CON(9), 3703 0, DIV(2, 0), 3704 { RK3568_PPLL_PH0 } 3705 }, 3706 { 3707 RK3568_CLK_PCIEPHY0_REF, RK3568_PMUCRU_CLKSEL_CON(9), 3708 SEL(3, 3), 0, 3709 { RK3568_CLK_PCIEPHY0_OSC0, RK3568_CLK_PCIEPHY0_DIV }, 3710 SET_PARENT 3711 }, 3712 { 3713 RK3568_CLK_PCIEPHY1_OSC0, 0, 0, 0, 3714 { RK3568_XIN24M } 3715 }, 3716 { 3717 RK3568_CLK_PCIEPHY1_DIV, RK3568_PMUCRU_CLKSEL_CON(9), 3718 0, DIV(6, 4), 3719 { RK3568_PPLL_PH0 } 3720 }, 3721 { 3722 RK3568_CLK_PCIEPHY1_REF, RK3568_PMUCRU_CLKSEL_CON(9), 3723 SEL(7, 7), 0, 3724 { RK3568_CLK_PCIEPHY1_OSC0, RK3568_CLK_PCIEPHY1_DIV }, 3725 SET_PARENT 3726 }, 3727 { 3728 RK3568_CLK_PCIEPHY2_OSC0, 0, 0, 0, 3729 { RK3568_XIN24M } 3730 }, 3731 { 3732 RK3568_CLK_PCIEPHY2_DIV, RK3568_PMUCRU_CLKSEL_CON(9), 3733 0, DIV(10, 8), 3734 { RK3568_PPLL_PH0 } 3735 }, 3736 { 3737 RK3568_CLK_PCIEPHY2_REF, RK3568_PMUCRU_CLKSEL_CON(9), 3738 SEL(11, 11), 0, 3739 { RK3568_CLK_PCIEPHY2_OSC0, RK3568_CLK_PCIEPHY2_DIV }, 3740 SET_PARENT 3741 }, 3742 { 3743 RK3568_CLK_PDPMU, RK3568_PMUCRU_CLKSEL_CON(2), 3744 SEL(15, 15), 0, 3745 { RK3568_PLL_PPLL, 0 } 3746 }, 3747 { 3748 /* Sentinel */ 3749 } 3750 }; 3751 3752 void 3753 rk3568_pmu_init(struct rkclock_softc *sc) 3754 { 3755 int i; 3756 3757 /* The code below assumes all clocks are enabled. Check this!. */ 3758 for (i = 0; i <= 2; i++) { 3759 if (HREAD4(sc, RK3568_PMUCRU_GATE_CON(i)) != 0x00000000) { 3760 printf("CRU_GATE_CON%d: 0x%08x\n", i, 3761 HREAD4(sc, RK3568_CRU_GATE_CON(i))); 3762 } 3763 } 3764 3765 sc->sc_clocks = rk3568_pmu_clocks; 3766 } 3767 3768 int 3769 rk3568_pmu_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq) 3770 { 3771 uint32_t fbdiv, postdiv1, postdiv2, refdiv; 3772 int mode_shift = -1; 3773 3774 switch (base) { 3775 case RK3568_PMUCRU_PPLL_CON(0): 3776 mode_shift = 0; 3777 break; 3778 case RK3568_PMUCRU_HPLL_CON(0): 3779 mode_shift = 2; 3780 break; 3781 } 3782 KASSERT(mode_shift != -1); 3783 3784 /* 3785 * It is not clear whether all combinations of the clock 3786 * dividers result in a stable clock. Therefore this function 3787 * only supports a limited set of PLL clock rates. 3788 */ 3789 switch (freq) { 3790 case 200000000U: 3791 postdiv1 = 3; postdiv2 = 4; refdiv = 1; 3792 break; 3793 default: 3794 printf("%s: %u Hz\n", __func__, freq); 3795 return -1; 3796 } 3797 3798 /* Calculate feedback divider. */ 3799 fbdiv = freq * postdiv1 * postdiv2 * refdiv / 24000000; 3800 3801 /* 3802 * Select slow mode to guarantee a stable clock while we're 3803 * adjusting the PLL. 3804 */ 3805 HWRITE4(sc, RK3568_PMUCRU_MODE_CON, 3806 (RK3328_CRU_CRU_MODE_MASK << 16 | 3807 RK3328_CRU_CRU_MODE_SLOW) << mode_shift); 3808 3809 /* Set PLL rate. */ 3810 HWRITE4(sc, base + 0x0000, 3811 RK3328_CRU_PLL_POSTDIV1_MASK << 16 | 3812 postdiv1 << RK3328_CRU_PLL_POSTDIV1_SHIFT | 3813 RK3328_CRU_PLL_FBDIV_MASK << 16 | 3814 fbdiv << RK3328_CRU_PLL_FBDIV_SHIFT); 3815 HWRITE4(sc, base + 0x0004, 3816 RK3328_CRU_PLL_DSMPD << 16 | RK3328_CRU_PLL_DSMPD | 3817 RK3328_CRU_PLL_POSTDIV2_MASK << 16 | 3818 postdiv2 << RK3328_CRU_PLL_POSTDIV2_SHIFT | 3819 RK3328_CRU_PLL_REFDIV_MASK << 16 | 3820 refdiv << RK3328_CRU_PLL_REFDIV_SHIFT); 3821 3822 /* Wait for PLL to stabilize. */ 3823 while ((HREAD4(sc, base + 0x0004) & RK3328_CRU_PLL_PLL_LOCK) == 0) 3824 delay(10); 3825 3826 /* Switch back to normal mode. */ 3827 HWRITE4(sc, RK3568_PMUCRU_MODE_CON, 3828 (RK3328_CRU_CRU_MODE_MASK << 16 | 3829 RK3328_CRU_CRU_MODE_NORMAL) << mode_shift); 3830 3831 return 0; 3832 } 3833 3834 uint32_t 3835 rk3568_pmu_get_frequency(void *cookie, uint32_t *cells) 3836 { 3837 struct rkclock_softc *sc = cookie; 3838 uint32_t idx = cells[0]; 3839 3840 switch (idx) { 3841 case RK3568_PLL_PPLL: 3842 return rk3328_get_pll(sc, RK3568_PMUCRU_PPLL_CON(0)); 3843 case RK3568_PLL_HPLL: 3844 return rk3328_get_pll(sc, RK3568_PMUCRU_HPLL_CON(0)); 3845 case RK3568_CLK_RTC32K_FRAC: 3846 return rk3399_get_frac(sc, RK3568_XIN24M, 3847 RK3568_PMUCRU_CLKSEL_CON(1)); 3848 case RK3568_PPLL_PH0: 3849 idx = RK3568_PLL_PPLL; 3850 return rk3568_get_frequency(sc, &idx) / 2; 3851 case RK3568_XIN32K: 3852 return 32768; 3853 case RK3568_XIN24M: 3854 return 24000000; 3855 default: 3856 break; 3857 } 3858 3859 return rkclock_get_frequency(sc, idx); 3860 } 3861 3862 int 3863 rk3568_pmu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 3864 { 3865 struct rkclock_softc *sc = cookie; 3866 uint32_t idx = cells[0]; 3867 3868 switch (idx) { 3869 case RK3568_PLL_PPLL: 3870 return rk3568_pmu_set_pll(sc, RK3568_PMUCRU_PPLL_CON(0), freq); 3871 case RK3568_PLL_HPLL: 3872 return rk3568_pmu_set_pll(sc, RK3568_PMUCRU_HPLL_CON(0), freq); 3873 case RK3568_CLK_RTC32K_FRAC: 3874 return rk3399_set_frac(sc, RK3568_XIN24M, 3875 RK3568_PMUCRU_CLKSEL_CON(1), freq); 3876 default: 3877 break; 3878 } 3879 3880 return rkclock_set_frequency(sc, idx, freq); 3881 } 3882 3883 void 3884 rk3568_pmu_enable(void *cookie, uint32_t *cells, int on) 3885 { 3886 uint32_t idx = cells[0]; 3887 3888 switch (idx) { 3889 case RK3568_CLK_USBPHY0_REF: 3890 case RK3568_CLK_USBPHY1_REF: 3891 case RK3568_CLK_PCIEPHY0_REF: 3892 case RK3568_CLK_PCIEPHY1_REF: 3893 case RK3568_CLK_PCIEPHY2_REF: 3894 case RK3568_CLK_PCIE30PHY_REF_M: 3895 case RK3568_CLK_PCIE30PHY_REF_N: 3896 case RK3568_CLK_I2C0: 3897 case RK3568_SCLK_UART0: 3898 case RK3568_PCLK_I2C0: 3899 /* Enabled by default. */ 3900 break; 3901 default: 3902 printf("%s: 0x%08x\n", __func__, idx); 3903 break; 3904 } 3905 } 3906 3907 void 3908 rk3568_pmu_reset(void *cookie, uint32_t *cells, int on) 3909 { 3910 uint32_t idx = cells[0]; 3911 3912 printf("%s: 0x%08x\n", __func__, idx); 3913 } 3914 3915 /* 3916 * Rockchip RK3588 3917 */ 3918 3919 const struct rkclock rk3588_clocks[] = { 3920 { 3921 RK3588_CLK_PWM1, RK3588_CRU_CLKSEL_CON(59), 3922 SEL(13, 12), 0, 3923 { RK3588_CLK_100M_SRC, RK3588_CLK_50M_SRC, RK3588_XIN24M }, 3924 }, 3925 { 3926 RK3588_CLK_PWM2, RK3588_CRU_CLKSEL_CON(59), 3927 SEL(15, 14), 0, 3928 { RK3588_CLK_100M_SRC, RK3588_CLK_50M_SRC, RK3588_XIN24M }, 3929 }, 3930 { 3931 RK3588_CLK_PWM3, RK3588_CRU_CLKSEL_CON(60), 3932 SEL(1, 0), 0, 3933 { RK3588_CLK_100M_SRC, RK3588_CLK_50M_SRC, RK3588_XIN24M }, 3934 }, 3935 { 3936 RK3588_ACLK_BUS_ROOT, RK3588_CRU_CLKSEL_CON(38), 3937 SEL(5, 5), DIV(4, 0), 3938 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 3939 }, 3940 { 3941 RK3588_CLK_I2C1, RK3588_CRU_CLKSEL_CON(38), 3942 SEL(6, 6), 0, 3943 { RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC }, 3944 }, 3945 { 3946 RK3588_CLK_I2C2, RK3588_CRU_CLKSEL_CON(38), 3947 SEL(7, 7), 0, 3948 { RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC }, 3949 }, 3950 { 3951 RK3588_CLK_I2C3, RK3588_CRU_CLKSEL_CON(38), 3952 SEL(8, 8), 0, 3953 { RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC }, 3954 }, 3955 { 3956 RK3588_CLK_I2C4, RK3588_CRU_CLKSEL_CON(38), 3957 SEL(9, 9), 0, 3958 { RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC }, 3959 }, 3960 { 3961 RK3588_CLK_I2C5, RK3588_CRU_CLKSEL_CON(38), 3962 SEL(10, 10), 0, 3963 { RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC }, 3964 }, 3965 { 3966 RK3588_CLK_I2C6, RK3588_CRU_CLKSEL_CON(38), 3967 SEL(11, 11), 0, 3968 { RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC }, 3969 }, 3970 { 3971 RK3588_CLK_I2C7, RK3588_CRU_CLKSEL_CON(38), 3972 SEL(12, 12), 0, 3973 { RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC }, 3974 }, 3975 { 3976 RK3588_CLK_I2C8, RK3588_CRU_CLKSEL_CON(38), 3977 SEL(13, 13), 0, 3978 { RK3588_CLK_200M_SRC , RK3588_CLK_100M_SRC }, 3979 }, 3980 { 3981 RK3588_CLK_SPI0, RK3588_CRU_CLKSEL_CON(59), 3982 SEL(3, 2), 0, 3983 { RK3588_CLK_200M_SRC, RK3588_CLK_150M_SRC, RK3588_XIN24M }, 3984 }, 3985 { 3986 RK3588_CLK_SPI1, RK3588_CRU_CLKSEL_CON(59), 3987 SEL(5, 4), 0, 3988 { RK3588_CLK_200M_SRC, RK3588_CLK_150M_SRC, RK3588_XIN24M }, 3989 }, 3990 { 3991 RK3588_CLK_SPI2, RK3588_CRU_CLKSEL_CON(59), 3992 SEL(7, 6), 0, 3993 { RK3588_CLK_200M_SRC, RK3588_CLK_150M_SRC, RK3588_XIN24M }, 3994 }, 3995 { 3996 RK3588_CLK_SPI3, RK3588_CRU_CLKSEL_CON(59), 3997 SEL(9, 8), 0, 3998 { RK3588_CLK_200M_SRC, RK3588_CLK_150M_SRC, RK3588_XIN24M }, 3999 }, 4000 { 4001 RK3588_CLK_SPI4, RK3588_CRU_CLKSEL_CON(59), 4002 SEL(11, 10), 0, 4003 { RK3588_CLK_200M_SRC, RK3588_CLK_150M_SRC, RK3588_XIN24M }, 4004 }, 4005 { 4006 RK3588_CLK_TSADC, RK3588_CRU_CLKSEL_CON(41), 4007 SEL(8, 8), DIV(7, 0), 4008 { RK3588_PLL_GPLL, RK3588_XIN24M }, 4009 }, 4010 { 4011 RK3588_CLK_UART1_SRC, RK3588_CRU_CLKSEL_CON(41), 4012 SEL(14, 14), DIV(13, 9), 4013 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4014 }, 4015 { 4016 RK3588_CLK_UART1, RK3588_CRU_CLKSEL_CON(43), 4017 SEL(1, 0), 0, 4018 { RK3588_CLK_UART1_SRC, RK3588_CLK_UART1_FRAC, RK3588_XIN24M } 4019 }, 4020 { 4021 RK3588_SCLK_UART1, 0, 0, 0, 4022 { RK3588_CLK_UART1 } 4023 }, 4024 { 4025 RK3588_CLK_UART2_SRC, RK3588_CRU_CLKSEL_CON(43), 4026 SEL(7, 7), DIV(6, 2), 4027 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4028 }, 4029 { 4030 RK3588_CLK_UART2, RK3588_CRU_CLKSEL_CON(45), 4031 SEL(1, 0), 0, 4032 { RK3588_CLK_UART2_SRC, RK3588_CLK_UART2_FRAC, RK3588_XIN24M } 4033 }, 4034 { 4035 RK3588_SCLK_UART2, 0, 0, 0, 4036 { RK3588_CLK_UART2 } 4037 }, 4038 { 4039 RK3588_CLK_UART3_SRC, RK3588_CRU_CLKSEL_CON(45), 4040 SEL(7, 7), DIV(6, 2), 4041 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4042 }, 4043 { 4044 RK3588_CLK_UART3, RK3588_CRU_CLKSEL_CON(47), 4045 SEL(1, 0), 0, 4046 { RK3588_CLK_UART3_SRC, RK3588_CLK_UART3_FRAC, RK3588_XIN24M } 4047 }, 4048 { 4049 RK3588_SCLK_UART3, 0, 0, 0, 4050 { RK3588_CLK_UART3 } 4051 }, 4052 { 4053 RK3588_CLK_UART4_SRC, RK3588_CRU_CLKSEL_CON(47), 4054 SEL(7, 7), DIV(6, 2), 4055 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4056 }, 4057 { 4058 RK3588_CLK_UART4, RK3588_CRU_CLKSEL_CON(49), 4059 SEL(1, 0), 0, 4060 { RK3588_CLK_UART4_SRC, RK3588_CLK_UART4_FRAC, RK3588_XIN24M } 4061 }, 4062 { 4063 RK3588_SCLK_UART4, 0, 0, 0, 4064 { RK3588_CLK_UART4 } 4065 }, 4066 { 4067 RK3588_CLK_UART5_SRC, RK3588_CRU_CLKSEL_CON(49), 4068 SEL(7, 7), DIV(6, 2), 4069 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4070 }, 4071 { 4072 RK3588_CLK_UART5, RK3588_CRU_CLKSEL_CON(51), 4073 SEL(1, 0), 0, 4074 { RK3588_CLK_UART5_SRC, RK3588_CLK_UART5_FRAC, RK3588_XIN24M } 4075 }, 4076 { 4077 RK3588_SCLK_UART5, 0, 0, 0, 4078 { RK3588_CLK_UART5 } 4079 }, 4080 { 4081 RK3588_CLK_UART6_SRC, RK3588_CRU_CLKSEL_CON(51), 4082 SEL(7, 7), DIV(6, 2), 4083 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4084 }, 4085 { 4086 RK3588_CLK_UART6, RK3588_CRU_CLKSEL_CON(53), 4087 SEL(1, 0), 0, 4088 { RK3588_CLK_UART6_SRC, RK3588_CLK_UART6_FRAC, RK3588_XIN24M } 4089 }, 4090 { 4091 RK3588_SCLK_UART6, 0, 0, 0, 4092 { RK3588_CLK_UART6 } 4093 }, 4094 { 4095 RK3588_CLK_UART7_SRC, RK3588_CRU_CLKSEL_CON(53), 4096 SEL(7, 7), DIV(6, 2), 4097 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4098 }, 4099 { 4100 RK3588_CLK_UART7, RK3588_CRU_CLKSEL_CON(55), 4101 SEL(1, 0), 0, 4102 { RK3588_CLK_UART7_SRC, RK3588_CLK_UART7_FRAC, RK3588_XIN24M } 4103 }, 4104 { 4105 RK3588_SCLK_UART7, 0, 0, 0, 4106 { RK3588_CLK_UART7 } 4107 }, 4108 { 4109 RK3588_CLK_UART8_SRC, RK3588_CRU_CLKSEL_CON(55), 4110 SEL(7, 7), DIV(6, 2), 4111 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4112 }, 4113 { 4114 RK3588_CLK_UART8, RK3588_CRU_CLKSEL_CON(57), 4115 SEL(1, 0), 0, 4116 { RK3588_CLK_UART8_SRC, RK3588_CLK_UART8_FRAC, RK3588_XIN24M } 4117 }, 4118 { 4119 RK3588_SCLK_UART8, 0, 0, 0, 4120 { RK3588_CLK_UART8 } 4121 }, 4122 { 4123 RK3588_CLK_UART9_SRC, RK3588_CRU_CLKSEL_CON(57), 4124 SEL(7, 7), DIV(6, 2), 4125 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4126 }, 4127 { 4128 RK3588_CLK_UART9, RK3588_CRU_CLKSEL_CON(59), 4129 SEL(1, 0), 0, 4130 { RK3588_CLK_UART9_SRC, RK3588_CLK_UART9_FRAC, RK3588_XIN24M } 4131 }, 4132 { 4133 RK3588_SCLK_UART9, 0, 0, 0, 4134 { RK3588_CLK_UART9 } 4135 }, 4136 { 4137 RK3588_ACLK_CENTER_ROOT, RK3588_CRU_CLKSEL_CON(165), 4138 SEL(1, 0), 0, 4139 { RK3588_CLK_700M_SRC, RK3588_CLK_400M_SRC, 4140 RK3588_CLK_200M_SRC, RK3588_XIN24M } 4141 }, 4142 { 4143 RK3588_ACLK_CENTER_LOW_ROOT, RK3588_CRU_CLKSEL_CON(165), 4144 SEL(3, 2), 0, 4145 { RK3588_CLK_500M_SRC, RK3588_CLK_250M_SRC, 4146 RK3588_CLK_100M_SRC, RK3588_XIN24M } 4147 }, 4148 { 4149 RK3588_HCLK_CENTER_ROOT, RK3588_CRU_CLKSEL_CON(165), 4150 SEL(5, 4), 0, 4151 { RK3588_CLK_400M_SRC, RK3588_CLK_200M_SRC, 4152 RK3588_CLK_100M_SRC, RK3588_XIN24M } 4153 }, 4154 { 4155 RK3588_CLK_50M_SRC, RK3588_CRU_CLKSEL_CON(0), 4156 SEL(5, 5), DIV(4, 0), 4157 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4158 }, 4159 { 4160 RK3588_CLK_100M_SRC, RK3588_CRU_CLKSEL_CON(0), 4161 SEL(11, 11), DIV(10, 6), 4162 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4163 }, 4164 { 4165 RK3588_CLK_150M_SRC, RK3588_CRU_CLKSEL_CON(1), 4166 SEL(5, 5), DIV(4, 0), 4167 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4168 }, 4169 { 4170 RK3588_CLK_200M_SRC, RK3588_CRU_CLKSEL_CON(1), 4171 SEL(11, 11), DIV(10, 6), 4172 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4173 }, 4174 { 4175 RK3588_CLK_250M_SRC, RK3588_CRU_CLKSEL_CON(2), 4176 SEL(5, 5), DIV(4, 0), 4177 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4178 }, 4179 { 4180 RK3588_CLK_400M_SRC, RK3588_CRU_CLKSEL_CON(3), 4181 SEL(11, 11), DIV(10, 6), 4182 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4183 }, 4184 { 4185 RK3588_CLK_500M_SRC, RK3588_CRU_CLKSEL_CON(4), 4186 SEL(11, 11), DIV(10, 6), 4187 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4188 }, 4189 { 4190 RK3588_CLK_700M_SRC, RK3588_CRU_CLKSEL_CON(6), 4191 SEL(5, 5), DIV(4, 0), 4192 { RK3588_PLL_GPLL, RK3588_PLL_SPLL } 4193 }, 4194 { 4195 RK3588_ACLK_TOP_ROOT, RK3588_CRU_CLKSEL_CON(8), 4196 SEL(6, 5), 0, 4197 { RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_PLL_AUPLL } 4198 }, 4199 { 4200 RK3588_PCLK_TOP_ROOT, RK3588_CRU_CLKSEL_CON(8), 4201 SEL(8, 7), 0, 4202 { RK3588_CLK_100M_SRC, RK3588_CLK_50M_SRC, RK3588_XIN24M } 4203 }, 4204 { 4205 RK3588_ACLK_LOW_TOP_ROOT, RK3588_CRU_CLKSEL_CON(8), 4206 SEL(14, 14), DIV(13, 9), 4207 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4208 }, 4209 { 4210 RK3588_CLK_GPU_SRC, RK3588_CRU_CLKSEL_CON(158), 4211 SEL(7, 5), DIV(4, 0), 4212 { RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_PLL_AUPLL, 4213 RK3588_PLL_NPLL, RK3588_PLL_SPLL } 4214 }, 4215 { 4216 RK3588_CLK_GPU, 0, 0, 0, 4217 { RK3588_CLK_GPU_SRC }, 4218 SET_PARENT 4219 }, 4220 { 4221 RK3588_CCLK_EMMC, RK3588_CRU_CLKSEL_CON(77), 4222 SEL(15, 14), DIV(13, 8), 4223 { RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_XIN24M } 4224 }, 4225 { 4226 RK3588_BCLK_EMMC, RK3588_CRU_CLKSEL_CON(78), 4227 SEL(5, 5), DIV(4, 0), 4228 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4229 }, 4230 { 4231 RK3588_TMCLK_EMMC, 0, 0, 0, 4232 { RK3588_XIN24M } 4233 }, 4234 { 4235 RK3588_CLK_GMAC_125M, RK3588_CRU_CLKSEL_CON(83), 4236 SEL(15, 15), DIV(14, 8), 4237 { RK3588_PLL_GPLL, RK3588_PLL_CPLL } 4238 }, 4239 { 4240 RK3588_CCLK_SRC_SDIO, RK3588_CRU_CLKSEL_CON(172), 4241 SEL(9, 8), DIV(7, 2), 4242 { RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_XIN24M } 4243 }, 4244 { 4245 RK3588_ACLK_VOP_ROOT, RK3588_CRU_CLKSEL_CON(110), 4246 SEL(7, 5), DIV(4, 0), 4247 { RK3588_PLL_GPLL, RK3588_PLL_CPLL, RK3588_PLL_AUPLL, 4248 RK3588_PLL_NPLL, RK3588_PLL_SPLL } 4249 }, 4250 { 4251 RK3588_ACLK_VOP, 0, 0, 0, 4252 { RK3588_ACLK_VOP_SUB_SRC }, 4253 SET_PARENT 4254 }, 4255 { 4256 RK3588_ACLK_VOP_SUB_SRC, RK3588_CRU_CLKSEL_CON(115), 4257 SEL(9, 9), 0, 4258 { RK3588_ACLK_VOP_ROOT, 0 /* RK3588_ACLK_VOP_DIV2_SRC */ }, 4259 SET_PARENT 4260 }, 4261 { 4262 RK3588_CLK_I2C0, RK3588_CRU_CLKSEL_CON(3), 4263 SEL(6, 6), 0, 4264 { RK3588_CLK_PMU1_200M_SRC, RK3588_CLK_PMU1_100M_SRC }, 4265 }, 4266 { 4267 RK3588_CLK_PMU1_50M_SRC, RK3588_PMUCRU_CLKSEL_CON(0), 4268 0, DIV(3, 0), 4269 { RK3588_CLK_PMU1_400M_SRC } 4270 }, 4271 { 4272 RK3588_CLK_PMU1_100M_SRC, RK3588_PMUCRU_CLKSEL_CON(0), 4273 0, DIV(6, 4), 4274 { RK3588_CLK_PMU1_400M_SRC } 4275 }, 4276 { 4277 RK3588_CLK_PMU1_200M_SRC, RK3588_PMUCRU_CLKSEL_CON(0), 4278 0, DIV(9, 7), 4279 { RK3588_CLK_PMU1_400M_SRC } 4280 }, 4281 { 4282 RK3588_CLK_PMU1_400M_SRC, RK3588_PMUCRU_CLKSEL_CON(1), 4283 SEL(5, 5), DIV(4, 0), 4284 { RK3588_CLK_400M_SRC, RK3588_XIN24M } 4285 }, 4286 { 4287 RK3588_PCLK_PMU1_ROOT, RK3588_PMUCRU_CLKSEL_CON(1), 4288 SEL(9, 8), 0, 4289 { RK3588_CLK_PMU1_100M_SRC, RK3588_CLK_PMU1_50M_SRC, 4290 RK3588_XIN24M } 4291 }, 4292 { 4293 RK3588_PCLK_PMU0_ROOT, 0, 0, 0, 4294 { RK3588_PCLK_PMU1_ROOT }, 4295 SET_PARENT 4296 }, 4297 { 4298 RK3588_HCLK_PMU_CM0_ROOT, RK3588_PMUCRU_CLKSEL_CON(1), 4299 SEL(11, 10), 0, 4300 { RK3588_CLK_PMU1_400M_SRC, RK3588_CLK_PMU1_200M_SRC, 4301 RK3588_CLK_PMU1_100M_SRC, RK3588_XIN24M } 4302 }, 4303 { 4304 RK3588_CLK_PMU1PWM, RK3588_PMUCRU_CLKSEL_CON(2), 4305 SEL(10, 9), 0, 4306 { RK3588_CLK_PMU1_100M_SRC, RK3588_CLK_PMU1_50M_SRC, 4307 RK3588_XIN24M } 4308 }, 4309 { 4310 RK3588_CLK_UART0_SRC, RK3588_PMUCRU_CLKSEL_CON(3), 4311 0, DIV(11, 7), 4312 { RK3588_PLL_CPLL } 4313 }, 4314 { 4315 RK3588_CLK_UART0, RK3588_PMUCRU_CLKSEL_CON(5), 4316 SEL(1, 0), 0, 4317 { RK3588_CLK_UART0_SRC, RK3588_CLK_UART0_FRAC, RK3588_XIN24M } 4318 }, 4319 { 4320 RK3588_SCLK_UART0, 0, 0, 0, 4321 { RK3588_CLK_UART0 } 4322 }, 4323 { 4324 RK3588_CLK_REF_PIPE_PHY0_OSC_SRC, 0, 0, 0, 4325 { RK3588_XIN24M } 4326 }, 4327 { 4328 RK3588_CLK_REF_PIPE_PHY1_OSC_SRC, 0, 0, 0, 4329 { RK3588_XIN24M } 4330 }, 4331 { 4332 RK3588_CLK_REF_PIPE_PHY2_OSC_SRC, 0, 0, 0, 4333 { RK3588_XIN24M } 4334 }, 4335 { 4336 RK3588_CLK_REF_PIPE_PHY0_PLL_SRC, RK3588_CRU_CLKSEL_CON(176), 4337 0, DIV(5, 0), 4338 { RK3588_PLL_PPLL } 4339 }, 4340 { 4341 RK3588_CLK_REF_PIPE_PHY1_PLL_SRC, RK3588_CRU_CLKSEL_CON(176), 4342 0, DIV(11, 6), 4343 { RK3588_PLL_PPLL } 4344 }, 4345 { 4346 RK3588_CLK_REF_PIPE_PHY2_PLL_SRC, RK3588_CRU_CLKSEL_CON(177), 4347 0, DIV(5, 0), 4348 { RK3588_PLL_PPLL } 4349 }, 4350 { 4351 RK3588_CLK_REF_PIPE_PHY0, RK3588_CRU_CLKSEL_CON(177), 4352 SEL(6, 6), 0, 4353 { RK3588_CLK_REF_PIPE_PHY0_OSC_SRC, 4354 RK3588_CLK_REF_PIPE_PHY0_PLL_SRC }, 4355 }, 4356 { 4357 RK3588_CLK_REF_PIPE_PHY1, RK3588_CRU_CLKSEL_CON(177), 4358 SEL(7, 7), 0, 4359 { RK3588_CLK_REF_PIPE_PHY1_OSC_SRC, 4360 RK3588_CLK_REF_PIPE_PHY1_PLL_SRC }, 4361 }, 4362 { 4363 RK3588_CLK_REF_PIPE_PHY2, RK3588_CRU_CLKSEL_CON(177), 4364 SEL(8, 8), 0, 4365 { RK3588_CLK_REF_PIPE_PHY2_OSC_SRC, 4366 RK3588_CLK_REF_PIPE_PHY2_PLL_SRC }, 4367 }, 4368 { 4369 /* Sentinel */ 4370 } 4371 }; 4372 4373 /* Certain test clocks are disabled. */ 4374 const uint32_t rk3588_gates[78] = { 4375 [2] = 0x00000050, 4376 [22] = 0x00000200, 4377 [25] = 0x00000200, 4378 [29] = 0x00000004, 4379 [66] = 0x00000004, 4380 }; 4381 4382 void 4383 rk3588_init(struct rkclock_softc *sc) 4384 { 4385 int i; 4386 4387 /* The code below assumes all clocks are enabled. Check this!. */ 4388 for (i = 0; i < nitems(rk3588_gates); i++) { 4389 if (HREAD4(sc, RK3588_CRU_GATE_CON(i)) != rk3588_gates[i]) { 4390 printf("CRU_GATE_CON%d: 0x%08x\n", i, 4391 HREAD4(sc, RK3588_CRU_GATE_CON(i))); 4392 } 4393 } 4394 4395 sc->sc_clocks = rk3588_clocks; 4396 } 4397 4398 int 4399 rk3588_set_pll(struct rkclock_softc *sc, bus_size_t base, uint32_t freq) 4400 { 4401 uint32_t p, m, s, k; 4402 int mode_shift = -1; 4403 4404 switch (base) { 4405 case RK3588_CRU_AUPLL_CON(0): 4406 mode_shift = 6; 4407 break; 4408 case RK3588_CRU_GPLL_CON(0): 4409 mode_shift = 2; 4410 break; 4411 case RK3588_CRU_NPLL_CON(0): 4412 mode_shift = 0; 4413 break; 4414 case RK3588_PHPTOPCRU_PPLL_CON(0): 4415 mode_shift = 10; 4416 break; 4417 } 4418 KASSERT(mode_shift != -1); 4419 4420 /* 4421 * It is not clear whether all combinations of the clock 4422 * dividers result in a stable clock. Therefore this function 4423 * only supports a limited set of PLL clock rates. 4424 */ 4425 switch (freq) { 4426 case 1188000000U: 4427 p = 2; m = 198; s = 1; k = 0; 4428 break; 4429 case 1100000000U: 4430 p = 3; m = 550; s = 2; k = 0; 4431 break; 4432 case 850000000U: 4433 p = 3; m = 425; s = 2; k = 0; 4434 break; 4435 case 786432000U: 4436 p = 2; m = 262; s = 2; k = 9437; 4437 break; 4438 case 100000000U: 4439 p = 3; m = 400; s = 5; k = 0; 4440 break; 4441 default: 4442 printf("%s: %u Hz\n", __func__, freq); 4443 return -1; 4444 } 4445 4446 /* 4447 * Select slow mode to guarantee a stable clock while we're 4448 * adjusting the PLL. 4449 */ 4450 HWRITE4(sc, RK3588_CRU_MODE_CON, 4451 (RK3588_CRU_MODE_MASK << 16 |RK3588_CRU_MODE_SLOW) << mode_shift); 4452 4453 /* Power down PLL. */ 4454 HWRITE4(sc, base + 0x0004, 4455 RK3588_CRU_PLL_RESETB << 16 | RK3588_CRU_PLL_RESETB); 4456 4457 /* Set PLL rate. */ 4458 HWRITE4(sc, base + 0x0000, 4459 RK3588_CRU_PLL_M_MASK << 16 | m << RK3588_CRU_PLL_M_SHIFT); 4460 HWRITE4(sc, base + 0x0004, 4461 RK3588_CRU_PLL_S_MASK << 16 | s << RK3588_CRU_PLL_S_SHIFT | 4462 RK3588_CRU_PLL_P_MASK << 16 | p << RK3588_CRU_PLL_P_SHIFT); 4463 HWRITE4(sc, base + 0x0008, 4464 RK3588_CRU_PLL_K_MASK << 16 | k << RK3588_CRU_PLL_K_SHIFT); 4465 4466 /* Power up PLL. */ 4467 HWRITE4(sc, base + 0x0004, RK3588_CRU_PLL_RESETB << 16); 4468 4469 /* Wait for PLL to stabilize. */ 4470 while ((HREAD4(sc, base + 0x0018) & RK3588_CRU_PLL_PLL_LOCK) == 0) 4471 delay(10); 4472 4473 /* Switch back to normal mode. */ 4474 HWRITE4(sc, RK3588_CRU_MODE_CON, 4475 (RK3588_CRU_MODE_MASK << 16 | RK3588_CRU_MODE_NORMAL) << mode_shift); 4476 4477 return 0; 4478 } 4479 4480 uint32_t 4481 rk3588_get_pll(struct rkclock_softc *sc, bus_size_t base) 4482 { 4483 uint64_t freq, frac; 4484 uint32_t k, m, p, s; 4485 uint32_t reg; 4486 4487 reg = HREAD4(sc, base); 4488 m = (reg & RK3588_CRU_PLL_M_MASK) >> RK3588_CRU_PLL_M_SHIFT; 4489 reg = HREAD4(sc, base + 4); 4490 p = (reg & RK3588_CRU_PLL_P_MASK) >> RK3588_CRU_PLL_P_SHIFT; 4491 s = (reg & RK3588_CRU_PLL_S_MASK) >> RK3588_CRU_PLL_S_SHIFT; 4492 reg = HREAD4(sc, base + 8); 4493 k = (reg & RK3588_CRU_PLL_K_MASK) >> RK3588_CRU_PLL_K_SHIFT; 4494 4495 freq = (24000000ULL * m) / p; 4496 if (k) { 4497 frac = ((24000000ULL * k) / (p * 65535)); 4498 freq += frac; 4499 } 4500 4501 return freq >> s; 4502 } 4503 4504 uint32_t 4505 rk3588_get_frequency(void *cookie, uint32_t *cells) 4506 { 4507 struct rkclock_softc *sc = cookie; 4508 uint32_t idx = cells[0]; 4509 uint32_t freq; 4510 4511 switch (idx) { 4512 case RK3588_PLL_AUPLL: 4513 return rk3588_get_pll(sc, RK3588_CRU_AUPLL_CON(0)); 4514 case RK3588_PLL_CPLL: 4515 return rk3588_get_pll(sc, RK3588_CRU_CPLL_CON(0)); 4516 case RK3588_PLL_GPLL: 4517 return rk3588_get_pll(sc, RK3588_CRU_GPLL_CON(0)); 4518 case RK3588_PLL_NPLL: 4519 return rk3588_get_pll(sc, RK3588_CRU_NPLL_CON(0)); 4520 case RK3588_PLL_PPLL: 4521 return rk3588_get_pll(sc, RK3588_PHPTOPCRU_PPLL_CON(0)); 4522 case RK3588_PLL_SPLL: 4523 return rkclock_external_frequency("spll"); 4524 case RK3588_XIN24M: 4525 return 24000000; 4526 default: 4527 break; 4528 } 4529 4530 freq = rkclock_get_frequency(sc, idx); 4531 return freq; 4532 } 4533 4534 int 4535 rk3588_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) 4536 { 4537 struct rkclock_softc *sc = cookie; 4538 uint32_t idx = cells[0]; 4539 4540 switch (idx) { 4541 case RK3588_PLL_AUPLL: 4542 return rk3588_set_pll(sc, RK3588_CRU_AUPLL_CON(0), freq); 4543 case RK3588_PLL_GPLL: 4544 return rk3588_set_pll(sc, RK3588_CRU_GPLL_CON(0), freq); 4545 case RK3588_PLL_NPLL: 4546 return rk3588_set_pll(sc, RK3588_CRU_NPLL_CON(0), freq); 4547 case RK3588_PLL_PPLL: 4548 return rk3588_set_pll(sc, RK3588_PHPTOPCRU_PPLL_CON(0), freq); 4549 default: 4550 break; 4551 } 4552 4553 return rkclock_set_frequency(sc, idx, freq); 4554 } 4555 4556 void 4557 rk3588_enable(void *cookie, uint32_t *cells, int on) 4558 { 4559 uint32_t idx = cells[0]; 4560 4561 /* All clocks are enabled upon hardware reset. */ 4562 if (!on) { 4563 printf("%s: 0x%08x\n", __func__, idx); 4564 return; 4565 } 4566 } 4567 4568 void 4569 rk3588_reset(void *cookie, uint32_t *cells, int on) 4570 { 4571 struct rkclock_softc *sc = cookie; 4572 uint32_t idx = cells[0]; 4573 uint32_t bit, mask, reg; 4574 4575 switch (idx) { 4576 case RK3588_SRST_P_TSADC: 4577 reg = RK3588_CRU_SOFTRST_CON(12); 4578 bit = 0; 4579 break; 4580 case RK3588_SRST_TSADC: 4581 reg = RK3588_CRU_SOFTRST_CON(12); 4582 bit = 1; 4583 break; 4584 case RK3588_SRST_H_EMMC: 4585 reg = RK3588_CRU_SOFTRST_CON(31); 4586 bit = 4; 4587 break; 4588 case RK3588_SRST_A_EMMC: 4589 reg = RK3588_CRU_SOFTRST_CON(31); 4590 bit = 5; 4591 break; 4592 case RK3588_SRST_C_EMMC: 4593 reg = RK3588_CRU_SOFTRST_CON(31); 4594 bit = 6; 4595 break; 4596 case RK3588_SRST_B_EMMC: 4597 reg = RK3588_CRU_SOFTRST_CON(31); 4598 bit = 7; 4599 break; 4600 case RK3588_SRST_T_EMMC: 4601 reg = RK3588_CRU_SOFTRST_CON(31); 4602 bit = 8; 4603 break; 4604 case RK3588_SRST_A_GMAC0: 4605 reg = RK3588_CRU_SOFTRST_CON(32); 4606 bit = 10; 4607 break; 4608 case RK3588_SRST_A_GMAC1: 4609 reg = RK3588_CRU_SOFTRST_CON(32); 4610 bit = 11; 4611 break; 4612 case RK3588_SRST_PCIE0_POWER_UP: 4613 reg = RK3588_CRU_SOFTRST_CON(32); 4614 bit = 13; 4615 break; 4616 case RK3588_SRST_PCIE1_POWER_UP: 4617 reg = RK3588_CRU_SOFTRST_CON(32); 4618 bit = 14; 4619 break; 4620 case RK3588_SRST_PCIE2_POWER_UP: 4621 reg = RK3588_CRU_SOFTRST_CON(32); 4622 bit = 15; 4623 break; 4624 case RK3588_SRST_PCIE3_POWER_UP: 4625 reg = RK3588_CRU_SOFTRST_CON(33); 4626 bit = 0; 4627 break; 4628 case RK3588_SRST_PCIE4_POWER_UP: 4629 reg = RK3588_CRU_SOFTRST_CON(33); 4630 bit = 1; 4631 break; 4632 case RK3588_SRST_P_PCIE0: 4633 reg = RK3588_CRU_SOFTRST_CON(33); 4634 bit = 12; 4635 break; 4636 case RK3588_SRST_P_PCIE1: 4637 reg = RK3588_CRU_SOFTRST_CON(33); 4638 bit = 13; 4639 break; 4640 case RK3588_SRST_P_PCIE2: 4641 reg = RK3588_CRU_SOFTRST_CON(33); 4642 bit = 14; 4643 break; 4644 case RK3588_SRST_P_PCIE3: 4645 reg = RK3588_CRU_SOFTRST_CON(33); 4646 bit = 15; 4647 break; 4648 case RK3588_SRST_P_PCIE4: 4649 reg = RK3588_CRU_SOFTRST_CON(34); 4650 bit = 0; 4651 break; 4652 case RK3588_SRST_A_USB3OTG2: 4653 reg = RK3588_CRU_SOFTRST_CON(35); 4654 bit = 7; 4655 break; 4656 case RK3588_SRST_A_USB3OTG0: 4657 reg = RK3588_CRU_SOFTRST_CON(42); 4658 bit = 4; 4659 break; 4660 case RK3588_SRST_A_USB3OTG1: 4661 reg = RK3588_CRU_SOFTRST_CON(42); 4662 bit = 7; 4663 break; 4664 case RK3588_SRST_REF_PIPE_PHY0: 4665 reg = RK3588_CRU_SOFTRST_CON(77); 4666 bit = 6; 4667 break; 4668 case RK3588_SRST_REF_PIPE_PHY1: 4669 reg = RK3588_CRU_SOFTRST_CON(77); 4670 bit = 7; 4671 break; 4672 case RK3588_SRST_REF_PIPE_PHY2: 4673 reg = RK3588_CRU_SOFTRST_CON(77); 4674 bit = 8; 4675 break; 4676 case RK3588_SRST_P_PCIE2_PHY0: 4677 reg = RK3588_PHPTOPCRU_SOFTRST_CON(0); 4678 bit = 5; 4679 break; 4680 case RK3588_SRST_P_PCIE2_PHY1: 4681 reg = RK3588_PHPTOPCRU_SOFTRST_CON(0); 4682 bit = 6; 4683 break; 4684 case RK3588_SRST_P_PCIE2_PHY2: 4685 reg = RK3588_PHPTOPCRU_SOFTRST_CON(0); 4686 bit = 7; 4687 break; 4688 case RK3588_SRST_PCIE30_PHY: 4689 reg = RK3588_PHPTOPCRU_SOFTRST_CON(0); 4690 bit = 10; 4691 break; 4692 default: 4693 printf("%s: 0x%08x\n", __func__, idx); 4694 return; 4695 } 4696 4697 mask = (1 << bit); 4698 HWRITE4(sc, reg, mask << 16 | (on ? mask : 0)); 4699 } 4700