1 1.6 msaitoh /* $NetBSD: meson_usbctrl.c,v 1.6 2024/02/07 04:20:26 msaitoh Exp $ */ 2 1.1 ryo 3 1.1 ryo /* 4 1.6 msaitoh * Copyright (c) 2021 Ryo Shimizu 5 1.1 ryo * All rights reserved. 6 1.1 ryo * 7 1.1 ryo * Redistribution and use in source and binary forms, with or without 8 1.1 ryo * modification, are permitted provided that the following conditions 9 1.1 ryo * are met: 10 1.1 ryo * 1. Redistributions of source code must retain the above copyright 11 1.1 ryo * notice, this list of conditions and the following disclaimer. 12 1.1 ryo * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 ryo * notice, this list of conditions and the following disclaimer in the 14 1.1 ryo * documentation and/or other materials provided with the distribution. 15 1.1 ryo * 16 1.1 ryo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 17 1.1 ryo * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 1.1 ryo * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 1.1 ryo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 1.1 ryo * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 1.1 ryo * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 1.1 ryo * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 1.1 ryo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 1.1 ryo * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 1.1 ryo * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 1.1 ryo * POSSIBILITY OF SUCH DAMAGE. 27 1.1 ryo */ 28 1.1 ryo 29 1.1 ryo #include <sys/cdefs.h> 30 1.6 msaitoh __KERNEL_RCSID(0, "$NetBSD: meson_usbctrl.c,v 1.6 2024/02/07 04:20:26 msaitoh Exp $"); 31 1.1 ryo 32 1.1 ryo #include <sys/param.h> 33 1.1 ryo #include <sys/types.h> 34 1.1 ryo #include <sys/bus.h> 35 1.1 ryo #include <sys/device.h> 36 1.1 ryo 37 1.1 ryo #include <dev/fdt/fdtvar.h> 38 1.1 ryo 39 1.1 ryo /* 40 1.1 ryo * USB Glue registers: 0xffe09000 41 1.1 ryo */ 42 1.1 ryo 43 1.1 ryo /* usb2 phy ports control registers */ 44 1.1 ryo #define MESONUSBCTRL_MAXPHYS 3 45 1.1 ryo #define U2P_R0_REG(i) (0x20 * (i) + 0x00) 46 1.1 ryo #define U2P_R0_DRV_VBUS __BIT(5) 47 1.1 ryo #define U2P_R0_ID_PULLUP __BIT(4) 48 1.1 ryo #define U2P_R0_POWER_ON_RESET __BIT(3) 49 1.1 ryo #define U2P_R0_HAST_MODE __BIT(2) 50 1.1 ryo #define U2P_R0_POWER_OK __BIT(1) 51 1.1 ryo #define U2P_R0_HOST_DEVICE __BIT(0) 52 1.1 ryo #define U2P_R1_REG(i) (0x20 * (i) + 0x04) 53 1.1 ryo #define U2P_R1_VBUS_VALID __BIT(3) 54 1.1 ryo #define U2P_R1_OTG_SESSION_VALID __BIT(2) 55 1.1 ryo #define U2P_R1_ID_DIG __BIT(1) 56 1.1 ryo #define U2P_R1_PHY_READY __BIT(0) 57 1.1 ryo 58 1.1 ryo /* glue registers */ 59 1.1 ryo #define USB_R0_REG 0x80 60 1.1 ryo #define USB_R0_U2D_ACT __BIT(31) 61 1.1 ryo #define USB_R0_U2D_SS_SCALEDOWN_MODE_MASK __BITS(30,29) 62 1.1 ryo #define USB_R0_P30_PCS_RX_LOS_MASK_VAL_MASK __BITS(28,19) 63 1.1 ryo #define USB_R0_P30_LANE0_EXT_PCLK_REQ __BIT(18) 64 1.1 ryo #define USB_R0_P30_LANE0_TX2RX_LOOPBACK __BIT(17) 65 1.1 ryo #define USB_R1_REG 0x84 66 1.1 ryo #define USB_R1_P30_PCS_TX_SWING_FULL_MASK __BITS(31,25) 67 1.1 ryo #define USB_R1_U3H_FLADJ_30MHZ_REG_MASK __BITS(24,19) 68 1.1 ryo #define USB_R1_U3H_HOST_MSI_ENABLE __BIT(18) 69 1.1 ryo #define USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT __BIT(17) 70 1.1 ryo #define USB_R1_U3H_HOST_U3_PORT_DISABLE __BIT(16) 71 1.1 ryo #define USB_R1_U3H_HOST_U2_PORT_DISABLE_MASK __BITS(13,12) 72 1.1 ryo #define USB_R1_U3H_HUB_PORT_PERM_ATTACH_MASK __BITS(9,7) 73 1.1 ryo #define USB_R1_U3H_HUB_PORT_OVERCURRENT_MASK __BITS(4,2) 74 1.1 ryo #define USB_R1_U3H_PME_ENABLE __BIT(1) 75 1.1 ryo #define USB_R1_U3H_BIGENDIAN_GS __BIT(0) 76 1.1 ryo #define USB_R2_REG 0x88 77 1.1 ryo #define USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK __BITS(31,26) 78 1.1 ryo #define USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK __BITS(25,20) 79 1.1 ryo #define USB_R3_REG 0x8c 80 1.1 ryo #define USB_R3_P30_REF_SSP_EN __BIT(13) 81 1.1 ryo #define USB_R3_P30_SSC_REF_CLK_SEL_MASK __BITS(12,4) 82 1.1 ryo #define USB_R3_P30_SSC_RANGE_MASK __BITS(3,1) 83 1.1 ryo #define USB_R3_P30_SSC_ENABLE __BIT(0) 84 1.1 ryo #define USB_R4_REG 0x90 85 1.1 ryo #define USB_R4_P21_ONLY __BIT(4) 86 1.1 ryo #define USB_R4_MEM_PD_MASK __BITS(3,2) 87 1.1 ryo #define USB_R4_P21_SLEEP_M0 __BIT(1) 88 1.1 ryo #define USB_R4_P21_PORT_RESET_0 __BIT(0) 89 1.1 ryo #define USB_R5_REG 0x94 90 1.1 ryo #define USB_R5_ID_DIG_CNT_MASK __BITS(23,16) 91 1.1 ryo #define USB_R5_ID_DIG_TH_MASK __BITS(15,8) 92 1.1 ryo #define USB_R5_ID_DIG_IRQ __BIT(7) 93 1.1 ryo #define USB_R5_ID_DIG_CURR __BIT(6) 94 1.1 ryo #define USB_R5_ID_DIG_EN_1 __BIT(5) 95 1.1 ryo #define USB_R5_ID_DIG_EN_0 __BIT(4) 96 1.1 ryo #define USB_R5_ID_DIG_CFG_MASK __BITS(3,2) 97 1.1 ryo #define USB_R5_ID_DIG_REG __BIT(1) 98 1.1 ryo #define USB_R5_ID_DIG_SYNC __BIT(0) 99 1.1 ryo 100 1.1 ryo #define USBCTRL_READ_REG(sc, reg) \ 101 1.1 ryo bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 102 1.1 ryo #define USBCTRL_WRITE_REG(sc, reg, val) \ 103 1.1 ryo bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 104 1.1 ryo 105 1.1 ryo struct meson_usbctrl_config { 106 1.1 ryo int num_phys; 107 1.1 ryo }; 108 1.1 ryo 109 1.1 ryo struct meson_usbctrl_config mesong12_conf = { 110 1.1 ryo .num_phys = 3 111 1.1 ryo }; 112 1.1 ryo 113 1.2 thorpej static const struct device_compatible_entry compat_data[] = { 114 1.2 thorpej { .compat = "amlogic,meson-g12a-usb-ctrl", .data = &mesong12_conf }, 115 1.4 thorpej DEVICE_COMPAT_EOL 116 1.1 ryo }; 117 1.1 ryo 118 1.1 ryo struct meson_usbctrl_softc { 119 1.1 ryo device_t sc_dev; 120 1.1 ryo bus_space_tag_t sc_bst; 121 1.1 ryo bus_space_handle_t sc_bsh; 122 1.2 thorpej const struct meson_usbctrl_config *sc_conf; 123 1.1 ryo struct fdtbus_regulator *sc_supply; 124 1.1 ryo int sc_phandle; 125 1.1 ryo }; 126 1.1 ryo 127 1.1 ryo static void 128 1.1 ryo meson_usbctrl_usb2_init(struct meson_usbctrl_softc *sc) 129 1.1 ryo { 130 1.1 ryo int i; 131 1.1 ryo const char *p; 132 1.1 ryo 133 1.1 ryo for (i = 0; i < sc->sc_conf->num_phys; i++) { 134 1.1 ryo /* setup only for usb2 phys */ 135 1.1 ryo p = fdtbus_get_string_index(sc->sc_phandle, "phy-names", i); 136 1.1 ryo if (p == NULL || strstr(p, "usb2") == NULL) 137 1.1 ryo continue; 138 1.1 ryo 139 1.1 ryo USBCTRL_WRITE_REG(sc, U2P_R0_REG(i), 140 1.1 ryo USBCTRL_READ_REG(sc, U2P_R0_REG(i)) | 141 1.1 ryo U2P_R0_POWER_ON_RESET); 142 1.1 ryo 143 1.1 ryo /* XXX: OTG not supported. always set HOST_DEVICE mode */ 144 1.1 ryo USBCTRL_WRITE_REG(sc, U2P_R0_REG(i), 145 1.1 ryo USBCTRL_READ_REG(sc, U2P_R0_REG(i)) | 146 1.1 ryo U2P_R0_HOST_DEVICE); 147 1.1 ryo 148 1.1 ryo USBCTRL_WRITE_REG(sc, U2P_R0_REG(i), 149 1.1 ryo USBCTRL_READ_REG(sc, U2P_R0_REG(i)) & 150 1.1 ryo ~U2P_R0_POWER_ON_RESET); 151 1.1 ryo } 152 1.1 ryo } 153 1.1 ryo 154 1.1 ryo static void 155 1.1 ryo meson_usbctrl_usb_glue_init(struct meson_usbctrl_softc *sc) 156 1.1 ryo { 157 1.1 ryo uint32_t val; 158 1.1 ryo 159 1.1 ryo val = USBCTRL_READ_REG(sc, USB_R1_REG); 160 1.1 ryo val &= ~USB_R1_U3H_FLADJ_30MHZ_REG_MASK; 161 1.1 ryo val |= __SHIFTIN(0x20, USB_R1_U3H_FLADJ_30MHZ_REG_MASK); 162 1.1 ryo USBCTRL_WRITE_REG(sc, USB_R1_REG, val); 163 1.1 ryo 164 1.1 ryo val = USBCTRL_READ_REG(sc, USB_R5_REG); 165 1.1 ryo val |= USB_R5_ID_DIG_EN_0; 166 1.1 ryo USBCTRL_WRITE_REG(sc, USB_R5_REG, val); 167 1.1 ryo 168 1.1 ryo val = USBCTRL_READ_REG(sc, USB_R5_REG); 169 1.1 ryo val |= USB_R5_ID_DIG_EN_1; 170 1.1 ryo USBCTRL_WRITE_REG(sc, USB_R5_REG, val); 171 1.1 ryo 172 1.1 ryo val = USBCTRL_READ_REG(sc, USB_R5_REG); 173 1.1 ryo val &= ~USB_R5_ID_DIG_TH_MASK; 174 1.1 ryo val |= __SHIFTIN(0xff, USB_R5_ID_DIG_TH_MASK); 175 1.1 ryo USBCTRL_WRITE_REG(sc, USB_R5_REG, val); 176 1.1 ryo } 177 1.1 ryo 178 1.1 ryo static void 179 1.1 ryo meson_usbctrl_usb3_init(struct meson_usbctrl_softc *sc) 180 1.1 ryo { 181 1.1 ryo uint32_t val; 182 1.1 ryo 183 1.1 ryo val = USBCTRL_READ_REG(sc, USB_R3_REG); 184 1.1 ryo val &= ~USB_R3_P30_SSC_RANGE_MASK; 185 1.1 ryo val &= ~USB_R3_P30_SSC_ENABLE; 186 1.1 ryo val |= __SHIFTIN(2, USB_R3_P30_SSC_RANGE_MASK); 187 1.1 ryo val |= USB_R3_P30_REF_SSP_EN; 188 1.1 ryo USBCTRL_WRITE_REG(sc, USB_R3_REG, val); 189 1.1 ryo 190 1.1 ryo delay(2); 191 1.1 ryo 192 1.1 ryo val = USBCTRL_READ_REG(sc, USB_R2_REG); 193 1.1 ryo val &= ~USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK; 194 1.1 ryo val |= __SHIFTIN(0x15, USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK); 195 1.1 ryo USBCTRL_WRITE_REG(sc, USB_R2_REG, val); 196 1.1 ryo 197 1.1 ryo val = USBCTRL_READ_REG(sc, USB_R2_REG); 198 1.1 ryo val &= ~USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK; 199 1.1 ryo val |= __SHIFTIN(0x20, USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK); 200 1.1 ryo USBCTRL_WRITE_REG(sc, USB_R2_REG, val); 201 1.1 ryo 202 1.1 ryo delay(2); 203 1.1 ryo 204 1.1 ryo val = USBCTRL_READ_REG(sc, USB_R1_REG); 205 1.1 ryo val |= USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT; 206 1.1 ryo USBCTRL_WRITE_REG(sc, USB_R1_REG, val); 207 1.1 ryo 208 1.1 ryo val = USBCTRL_READ_REG(sc, USB_R1_REG); 209 1.1 ryo val &= ~USB_R1_P30_PCS_TX_SWING_FULL_MASK; 210 1.1 ryo val |= __SHIFTIN(127, USB_R1_P30_PCS_TX_SWING_FULL_MASK); 211 1.1 ryo USBCTRL_WRITE_REG(sc, USB_R1_REG, val); 212 1.1 ryo 213 1.1 ryo /* XXX: force HOST_DEVICE mode */ 214 1.1 ryo val = USBCTRL_READ_REG(sc, USB_R0_REG); 215 1.1 ryo val &= ~USB_R0_U2D_ACT; 216 1.1 ryo USBCTRL_WRITE_REG(sc, USB_R0_REG, val); 217 1.1 ryo 218 1.1 ryo val = USBCTRL_READ_REG(sc, USB_R4_REG); 219 1.1 ryo val &= ~USB_R4_P21_SLEEP_M0; 220 1.1 ryo USBCTRL_WRITE_REG(sc, USB_R4_REG, val); 221 1.1 ryo } 222 1.1 ryo 223 1.1 ryo static void 224 1.1 ryo meson_usbctrl_enable_usb3_phys(struct meson_usbctrl_softc *sc) 225 1.1 ryo { 226 1.1 ryo struct fdtbus_phy *phy; 227 1.1 ryo int i; 228 1.1 ryo const char *phyname; 229 1.1 ryo 230 1.1 ryo /* 231 1.1 ryo * enable only for usb3 phys. 232 1.1 ryo * node of "snps,dwc3" decl in "amlogic,meson-g12a-usb-ctrl" have 233 1.1 ryo * no "phys" property, so enable the phy here. 234 1.1 ryo */ 235 1.1 ryo for (i = 0; i < sc->sc_conf->num_phys; i++) { 236 1.1 ryo phyname = fdtbus_get_string_index(sc->sc_phandle, 237 1.1 ryo "phy-names", i); 238 1.1 ryo if (strstr(phyname, "usb3") == NULL) 239 1.1 ryo continue; 240 1.1 ryo 241 1.1 ryo phy = fdtbus_phy_get_index(sc->sc_phandle, i); 242 1.1 ryo if (phy == NULL) 243 1.1 ryo continue; 244 1.1 ryo if (fdtbus_phy_enable(phy, true) != 0) 245 1.1 ryo aprint_error_dev(sc->sc_dev, "couldn't enable phy %s\n", 246 1.1 ryo phyname); 247 1.1 ryo } 248 1.1 ryo } 249 1.1 ryo 250 1.1 ryo static int 251 1.1 ryo meson_usbctrl_match(device_t parent, cfdata_t cf, void *aux) 252 1.1 ryo { 253 1.1 ryo struct fdt_attach_args * const faa = aux; 254 1.1 ryo 255 1.5 thorpej return of_compatible_match(faa->faa_phandle, compat_data); 256 1.1 ryo } 257 1.1 ryo 258 1.1 ryo static void 259 1.1 ryo meson_usbctrl_attach(device_t parent, device_t self, void *aux) 260 1.1 ryo { 261 1.1 ryo struct meson_usbctrl_softc * const sc = device_private(self); 262 1.1 ryo struct fdt_attach_args * const faa = aux; 263 1.1 ryo bus_addr_t addr; 264 1.1 ryo bus_size_t size; 265 1.1 ryo int phandle, child; 266 1.1 ryo 267 1.1 ryo sc->sc_dev = self; 268 1.1 ryo sc->sc_bst = faa->faa_bst; 269 1.1 ryo sc->sc_phandle = phandle = faa->faa_phandle; 270 1.5 thorpej sc->sc_conf = of_compatible_lookup(phandle, compat_data)->data; 271 1.1 ryo 272 1.1 ryo if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 273 1.1 ryo aprint_error(": couldn't get registers\n"); 274 1.1 ryo return; 275 1.1 ryo } 276 1.1 ryo if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { 277 1.1 ryo aprint_error(": couldn't map registers\n"); 278 1.1 ryo return; 279 1.1 ryo } 280 1.1 ryo 281 1.1 ryo aprint_naive("\n"); 282 1.1 ryo aprint_normal(": USB Controllers\n"); 283 1.1 ryo 284 1.1 ryo sc->sc_supply = fdtbus_regulator_acquire(phandle, "vbus-supply"); 285 1.1 ryo if (sc->sc_supply != NULL) 286 1.1 ryo fdtbus_regulator_enable(sc->sc_supply); /* USB HOST MODE */ 287 1.1 ryo 288 1.1 ryo meson_usbctrl_usb2_init(sc); 289 1.1 ryo meson_usbctrl_usb_glue_init(sc); 290 1.1 ryo meson_usbctrl_usb3_init(sc); 291 1.1 ryo meson_usbctrl_enable_usb3_phys(sc); 292 1.1 ryo 293 1.1 ryo for (child = OF_child(phandle); child; child = OF_peer(child)) { 294 1.1 ryo fdt_add_child(parent, child, faa, 0); 295 1.1 ryo } 296 1.1 ryo } 297 1.1 ryo 298 1.1 ryo CFATTACH_DECL_NEW(meson_usbctrl, sizeof(struct meson_usbctrl_softc), 299 1.1 ryo meson_usbctrl_match, meson_usbctrl_attach, NULL, NULL); 300