1 /* $NetBSD: mesong12_usb3pciephy.c,v 1.2 2021/01/27 03:10:18 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 2021 Ryo Shimizu <ryo@nerv.org> 5 * All rights reserved. 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 ``AS IS'' AND ANY EXPRESS 17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: mesong12_usb3pciephy.c,v 1.2 2021/01/27 03:10:18 thorpej Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/types.h> 34 #include <sys/bus.h> 35 #include <sys/device.h> 36 37 #include <dev/fdt/fdtvar.h> 38 39 #define USB3PCIEPHY_R0_REG 0x00 40 #define USB3PCIEPHY_R0_PCIE_USB3_SWITCH __BITS(6,5) 41 #define USB3PCIEPHY_R0_PCIE_POWER_STATE __BITS(4,0) 42 #define USB3PCIEPHY_R1_REG 0x04 43 #define USB3PCIEPHY_R1_PHY_MPLL_MULTIPLIER __BITS(31,25) 44 #define USB3PCIEPHY_R1_PHY_REF_CLKDIV2 __BIT(24) 45 #define USB3PCIEPHY_R1_PHY_LOS_BIAS __BITS(23,21) 46 #define USB3PCIEPHY_R1_PHY_LOS_LEVEL __BITS(20,16) 47 #define USB3PCIEPHY_R1_PHY_RX0_EQ __BITS(15,13) 48 #define USB3PCIEPHY_R1_PHY_RX1_EQ __BITS(12,10) 49 #define USB3PCIEPHY_R1_PHY_TX0_TERM_OFFSET __BITS(9,5) 50 #define USB3PCIEPHY_R1_PHY_TX1_TERM_OFFSET __BITS(4,0) 51 #define USB3PCIEPHY_R2_REG 0x08 52 #define USB3PCIEPHY_R2_PHY_TX_VBOOST_LVL __BITS(20,18) 53 #define USB3PCIEPHY_R2_PCS_TX_DEEMPH_GEN1 __BITS(17,12) 54 #define USB3PCIEPHY_R2_PCS_TX_DEEMPH_GEN2_3P5DB __BITS(11,6) 55 #define USB3PCIEPHY_R2_PCS_TX_DEEMPH_GEN2_6DB __BITS(5,0) 56 #define USB3PCIEPHY_R4_REG 0x10 57 #define USB3PCIEPHY_R4_PHY_CR_CAP_ADDR __BIT(19) 58 #define USB3PCIEPHY_R4_PHY_CR_CAP_DATA __BIT(18) 59 #define USB3PCIEPHY_R4_PHY_CR_DATA_IN __BITS(17,2) 60 #define USB3PCIEPHY_R4_PHY_CR_READ __BIT(1) 61 #define USB3PCIEPHY_R4_PHY_CR_WRITE __BIT(0) 62 #define USB3PCIEPHY_R5_REG 0x14 63 #define USB3PCIEPHY_R5_PHY_BS_OUT __BIT(17) 64 #define USB3PCIEPHY_R5_PHY_CR_ACK __BIT(16) 65 #define USB3PCIEPHY_R5_PHY_CR_DATA_OUT __BITS(15,0) 66 67 #define PHY_READ_REG(sc, reg) \ 68 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 69 #define PHY_WRITE_REG(sc, reg, val) \ 70 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 71 72 73 /* The values must be matched to those in dt-bindings/phy/phy.h */ 74 #define PHY_NONE 0 75 #define PHY_TYPE_PCIE 2 76 #define PHY_TYPE_USB3 4 77 78 struct mesong12_usb3pciephy_softc { 79 device_t sc_dev; 80 bus_space_tag_t sc_bst; 81 bus_space_handle_t sc_bsh; 82 struct clk *sc_clk; 83 struct fdtbus_reset *sc_reset; 84 struct fdtbus_regulator *sc_supply; 85 int sc_phandle; 86 int sc_phy_type; 87 }; 88 89 static void * 90 mesong12_usb3pciephy_acquire(device_t dev, const void *data, size_t len) 91 { 92 struct mesong12_usb3pciephy_softc * const sc = device_private(dev); 93 const uint32_t *p = data; 94 95 /* already acquired? */ 96 if (sc->sc_phy_type != PHY_NONE) 97 return NULL; 98 99 if (len != sizeof(uint32_t)) 100 return NULL; 101 102 switch (be32toh(p[0])) { 103 case PHY_TYPE_USB3: 104 sc->sc_phy_type = PHY_TYPE_USB3; 105 break; 106 case PHY_TYPE_PCIE: 107 return NULL; /* PCIe mode is not supported */ 108 default: 109 return NULL; 110 } 111 112 return sc; 113 } 114 115 static void 116 mesong12_usb3pciephy_release(device_t dev, void *priv) 117 { 118 struct mesong12_usb3pciephy_softc * const sc = device_private(dev); 119 120 sc->sc_phy_type = PHY_NONE; 121 } 122 123 static inline int 124 mesong12_usb3pciephy_ack(struct mesong12_usb3pciephy_softc *sc, bool ack, 125 const char *str) 126 { 127 int timeout; 128 uint32_t val; 129 130 for (timeout = 1000; timeout > 0; timeout--) { 131 val = PHY_READ_REG(sc, USB3PCIEPHY_R5_REG); 132 if (!(val & USB3PCIEPHY_R5_PHY_CR_ACK) == !ack) 133 return 0; 134 delay(5); 135 } 136 device_printf(sc->sc_dev, "phy %s %s timeout\n", 137 str, ack ? "ack" : "nack"); 138 return ETIMEDOUT; 139 } 140 141 static void 142 mesong12_usb3pciephy_addr(struct mesong12_usb3pciephy_softc *sc, 143 bus_addr_t addr) 144 { 145 uint32_t val; 146 147 val = __SHIFTIN(addr, USB3PCIEPHY_R4_PHY_CR_DATA_IN); 148 PHY_WRITE_REG(sc, USB3PCIEPHY_R4_REG, val); 149 PHY_WRITE_REG(sc, USB3PCIEPHY_R4_REG, val); 150 PHY_WRITE_REG(sc, USB3PCIEPHY_R4_REG, val | 151 USB3PCIEPHY_R4_PHY_CR_CAP_ADDR); 152 if (mesong12_usb3pciephy_ack(sc, true, "addr") != 0) 153 return; 154 155 PHY_WRITE_REG(sc, USB3PCIEPHY_R4_REG, val); 156 mesong12_usb3pciephy_ack(sc, false, "addr"); 157 } 158 159 static uint16_t 160 mesong12_usb3pciephy_read(struct mesong12_usb3pciephy_softc *sc, 161 bus_addr_t addr) 162 { 163 uint32_t val; 164 165 mesong12_usb3pciephy_addr(sc, addr); 166 167 PHY_WRITE_REG(sc, USB3PCIEPHY_R4_REG, 0); 168 PHY_WRITE_REG(sc, USB3PCIEPHY_R4_REG, USB3PCIEPHY_R4_PHY_CR_READ); 169 if (mesong12_usb3pciephy_ack(sc, true, "read data") != 0) 170 return 0; 171 172 val = PHY_READ_REG(sc, USB3PCIEPHY_R5_REG); 173 PHY_WRITE_REG(sc, USB3PCIEPHY_R4_REG, 0); 174 if (mesong12_usb3pciephy_ack(sc, false, "read data") != 0) 175 return 0; 176 177 return __SHIFTOUT(val, USB3PCIEPHY_R5_PHY_CR_DATA_OUT); 178 } 179 180 static void 181 mesong12_usb3pciephy_write(struct mesong12_usb3pciephy_softc *sc, 182 bus_addr_t addr, uint16_t data) 183 { 184 uint32_t val; 185 186 mesong12_usb3pciephy_addr(sc, addr); 187 188 val = __SHIFTIN(addr, USB3PCIEPHY_R4_PHY_CR_DATA_IN); 189 PHY_WRITE_REG(sc, USB3PCIEPHY_R4_REG, val); 190 PHY_WRITE_REG(sc, USB3PCIEPHY_R4_REG, val); 191 PHY_WRITE_REG(sc, USB3PCIEPHY_R4_REG, val | 192 USB3PCIEPHY_R4_PHY_CR_CAP_DATA); 193 if (mesong12_usb3pciephy_ack(sc, true, "write addr") != 0) 194 return; 195 PHY_WRITE_REG(sc, USB3PCIEPHY_R4_REG, val); 196 if (mesong12_usb3pciephy_ack(sc, false, "write addr") != 0) 197 return; 198 199 PHY_WRITE_REG(sc, USB3PCIEPHY_R4_REG, val); 200 PHY_WRITE_REG(sc, USB3PCIEPHY_R4_REG, val | 201 USB3PCIEPHY_R4_PHY_CR_WRITE); 202 if (mesong12_usb3pciephy_ack(sc, true, "write data") != 0) 203 return; 204 PHY_WRITE_REG(sc, USB3PCIEPHY_R4_REG, val); 205 if (mesong12_usb3pciephy_ack(sc, false, "write data") != 0) 206 return; 207 } 208 209 static int 210 mesong12_usb3pciephy_enable(device_t dev, void *priv, bool enable) 211 { 212 struct mesong12_usb3pciephy_softc * const sc = device_private(dev); 213 uint32_t val; 214 215 fdtbus_clock_assign(sc->sc_phandle); 216 if (sc->sc_reset != NULL) { 217 fdtbus_reset_assert(sc->sc_reset); 218 delay(10); 219 fdtbus_reset_deassert(sc->sc_reset); 220 } 221 222 if (!enable) 223 return 0; 224 225 /* switch to USB3.0 */ 226 val = PHY_READ_REG(sc, USB3PCIEPHY_R0_REG); 227 val &= ~USB3PCIEPHY_R0_PCIE_USB3_SWITCH; 228 val |= __SHIFTIN(3, USB3PCIEPHY_R0_PCIE_USB3_SWITCH); 229 PHY_WRITE_REG(sc, USB3PCIEPHY_R0_REG, val); 230 delay(10); 231 232 #if 0 /* XXX: doesn't work? */ 233 /* workaround for SSPHY(SuperSpeedPHY) suspend bug */ 234 val = mesong12_usb3pciephy_read(sc, 0x102d); 235 val |= __BIT(7); 236 mesong12_usb3pciephy_write(sc, 0x102d, val); 237 #endif 238 239 val = mesong12_usb3pciephy_read(sc, 0x1010); 240 val &= ~__BITS(11,4); 241 val |= __SHIFTIN(2, __BITS(11,4)); 242 mesong12_usb3pciephy_write(sc, 0x1010, val); 243 244 #if 0 /* XXX: doesn't work? */ 245 /* Rx equalization magic */ 246 val = mesong12_usb3pciephy_read(sc, 0x1006); 247 val &= ~__BITS(7,6); 248 val |= __SHIFTIN(2, __BITS(7,6)); 249 val &= ~__BITS(10,8); 250 val |= __SHIFTIN(3, __BITS(10,8)); 251 val |= __BIT(11); 252 mesong12_usb3pciephy_write(sc, 0x1006, val); 253 #endif 254 255 /* Tx equalization magic */ 256 val = mesong12_usb3pciephy_read(sc, 0x1002); 257 val &= ~__BITS(13,7); 258 val |= __SHIFTIN(0x16, __BITS(13,7)); 259 val &= ~__BITS(6,0); 260 val |= __SHIFTIN(0x7f, __BITS(6,0)); 261 val |= __BIT(14); 262 mesong12_usb3pciephy_write(sc, 0x1002, val); 263 264 /* MPLL loop magic */ 265 val = mesong12_usb3pciephy_read(sc, 0x30); 266 val &= ~__BITS(7,4); 267 val |= __SHIFTIN(8, __BITS(7,4)); 268 mesong12_usb3pciephy_write(sc, 0x30, val); 269 270 271 val = PHY_READ_REG(sc, USB3PCIEPHY_R2_REG); 272 val &= ~USB3PCIEPHY_R2_PHY_TX_VBOOST_LVL; 273 val |= __SHIFTIN(4, USB3PCIEPHY_R2_PHY_TX_VBOOST_LVL); 274 PHY_WRITE_REG(sc, USB3PCIEPHY_R2_REG, val); 275 276 val = PHY_READ_REG(sc, USB3PCIEPHY_R1_REG); 277 val &= ~USB3PCIEPHY_R1_PHY_LOS_BIAS; 278 val |= __SHIFTIN(4, USB3PCIEPHY_R1_PHY_LOS_BIAS); 279 val &= ~USB3PCIEPHY_R1_PHY_LOS_LEVEL; 280 val |= __SHIFTIN(9, USB3PCIEPHY_R1_PHY_LOS_LEVEL); 281 PHY_WRITE_REG(sc, USB3PCIEPHY_R1_REG, val); 282 283 return 0; 284 } 285 286 static const struct device_compatible_entry compat_data[] = { 287 { .compat = "amlogic,g12a-usb3-pcie-phy" }, 288 DEVICE_COMPAT_EOL 289 }; 290 291 static int 292 mesong12_usb3pciephy_match(device_t parent, cfdata_t cf, void *aux) 293 { 294 struct fdt_attach_args * const faa = aux; 295 296 return of_compatible_match(faa->faa_phandle, compat_data); 297 } 298 299 static const struct fdtbus_phy_controller_func mesong12_usb3pciephy_funcs = { 300 .acquire = mesong12_usb3pciephy_acquire, 301 .release = mesong12_usb3pciephy_release, 302 .enable = mesong12_usb3pciephy_enable 303 }; 304 305 static void 306 mesong12_usb3pciephy_attach(device_t parent, device_t self, void *aux) 307 { 308 struct mesong12_usb3pciephy_softc * const sc = device_private(self); 309 struct fdt_attach_args * const faa = aux; 310 const int phandle = faa->faa_phandle; 311 bus_addr_t addr; 312 bus_size_t size; 313 314 sc->sc_dev = self; 315 sc->sc_bst = faa->faa_bst; 316 sc->sc_phandle = phandle; 317 318 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 319 aprint_error(": couldn't get registers\n"); 320 return; 321 } 322 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { 323 aprint_error(": couldn't map registers\n"); 324 return; 325 } 326 327 sc->sc_clk = fdtbus_clock_get_index(phandle, 0); 328 if (sc->sc_clk == NULL) { 329 aprint_error(": couldn't get clock\n"); 330 goto attach_failure; 331 } 332 if (clk_enable(sc->sc_clk) != 0) { 333 aprint_error(": couldn't enable clock\n"); 334 goto attach_failure; 335 } 336 337 sc->sc_reset = fdtbus_reset_get_index(phandle, 0); 338 sc->sc_supply = fdtbus_regulator_acquire(phandle, "phy-supply"); 339 if (sc->sc_supply != NULL) 340 fdtbus_regulator_enable(sc->sc_supply); 341 342 aprint_naive("\n"); 343 aprint_normal(": USB3 PCIe PHY\n"); 344 345 fdtbus_register_phy_controller(self, phandle, 346 &mesong12_usb3pciephy_funcs); 347 return; 348 349 attach_failure: 350 bus_space_unmap(sc->sc_bst, sc->sc_bsh, size); 351 return; 352 } 353 354 CFATTACH_DECL_NEW(mesong12_usb3pciephy, 355 sizeof(struct mesong12_usb3pciephy_softc), 356 mesong12_usb3pciephy_match, mesong12_usb3pciephy_attach, NULL, NULL); 357