1 /* $OpenBSD: rktcphy.c,v 1.1 2021/06/29 12:43:09 patrick Exp $ */ 2 /*- 3 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 4 * 5 * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.Org> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* 30 * Rockchip PHY TYPEC 31 */ 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/device.h> 36 37 #include <machine/intr.h> 38 #include <machine/bus.h> 39 #include <machine/fdt.h> 40 41 #include <dev/ofw/openfirm.h> 42 #include <dev/ofw/ofw_clock.h> 43 #include <dev/ofw/ofw_misc.h> 44 #include <dev/ofw/fdt.h> 45 46 #define GRF_USB3OTG_BASE(x) (0x2430 + (0x10 * x)) 47 #define GRF_USB3OTG_CON0(x) (GRF_USB3OTG_BASE(x) + 0x0) 48 #define GRF_USB3OTG_CON1(x) (GRF_USB3OTG_BASE(x) + 0x4) 49 #define USB3OTG_CON1_U3_DIS (1 << 0) 50 51 #define GRF_USB3PHY_BASE(x) (0x0e580 + (0xc * (x))) 52 #define GRF_USB3PHY_CON0(x) (GRF_USB3PHY_BASE(x) + 0x0) 53 #define USB3PHY_CON0_USB2_ONLY (1 << 3) 54 #define GRF_USB3PHY_CON1(x) (GRF_USB3PHY_BASE(x) + 0x4) 55 #define GRF_USB3PHY_CON2(x) (GRF_USB3PHY_BASE(x) + 0x8) 56 #define GRF_USB3PHY_STATUS0 0x0e5c0 57 #define GRF_USB3PHY_STATUS1 0x0e5c4 58 59 #define CMN_PLL0_VCOCAL_INIT (0x84 << 2) 60 #define CMN_PLL0_VCOCAL_ITER (0x85 << 2) 61 #define CMN_PLL0_INTDIV (0x94 << 2) 62 #define CMN_PLL0_FRACDIV (0x95 << 2) 63 #define CMN_PLL0_HIGH_THR (0x96 << 2) 64 #define CMN_PLL0_DSM_DIAG (0x97 << 2) 65 #define CMN_PLL0_SS_CTRL1 (0x98 << 2) 66 #define CMN_PLL0_SS_CTRL2 (0x99 << 2) 67 #define CMN_DIAG_PLL0_FBH_OVRD (0x1c0 << 2) 68 #define CMN_DIAG_PLL0_FBL_OVRD (0x1c1 << 2) 69 #define CMN_DIAG_PLL0_OVRD (0x1c2 << 2) 70 #define CMN_DIAG_PLL0_V2I_TUNE (0x1c5 << 2) 71 #define CMN_DIAG_PLL0_CP_TUNE (0x1c6 << 2) 72 #define CMN_DIAG_PLL0_LF_PROG (0x1c7 << 2) 73 #define CMN_DIAG_HSCLK_SEL (0x1e0 << 2) 74 #define CMN_DIAG_HSCLK_SEL_PLL_CONFIG 0x30 75 #define CMN_DIAG_HSCLK_SEL_PLL_MASK 0x33 76 77 #define TX_TXCC_MGNFS_MULT_000(lane) ((0x4050 | ((lane) << 9)) << 2) 78 #define XCVR_DIAG_BIDI_CTRL(lane) ((0x40e8 | ((lane) << 9)) << 2) 79 #define XCVR_DIAG_LANE_FCM_EN_MGN(lane) ((0x40f2 | ((lane) << 9)) << 2) 80 #define TX_PSC_A0(lane) ((0x4100 | ((lane) << 9)) << 2) 81 #define TX_PSC_A1(lane) ((0x4101 | ((lane) << 9)) << 2) 82 #define TX_PSC_A2(lane) ((0x4102 | ((lane) << 9)) << 2) 83 #define TX_PSC_A3(lane) ((0x4103 | ((lane) << 9)) << 2) 84 #define TX_RCVDET_EN_TMR(lane) ((0x4122 | ((lane) << 9)) << 2) 85 #define TX_RCVDET_ST_TMR(lane) ((0x4123 | ((lane) << 9)) << 2) 86 87 #define RX_PSC_A0(lane) ((0x8000 | ((lane) << 9)) << 2) 88 #define RX_PSC_A1(lane) ((0x8001 | ((lane) << 9)) << 2) 89 #define RX_PSC_A2(lane) ((0x8002 | ((lane) << 9)) << 2) 90 #define RX_PSC_A3(lane) ((0x8003 | ((lane) << 9)) << 2) 91 #define RX_PSC_CAL(lane) ((0x8006 | ((lane) << 9)) << 2) 92 #define RX_PSC_RDY(lane) ((0x8007 | ((lane) << 9)) << 2) 93 #define RX_SIGDET_HL_FILT_TMR(lane) ((0x8090 | ((lane) << 9)) << 2) 94 #define RX_REE_CTRL_DATA_MASK(lane) ((0x81bb | ((lane) << 9)) << 2) 95 #define RX_DIAG_SIGDET_TUNE(lane) ((0x81dc | ((lane) << 9)) << 2) 96 97 #define PMA_LANE_CFG (0xc000 << 2) 98 #define PIN_ASSIGN_D_F 0x5100 99 #define DP_MODE_CTL (0xc008 << 2) 100 #define DP_MODE_ENTER_A2 0xc104 101 #define PMA_CMN_CTRL1 (0xc800 << 2) 102 #define PMA_CMN_CTRL1_READY (1 << 0) 103 104 #define HREAD4(sc, reg) \ 105 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 106 #define HWRITE4(sc, reg, val) \ 107 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 108 #define HSET4(sc, reg, bits) \ 109 HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) 110 #define HCLR4(sc, reg, bits) \ 111 HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) 112 113 struct rktcphy_softc { 114 struct device sc_dev; 115 bus_space_tag_t sc_iot; 116 bus_space_handle_t sc_ioh; 117 int sc_node; 118 struct regmap *sc_grf; 119 120 struct phy_device sc_pd; 121 int sc_mode; 122 int sc_phy_ctrl_id; 123 }; 124 125 int rktcphy_match(struct device *, void *, void *); 126 void rktcphy_attach(struct device *, struct device *, void *); 127 128 void rktcphy_set_usb2_only(struct rktcphy_softc *, int); 129 int rktcphy_enable(void *, uint32_t *); 130 131 struct cfattach rktcphy_ca = { 132 sizeof (struct rktcphy_softc), rktcphy_match, rktcphy_attach 133 }; 134 135 struct cfdriver rktcphy_cd = { 136 NULL, "rktcphy", DV_DULL 137 }; 138 139 int 140 rktcphy_match(struct device *parent, void *match, void *aux) 141 { 142 struct fdt_attach_args *faa = aux; 143 144 return OF_is_compatible(faa->fa_node, "rockchip,rk3399-typec-phy"); 145 } 146 147 void 148 rktcphy_attach(struct device *parent, struct device *self, void *aux) 149 { 150 struct rktcphy_softc *sc = (struct rktcphy_softc *)self; 151 struct fdt_attach_args *faa = aux; 152 uint32_t grf; 153 int usb3; 154 155 if (faa->fa_nreg < 1) { 156 printf(": no registers\n"); 157 return; 158 } 159 160 sc->sc_node = faa->fa_node; 161 sc->sc_iot = faa->fa_iot; 162 163 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, 164 faa->fa_reg[0].size, 0, &sc->sc_ioh)) { 165 printf(": can't map registers\n"); 166 return; 167 } 168 169 /* 170 * Find out which phy we are. There is no property for this so we need 171 * to know the address to use the correct GRF registers. 172 */ 173 switch (faa->fa_reg[0].addr) { 174 case 0xff7c0000: 175 sc->sc_phy_ctrl_id = 0; 176 break; 177 case 0xff800000: 178 sc->sc_phy_ctrl_id = 1; 179 break; 180 default: 181 printf(": unknown address 0x%llx\n", faa->fa_reg[0].addr); 182 return; 183 } 184 185 grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0); 186 sc->sc_grf = regmap_byphandle(grf); 187 188 reset_assert(sc->sc_node, "uphy"); 189 reset_assert(sc->sc_node, "uphy-pipe"); 190 reset_assert(sc->sc_node, "uphy-tcphy"); 191 192 clock_set_assigned(sc->sc_node); 193 194 /* Only usb3 port is supported right now */ 195 usb3 = OF_getnodebyname(sc->sc_node, "usb3-port"); 196 if (usb3 == 0) { 197 printf(": no usb3-port child node\n"); 198 return; 199 } 200 201 printf("\n"); 202 203 sc->sc_pd.pd_node = usb3; 204 sc->sc_pd.pd_cookie = sc; 205 sc->sc_pd.pd_enable = rktcphy_enable; 206 phy_register(&sc->sc_pd); 207 } 208 209 void 210 rktcphy_set_usb2_only(struct rktcphy_softc *sc, int usb2only) 211 { 212 uint32_t reg; 213 214 /* Disable usb3tousb2 only */ 215 reg = regmap_read_4(sc->sc_grf, GRF_USB3PHY_CON0(sc->sc_phy_ctrl_id)); 216 if (usb2only) 217 reg |= USB3PHY_CON0_USB2_ONLY; 218 else 219 reg &= ~USB3PHY_CON0_USB2_ONLY; 220 /* Write Mask */ 221 reg |= (USB3PHY_CON0_USB2_ONLY) << 16; 222 regmap_write_4(sc->sc_grf, GRF_USB3PHY_CON0(sc->sc_phy_ctrl_id), reg); 223 224 /* Enable the USB3 Super Speed port */ 225 reg = regmap_read_4(sc->sc_grf, GRF_USB3OTG_CON1(sc->sc_phy_ctrl_id)); 226 if (usb2only) 227 reg |= USB3OTG_CON1_U3_DIS; 228 else 229 reg &= ~USB3OTG_CON1_U3_DIS; 230 /* Write Mask */ 231 reg |= (USB3OTG_CON1_U3_DIS) << 16; 232 regmap_write_4(sc->sc_grf, GRF_USB3OTG_CON1(sc->sc_phy_ctrl_id), reg); 233 } 234 235 int 236 rktcphy_enable(void *cookie, uint32_t *cells) 237 { 238 struct rktcphy_softc *sc = cookie; 239 uint32_t reg; 240 int i; 241 242 rktcphy_set_usb2_only(sc, false); 243 244 clock_enable(sc->sc_node, "tcpdcore"); 245 clock_enable(sc->sc_node, "tcpdphy-ref"); 246 247 reset_deassert(sc->sc_node, "uphy-tcphy"); 248 249 /* 24M configuration, magic values from rockchip */ 250 HWRITE4(sc, PMA_CMN_CTRL1, 0x830); 251 for (i = 0; i < 4; i++) { 252 HWRITE4(sc, XCVR_DIAG_LANE_FCM_EN_MGN(i), 0x90); 253 HWRITE4(sc, TX_RCVDET_EN_TMR(i), 0x960); 254 HWRITE4(sc, TX_RCVDET_ST_TMR(i), 0x30); 255 } 256 reg = HREAD4(sc, CMN_DIAG_HSCLK_SEL); 257 reg &= ~CMN_DIAG_HSCLK_SEL_PLL_MASK; 258 reg |= CMN_DIAG_HSCLK_SEL_PLL_CONFIG; 259 HWRITE4(sc, CMN_DIAG_HSCLK_SEL, reg); 260 261 /* PLL configuration, magic values from rockchip */ 262 HWRITE4(sc, CMN_PLL0_VCOCAL_INIT, 0xf0); 263 HWRITE4(sc, CMN_PLL0_VCOCAL_ITER, 0x18); 264 HWRITE4(sc, CMN_PLL0_INTDIV, 0xd0); 265 HWRITE4(sc, CMN_PLL0_FRACDIV, 0x4a4a); 266 HWRITE4(sc, CMN_PLL0_HIGH_THR, 0x34); 267 HWRITE4(sc, CMN_PLL0_SS_CTRL1, 0x1ee); 268 HWRITE4(sc, CMN_PLL0_SS_CTRL2, 0x7f03); 269 HWRITE4(sc, CMN_PLL0_DSM_DIAG, 0x20); 270 HWRITE4(sc, CMN_DIAG_PLL0_OVRD, 0); 271 HWRITE4(sc, CMN_DIAG_PLL0_FBH_OVRD, 0); 272 HWRITE4(sc, CMN_DIAG_PLL0_FBL_OVRD, 0); 273 HWRITE4(sc, CMN_DIAG_PLL0_V2I_TUNE, 0x7); 274 HWRITE4(sc, CMN_DIAG_PLL0_CP_TUNE, 0x45); 275 HWRITE4(sc, CMN_DIAG_PLL0_LF_PROG, 0x8); 276 277 /* Configure the TX and RX line, magic values from rockchip */ 278 HWRITE4(sc, TX_PSC_A0(0), 0x7799); 279 HWRITE4(sc, TX_PSC_A1(0), 0x7798); 280 HWRITE4(sc, TX_PSC_A2(0), 0x5098); 281 HWRITE4(sc, TX_PSC_A3(0), 0x5098); 282 HWRITE4(sc, TX_TXCC_MGNFS_MULT_000(0), 0x0); 283 HWRITE4(sc, XCVR_DIAG_BIDI_CTRL(0), 0xbf); 284 285 HWRITE4(sc, RX_PSC_A0(1), 0xa6fd); 286 HWRITE4(sc, RX_PSC_A1(1), 0xa6fd); 287 HWRITE4(sc, RX_PSC_A2(1), 0xa410); 288 HWRITE4(sc, RX_PSC_A3(1), 0x2410); 289 HWRITE4(sc, RX_PSC_CAL(1), 0x23ff); 290 HWRITE4(sc, RX_SIGDET_HL_FILT_TMR(1), 0x13); 291 HWRITE4(sc, RX_REE_CTRL_DATA_MASK(1), 0x03e7); 292 HWRITE4(sc, RX_DIAG_SIGDET_TUNE(1), 0x1004); 293 HWRITE4(sc, RX_PSC_RDY(1), 0x2010); 294 HWRITE4(sc, XCVR_DIAG_BIDI_CTRL(1), 0xfb); 295 296 HWRITE4(sc, PMA_LANE_CFG, PIN_ASSIGN_D_F); 297 298 HWRITE4(sc, DP_MODE_CTL, DP_MODE_ENTER_A2); 299 300 reset_deassert(sc->sc_node, "uphy"); 301 302 for (i = 10000; i > 0; i--) { 303 reg = HREAD4(sc, PMA_CMN_CTRL1); 304 if (reg & PMA_CMN_CTRL1_READY) 305 break; 306 delay(10); 307 } 308 if (i == 0) { 309 printf("%s: timeout waiting for PMA\n", sc->sc_dev.dv_xname); 310 return ENXIO; 311 } 312 313 reset_deassert(sc->sc_node, "uphy-pipe"); 314 return 0; 315 } 316