1 /* $NetBSD: ehci_mv.c,v 1.10 2021/08/07 16:19:13 thorpej Exp $ */ 2 /* 3 * Copyright (c) 2008 KIYOHARA Takashi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: ehci_mv.c,v 1.10 2021/08/07 16:19:13 thorpej Exp $"); 30 31 #include <sys/param.h> 32 #include <sys/bus.h> 33 #include <sys/device.h> 34 #include <sys/errno.h> 35 #include <sys/systm.h> 36 37 #include <dev/marvell/marvellreg.h> 38 #include <dev/marvell/marvellvar.h> 39 40 #include <dev/usb/usb.h> 41 #include <dev/usb/usbdi.h> 42 #include <dev/usb/usbdivar.h> 43 #include <dev/usb/usb_mem.h> 44 45 #include <dev/usb/ehcireg.h> 46 #include <dev/usb/ehcivar.h> 47 48 #include "locators.h" 49 50 #ifdef EHCI_DEBUG 51 #define DPRINTF(x) if (ehcidebug) printf x 52 extern int ehcidebug; 53 #else 54 #define DPRINTF(x) 55 #endif 56 57 58 #define MARVELL_USB_SIZE 0x1000 59 60 #define MARVELL_USB_NWINDOW 4 61 62 #define MARVELL_USB_ID 0x000 63 #define MARVELL_USB_HWGENERAL 0x004 64 #define MARVELL_USB_HWHOST 0x008 65 #define MARVELL_USB_HWDEVICE 0x00c 66 #define MARVELL_USB_HWTXBUF 0x010 67 #define MARVELL_USB_HWRXBUF 0x014 68 #define MARVELL_USB_HWTTTXBUF 0x018 69 #define MARVELL_USB_HWTTRXBUF 0x01c 70 71 /* ehci generic registers */ 72 #define MARVELL_USB_EHCI_BASE 0x100 73 #define MARVELL_USB_EHCI_SIZE 0x100 74 75 /* ehci vendor extension registers */ 76 #define MARVELL_USB_EHCI_PS_PSPD 0x0c000000 /* Port speed */ 77 #define MARVELL_USB_EHCI_PS_PSPD_FS 0x00000000 /* Full speed */ 78 #define MARVELL_USB_EHCI_PS_PSPD_LS 0x04000000 /* Low speed */ 79 #define MARVELL_USB_EHCI_PS_PSPD_HS 0x08000000 /* High speed */ 80 81 #define MARVELL_USB_EHCI_USBMODE 0x68 82 #define MARVELL_USB_EHCI_MODE_STRMDIS 0x00000008 /* RW straming disable */ 83 #define MARVELL_USB_EHCI_MODE_BE 0x00000004 /* RW B/L endianness select*/ 84 #define MARVELL_USB_EHCI_MODE_HDMASK 0x00000003 /* RW host/device Mask */ 85 #define MARVELL_USB_EHCI_MODE_HOST 0x00000003 /* RW mode host */ 86 #define MARVELL_USB_EHCI_MODE_DEVICE 0x00000002 /* RW mode device */ 87 88 #define MARVELL_USB_DCIVERSION 0x120 89 #define MARVELL_USB_DCCPARAMS 0x124 90 #define MARVELL_USB_TTCTRL 0x15c 91 #define MARVELL_USB_BURSTSIZE 0x160 92 #define MARVELL_USB_TXFILLTUNING 0x164 93 #define MARVELL_USB_TXTTFILLTUNING 0x168 94 #define MARVELL_USB_OTGSC 0x1a4 95 #define MARVELL_USB_USBMODE 0x1a8 96 #define MARVELL_USB_USBMODE_MASK (3 << 0) 97 #define MARVELL_USB_USBMODE_HOST (3 << 0) 98 #define MARVELL_USB_USBMODE_DEVICE (2 << 0) 99 #define MARVELL_USB_USBMODE_STREAMDISABLE (1 << 4) 100 #define MARVELL_USB_ENPDTSETUPSTAT 0x1ac 101 #define MARVELL_USB_ENDPTPRIME 0x1b0 102 #define MARVELL_USB_ENDPTFLUSH 0x1b4 103 #define MARVELL_USB_ENDPTSTATS 0x1b8 104 #define MARVELL_USB_ENDPTCOMPLETE 0x1bc 105 #define MARVELL_USB_ENDPTCTRL0 0x1c0 106 #define MARVELL_USB_ENDPTCTRL1 0x1c1 107 #define MARVELL_USB_ENDPTCTRL2 0x1c2 108 #define MARVELL_USB_ENDPTCTRL3 0x1c3 109 /* Bridge Control And Status Registers */ 110 #define MARVELL_USB_BCR 0x300 /* Control */ 111 /* Bridge Interrupt and Error Registers */ 112 #define MARVELL_USB_BICR 0x310 /* Interrupt Cause */ 113 #define MARVELL_USB_BIMR 0x314 /* Interrupt Mask */ 114 #define MARVELL_USB_BIR_ADDRDECERR (1 << 0) 115 #define MARVELL_USB_BEAR 0x31c /* Error Address */ 116 /* Bridge Address Decoding Registers */ 117 #define MARVELL_USB_WCR(n) (0x320 + (n) * 0x10) /* WinN Control */ 118 #define MARVELL_USB_WCR_WINEN (1 << 0) 119 #define MARVELL_USB_WCR_TARGET(t) (((t) & 0xf) << 4) 120 #define MARVELL_USB_WCR_ATTR(a) (((a) & 0xff) << 8) 121 #define MARVELL_USB_WCR_SIZE(s) (((s) - 1) & 0xffff0000) 122 #define MARVELL_USB_WBR(n) (0x324 + (n) * 0x10) /* WinN Base */ 123 #define MARVELL_USB_WBR_BASE(b) ((b) & 0xffff0000) 124 /* IPG Metal Fix Register ??? */ 125 #define MARVELL_USB_IPGR 0x360 126 /* USB 2.0 PHY Register Map */ 127 #define MARVELL_USB_PCR 0x400 /* Power Control */ 128 #define MARVELL_USB_PCR_PU (1 << 0) /* Power Up */ 129 #define MARVELL_USB_PCR_PUPLL (1 << 1) /*Power Up PLL*/ 130 #define MARVELL_USB_PCR_SUSPENDM (1 << 2) 131 #define MARVELL_USB_PCR_VBUSPWRFAULT (1 << 3) 132 #define MARVELL_USB_PCR_PWRCTLWAKEUP (1 << 4) 133 #define MARVELL_USB_PCR_PUREF (1 << 5) 134 #define MARVELL_USB_PCR_BGVSEL_MASK (3 << 6) 135 #define MARVELL_USB_PCR_BGVSEL_CONNECT_ANAGRP (1 << 6) 136 #define MARVELL_USB_PCR_REGARCDPDMMODE (1 << 8) 137 #define MARVELL_USB_PCR_REGDPPULLDOWN (1 << 9) 138 #define MARVELL_USB_PCR_REGDMPULLDOWN (1 << 10) 139 #define MARVELL_USB_PCR_UTMISESSION (1 << 23) 140 #define MARVELL_USB_PCR_UTMIVBUSVALID (1 << 24) 141 #define MARVELL_USB_PCR_UTMIAVALID (1 << 25) 142 #define MARVELL_USB_PCR_UTMIBVALID (1 << 26) 143 #define MARVELL_USB_PCR_TXBITSTUFF (1 << 27) 144 /* USB PHY Tx Control Register */ 145 #define MARVELL_USB_PTCR 0x420 146 /* USB PHY Rx Control Register */ 147 #define MARVELL_USB_PRCR 0x430 148 /* USB PHY IVREFF Control Register */ 149 #define MARVELL_USB_PIVREFFCR 0x440 150 /* USB PHY Test Group Control Register */ 151 #define MARVELL_USB_PTGCR 0x450 152 153 154 struct mvusb_softc { 155 ehci_softc_t sc; 156 157 int sc_model; 158 int sc_rev; 159 160 bus_space_tag_t sc_iot; 161 bus_space_handle_t sc_ioh; 162 }; 163 164 static int mvusb_match(device_t, cfdata_t, void *); 165 static void mvusb_attach(device_t, device_t, void *); 166 167 static void mvusb_init(struct mvusb_softc *, enum marvell_tags *); 168 static void mvusb_wininit(struct mvusb_softc *, enum marvell_tags *); 169 170 static void mvusb_vendor_init(struct ehci_softc *); 171 static int mvusb_vendor_port_status(struct ehci_softc *, uint32_t, int); 172 173 CFATTACH_DECL2_NEW(mvusb_gt, sizeof(struct mvusb_softc), 174 mvusb_match, mvusb_attach, NULL, ehci_activate, NULL, ehci_childdet); 175 CFATTACH_DECL2_NEW(mvusb_mbus, sizeof(struct mvusb_softc), 176 mvusb_match, mvusb_attach, NULL, ehci_activate, NULL, ehci_childdet); 177 178 179 /* ARGSUSED */ 180 static int 181 mvusb_match(device_t parent, cfdata_t match, void *aux) 182 { 183 struct marvell_attach_args *mva = aux; 184 185 if (strcmp(mva->mva_name, match->cf_name) != 0) 186 return 0; 187 if (mva->mva_offset == MVA_OFFSET_DEFAULT || 188 mva->mva_irq == MVA_IRQ_DEFAULT) 189 return 0; 190 191 mva->mva_size = MARVELL_USB_SIZE; 192 return 1; 193 } 194 195 /* ARGSUSED */ 196 static void 197 mvusb_attach(device_t parent, device_t self, void *aux) 198 { 199 struct mvusb_softc *sc = device_private(self); 200 struct marvell_attach_args *mva = aux; 201 202 aprint_normal(": Marvell USB 2.0 Interface\n"); 203 aprint_naive("\n"); 204 205 sc->sc.sc_dev = self; 206 sc->sc.sc_bus.ub_hcpriv = sc; 207 208 sc->sc_model = mva->mva_model; 209 sc->sc_rev = mva->mva_revision; 210 sc->sc_iot = mva->mva_iot; 211 212 /* Map I/O registers for marvell usb */ 213 if (bus_space_subregion(mva->mva_iot, mva->mva_ioh, mva->mva_offset, 214 mva->mva_size, &sc->sc_ioh)) { 215 aprint_error_dev(self, "can't map registers\n"); 216 return; 217 } 218 mvusb_init(sc, mva->mva_tags); 219 220 /* Map I/O registers for ehci */ 221 sc->sc.sc_size = MARVELL_USB_EHCI_SIZE; 222 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, MARVELL_USB_EHCI_BASE, 223 sc->sc.sc_size, &sc->sc.ioh)) { 224 aprint_error_dev(self, "can't subregion registers\n"); 225 return; 226 } 227 sc->sc.iot = sc->sc_iot; 228 sc->sc.sc_bus.ub_dmatag = mva->mva_dmat; 229 230 /* Disable interrupts, so we don't get any spurious ones. */ 231 sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH); 232 DPRINTF(("%s: offs=%d\n", device_xname(self), sc->sc.sc_offs)); 233 EOWRITE2(&sc->sc, EHCI_USBINTR, 0); 234 235 marvell_intr_establish(mva->mva_irq, IPL_USB, ehci_intr, sc); 236 237 sc->sc.sc_bus.ub_revision = USBREV_2_0; 238 239 sc->sc.sc_vendor_init = mvusb_vendor_init; 240 sc->sc.sc_vendor_port_status = mvusb_vendor_port_status; 241 242 int err = ehci_init(&sc->sc); 243 if (err) { 244 aprint_error_dev(self, "init failed, error=%d\n", err); 245 return; 246 } 247 248 /* Attach usb device. */ 249 sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint, 250 CFARGS_NONE); 251 } 252 253 static void 254 mvusb_init(struct mvusb_softc *sc, enum marvell_tags *tags) 255 { 256 uint32_t reg; 257 int opr_offs; 258 259 /* Clear Interrupt Cause and Mask registers */ 260 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_BICR, 0); 261 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_BIMR, 0); 262 263 opr_offs = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 264 MARVELL_USB_EHCI_BASE + EHCI_CAPLENGTH); 265 266 /* Reset controller */ 267 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 268 MARVELL_USB_EHCI_BASE + opr_offs + EHCI_USBCMD); 269 reg |= EHCI_CMD_HCRESET; 270 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 271 MARVELL_USB_EHCI_BASE + opr_offs + EHCI_USBCMD, reg); 272 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, 273 MARVELL_USB_EHCI_BASE + opr_offs + EHCI_USBCMD) & EHCI_CMD_HCRESET); 274 275 if (!((sc->sc_model == MARVELL_ORION_1_88F5181 && 276 (sc->sc_rev <= 3 || sc->sc_rev == 8)) || 277 (sc->sc_model == MARVELL_ORION_1_88F5182 && sc->sc_rev <= 1) || 278 (sc->sc_model == MARVELL_ORION_2_88F5281 && sc->sc_rev <= 1))) { 279 reg = 280 bus_space_read_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_IPGR); 281 /* 282 * Change bits[14:8] - IPG for non Start of Frame Packets 283 * from 0x9(default) to 0xc 284 */ 285 reg &= ~(0x7f << 8); 286 reg |= (0x0c << 8); 287 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_IPGR, 288 reg); 289 } 290 if (!(sc->sc_model == MARVELL_ARMADAXP_MV78460)) { 291 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PCR); 292 reg &= ~MARVELL_USB_PCR_BGVSEL_MASK; 293 reg |= MARVELL_USB_PCR_BGVSEL_CONNECT_ANAGRP; 294 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PCR, reg); 295 296 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 297 MARVELL_USB_PTCR); 298 if (sc->sc_model == MARVELL_ORION_1_88F5181 && sc->sc_rev <= 1) 299 /* For OrionI A1/A0 rev: bit[21]=0 (TXDATA_BLOCK_EN=0) */ 300 reg &= ~(1 << 21); 301 else 302 reg |= (1 << 21); 303 /* bit[13]=1, (REG_EXT_RCAL_EN=1) */ 304 reg |= (1 << 13); 305 /* bits[6:3]=8 (IMP_CAL=8) */ 306 reg &= ~(0xf << 3); 307 reg |= (8 << 3); 308 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PTCR, 309 reg); 310 311 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 312 MARVELL_USB_PRCR); 313 /* bits[8:9] - (DISCON_THRESHOLD ) */ 314 /* 315 * Orion1-A0/A1/B0=11, Orion2-A0=10, 316 * Orion1-B1 and Orion2-B0 later=00 317 */ 318 reg &= ~(3 << 8); 319 if (sc->sc_model == MARVELL_ORION_1_88F5181 && sc->sc_rev <= 2) 320 reg |= (3 << 8); 321 else if (sc->sc_model == MARVELL_ORION_2_88F5281 && 322 sc->sc_rev == 0) 323 reg |= (2 << 8); 324 /* bit[21]=0 (CDR_FASTLOCK_EN=0) */ 325 reg &= ~(1 << 21); 326 /* bits[27:26]=0 (EDGE_DET_SEL=0) */ 327 reg &= ~(3 << 26); 328 /* bits[31:30]=3 (RXDATA_BLOCK_LENGTH=3) */ 329 reg |= (3 << 30); 330 /* bits[7:4]=1 (SQ_THRESH=1) */ 331 reg &= ~(0xf << 4); 332 reg |= (1 << 4); 333 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PRCR, 334 reg); 335 336 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 337 MARVELL_USB_PIVREFFCR); 338 /* bits[1:0]=2 (PLLVDD12=2)*/ 339 reg &= ~(3 << 0); 340 reg |= (2 << 0); 341 /* bits[5:4]=3 (RXVDD=3) */ 342 reg &= ~(3 << 4); 343 reg |= (3 << 4); 344 /* bit[19] (Reserved) */ 345 reg &= ~(1 << 19); 346 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 347 MARVELL_USB_PIVREFFCR, reg); 348 349 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 350 MARVELL_USB_PTGCR); 351 /* bit[15]=0 (REG_FIFO_SQ_RST=0) */ 352 reg &= ~(1 << 15); 353 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PTGCR, 354 reg); 355 } 356 357 mvusb_wininit(sc, tags); 358 } 359 360 static void 361 mvusb_wininit(struct mvusb_softc *sc, enum marvell_tags *tags) 362 { 363 device_t pdev = device_parent(sc->sc.sc_dev); 364 uint64_t base; 365 uint32_t size; 366 int window, target, attr, rv, i; 367 368 for (window = 0, i = 0; 369 tags[i] != MARVELL_TAG_UNDEFINED && window < MARVELL_USB_NWINDOW; 370 i++) { 371 rv = marvell_winparams_by_tag(pdev, tags[i], 372 &target, &attr, &base, &size); 373 if (rv != 0 || size == 0) 374 continue; 375 if (base > 0xffffffffULL) { 376 aprint_error_dev(sc->sc.sc_dev, 377 "tag %d address 0x%llx not support\n", 378 tags[i], base); 379 continue; 380 } 381 382 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 383 MARVELL_USB_WCR(window), 384 MARVELL_USB_WCR_WINEN | 385 MARVELL_USB_WCR_TARGET(target) | 386 MARVELL_USB_WCR_ATTR(attr) | 387 MARVELL_USB_WCR_SIZE(size)); 388 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 389 MARVELL_USB_WBR(window), MARVELL_USB_WBR_BASE(base)); 390 window++; 391 } 392 for (; window < MARVELL_USB_NWINDOW; window++) 393 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 394 MARVELL_USB_WCR(window), 0); 395 } 396 397 static void 398 mvusb_vendor_init(struct ehci_softc *sc) 399 { 400 uint32_t mode; 401 402 /* put TDI/ARC silicon into EHCI mode */ 403 mode = EOREAD4(sc, MARVELL_USB_EHCI_USBMODE); 404 mode &= ~MARVELL_USB_EHCI_MODE_HDMASK; /* Host/Device Mask */ 405 mode |= MARVELL_USB_EHCI_MODE_HOST; 406 mode |= MARVELL_USB_EHCI_MODE_STRMDIS; 407 EOWRITE4(sc, MARVELL_USB_EHCI_USBMODE, mode); 408 } 409 410 static int 411 mvusb_vendor_port_status(struct ehci_softc *sc, uint32_t v, int i) 412 { 413 414 i &= ~UPS_HIGH_SPEED; 415 if (v & EHCI_PS_CS) { 416 switch (v & MARVELL_USB_EHCI_PS_PSPD) { 417 case MARVELL_USB_EHCI_PS_PSPD_FS: 418 break; 419 case MARVELL_USB_EHCI_PS_PSPD_LS: 420 i |= UPS_LOW_SPEED; 421 break; 422 case MARVELL_USB_EHCI_PS_PSPD_HS: 423 default: 424 i |= UPS_HIGH_SPEED; 425 } 426 } 427 428 return i; 429 } 430