1 /* $NetBSD: ehci_mv.c,v 1.7 2018/04/09 16:21:10 jakllsch 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.7 2018/04/09 16:21:10 jakllsch 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 } 251 252 static void 253 mvusb_init(struct mvusb_softc *sc, enum marvell_tags *tags) 254 { 255 uint32_t reg; 256 int opr_offs; 257 258 /* Clear Interrupt Cause and Mask registers */ 259 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_BICR, 0); 260 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_BIMR, 0); 261 262 opr_offs = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 263 MARVELL_USB_EHCI_BASE + EHCI_CAPLENGTH); 264 265 /* Reset controller */ 266 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 267 MARVELL_USB_EHCI_BASE + opr_offs + EHCI_USBCMD); 268 reg |= EHCI_CMD_HCRESET; 269 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 270 MARVELL_USB_EHCI_BASE + opr_offs + EHCI_USBCMD, reg); 271 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, 272 MARVELL_USB_EHCI_BASE + opr_offs + EHCI_USBCMD) & EHCI_CMD_HCRESET); 273 274 if (!((sc->sc_model == MARVELL_ORION_1_88F5181 && 275 (sc->sc_rev <= 3 || sc->sc_rev == 8)) || 276 (sc->sc_model == MARVELL_ORION_1_88F5182 && sc->sc_rev <= 1) || 277 (sc->sc_model == MARVELL_ORION_2_88F5281 && sc->sc_rev <= 1))) { 278 reg = 279 bus_space_read_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_IPGR); 280 /* 281 * Change bits[14:8] - IPG for non Start of Frame Packets 282 * from 0x9(default) to 0xc 283 */ 284 reg &= ~(0x7f << 8); 285 reg |= (0x0c << 8); 286 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_IPGR, 287 reg); 288 } 289 if (!(sc->sc_model == MARVELL_ARMADAXP_MV78460)) { 290 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PCR); 291 reg &= ~MARVELL_USB_PCR_BGVSEL_MASK; 292 reg |= MARVELL_USB_PCR_BGVSEL_CONNECT_ANAGRP; 293 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PCR, reg); 294 295 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 296 MARVELL_USB_PTCR); 297 if (sc->sc_model == MARVELL_ORION_1_88F5181 && sc->sc_rev <= 1) 298 /* For OrionI A1/A0 rev: bit[21]=0 (TXDATA_BLOCK_EN=0) */ 299 reg &= ~(1 << 21); 300 else 301 reg |= (1 << 21); 302 /* bit[13]=1, (REG_EXT_RCAL_EN=1) */ 303 reg |= (1 << 13); 304 /* bits[6:3]=8 (IMP_CAL=8) */ 305 reg &= ~(0xf << 3); 306 reg |= (8 << 3); 307 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PTCR, 308 reg); 309 310 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 311 MARVELL_USB_PRCR); 312 /* bits[8:9] - (DISCON_THRESHOLD ) */ 313 /* 314 * Orion1-A0/A1/B0=11, Orion2-A0=10, 315 * Orion1-B1 and Orion2-B0 later=00 316 */ 317 reg &= ~(3 << 8); 318 if (sc->sc_model == MARVELL_ORION_1_88F5181 && sc->sc_rev <= 2) 319 reg |= (3 << 8); 320 else if (sc->sc_model == MARVELL_ORION_2_88F5281 && 321 sc->sc_rev == 0) 322 reg |= (2 << 8); 323 /* bit[21]=0 (CDR_FASTLOCK_EN=0) */ 324 reg &= ~(1 << 21); 325 /* bits[27:26]=0 (EDGE_DET_SEL=0) */ 326 reg &= ~(3 << 26); 327 /* bits[31:30]=3 (RXDATA_BLOCK_LENGHT=3) */ 328 reg |= (3 << 30); 329 /* bits[7:4]=1 (SQ_THRESH=1) */ 330 reg &= ~(0xf << 4); 331 reg |= (1 << 4); 332 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PRCR, 333 reg); 334 335 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 336 MARVELL_USB_PIVREFFCR); 337 /* bits[1:0]=2 (PLLVDD12=2)*/ 338 reg &= ~(3 << 0); 339 reg |= (2 << 0); 340 /* bits[5:4]=3 (RXVDD=3) */ 341 reg &= ~(3 << 4); 342 reg |= (3 << 4); 343 /* bit[19] (Reserved) */ 344 reg &= ~(1 << 19); 345 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 346 MARVELL_USB_PIVREFFCR, reg); 347 348 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 349 MARVELL_USB_PTGCR); 350 /* bit[15]=0 (REG_FIFO_SQ_RST=0) */ 351 reg &= ~(1 << 15); 352 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PTGCR, 353 reg); 354 } 355 356 mvusb_wininit(sc, tags); 357 } 358 359 static void 360 mvusb_wininit(struct mvusb_softc *sc, enum marvell_tags *tags) 361 { 362 device_t pdev = device_parent(sc->sc.sc_dev); 363 uint64_t base; 364 uint32_t size; 365 int window, target, attr, rv, i; 366 367 for (window = 0, i = 0; 368 tags[i] != MARVELL_TAG_UNDEFINED && window < MARVELL_USB_NWINDOW; 369 i++) { 370 rv = marvell_winparams_by_tag(pdev, tags[i], 371 &target, &attr, &base, &size); 372 if (rv != 0 || size == 0) 373 continue; 374 if (base > 0xffffffffULL) { 375 aprint_error_dev(sc->sc.sc_dev, 376 "tag %d address 0x%llx not support\n", 377 tags[i], base); 378 continue; 379 } 380 381 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 382 MARVELL_USB_WCR(window), 383 MARVELL_USB_WCR_WINEN | 384 MARVELL_USB_WCR_TARGET(target) | 385 MARVELL_USB_WCR_ATTR(attr) | 386 MARVELL_USB_WCR_SIZE(size)); 387 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 388 MARVELL_USB_WBR(window), MARVELL_USB_WBR_BASE(base)); 389 window++; 390 } 391 for (; window < MARVELL_USB_NWINDOW; window++) 392 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 393 MARVELL_USB_WCR(window), 0); 394 } 395 396 static void 397 mvusb_vendor_init(struct ehci_softc *sc) 398 { 399 uint32_t mode; 400 401 /* put TDI/ARC silicon into EHCI mode */ 402 mode = EOREAD4(sc, MARVELL_USB_EHCI_USBMODE); 403 mode &= ~MARVELL_USB_EHCI_MODE_HDMASK; /* Host/Device Mask */ 404 mode |= MARVELL_USB_EHCI_MODE_HOST; 405 mode |= MARVELL_USB_EHCI_MODE_STRMDIS; 406 EOWRITE4(sc, MARVELL_USB_EHCI_USBMODE, mode); 407 } 408 409 static int 410 mvusb_vendor_port_status(struct ehci_softc *sc, uint32_t v, int i) 411 { 412 413 i &= ~UPS_HIGH_SPEED; 414 if (v & EHCI_PS_CS) { 415 switch (v & MARVELL_USB_EHCI_PS_PSPD) { 416 case MARVELL_USB_EHCI_PS_PSPD_FS: 417 break; 418 case MARVELL_USB_EHCI_PS_PSPD_LS: 419 i |= UPS_LOW_SPEED; 420 break; 421 case MARVELL_USB_EHCI_PS_PSPD_HS: 422 default: 423 i |= UPS_HIGH_SPEED; 424 } 425 } 426 427 return i; 428 } 429