1 /* $OpenBSD: rkcomphy.c,v 1.2 2023/04/27 08:56:39 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2023 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/device.h> 21 22 #include <machine/intr.h> 23 #include <machine/bus.h> 24 #include <machine/fdt.h> 25 26 #include <dev/ofw/openfirm.h> 27 #include <dev/ofw/ofw_clock.h> 28 #include <dev/ofw/ofw_misc.h> 29 #include <dev/ofw/fdt.h> 30 31 /* 32 * WARNING: Most (but not all!) of the register numbers in the Linux 33 * driver are off-by-one! This driver uses 0-based register numbers 34 * like in the TRM. 35 */ 36 37 /* Combo PHY registers */ 38 #define COMBO_PIPE_PHY_REG(idx) ((idx) * 4) 39 /* REG_005 */ 40 #define COMBO_PIPE_PHY_PLL_DIV_MASK (0x3 << 6) 41 #define COMBO_PIPE_PHY_PLL_DIV_2 (0x1 << 6) 42 /* REG_006 */ 43 #define COMBO_PIPE_PHY_TX_RTERM_50OHM (0x8 << 4) 44 #define COMBO_PIPE_PHY_RX_RTERM_44OHM (0xf << 4) 45 /* REG_010 */ 46 #define COMBO_PIPE_PHY_SU_TRIM_0_7 0xf0 47 /* REG_011 */ 48 #define COMBO_PIPE_PHY_PLL_LPF_ADJ_VALUE 4 49 /* REG_014 */ 50 #define COMBO_PIPE_PHY_SSC_CNT_LO_MASK (0x3 << 6) 51 #define COMBO_PIPE_PHY_SSC_CNT_LO_VALUE (0x1 << 6) 52 #define COMBO_PIPE_PHY_CTLE_EN (1 << 0) 53 /* REG_015 */ 54 #define COMBO_PIPE_PHY_SSC_CNT_HI_MASK (0xff << 0) 55 #define COMBO_PIPE_PHY_SSC_CNT_HI_VALUE (0x5f << 0) 56 /* REG_017 */ 57 #define COMBO_PIPE_PHY_PLL_LOOP 0x32 58 /* REG_027 */ 59 #define COMBO_PIPE_PHY_RX_TRIM_RK3588 0x4c 60 /* REG_031 */ 61 #define COMBO_PIPE_PHY_SSC_DIR_MASK (0x3 << 4) 62 #define COMBO_PIPE_PHY_SSC_DIR_DOWN (0x1 << 4) 63 #define COMBO_PIPE_PHY_SSC_OFFSET_MASK (0x3 << 6) 64 #define COMBO_PIPE_PHY_SSC_OFFSET_500PPM (0x1 << 6) 65 /* REG_032 */ 66 #define COMBO_PIPE_PHY_PLL_KVCO_MASK (0x7 << 2) 67 #define COMBO_PIPE_PHY_PLL_KVCO_VALUE (0x2 << 2) 68 #define COMBO_PIPE_PHY_PLL_KVCO_VALUE_RK3588 (0x4 << 2) 69 70 /* GRF registers */ 71 #define PIPE_GRF_PIPE_CON0 0x0000 72 73 /* PHP GRF registers (for RK3588) */ 74 #define PHP_GRF_PCIESEL_CON 0x0100 75 76 /* PHY GRF registers */ 77 #define PIPE_PHY_GRF_PIPE_CON(idx) ((idx) * 4) 78 /* CON0 */ 79 #define PIPE_PHY_GRF_PIPE_MODE_PCIE 0x003f0000 80 #define PIPE_PHY_GRF_PIPE_MODE_USB 0x003f0004 81 #define PIPE_PHY_GRF_PIPE_MODE_SATA 0x003f0019 82 /* CON1 */ 83 #define PIPE_PHY_GRF_PIPE_CLK_24M 0x60000000 84 #define PIPE_PHY_GRF_PIPE_CLK_25M 0x60002000 85 #define PIPE_PHY_GRF_PIPE_CLK_100M 0x60004000 86 /* CON2 */ 87 #define PIPE_PHY_GRF_PIPE_TXCOMP_SEL_CTRL 0x80000000 88 #define PIPE_PHY_GRF_PIPE_TXCOMP_SEL_GRF 0x80008000 89 #define PIPE_PHY_GRF_PIPE_TXELEC_SEL_CTRL 0x10000000 90 #define PIPE_PHY_GRF_PIPE_TXELEC_SEL_GRF 0x10001000 91 /* CON3 */ 92 #define PIPE_PHY_GRF_PIPE_SEL_PCIE 0x60000000 93 #define PIPE_PHY_GRF_PIPE_SEL_USB 0x60002000 94 #define PIPE_PHY_GRF_PIPE_SEL_SATA 0x60004000 95 /* STATUS1 */ 96 #define PIPE_PHY_GRF_PIPE_STATUS1 0x34 97 #define PIPE_PHY_GRF_PIPE_PHYSTATUS (1 << 6) 98 99 #define HREAD4(sc, reg) \ 100 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 101 #define HWRITE4(sc, reg, val) \ 102 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 103 #define HSET4(sc, reg, bits) \ 104 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) 105 #define HCLR4(sc, reg, bits) \ 106 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) 107 108 struct rkcomphy_softc { 109 struct device sc_dev; 110 bus_space_tag_t sc_iot; 111 bus_space_handle_t sc_ioh; 112 113 struct phy_device sc_pd; 114 }; 115 116 int rkcomphy_match(struct device *, void *, void *); 117 void rkcomphy_attach(struct device *, struct device *, void *); 118 119 const struct cfattach rkcomphy_ca = { 120 sizeof (struct rkcomphy_softc), rkcomphy_match, rkcomphy_attach 121 }; 122 123 struct cfdriver rkcomphy_cd = { 124 NULL, "rkcomphy", DV_DULL 125 }; 126 127 int rkcomphy_rk3568_enable(void *, uint32_t *); 128 int rkcomphy_rk3588_enable(void *, uint32_t *); 129 130 int 131 rkcomphy_match(struct device *parent, void *match, void *aux) 132 { 133 struct fdt_attach_args *faa = aux; 134 int node = faa->fa_node; 135 136 return OF_is_compatible(node, "rockchip,rk3568-naneng-combphy") || 137 OF_is_compatible(node, "rockchip,rk3588-naneng-combphy"); 138 } 139 140 void 141 rkcomphy_attach(struct device *parent, struct device *self, void *aux) 142 { 143 struct rkcomphy_softc *sc = (struct rkcomphy_softc *)self; 144 struct fdt_attach_args *faa = aux; 145 146 if (faa->fa_nreg < 1) { 147 printf(": no registers\n"); 148 return; 149 } 150 151 sc->sc_iot = faa->fa_iot; 152 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 153 faa->fa_reg[0].size, 0, &sc->sc_ioh)) { 154 printf(": can't map registers\n"); 155 return; 156 } 157 158 reset_assert_all(faa->fa_node); 159 160 printf("\n"); 161 162 sc->sc_pd.pd_node = faa->fa_node; 163 sc->sc_pd.pd_cookie = sc; 164 if (OF_is_compatible(faa->fa_node, "rockchip,rk3568-naneng-combphy")) 165 sc->sc_pd.pd_enable = rkcomphy_rk3568_enable; 166 else 167 sc->sc_pd.pd_enable = rkcomphy_rk3588_enable; 168 phy_register(&sc->sc_pd); 169 } 170 171 void 172 rkcomphy_rk3568_pll_tune(struct rkcomphy_softc *sc) 173 { 174 uint32_t reg; 175 176 reg = HREAD4(sc, COMBO_PIPE_PHY_REG(32)); 177 reg &= ~COMBO_PIPE_PHY_PLL_KVCO_MASK; 178 reg |= COMBO_PIPE_PHY_PLL_KVCO_VALUE; 179 HWRITE4(sc, COMBO_PIPE_PHY_REG(32), reg); 180 181 HWRITE4(sc, COMBO_PIPE_PHY_REG(11), COMBO_PIPE_PHY_PLL_LPF_ADJ_VALUE); 182 183 reg = HREAD4(sc, COMBO_PIPE_PHY_REG(5)); 184 reg &= ~COMBO_PIPE_PHY_PLL_DIV_MASK; 185 reg |= COMBO_PIPE_PHY_PLL_DIV_2; 186 HWRITE4(sc, COMBO_PIPE_PHY_REG(5), reg); 187 188 HWRITE4(sc, COMBO_PIPE_PHY_REG(17), COMBO_PIPE_PHY_PLL_LOOP); 189 HWRITE4(sc, COMBO_PIPE_PHY_REG(10), COMBO_PIPE_PHY_SU_TRIM_0_7); 190 } 191 192 int 193 rkcomphy_rk3568_enable(void *cookie, uint32_t *cells) 194 { 195 struct rkcomphy_softc *sc = cookie; 196 struct regmap *rm, *phy_rm; 197 int node = sc->sc_pd.pd_node; 198 uint32_t type = cells[0]; 199 uint32_t freq, grf, phy_grf, reg; 200 int stat, timo; 201 202 /* We only support PCIe, SATA and USB 3 for now. */ 203 switch (type) { 204 case PHY_TYPE_PCIE: 205 case PHY_TYPE_SATA: 206 case PHY_TYPE_USB3: 207 break; 208 default: 209 return EINVAL; 210 } 211 212 grf = OF_getpropint(node, "rockchip,pipe-grf", 0); 213 rm = regmap_byphandle(grf); 214 if (rm == NULL) 215 return ENXIO; 216 217 phy_grf = OF_getpropint(node, "rockchip,pipe-phy-grf", 0); 218 phy_rm = regmap_byphandle(phy_grf); 219 if (phy_rm == NULL) 220 return ENXIO; 221 222 clock_set_assigned(node); 223 clock_enable_all(node); 224 225 if (type == PHY_TYPE_PCIE || type == PHY_TYPE_USB3) { 226 reg = HREAD4(sc, COMBO_PIPE_PHY_REG(31)); 227 reg &= ~COMBO_PIPE_PHY_SSC_OFFSET_MASK; 228 reg &= ~COMBO_PIPE_PHY_SSC_DIR_MASK; 229 reg |= COMBO_PIPE_PHY_SSC_DIR_DOWN; 230 HWRITE4(sc, COMBO_PIPE_PHY_REG(31), reg); 231 } 232 233 if (type == PHY_TYPE_SATA || type == PHY_TYPE_USB3) { 234 reg = HREAD4(sc, COMBO_PIPE_PHY_REG(14)); 235 reg |= COMBO_PIPE_PHY_CTLE_EN; 236 HWRITE4(sc, COMBO_PIPE_PHY_REG(14), reg); 237 } 238 239 switch (type) { 240 case PHY_TYPE_PCIE: 241 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(0), 0xffff1000); 242 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1), 0xffff0000); 243 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(2), 0xffff0101); 244 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(3), 0xffff0200); 245 break; 246 case PHY_TYPE_SATA: 247 HWRITE4(sc, COMBO_PIPE_PHY_REG(6), 248 COMBO_PIPE_PHY_TX_RTERM_50OHM | 249 COMBO_PIPE_PHY_RX_RTERM_44OHM); 250 251 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(0), 0xffff0119); 252 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1), 0xffff0040); 253 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(2), 0xffff80c3); 254 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(3), 0xffff4407); 255 regmap_write_4(rm, PIPE_GRF_PIPE_CON0, 0xffff2220); 256 break; 257 case PHY_TYPE_USB3: 258 rkcomphy_rk3568_pll_tune(sc); 259 260 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(0), 261 PIPE_PHY_GRF_PIPE_MODE_USB); 262 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(2), 263 PIPE_PHY_GRF_PIPE_TXCOMP_SEL_CTRL); 264 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(2), 265 PIPE_PHY_GRF_PIPE_TXELEC_SEL_CTRL); 266 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(3), 267 PIPE_PHY_GRF_PIPE_SEL_USB); 268 break; 269 } 270 271 freq = clock_get_frequency(node, "ref"); 272 switch (freq) { 273 case 24000000: 274 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1), 275 PIPE_PHY_GRF_PIPE_CLK_24M); 276 if (type == PHY_TYPE_SATA || type == PHY_TYPE_USB3) { 277 reg = HREAD4(sc, COMBO_PIPE_PHY_REG(14)); 278 reg &= ~COMBO_PIPE_PHY_SSC_CNT_LO_MASK; 279 reg |= COMBO_PIPE_PHY_SSC_CNT_LO_VALUE; 280 HWRITE4(sc, COMBO_PIPE_PHY_REG(14), reg); 281 reg = HREAD4(sc, COMBO_PIPE_PHY_REG(15)); 282 reg &= ~COMBO_PIPE_PHY_SSC_CNT_HI_MASK; 283 reg |= COMBO_PIPE_PHY_SSC_CNT_HI_VALUE; 284 HWRITE4(sc, COMBO_PIPE_PHY_REG(15), reg); 285 } 286 break; 287 case 25000000: 288 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1), 289 PIPE_PHY_GRF_PIPE_CLK_25M); 290 break; 291 case 100000000: 292 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1), 293 PIPE_PHY_GRF_PIPE_CLK_100M); 294 switch (type) { 295 case PHY_TYPE_PCIE: 296 rkcomphy_rk3568_pll_tune(sc); 297 break; 298 case PHY_TYPE_SATA: 299 reg = HREAD4(sc, COMBO_PIPE_PHY_REG(31)); 300 reg &= ~COMBO_PIPE_PHY_SSC_OFFSET_MASK; 301 reg |= COMBO_PIPE_PHY_SSC_OFFSET_500PPM; 302 reg &= ~COMBO_PIPE_PHY_SSC_DIR_MASK; 303 reg |= COMBO_PIPE_PHY_SSC_DIR_DOWN; 304 HWRITE4(sc, COMBO_PIPE_PHY_REG(31), reg); 305 break; 306 } 307 break; 308 } 309 310 reset_deassert_all(node); 311 312 if (type == PHY_TYPE_USB3) { 313 for (timo = 100; timo > 0; timo--) { 314 stat = regmap_read_4(phy_rm, 315 PIPE_PHY_GRF_PIPE_STATUS1); 316 if ((stat & PIPE_PHY_GRF_PIPE_PHYSTATUS) == 0) 317 break; 318 delay(10); 319 } 320 if (timo == 0) { 321 printf("%s: timeout\n", sc->sc_dev.dv_xname); 322 return ETIMEDOUT; 323 } 324 } 325 326 return 0; 327 } 328 329 void 330 rkcomphy_rk3588_pll_tune(struct rkcomphy_softc *sc) 331 { 332 uint32_t reg; 333 334 reg = HREAD4(sc, COMBO_PIPE_PHY_REG(32)); 335 reg &= ~COMBO_PIPE_PHY_PLL_KVCO_MASK; 336 reg |= COMBO_PIPE_PHY_PLL_KVCO_VALUE_RK3588; 337 HWRITE4(sc, COMBO_PIPE_PHY_REG(32), reg); 338 339 HWRITE4(sc, COMBO_PIPE_PHY_REG(11), COMBO_PIPE_PHY_PLL_LPF_ADJ_VALUE); 340 341 HWRITE4(sc, COMBO_PIPE_PHY_REG(27), COMBO_PIPE_PHY_RX_TRIM_RK3588); 342 HWRITE4(sc, COMBO_PIPE_PHY_REG(10), COMBO_PIPE_PHY_SU_TRIM_0_7); 343 } 344 345 int 346 rkcomphy_rk3588_enable(void *cookie, uint32_t *cells) 347 { 348 struct rkcomphy_softc *sc = cookie; 349 struct regmap *rm, *phy_rm; 350 int node = sc->sc_pd.pd_node; 351 uint32_t type = cells[0]; 352 uint32_t freq, grf, phy_grf; 353 354 /* We only support PCIe for now. */ 355 switch (type) { 356 case PHY_TYPE_PCIE: 357 break; 358 default: 359 return EINVAL; 360 } 361 362 grf = OF_getpropint(node, "rockchip,pipe-grf", 0); 363 rm = regmap_byphandle(grf); 364 if (rm == NULL) 365 return ENXIO; 366 367 phy_grf = OF_getpropint(node, "rockchip,pipe-phy-grf", 0); 368 phy_rm = regmap_byphandle(phy_grf); 369 if (phy_rm == NULL) 370 return ENXIO; 371 372 clock_set_assigned(node); 373 clock_enable_all(node); 374 375 switch (type) { 376 case PHY_TYPE_PCIE: 377 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(0), 0xffff1000); 378 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1), 0xffff0000); 379 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(2), 0xffff0101); 380 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(3), 0xffff0200); 381 regmap_write_4(rm, PHP_GRF_PCIESEL_CON, 0x00010000); 382 regmap_write_4(rm, PHP_GRF_PCIESEL_CON, 0x00020000); 383 break; 384 } 385 386 freq = clock_get_frequency(node, "ref"); 387 switch (freq) { 388 case 25000000: 389 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1), 390 PIPE_PHY_GRF_PIPE_CLK_25M); 391 break; 392 case 100000000: 393 regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1), 394 PIPE_PHY_GRF_PIPE_CLK_100M); 395 switch (type) { 396 case PHY_TYPE_PCIE: 397 rkcomphy_rk3588_pll_tune(sc); 398 break; 399 } 400 } 401 402 reset_deassert_all(node); 403 404 return 0; 405 } 406