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