1 /* $NetBSD: rk_tcphy.c,v 1.1 2025/06/03 19:10:26 rjs Exp $ */ 2 /* $OpenBSD: rktcphy.c,v 1.2 2022/04/06 18:59:28 naddy Exp $ */ 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 5 * 6 * Copyright (c) 2019 Emmanuel Vadot <manu (at) FreeBSD.Org> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /* 31 * Rockchip PHY TYPEC 32 */ 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/device.h> 37 38 #include <dev/fdt/fdtvar.h> 39 #include <dev/fdt/syscon.h> 40 41 #define GRF_USB3OTG_BASE(x) (0x2430 + (0x10 * x)) 42 #define GRF_USB3OTG_CON0(x) (GRF_USB3OTG_BASE(x) + 0x0) 43 #define GRF_USB3OTG_CON1(x) (GRF_USB3OTG_BASE(x) + 0x4) 44 #define USB3OTG_CON1_U3_DIS (1 << 0) 45 46 #define GRF_USB3PHY_BASE(x) (0x0e580 + (0xc * (x))) 47 #define GRF_USB3PHY_CON0(x) (GRF_USB3PHY_BASE(x) + 0x0) 48 #define USB3PHY_CON0_USB2_ONLY (1 << 3) 49 #define GRF_USB3PHY_CON1(x) (GRF_USB3PHY_BASE(x) + 0x4) 50 #define GRF_USB3PHY_CON2(x) (GRF_USB3PHY_BASE(x) + 0x8) 51 #define GRF_USB3PHY_STATUS0 0x0e5c0 52 #define GRF_USB3PHY_STATUS1 0x0e5c4 53 54 #define CMN_PLL0_VCOCAL_INIT (0x84 << 2) 55 #define CMN_PLL0_VCOCAL_ITER (0x85 << 2) 56 #define CMN_PLL0_INTDIV (0x94 << 2) 57 #define CMN_PLL0_FRACDIV (0x95 << 2) 58 #define CMN_PLL0_HIGH_THR (0x96 << 2) 59 #define CMN_PLL0_DSM_DIAG (0x97 << 2) 60 #define CMN_PLL0_SS_CTRL1 (0x98 << 2) 61 #define CMN_PLL0_SS_CTRL2 (0x99 << 2) 62 #define CMN_DIAG_PLL0_FBH_OVRD (0x1c0 << 2) 63 #define CMN_DIAG_PLL0_FBL_OVRD (0x1c1 << 2) 64 #define CMN_DIAG_PLL0_OVRD (0x1c2 << 2) 65 #define CMN_DIAG_PLL0_V2I_TUNE (0x1c5 << 2) 66 #define CMN_DIAG_PLL0_CP_TUNE (0x1c6 << 2) 67 #define CMN_DIAG_PLL0_LF_PROG (0x1c7 << 2) 68 #define CMN_DIAG_HSCLK_SEL (0x1e0 << 2) 69 #define CMN_DIAG_HSCLK_SEL_PLL_CONFIG 0x30 70 #define CMN_DIAG_HSCLK_SEL_PLL_MASK 0x33 71 72 #define TX_TXCC_MGNFS_MULT_000(lane) ((0x4050 | ((lane) << 9)) << 2) 73 #define XCVR_DIAG_BIDI_CTRL(lane) ((0x40e8 | ((lane) << 9)) << 2) 74 #define XCVR_DIAG_LANE_FCM_EN_MGN(lane) ((0x40f2 | ((lane) << 9)) << 2) 75 #define TX_PSC_A0(lane) ((0x4100 | ((lane) << 9)) << 2) 76 #define TX_PSC_A1(lane) ((0x4101 | ((lane) << 9)) << 2) 77 #define TX_PSC_A2(lane) ((0x4102 | ((lane) << 9)) << 2) 78 #define TX_PSC_A3(lane) ((0x4103 | ((lane) << 9)) << 2) 79 #define TX_RCVDET_EN_TMR(lane) ((0x4122 | ((lane) << 9)) << 2) 80 #define TX_RCVDET_ST_TMR(lane) ((0x4123 | ((lane) << 9)) << 2) 81 82 #define RX_PSC_A0(lane) ((0x8000 | ((lane) << 9)) << 2) 83 #define RX_PSC_A1(lane) ((0x8001 | ((lane) << 9)) << 2) 84 #define RX_PSC_A2(lane) ((0x8002 | ((lane) << 9)) << 2) 85 #define RX_PSC_A3(lane) ((0x8003 | ((lane) << 9)) << 2) 86 #define RX_PSC_CAL(lane) ((0x8006 | ((lane) << 9)) << 2) 87 #define RX_PSC_RDY(lane) ((0x8007 | ((lane) << 9)) << 2) 88 #define RX_SIGDET_HL_FILT_TMR(lane) ((0x8090 | ((lane) << 9)) << 2) 89 #define RX_REE_CTRL_DATA_MASK(lane) ((0x81bb | ((lane) << 9)) << 2) 90 #define RX_DIAG_SIGDET_TUNE(lane) ((0x81dc | ((lane) << 9)) << 2) 91 92 #define PMA_LANE_CFG (0xc000 << 2) 93 #define PIN_ASSIGN_D_F 0x5100 94 #define DP_MODE_CTL (0xc008 << 2) 95 #define DP_MODE_ENTER_A2 0xc104 96 #define PMA_CMN_CTRL1 (0xc800 << 2) 97 #define PMA_CMN_CTRL1_READY (1 << 0) 98 99 #define HREAD4(sc, reg) \ 100 (bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))) 101 #define HWRITE4(sc, reg, val) \ 102 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (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 static int rk_typec_match(device_t, cfdata_t, void *); 109 static void rk_typec_attach(device_t, device_t, void *); 110 111 static const struct device_compatible_entry compat_data[] = { 112 { .compat = "rockchip,rk3399-typec-phy" }, 113 DEVICE_COMPAT_EOL 114 }; 115 116 struct rk_typec_softc { 117 device_t sc_dev; 118 bus_space_tag_t sc_bst; 119 bus_space_handle_t sc_bsh; 120 int sc_phandle; 121 122 struct syscon *sc_grf; 123 struct clk *sc_core_clk; 124 struct clk *sc_phy_ref_clk; 125 struct fdtbus_reset *sc_rst; 126 struct fdtbus_reset *sc_rst_pipe; 127 struct fdtbus_reset *sc_rst_tcphy; 128 129 int sc_mode; 130 int sc_phy_ctrl_id; 131 }; 132 133 CFATTACH_DECL_NEW(rk_typec, sizeof(struct rk_typec_softc), 134 rk_typec_match, rk_typec_attach, NULL, NULL); 135 136 int 137 rk_typec_match(device_t parent, cfdata_t match, void *aux) 138 { 139 struct fdt_attach_args * const faa = aux; 140 141 return of_compatible_match(faa->faa_phandle, compat_data); 142 } 143 144 void 145 rk_typec_attach(device_t parent, device_t self, void *aux) 146 { 147 struct rk_typec_softc * const sc = device_private(self); 148 struct fdt_attach_args * const faa = aux; 149 const int phandle = faa->faa_phandle; 150 bus_addr_t addr; 151 bus_size_t size; 152 int child; 153 154 sc->sc_dev = self; 155 sc->sc_phandle = faa->faa_phandle; 156 sc->sc_bst = faa->faa_bst; 157 158 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 159 aprint_error(": couldn't get registers\n"); 160 return; 161 } 162 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { 163 aprint_error(": couldn't map registers\n"); 164 return; 165 }; 166 167 /* 168 * Find out which phy we are. There is no property for this so we need 169 * to know the address to use the correct GRF registers. 170 */ 171 switch (addr) { 172 case 0xff7c0000: 173 sc->sc_phy_ctrl_id = 0; 174 break; 175 case 0xff800000: 176 sc->sc_phy_ctrl_id = 1; 177 break; 178 default: 179 aprint_error(": unknown address 0x%lx\n", addr); 180 return; 181 } 182 183 sc->sc_grf = fdtbus_syscon_acquire(phandle, "rockchip,grf"); 184 if (sc->sc_grf == NULL) { 185 aprint_error(": couldn't get grf syscon\n"); 186 return; 187 } 188 189 sc->sc_rst = fdtbus_reset_get(phandle, "uphy"); 190 if (sc->sc_rst == NULL) { 191 aprint_error(": couldn't get reset uphy\n"); 192 return; 193 } 194 sc->sc_rst_pipe = fdtbus_reset_get(phandle, "uphy-pipe"); 195 if (sc->sc_rst_pipe == NULL) { 196 aprint_error(": couldn't get reset uphy-pipe\n"); 197 return; 198 } 199 sc->sc_rst_tcphy = fdtbus_reset_get(phandle, "uphy-tcphy"); 200 if (sc->sc_rst_tcphy == NULL) { 201 aprint_error(": couldn't get reset uphy-tcphy\n"); 202 return; 203 } 204 fdtbus_reset_assert(sc->sc_rst); 205 fdtbus_reset_assert(sc->sc_rst_pipe); 206 fdtbus_reset_assert(sc->sc_rst_tcphy); 207 208 fdtbus_clock_assign(phandle); 209 sc->sc_core_clk = fdtbus_clock_get(phandle, "tcpdcore"); 210 if (sc->sc_core_clk == NULL) { 211 aprint_error(": couldn't get tcpdcore clock\n"); 212 return; 213 } 214 sc->sc_phy_ref_clk = fdtbus_clock_get(phandle, "tcpdphy-ref"); 215 if (sc->sc_phy_ref_clk == NULL) { 216 aprint_error(": couldn't get tcpdphy-ref clock\n"); 217 return; 218 } 219 220 aprint_naive("\n"); 221 aprint_normal(": USB-C PHY\n"); 222 223 for (child = OF_child(phandle); child; child = OF_peer(child)) { 224 if (!fdtbus_status_okay(child)) 225 continue; 226 227 struct fdt_attach_args cfaa = *faa; 228 cfaa.faa_phandle = child; 229 cfaa.faa_name = fdtbus_get_string(child, "name"); 230 cfaa.faa_quiet = false; 231 232 config_found(self, &cfaa, NULL, CFARGS_NONE); 233 } 234 } 235 236 /* 237 * USB3 phy 238 */ 239 240 static int rk_tcphy_match(device_t, cfdata_t, void *); 241 static void rk_tcphy_attach(device_t, device_t, void *); 242 243 struct rk_tcphy_softc { 244 device_t sc_dev; 245 int sc_phandle; 246 }; 247 248 CFATTACH_DECL_NEW(rk_tcphy, sizeof(struct rk_tcphy_softc), 249 rk_tcphy_match, rk_tcphy_attach, NULL, NULL); 250 251 static void * 252 rk_tcphy_usb3_acquire(device_t dev, const void *data, size_t len) 253 { 254 struct rk_tcphy_softc * const sc = device_private(dev); 255 256 return sc; 257 } 258 259 static void 260 rk_tcphy_set_usb2_only(struct rk_typec_softc *sc, int usb2only) 261 { 262 uint32_t reg; 263 264 /* Disable usb3tousb2 only */ 265 syscon_lock(sc->sc_grf); 266 reg = syscon_read_4(sc->sc_grf, GRF_USB3PHY_CON0(sc->sc_phy_ctrl_id)); 267 if (usb2only) 268 reg |= USB3PHY_CON0_USB2_ONLY; 269 else 270 reg &= ~USB3PHY_CON0_USB2_ONLY; 271 /* Write Mask */ 272 reg |= (USB3PHY_CON0_USB2_ONLY) << 16; 273 syscon_write_4(sc->sc_grf, GRF_USB3PHY_CON0(sc->sc_phy_ctrl_id), reg); 274 275 /* Enable the USB3 Super Speed port */ 276 reg = syscon_read_4(sc->sc_grf, GRF_USB3OTG_CON1(sc->sc_phy_ctrl_id)); 277 if (usb2only) 278 reg |= USB3OTG_CON1_U3_DIS; 279 else 280 reg &= ~USB3OTG_CON1_U3_DIS; 281 /* Write Mask */ 282 reg |= (USB3OTG_CON1_U3_DIS) << 16; 283 syscon_write_4(sc->sc_grf, GRF_USB3OTG_CON1(sc->sc_phy_ctrl_id), reg); 284 syscon_unlock(sc->sc_grf); 285 } 286 287 static int 288 rk_tcphy_usb3_enable(device_t dev, void *priv, bool enable) 289 { 290 struct rk_typec_softc * const sc = device_private(device_parent(dev)); 291 uint32_t reg; 292 int i; 293 294 aprint_normal_dev(dev, "enable %d\n", enable); 295 if (enable == false) 296 return 0; 297 298 rk_tcphy_set_usb2_only(sc, false); 299 300 clk_enable(sc->sc_core_clk); 301 clk_enable(sc->sc_phy_ref_clk); 302 303 fdtbus_reset_deassert(sc->sc_rst_tcphy); 304 305 /* 24M configuration, magic values from rockchip */ 306 HWRITE4(sc, PMA_CMN_CTRL1, 0x830); 307 for (i = 0; i < 4; i++) { 308 HWRITE4(sc, XCVR_DIAG_LANE_FCM_EN_MGN(i), 0x90); 309 HWRITE4(sc, TX_RCVDET_EN_TMR(i), 0x960); 310 HWRITE4(sc, TX_RCVDET_ST_TMR(i), 0x30); 311 } 312 reg = HREAD4(sc, CMN_DIAG_HSCLK_SEL); 313 reg &= ~CMN_DIAG_HSCLK_SEL_PLL_MASK; 314 reg |= CMN_DIAG_HSCLK_SEL_PLL_CONFIG; 315 HWRITE4(sc, CMN_DIAG_HSCLK_SEL, reg); 316 317 /* PLL configuration, magic values from rockchip */ 318 HWRITE4(sc, CMN_PLL0_VCOCAL_INIT, 0xf0); 319 HWRITE4(sc, CMN_PLL0_VCOCAL_ITER, 0x18); 320 HWRITE4(sc, CMN_PLL0_INTDIV, 0xd0); 321 HWRITE4(sc, CMN_PLL0_FRACDIV, 0x4a4a); 322 HWRITE4(sc, CMN_PLL0_HIGH_THR, 0x34); 323 HWRITE4(sc, CMN_PLL0_SS_CTRL1, 0x1ee); 324 HWRITE4(sc, CMN_PLL0_SS_CTRL2, 0x7f03); 325 HWRITE4(sc, CMN_PLL0_DSM_DIAG, 0x20); 326 HWRITE4(sc, CMN_DIAG_PLL0_OVRD, 0); 327 HWRITE4(sc, CMN_DIAG_PLL0_FBH_OVRD, 0); 328 HWRITE4(sc, CMN_DIAG_PLL0_FBL_OVRD, 0); 329 HWRITE4(sc, CMN_DIAG_PLL0_V2I_TUNE, 0x7); 330 HWRITE4(sc, CMN_DIAG_PLL0_CP_TUNE, 0x45); 331 HWRITE4(sc, CMN_DIAG_PLL0_LF_PROG, 0x8); 332 333 /* Configure the TX and RX line, magic values from rockchip */ 334 HWRITE4(sc, TX_PSC_A0(0), 0x7799); 335 HWRITE4(sc, TX_PSC_A1(0), 0x7798); 336 HWRITE4(sc, TX_PSC_A2(0), 0x5098); 337 HWRITE4(sc, TX_PSC_A3(0), 0x5098); 338 HWRITE4(sc, TX_TXCC_MGNFS_MULT_000(0), 0x0); 339 HWRITE4(sc, XCVR_DIAG_BIDI_CTRL(0), 0xbf); 340 341 HWRITE4(sc, RX_PSC_A0(1), 0xa6fd); 342 HWRITE4(sc, RX_PSC_A1(1), 0xa6fd); 343 HWRITE4(sc, RX_PSC_A2(1), 0xa410); 344 HWRITE4(sc, RX_PSC_A3(1), 0x2410); 345 HWRITE4(sc, RX_PSC_CAL(1), 0x23ff); 346 HWRITE4(sc, RX_SIGDET_HL_FILT_TMR(1), 0x13); 347 HWRITE4(sc, RX_REE_CTRL_DATA_MASK(1), 0x03e7); 348 HWRITE4(sc, RX_DIAG_SIGDET_TUNE(1), 0x1004); 349 HWRITE4(sc, RX_PSC_RDY(1), 0x2010); 350 HWRITE4(sc, XCVR_DIAG_BIDI_CTRL(1), 0xfb); 351 352 HWRITE4(sc, PMA_LANE_CFG, PIN_ASSIGN_D_F); 353 354 HWRITE4(sc, DP_MODE_CTL, DP_MODE_ENTER_A2); 355 356 fdtbus_reset_deassert(sc->sc_rst); 357 358 for (i = 10000; i > 0; i--) { 359 reg = HREAD4(sc, PMA_CMN_CTRL1); 360 if (reg & PMA_CMN_CTRL1_READY) 361 break; 362 delay(10); 363 } 364 if (i == 0) { 365 aprint_error_dev(sc->sc_dev, "timeout waiting for PMA\n"); 366 return ENXIO; 367 } 368 369 fdtbus_reset_deassert(sc->sc_rst_pipe); 370 371 return 0; 372 } 373 374 const struct fdtbus_phy_controller_func rk_tcphy_usb3_funcs = { 375 .acquire = rk_tcphy_usb3_acquire, 376 .release = (void *)voidop, 377 .enable = rk_tcphy_usb3_enable, 378 }; 379 380 static int 381 rk_tcphy_match(device_t parent, cfdata_t cf, void *aux) 382 { 383 struct fdt_attach_args * const faa = aux; 384 const int phandle = faa->faa_phandle; 385 const char *name = fdtbus_get_string(phandle, "name"); 386 387 if (strcmp(name, "usb3-port") == 0) 388 return 1; 389 #if 0 390 if (strcmp(name, "dp-port") == 0) 391 return 1; 392 #endif 393 return 0; 394 } 395 396 static void 397 rk_tcphy_attach(device_t parent, device_t self, void *aux) 398 { 399 struct rk_tcphy_softc * const sc = device_private(self); 400 struct fdt_attach_args * const faa = aux; 401 const int phandle = faa->faa_phandle; 402 const char *name = fdtbus_get_string(phandle, "name"); 403 404 sc->sc_dev = self; 405 sc->sc_phandle = phandle; 406 407 aprint_naive("\n"); 408 409 if (strcmp(name, "usb3-port") == 0) { 410 aprint_normal(": USB3 port\n"); 411 fdtbus_register_phy_controller(self, phandle, &rk_tcphy_usb3_funcs); 412 } 413 } 414