1 /* $NetBSD: ehci_mv.c,v 1.5 2014/03/15 13:33:48 kiyohara 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.5 2014/03/15 13:33:48 kiyohara 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 usbd_status r; 202 203 aprint_normal(": Marvell USB 2.0 Interface\n"); 204 aprint_naive("\n"); 205 206 sc->sc.sc_dev = self; 207 sc->sc.sc_bus.hci_private = sc; 208 209 sc->sc_model = mva->mva_model; 210 sc->sc_rev = mva->mva_revision; 211 sc->sc_iot = mva->mva_iot; 212 213 /* Map I/O registers for marvell usb */ 214 if (bus_space_subregion(mva->mva_iot, mva->mva_ioh, mva->mva_offset, 215 mva->mva_size, &sc->sc_ioh)) { 216 aprint_error_dev(self, "can't map registers\n"); 217 return; 218 } 219 mvusb_init(sc, mva->mva_tags); 220 221 /* Map I/O registers for ehci */ 222 sc->sc.sc_size = MARVELL_USB_EHCI_SIZE; 223 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, MARVELL_USB_EHCI_BASE, 224 sc->sc.sc_size, &sc->sc.ioh)) { 225 aprint_error_dev(self, "can't subregion registers\n"); 226 return; 227 } 228 sc->sc.iot = sc->sc_iot; 229 sc->sc.sc_bus.dmatag = mva->mva_dmat; 230 231 /* Disable interrupts, so we don't get any spurious ones. */ 232 sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH); 233 DPRINTF(("%s: offs=%d\n", device_xname(self), sc->sc.sc_offs)); 234 EOWRITE2(&sc->sc, EHCI_USBINTR, 0); 235 236 marvell_intr_establish(mva->mva_irq, IPL_USB, ehci_intr, sc); 237 238 sc->sc.sc_bus.usbrev = USBREV_2_0; 239 /* Figure out vendor for root hub descriptor. */ 240 sc->sc.sc_id_vendor = 0x0000; /* XXXXX */ 241 strcpy(sc->sc.sc_vendor, "Marvell"); 242 243 sc->sc.sc_vendor_init = mvusb_vendor_init; 244 sc->sc.sc_vendor_port_status = mvusb_vendor_port_status; 245 246 r = ehci_init(&sc->sc); 247 if (r != USBD_NORMAL_COMPLETION) { 248 aprint_error_dev(self, "init failed, error=%d\n", r); 249 return; 250 } 251 252 /* Attach usb device. */ 253 sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint); 254 } 255 256 static void 257 mvusb_init(struct mvusb_softc *sc, enum marvell_tags *tags) 258 { 259 uint32_t reg; 260 int opr_offs; 261 262 /* Clear Interrupt Cause and Mask registers */ 263 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_BICR, 0); 264 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_BIMR, 0); 265 266 opr_offs = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 267 MARVELL_USB_EHCI_BASE + EHCI_CAPLENGTH); 268 269 /* Reset controller */ 270 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 271 MARVELL_USB_EHCI_BASE + opr_offs + EHCI_USBCMD); 272 reg |= EHCI_CMD_HCRESET; 273 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 274 MARVELL_USB_EHCI_BASE + opr_offs + EHCI_USBCMD, reg); 275 while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, 276 MARVELL_USB_EHCI_BASE + opr_offs + EHCI_USBCMD) & EHCI_CMD_HCRESET); 277 278 if (!((sc->sc_model == MARVELL_ORION_1_88F5181 && 279 (sc->sc_rev <= 3 || sc->sc_rev == 8)) || 280 (sc->sc_model == MARVELL_ORION_1_88F5182 && sc->sc_rev <= 1) || 281 (sc->sc_model == MARVELL_ORION_2_88F5281 && sc->sc_rev <= 1))) { 282 reg = 283 bus_space_read_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_IPGR); 284 /* 285 * Change bits[14:8] - IPG for non Start of Frame Packets 286 * from 0x9(default) to 0xc 287 */ 288 reg &= ~(0x7f << 8); 289 reg |= (0x0c << 8); 290 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_IPGR, 291 reg); 292 } 293 if (!(sc->sc_model == MARVELL_ARMADAXP_MV78460)) { 294 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PCR); 295 reg &= ~MARVELL_USB_PCR_BGVSEL_MASK; 296 reg |= MARVELL_USB_PCR_BGVSEL_CONNECT_ANAGRP; 297 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PCR, reg); 298 299 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 300 MARVELL_USB_PTCR); 301 if (sc->sc_model == MARVELL_ORION_1_88F5181 && sc->sc_rev <= 1) 302 /* For OrionI A1/A0 rev: bit[21]=0 (TXDATA_BLOCK_EN=0) */ 303 reg &= ~(1 << 21); 304 else 305 reg |= (1 << 21); 306 /* bit[13]=1, (REG_EXT_RCAL_EN=1) */ 307 reg |= (1 << 13); 308 /* bits[6:3]=8 (IMP_CAL=8) */ 309 reg &= ~(0xf << 3); 310 reg |= (8 << 3); 311 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PTCR, 312 reg); 313 314 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 315 MARVELL_USB_PRCR); 316 /* bits[8:9] - (DISCON_THRESHOLD ) */ 317 /* 318 * Orion1-A0/A1/B0=11, Orion2-A0=10, 319 * Orion1-B1 and Orion2-B0 later=00 320 */ 321 reg &= ~(3 << 8); 322 if (sc->sc_model == MARVELL_ORION_1_88F5181 && sc->sc_rev <= 2) 323 reg |= (3 << 8); 324 else if (sc->sc_model == MARVELL_ORION_2_88F5281 && 325 sc->sc_rev == 0) 326 reg |= (2 << 8); 327 /* bit[21]=0 (CDR_FASTLOCK_EN=0) */ 328 reg &= ~(1 << 21); 329 /* bits[27:26]=0 (EDGE_DET_SEL=0) */ 330 reg &= ~(3 << 26); 331 /* bits[31:30]=3 (RXDATA_BLOCK_LENGHT=3) */ 332 reg |= (3 << 30); 333 /* bits[7:4]=1 (SQ_THRESH=1) */ 334 reg &= ~(0xf << 4); 335 reg |= (1 << 4); 336 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PRCR, 337 reg); 338 339 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 340 MARVELL_USB_PIVREFFCR); 341 /* bits[1:0]=2 (PLLVDD12=2)*/ 342 reg &= ~(3 << 0); 343 reg |= (2 << 0); 344 /* bits[5:4]=3 (RXVDD=3) */ 345 reg &= ~(3 << 4); 346 reg |= (3 << 4); 347 /* bit[19] (Reserved) */ 348 reg &= ~(1 << 19); 349 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 350 MARVELL_USB_PIVREFFCR, reg); 351 352 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 353 MARVELL_USB_PTGCR); 354 /* bit[15]=0 (REG_FIFO_SQ_RST=0) */ 355 reg &= ~(1 << 15); 356 bus_space_write_4(sc->sc_iot, sc->sc_ioh, MARVELL_USB_PTGCR, 357 reg); 358 } 359 360 mvusb_wininit(sc, tags); 361 } 362 363 static void 364 mvusb_wininit(struct mvusb_softc *sc, enum marvell_tags *tags) 365 { 366 device_t pdev = device_parent(sc->sc.sc_dev); 367 uint64_t base; 368 uint32_t size; 369 int window, target, attr, rv, i; 370 371 for (window = 0, i = 0; 372 tags[i] != MARVELL_TAG_UNDEFINED && window < MARVELL_USB_NWINDOW; 373 i++) { 374 rv = marvell_winparams_by_tag(pdev, tags[i], 375 &target, &attr, &base, &size); 376 if (rv != 0 || size == 0) 377 continue; 378 if (base > 0xffffffffULL) { 379 aprint_error_dev(sc->sc.sc_dev, 380 "tag %d address 0x%llx not support\n", 381 tags[i], base); 382 continue; 383 } 384 385 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 386 MARVELL_USB_WCR(window), 387 MARVELL_USB_WCR_WINEN | 388 MARVELL_USB_WCR_TARGET(target) | 389 MARVELL_USB_WCR_ATTR(attr) | 390 MARVELL_USB_WCR_SIZE(size)); 391 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 392 MARVELL_USB_WBR(window), MARVELL_USB_WBR_BASE(base)); 393 window++; 394 } 395 for (; window < MARVELL_USB_NWINDOW; window++) 396 bus_space_write_4(sc->sc_iot, sc->sc_ioh, 397 MARVELL_USB_WCR(window), 0); 398 } 399 400 static void 401 mvusb_vendor_init(struct ehci_softc *sc) 402 { 403 uint32_t mode; 404 405 /* put TDI/ARC silicon into EHCI mode */ 406 mode = EOREAD4(sc, MARVELL_USB_EHCI_USBMODE); 407 mode &= ~MARVELL_USB_EHCI_MODE_HDMASK; /* Host/Device Mask */ 408 mode |= MARVELL_USB_EHCI_MODE_HOST; 409 mode |= MARVELL_USB_EHCI_MODE_STRMDIS; 410 EOWRITE4(sc, MARVELL_USB_EHCI_USBMODE, mode); 411 } 412 413 static int 414 mvusb_vendor_port_status(struct ehci_softc *sc, uint32_t v, int i) 415 { 416 417 i &= ~UPS_HIGH_SPEED; 418 if (v & EHCI_PS_CS) { 419 switch (v & MARVELL_USB_EHCI_PS_PSPD) { 420 case MARVELL_USB_EHCI_PS_PSPD_FS: 421 break; 422 case MARVELL_USB_EHCI_PS_PSPD_LS: 423 i |= UPS_LOW_SPEED; 424 break; 425 case MARVELL_USB_EHCI_PS_PSPD_HS: 426 default: 427 i |= UPS_HIGH_SPEED; 428 } 429 } 430 431 return i; 432 } 433