static int ehci_ps3_attach(device_t dev) { ehci_softc_t *sc = device_get_softc(dev); int rid, err; sc->sc_bus.parent = dev; sc->sc_bus.devices = sc->sc_devices; sc->sc_bus.devices_max = EHCI_MAX_DEVICES; if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(dev), &ehci_iterate_hw_softc)) return (ENOMEM); rid = 1; sc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->sc_io_res) { device_printf(dev, "Could not map memory\n"); goto error; } sc->sc_io_tag = rman_get_bustag(sc->sc_io_res); sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res); sc->sc_io_size = rman_get_size(sc->sc_io_res); rid = 1; sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); if (sc->sc_irq_res == NULL) { device_printf(dev, "Could not allocate irq\n"); return (ENXIO); } sc->sc_bus.bdev = device_add_child(dev, "usbus", -1); if (!sc->sc_bus.bdev) { device_printf(dev, "Could not add USB device\n"); return (ENXIO); } device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); sprintf(sc->sc_vendor, "Sony"); err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); if (err) { device_printf(dev, "Could not setup error irq, %d\n", err); goto error; } sc->sc_flags |= EHCI_SCFLG_BIGEMMIO; err = ehci_init(sc); if (err) { device_printf(dev, "USB init failed err=%d\n", err); goto error; } err = device_probe_and_attach(sc->sc_bus.bdev); if (err == 0) return (0); error: return (ENXIO); }
void ehci_arbus_attach(device_t parent, device_t self, void *aux) { ehci_softc_t *sc = device_private(self); struct arbus_attach_args * const aa = aux; void *ih = NULL; int error; sc->iot = aa->aa_bst_le; sc->sc_size = aa->aa_size; //sc->sc_bus.ub_hcpriv = sc; sc->sc_bus.ub_dmatag = aa->aa_dmat; sc->sc_bus.ub_revision = USBREV_1_0; sc->sc_flags |= EHCIF_ETTF; sc->sc_vendor_init = ehci_arbus_init; error = bus_space_map(aa->aa_bst, aa->aa_addr, aa->aa_size, 0, &sc->ioh); if (error) { aprint_error(": failed to map registers: %d\n", error); return; } /* The recommended value is 0x20 for both ports and the host */ REGVAL(AR9344_USB_CONFIG_BASE) = 0x20c00; /* magic */ DELAY(1000); /* get offset to operational regs */ uint32_t r = bus_space_read_4(aa->aa_bst, sc->ioh, 0); if (r != 0x40) { aprint_error(": error: CAPLENGTH (%#x) != 0x40\n", sc->sc_offs); return; } sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH); aprint_normal("\n"); /* Disable EHCI interrupts */ EOWRITE4(sc, EHCI_USBINTR, 0); /* establish interrupt */ ih = arbus_intr_establish(aa->aa_cirq, aa->aa_mirq, ehci_intr, sc); if (ih == NULL) panic("%s: couldn't establish interrupt", device_xname(self)); /* * There are no companion controllers */ sc->sc_ncomp = 0; error = ehci_init(sc); if (error) { aprint_error("%s: init failed, error=%d\n", device_xname(self), error); if (ih != NULL) arbus_intr_disestablish(ih); return; } /* Attach USB device */ sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint); }
/* called during probe() after chip reset completes */ static int ehci_fsl_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval; struct fsl_usb2_platform_data *pdata; pdata = hcd->self.controller->platform_data; ehci->big_endian_desc = pdata->big_endian_desc; ehci->big_endian_mmio = pdata->big_endian_mmio; /* EHCI registers start at offset 0x100 */ ehci->caps = hcd->regs + 0x100; ehci->regs = hcd->regs + 0x100 + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); dbg_hcs_params(ehci, "reset"); dbg_hcc_params(ehci, "reset"); /* cache this readonly data; minimize chip reads */ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); retval = ehci_halt(ehci); /* data structure init */ retval = ehci_init(hcd); if (retval) return retval; hcd->has_tt = 1; ehci->sbrn = 0x20; ehci_reset(ehci); retval = ehci_fsl_reinit(ehci); #ifdef CHUMBY_USB_MODIFICATIONS /* Also, disable the IRQ for the 5V line. Turning on the screen causes * a massive drop in power, and the battery circuitry thinks we've * pulled the 5V line. */ HW_POWER_CTRL_CLR(1); /* Wait just enough time for the brownout. Any less than this and it * reboots when we bring the USB card up, or segfaults. */ msleep(5); /* Set bank 0, pins 26 and 28 to GPIO. */ HW_PINCTRL_MUXSEL1_SET(0x03300000); /* Set both pins to low, which ensures a reset takes place. */ HW_PINCTRL_DOUT0_CLR(0x24000000); HW_PINCTRL_DOE0_SET(0x24000000); HW_PINCTRL_DOUT0_CLR(0x24000000); msleep(5); /* Delay for one second, giving most USB devices the chance to * recognize they've been "unplugged". */ msleep(1000); /* Write a "1" to bank 0, pin 28. */ HW_PINCTRL_DOUT0_SET(0x20000000); msleep(5); /* Write a "1" to bank 0, pin 26, to disable USB. This ensures a reset. * Wait a short time after, then re-enable the IRQ that fires when power * is pulled. This is because by now, the voltages should have * stabilized. */ HW_PINCTRL_DOUT0_SET(0x04000000); msleep(5); /* Re-enable the power interrupt. */ HW_POWER_CTRL_SET(1); #endif /*CHUMBY_USB_MODIFICATIONS*/ return retval; }
static int ehci_ixp_attach(device_t self) { struct ixp_ehci_softc *isc = device_get_softc(self); ehci_softc_t *sc = &isc->base; int err; int rid; /* initialise some bus fields */ sc->sc_bus.parent = self; sc->sc_bus.devices = sc->sc_devices; sc->sc_bus.devices_max = EHCI_MAX_DEVICES; sc->sc_bus.dma_bits = 32; /* get all DMA memory */ if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) { return (ENOMEM); } /* NB: hints fix the memory location and irq */ rid = 0; sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->sc_io_res) { device_printf(self, "Could not map memory\n"); goto error; } /* * Craft special resource for bus space ops that handle * byte-alignment of non-word addresses. Also, since * we're already intercepting bus space ops we handle * the register window offset that could otherwise be * done with bus_space_subregion. */ isc->iot = rman_get_bustag(sc->sc_io_res); isc->tag.bs_privdata = isc->iot; /* read single */ isc->tag.bs_r_1 = ehci_bs_r_1, isc->tag.bs_r_2 = ehci_bs_r_2, isc->tag.bs_r_4 = ehci_bs_r_4, /* write (single) */ isc->tag.bs_w_1 = ehci_bs_w_1, isc->tag.bs_w_2 = ehci_bs_w_2, isc->tag.bs_w_4 = ehci_bs_w_4, sc->sc_io_tag = &isc->tag; sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res); sc->sc_io_size = IXP435_USB1_SIZE - 0x100; rid = 0; sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, RF_ACTIVE); if (sc->sc_irq_res == NULL) { device_printf(self, "Could not allocate irq\n"); goto error; } sc->sc_bus.bdev = device_add_child(self, "usbus", -1); if (!sc->sc_bus.bdev) { device_printf(self, "Could not add USB device\n"); goto error; } device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR); sprintf(sc->sc_vendor, "Intel"); err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); if (err) { device_printf(self, "Could not setup irq, %d\n", err); sc->sc_intr_hdl = NULL; goto error; } /* * Select big-endian byte alignment and arrange to not terminate * reset operations (the adapter will ignore it if we do but might * as well save a reg write). Also, the controller has an embedded * Transaction Translator which means port speed must be read from * the Port Status register following a port enable. */ sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_BIGEDESC | EHCI_SCFLG_NORESTERM ; /* Setup callbacks. */ sc->sc_vendor_post_reset = ehci_ixp_post_reset; sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc; err = ehci_init(sc); if (!err) { err = device_probe_and_attach(sc->sc_bus.bdev); } if (err) { device_printf(self, "USB init failed err=%d\n", err); goto error; } return (0); error: ehci_ixp_detach(self); return (ENXIO); }
static int ehci_pci_attach(device_t self) { ehci_softc_t *sc = device_get_softc(self); int err; int rid; /* initialise some bus fields */ sc->sc_bus.parent = self; sc->sc_bus.devices = sc->sc_devices; sc->sc_bus.devices_max = EHCI_MAX_DEVICES; /* get all DMA memory */ if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) { return (ENOMEM); } pci_enable_busmaster(self); switch (pci_read_config(self, PCI_USBREV, 1) & PCI_USB_REV_MASK) { case PCI_USB_REV_PRE_1_0: case PCI_USB_REV_1_0: case PCI_USB_REV_1_1: /* * NOTE: some EHCI USB controllers have the wrong USB * revision number. It appears those controllers are * fully compliant so we just ignore this value in * some common cases. */ device_printf(self, "pre-2.0 USB revision (ignored)\n"); /* fallthrough */ case PCI_USB_REV_2_0: break; default: /* Quirk for Parallels Desktop 4.0 */ device_printf(self, "USB revision is unknown. Assuming v2.0.\n"); break; } rid = PCI_CBMEM; sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->sc_io_res) { device_printf(self, "Could not map memory\n"); goto error; } sc->sc_io_tag = rman_get_bustag(sc->sc_io_res); sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res); sc->sc_io_size = rman_get_size(sc->sc_io_res); rid = 0; sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); if (sc->sc_irq_res == NULL) { device_printf(self, "Could not allocate irq\n"); goto error; } sc->sc_bus.bdev = device_add_child(self, "usbus", -1); if (!sc->sc_bus.bdev) { device_printf(self, "Could not add USB device\n"); goto error; } device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); /* * ehci_pci_match will never return NULL if ehci_pci_probe * succeeded */ device_set_desc(sc->sc_bus.bdev, ehci_pci_match(self)); switch (pci_get_vendor(self)) { case PCI_EHCI_VENDORID_ACERLABS: sprintf(sc->sc_vendor, "AcerLabs"); break; case PCI_EHCI_VENDORID_AMD: sprintf(sc->sc_vendor, "AMD"); break; case PCI_EHCI_VENDORID_APPLE: sprintf(sc->sc_vendor, "Apple"); break; case PCI_EHCI_VENDORID_ATI: sprintf(sc->sc_vendor, "ATI"); break; case PCI_EHCI_VENDORID_CMDTECH: sprintf(sc->sc_vendor, "CMDTECH"); break; case PCI_EHCI_VENDORID_INTEL: sprintf(sc->sc_vendor, "Intel"); break; case PCI_EHCI_VENDORID_NEC: sprintf(sc->sc_vendor, "NEC"); break; case PCI_EHCI_VENDORID_OPTI: sprintf(sc->sc_vendor, "OPTi"); break; case PCI_EHCI_VENDORID_PHILIPS: sprintf(sc->sc_vendor, "Philips"); break; case PCI_EHCI_VENDORID_SIS: sprintf(sc->sc_vendor, "SiS"); break; case PCI_EHCI_VENDORID_NVIDIA: case PCI_EHCI_VENDORID_NVIDIA2: sprintf(sc->sc_vendor, "nVidia"); break; case PCI_EHCI_VENDORID_VIA: sprintf(sc->sc_vendor, "VIA"); break; default: if (bootverbose) device_printf(self, "(New EHCI DeviceId=0x%08x)\n", pci_get_devid(self)); sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self)); } #if (__FreeBSD_version >= 700031) err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); #else err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); #endif if (err) { device_printf(self, "Could not setup irq, %d\n", err); sc->sc_intr_hdl = NULL; goto error; } ehci_pci_take_controller(self); /* Undocumented quirks taken from Linux */ switch (pci_get_vendor(self)) { case PCI_EHCI_VENDORID_ATI: /* SB600 and SB700 EHCI quirk */ switch (pci_get_device(self)) { case 0x4386: ehci_pci_ati_quirk(self, 0); break; case 0x4396: ehci_pci_ati_quirk(self, 1); break; default: break; } break; case PCI_EHCI_VENDORID_VIA: ehci_pci_via_quirk(self); break; default: break; } /* Dropped interrupts workaround */ switch (pci_get_vendor(self)) { case PCI_EHCI_VENDORID_ATI: case PCI_EHCI_VENDORID_VIA: sc->sc_flags |= EHCI_SCFLG_LOSTINTRBUG; if (bootverbose) device_printf(self, "Dropped interrupts workaround enabled\n"); break; default: break; } /* Doorbell feature workaround */ switch (pci_get_vendor(self)) { case PCI_EHCI_VENDORID_NVIDIA: case PCI_EHCI_VENDORID_NVIDIA2: sc->sc_flags |= EHCI_SCFLG_IAADBUG; if (bootverbose) device_printf(self, "Doorbell workaround enabled\n"); break; default: break; } err = ehci_init(sc); if (!err) { err = device_probe_and_attach(sc->sc_bus.bdev); } if (err) { device_printf(self, "USB init failed err=%d\n", err); goto error; } return (0); error: ehci_pci_detach(self); return (ENXIO); }
/* called during probe() after chip reset completes */ static int ehci_pci_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); struct pci_dev *p_smbus; u8 rev; u32 temp; int retval; switch (pdev->vendor) { case PCI_VENDOR_ID_TOSHIBA_2: /* celleb's companion chip */ if (pdev->device == 0x01b5) { #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO ehci->big_endian_mmio = 1; #else ehci_warn(ehci, "unsupported big endian Toshiba quirk\n"); #endif } break; } ehci->caps = hcd->regs; ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); dbg_hcs_params(ehci, "reset"); dbg_hcc_params(ehci, "reset"); /* ehci_init() causes memory for DMA transfers to be * allocated. Thus, any vendor-specific workarounds based on * limiting the type of memory used for DMA transfers must * happen before ehci_init() is called. */ switch (pdev->vendor) { case PCI_VENDOR_ID_NVIDIA: /* NVidia reports that certain chips don't handle * QH, ITD, or SITD addresses above 2GB. (But TD, * data buffer, and periodic schedule are normal.) */ switch (pdev->device) { case 0x003c: /* MCP04 */ case 0x005b: /* CK804 */ case 0x00d8: /* CK8 */ case 0x00e8: /* CK8S */ if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(31)) < 0) ehci_warn(ehci, "can't enable NVidia " "workaround for >2GB RAM\n"); break; } break; } /* cache this readonly data; minimize chip reads */ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); retval = ehci_halt(ehci); if (retval) return retval; /* data structure init */ retval = ehci_init(hcd); if (retval) return retval; switch (pdev->vendor) { case PCI_VENDOR_ID_NEC: ehci->need_io_watchdog = 0; break; case PCI_VENDOR_ID_INTEL: ehci->need_io_watchdog = 0; if (pdev->device == 0x27cc) { ehci->broken_periodic = 1; ehci_info(ehci, "using broken periodic workaround\n"); } break; case PCI_VENDOR_ID_TDI: if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { hcd->has_tt = 1; tdi_reset(ehci); } break; case PCI_VENDOR_ID_AMD: /* AMD8111 EHCI doesn't work, according to AMD errata */ if (pdev->device == 0x7463) { ehci_info(ehci, "ignoring AMD8111 (errata)\n"); retval = -EIO; goto done; } break; case PCI_VENDOR_ID_NVIDIA: switch (pdev->device) { /* Some NForce2 chips have problems with selective suspend; * fixed in newer silicon. */ case 0x0068: if (pdev->revision < 0xa4) ehci->no_selective_suspend = 1; break; } break; case PCI_VENDOR_ID_VIA: if (pdev->device == 0x3104 && (pdev->revision & 0xf0) == 0x60) { u8 tmp; /* The VT6212 defaults to a 1 usec EHCI sleep time which * hogs the PCI bus *badly*. Setting bit 5 of 0x4B makes * that sleep time use the conventional 10 usec. */ pci_read_config_byte(pdev, 0x4b, &tmp); if (tmp & 0x20) break; pci_write_config_byte(pdev, 0x4b, tmp | 0x20); } break; case PCI_VENDOR_ID_ATI: /* SB600 and old version of SB700 have a bug in EHCI controller, * which causes usb devices lose response in some cases. */ if ((pdev->device == 0x4386) || (pdev->device == 0x4396)) { p_smbus = pci_get_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL); if (!p_smbus) break; rev = p_smbus->revision; if ((pdev->device == 0x4386) || (rev == 0x3a) || (rev == 0x3b)) { u8 tmp; ehci_info(ehci, "applying AMD SB600/SB700 USB " "freeze workaround\n"); pci_read_config_byte(pdev, 0x53, &tmp); pci_write_config_byte(pdev, 0x53, tmp | (1<<3)); } pci_dev_put(p_smbus); } break; } /* optional debug port, normally in the first BAR */ temp = pci_find_capability(pdev, 0x0a); if (temp) { pci_read_config_dword(pdev, temp, &temp); temp >>= 16; if ((temp & (3 << 13)) == (1 << 13)) { temp &= 0x1fff; ehci->debug = ehci_to_hcd(ehci)->regs + temp; temp = ehci_readl(ehci, &ehci->debug->control); ehci_info(ehci, "debug port %d%s\n", HCS_DEBUG_PORT(ehci->hcs_params), (temp & DBGP_ENABLED) ? " IN USE" : ""); if (!(temp & DBGP_ENABLED)) ehci->debug = NULL; } } ehci_reset(ehci); /* at least the Genesys GL880S needs fixup here */ temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); temp &= 0x0f; if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) { ehci_dbg(ehci, "bogus port configuration: " "cc=%d x pcc=%d < ports=%d\n", HCS_N_CC(ehci->hcs_params), HCS_N_PCC(ehci->hcs_params), HCS_N_PORTS(ehci->hcs_params)); switch (pdev->vendor) { case 0x17a0: /* GENESYS */ /* GL880S: should be PORTS=2 */ temp |= (ehci->hcs_params & ~0xf); ehci->hcs_params = temp; break; case PCI_VENDOR_ID_NVIDIA: /* NF4: should be PCC=10 */ break; } } /* Serial Bus Release Number is at PCI 0x60 offset */ pci_read_config_byte(pdev, 0x60, &ehci->sbrn); /* Keep this around for a while just in case some EHCI * implementation uses legacy PCI PM support. This test * can be removed on 17 Dec 2009 if the dev_warn() hasn't * been triggered by then. */ if (!device_can_wakeup(&pdev->dev)) { u16 port_wake; pci_read_config_word(pdev, 0x62, &port_wake); if (port_wake & 0x0001) { dev_warn(&pdev->dev, "Enabling legacy PCI PM\n"); device_set_wakeup_capable(&pdev->dev, 1); } } #ifdef CONFIG_USB_SUSPEND /* REVISIT: the controller works fine for wakeup iff the root hub * itself is "globally" suspended, but usbcore currently doesn't * understand such things. * * System suspend currently expects to be able to suspend the entire * device tree, device-at-a-time. If we failed selective suspend * reports, system suspend would fail; so the root hub code must claim * success. That's lying to usbcore, and it matters for runtime * PM scenarios with selective suspend and remote wakeup... */ if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev)) ehci_warn(ehci, "selective suspend/wakeup unavailable\n"); #endif ehci_port_power(ehci, 1); retval = ehci_pci_reinit(ehci, pdev); done: return retval; }
static int fsl_ehci_attach(device_t self) { ehci_softc_t *sc; int rid; int err; bus_space_handle_t ioh; bus_space_tag_t iot; sc = device_get_softc(self); rid = 0; sc->sc_bus.parent = self; sc->sc_bus.devices = sc->sc_devices; sc->sc_bus.devices_max = EHCI_MAX_DEVICES; if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) return (ENOMEM); /* Allocate io resource for EHCI */ sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->sc_io_res == NULL) { err = fsl_ehci_detach(self); if (err) { device_printf(self, "Detach of the driver failed with error %d\n", err); } return (ENXIO); } iot = rman_get_bustag(sc->sc_io_res); /* * Set handle to USB related registers subregion used by generic * EHCI driver */ ioh = rman_get_bushandle(sc->sc_io_res); err = bus_space_subregion(iot, ioh, FSL_EHCI_REG_OFF, FSL_EHCI_REG_SIZE, &sc->sc_io_hdl); if (err != 0) { err = fsl_ehci_detach(self); if (err) { device_printf(self, "Detach of the driver failed with error %d\n", err); } return (ENXIO); } /* Set little-endian tag for use by the generic EHCI driver */ sc->sc_io_tag = &bs_le_tag; /* Allocate irq */ sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, RF_ACTIVE); if (sc->sc_irq_res == NULL) { err = fsl_ehci_detach(self); if (err) { device_printf(self, "Detach of the driver failed with error %d\n", err); } return (ENXIO); } /* Setup interrupt handler */ err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO, NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); if (err) { device_printf(self, "Could not setup irq, %d\n", err); sc->sc_intr_hdl = NULL; err = fsl_ehci_detach(self); if (err) { device_printf(self, "Detach of the driver failed with error %d\n", err); } return (ENXIO); } /* Add USB device */ sc->sc_bus.bdev = device_add_child(self, "usbus", -1); if (!sc->sc_bus.bdev) { device_printf(self, "Could not add USB device\n"); err = fsl_ehci_detach(self); if (err) { device_printf(self, "Detach of the driver failed with error %d\n", err); } return (ENOMEM); } device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); sc->sc_id_vendor = 0x1234; strlcpy(sc->sc_vendor, "Freescale", sizeof(sc->sc_vendor)); /* Enable USB */ err = ehci_reset(sc); if (err) { device_printf(self, "Could not reset the controller\n"); err = fsl_ehci_detach(self); if (err) { device_printf(self, "Detach of the driver failed with error %d\n", err); } return (ENXIO); } enable_usb(self, iot, ioh); set_snooping(iot, ioh); set_to_host_mode(sc); set_32b_prefetch(iot, ioh); /* * If usb subsystem is enabled in U-Boot, port power has to be turned * off to allow proper discovery of devices during boot up. */ clear_port_power(sc); /* Set flags */ sc->sc_flags |= EHCI_SCFLG_DONTRESET | EHCI_SCFLG_NORESTERM; err = ehci_init(sc); if (!err) { sc->sc_flags |= EHCI_SCFLG_DONEINIT; err = device_probe_and_attach(sc->sc_bus.bdev); } if (err) { device_printf(self, "USB init failed err=%d\n", err); err = fsl_ehci_detach(self); if (err) { device_printf(self, "Detach of the driver failed with error %d\n", err); } return (EIO); } return (0); }
static int imx_ehci_attach(device_t dev) { struct imx_ehci_softc *sc; ehci_softc_t *esc; int err, rid; sc = device_get_softc(dev); esc = &sc->ehci_softc; err = 0; /* Allocate bus_space resources. */ rid = 0; sc->ehci_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->ehci_mem_res == NULL) { device_printf(dev, "Cannot allocate memory resources\n"); err = ENXIO; goto out; } rid = 0; sc->ehci_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (sc->ehci_irq_res == NULL) { device_printf(dev, "Cannot allocate IRQ resources\n"); err = ENXIO; goto out; } esc->sc_io_tag = rman_get_bustag(sc->ehci_mem_res); esc->sc_bus.parent = dev; esc->sc_bus.devices = esc->sc_devices; esc->sc_bus.devices_max = EHCI_MAX_DEVICES; esc->sc_bus.dma_bits = 32; /* allocate all DMA memory */ if (usb_bus_mem_alloc_all(&esc->sc_bus, USB_GET_DMA_TAG(dev), &ehci_iterate_hw_softc) != 0) { device_printf(dev, "usb_bus_mem_alloc_all() failed\n"); err = ENOMEM; goto out; } /* * Set handle to USB related registers subregion used by * generic EHCI driver. */ err = bus_space_subregion(esc->sc_io_tag, rman_get_bushandle(sc->ehci_mem_res), IMX_EHCI_REG_OFF, IMX_EHCI_REG_SIZE, &esc->sc_io_hdl); if (err != 0) { device_printf(dev, "bus_space_subregion() failed\n"); err = ENXIO; goto out; } /* Setup interrupt handler. */ err = bus_setup_intr(dev, sc->ehci_irq_res, INTR_TYPE_BIO, NULL, (driver_intr_t *)ehci_interrupt, esc, &esc->sc_intr_hdl); if (err != 0) { device_printf(dev, "Could not setup IRQ\n"); goto out; } /* Turn on clocks. */ imx_ccm_usb_enable(dev); /* Add USB bus device. */ esc->sc_bus.bdev = device_add_child(dev, "usbus", -1); if (esc->sc_bus.bdev == NULL) { device_printf(dev, "Could not add USB device\n"); goto out; } device_set_ivars(esc->sc_bus.bdev, &esc->sc_bus); esc->sc_id_vendor = USB_VENDOR_FREESCALE; strlcpy(esc->sc_vendor, "Freescale", sizeof(esc->sc_vendor)); /* Set flags that affect ehci_init() behavior. */ esc->sc_flags |= EHCI_SCFLG_DONTRESET | EHCI_SCFLG_NORESTERM; err = ehci_init(esc); if (err != 0) { device_printf(dev, "USB init failed, usb_err_t=%d\n", err); goto out; } esc->sc_flags |= EHCI_SCFLG_DONEINIT; /* Probe the bus. */ err = device_probe_and_attach(esc->sc_bus.bdev); if (err != 0) { device_printf(dev, "device_probe_and_attach() failed\n"); goto out; } err = 0; out: if (err != 0) imx_ehci_detach(dev); return (err); }
/* called during probe() after chip reset completes */ static int ehci_pci_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); u32 temp; int retval; ehci->caps = hcd->regs; ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase)); dbg_hcs_params(ehci, "reset"); dbg_hcc_params(ehci, "reset"); /* cache this readonly data; minimize chip reads */ ehci->hcs_params = readl(&ehci->caps->hcs_params); retval = ehci_halt(ehci); if (retval) return retval; /* data structure init */ retval = ehci_init(hcd); if (retval) return retval; /* NOTE: only the parts below this line are PCI-specific */ switch (pdev->vendor) { case PCI_VENDOR_ID_TDI: if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { ehci->is_tdi_rh_tt = 1; tdi_reset(ehci); } break; case PCI_VENDOR_ID_AMD: /* AMD8111 EHCI doesn't work, according to AMD errata */ if (pdev->device == 0x7463) { ehci_info(ehci, "ignoring AMD8111 (errata)\n"); retval = -EIO; goto done; } break; case PCI_VENDOR_ID_NVIDIA: /* NVidia reports that certain chips don't handle * QH, ITD, or SITD addresses above 2GB. (But TD, * data buffer, and periodic schedule are normal.) */ switch (pdev->device) { case 0x003c: /* MCP04 */ case 0x005b: /* CK804 */ case 0x00d8: /* CK8 */ case 0x00e8: /* CK8S */ if (pci_set_consistent_dma_mask(pdev, DMA_31BIT_MASK) < 0) ehci_warn(ehci, "can't enable NVidia " "workaround for >2GB RAM\n"); break; } break; } if (ehci_is_TDI(ehci)) ehci_reset(ehci); /* at least the Genesys GL880S needs fixup here */ temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); temp &= 0x0f; if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) { ehci_dbg(ehci, "bogus port configuration: " "cc=%d x pcc=%d < ports=%d\n", HCS_N_CC(ehci->hcs_params), HCS_N_PCC(ehci->hcs_params), HCS_N_PORTS(ehci->hcs_params)); switch (pdev->vendor) { case 0x17a0: /* GENESYS */ /* GL880S: should be PORTS=2 */ temp |= (ehci->hcs_params & ~0xf); ehci->hcs_params = temp; break; case PCI_VENDOR_ID_NVIDIA: /* NF4: should be PCC=10 */ break; } } /* Serial Bus Release Number is at PCI 0x60 offset */ pci_read_config_byte(pdev, 0x60, &ehci->sbrn); /* Workaround current PCI init glitch: wakeup bits aren't * being set from PCI PM capability. */ if (!device_can_wakeup(&pdev->dev)) { u16 port_wake; pci_read_config_word(pdev, 0x62, &port_wake); if (port_wake & 0x0001) device_init_wakeup(&pdev->dev, 1); } retval = ehci_pci_reinit(ehci, pdev); done: return retval; }
static int qcom_ehci_attach(device_t self) { ehci_softc_t *sc; struct qcom_ehci_softc *esc; bus_space_handle_t bsh; int err; uint32_t val; esc = device_get_softc(self); sc = &esc->base; sc->sc_bus.parent = self; sc->sc_bus.devices = sc->sc_devices; sc->sc_bus.devices_max = EHCI_MAX_DEVICES; /* get all DMA memory */ if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) { return (ENOMEM); } sc->sc_bus.usbrev = USB_REV_2_0; if (bus_alloc_resources(self, qcom_ehci_spec, esc->res)) { device_printf(self, "could not allocate resources\n"); return (ENXIO); } /* EHCI registers */ sc->sc_io_tag = rman_get_bustag(esc->res[0]); bsh = rman_get_bushandle(esc->res[0]); sc->sc_io_size = rman_get_size(esc->res[0]); /* GPIO */ esc->gpio_bst = rman_get_bustag(esc->res[1]); esc->gpio_bsh = rman_get_bushandle(esc->res[1]); if (bus_space_subregion(sc->sc_io_tag, bsh, 0x100, sc->sc_io_size, &sc->sc_io_hdl) != 0) panic("%s: unable to subregion USB host registers", device_get_name(self)); sc->sc_bus.bdev = device_add_child(self, "usbus", -1); if (!sc->sc_bus.bdev) { device_printf(self, "Could not add USB device\n"); goto error; } device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR); sprintf(sc->sc_vendor, "Qualcomm"); err = bus_setup_intr(self, esc->res[2], INTR_TYPE_BIO | INTR_MPSAFE, NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); if (err) { device_printf(self, "Could not setup irq, %d\n", err); sc->sc_intr_hdl = NULL; goto error; } sc->sc_flags |= EHCI_SCFLG_DONTRESET; /* Configure GPIO for output */ gpio_tlmm_config(esc, 77, 0, QGPIO_OUTPUT, QGPIO_NO_PULL, QGPIO_8MA, QGPIO_ENABLE); /* Output High */ gpio_set(esc, 77, 2); /* ehci phy reset */ val = READ_4(sc, USB_PORTSC) & ~PORTSC_PTS_MASK; WRITE_4(sc, USB_PORTSC, val | PORTSC_PTS_ULPI); WRITE_4(sc, USB_USBCMD, USBCMD_RESET); /* reset */ WRITE_4(sc, USB_USBCMD, 0x00080000); /* select ULPI phy */ WRITE_4(sc, USB_PORTSC, 0x80000000); /* burst of unspecified len */ WRITE_4(sc, USB_AHB_BURST, 0); /* HPROT mode */ WRITE_4(sc, USB_AHB_MODE, 0x08); /* disable BAM */ WRITE_4(sc, USB_GENCONFIG, (1 << 13)); // READ_4(sc, USB_DCCPARAMS); /* Disable streaming mode and select host mode */ WRITE_4(sc, USB_USBMODE, 0x13); /* go to RUN mode (D+ pullup enable) */ WRITE_4(sc, USB_USBCMD, 0x00080000); // breakpoint(); err = ehci_init(sc); if (!err) err = device_probe_and_attach(sc->sc_bus.bdev); if (err) { device_printf(self, "USB init failed err=%d\n", err); goto error; } return (0); error: qcom_ehci_detach(self); return (ENXIO); }
static int ar71xx_ehci_attach(device_t self) { struct ar71xx_ehci_softc *isc = device_get_softc(self); ehci_softc_t *sc = &isc->base; int err; int rid; /* initialise some bus fields */ sc->sc_bus.parent = self; sc->sc_bus.devices = sc->sc_devices; sc->sc_bus.devices_max = EHCI_MAX_DEVICES; sc->sc_bus.dma_bits = 32; /* get all DMA memory */ if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) { return (ENOMEM); } sc->sc_bus.usbrev = USB_REV_2_0; /* NB: hints fix the memory location and irq */ rid = 0; sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->sc_io_res) { device_printf(self, "Could not map memory\n"); goto error; } /* * Craft special resource for bus space ops that handle * byte-alignment of non-word addresses. */ sc->sc_io_tag = ar71xx_bus_space_reversed; sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res); sc->sc_io_size = rman_get_size(sc->sc_io_res); rid = 0; sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, RF_ACTIVE | RF_SHAREABLE); if (sc->sc_irq_res == NULL) { device_printf(self, "Could not allocate irq\n"); goto error; } sc->sc_bus.bdev = device_add_child(self, "usbus", -1); if (!sc->sc_bus.bdev) { device_printf(self, "Could not add USB device\n"); goto error; } device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR); sprintf(sc->sc_vendor, "Atheros"); err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, NULL, ar71xx_ehci_intr, sc, &sc->sc_intr_hdl); if (err) { device_printf(self, "Could not setup irq, %d\n", err); sc->sc_intr_hdl = NULL; goto error; } /* * Arrange to force Host mode, select big-endian byte alignment, * and arrange to not terminate reset operations (the adapter * will ignore it if we do but might as well save a reg write). * Also, the controller has an embedded Transaction Translator * which means port speed must be read from the Port Status * register following a port enable. */ sc->sc_flags = 0; sc->sc_vendor_post_reset = ar71xx_ehci_post_reset; switch (ar71xx_soc) { case AR71XX_SOC_AR7241: case AR71XX_SOC_AR7242: case AR71XX_SOC_AR9130: case AR71XX_SOC_AR9132: case AR71XX_SOC_AR9330: case AR71XX_SOC_AR9331: case AR71XX_SOC_AR9341: case AR71XX_SOC_AR9342: case AR71XX_SOC_AR9344: case AR71XX_SOC_QCA9533: case AR71XX_SOC_QCA9533_V2: case AR71XX_SOC_QCA9556: case AR71XX_SOC_QCA9558: sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM; sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc; break; default: /* fallthrough */ break; } /* * ehci_reset() needs the correct offset to access the host controller * registers. The AR724x/AR913x offsets aren't 0. */ sc->sc_offs = EHCI_CAPLENGTH(EREAD4(sc, EHCI_CAPLEN_HCIVERSION)); (void) ehci_reset(sc); err = ehci_init(sc); if (!err) { err = device_probe_and_attach(sc->sc_bus.bdev); } if (err) { device_printf(self, "USB init failed err=%d\n", err); goto error; } return (0); error: ar71xx_ehci_detach(self); return (ENXIO); }
static int fsl_ehci_attach(device_t self) { struct imx_ehci_softc *sc; bus_space_tag_t iot; ehci_softc_t *esc; int err, i, rid; sc = device_get_softc(self); rid = 0; /* Allocate io resource for EHCI */ if (bus_alloc_resources(self, imx_ehci_spec, sc->sc_res)) { device_printf(self, "could not allocate resources\n"); return (ENXIO); } iot = rman_get_bustag(sc->sc_res[0]); /* TODO: Power/clock enable */ /* TODO: basic init */ for (i = 0; i < FSL_EHCI_COUNT; i ++) { /* No interrupt - no driver */ if (sc->sc_res[1 + i] == NULL) continue; esc = &sc->ehci[i]; esc->sc_io_tag = iot; esc->sc_bus.parent = self; esc->sc_bus.devices = esc->sc_devices; esc->sc_bus.devices_max = EHCI_MAX_DEVICES; if (usb_bus_mem_alloc_all(&esc->sc_bus, USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) continue; /* * Set handle to USB related registers subregion used by * generic EHCI driver. */ err = bus_space_subregion(iot, rman_get_bushandle(sc->sc_res[0]), FSL_EHCI_REG_OFF + (i * FSL_EHCI_REG_STEP), FSL_EHCI_REG_SIZE, &esc->sc_io_hdl); if (err != 0) continue; /* Setup interrupt handler */ err = bus_setup_intr(self, sc->sc_res[1 + i], INTR_TYPE_BIO, NULL, (driver_intr_t *)ehci_interrupt, esc, &esc->sc_intr_hdl); if (err) { device_printf(self, "Could not setup irq, " "for EHCI%d %d\n", i, err); continue; } /* Add USB device */ esc->sc_bus.bdev = device_add_child(self, "usbus", -1); if (!esc->sc_bus.bdev) { device_printf(self, "Could not add USB device\n"); err = bus_teardown_intr(self, esc->sc_irq_res, esc->sc_intr_hdl); if (err) device_printf(self, "Could not tear down irq," " %d\n", err); continue; } device_set_ivars(esc->sc_bus.bdev, &esc->sc_bus); esc->sc_id_vendor = 0x1234; strlcpy(esc->sc_vendor, "Freescale", sizeof(esc->sc_vendor)); /* Set flags */ esc->sc_flags |= EHCI_SCFLG_DONTRESET | EHCI_SCFLG_NORESTERM; err = ehci_init(esc); if (!err) { esc->sc_flags |= EHCI_SCFLG_DONEINIT; err = device_probe_and_attach(esc->sc_bus.bdev); } else { device_printf(self, "USB init failed err=%d\n", err); device_delete_child(self, esc->sc_bus.bdev); esc->sc_bus.bdev = NULL; err = bus_teardown_intr(self, esc->sc_irq_res, esc->sc_intr_hdl); if (err) device_printf(self, "Could not tear down irq," " %d\n", err); continue; } } return (0); }
static int zy7_ehci_attach(device_t dev) { ehci_softc_t *sc = device_get_softc(dev); bus_space_handle_t bsh; int err, rid; /* initialize some bus fields */ sc->sc_bus.parent = dev; sc->sc_bus.devices = sc->sc_devices; sc->sc_bus.devices_max = EHCI_MAX_DEVICES; sc->sc_bus.dma_bits = 32; /* get all DMA memory */ if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(dev), &ehci_iterate_hw_softc)) return (ENOMEM); /* Allocate memory. */ rid = 0; sc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->sc_io_res == NULL) { device_printf(dev, "Can't allocate memory"); zy7_ehci_detach(dev); return (ENOMEM); } sc->sc_io_tag = rman_get_bustag(sc->sc_io_res); bsh = rman_get_bushandle(sc->sc_io_res); sc->sc_io_size = EHCI_REG_SIZE; if (bus_space_subregion(sc->sc_io_tag, bsh, EHCI_REG_OFFSET, sc->sc_io_size, &sc->sc_io_hdl) != 0) panic("%s: unable to subregion USB host registers", device_get_name(dev)); /* Allocate IRQ. */ rid = 0; sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (sc->sc_irq_res == NULL) { device_printf(dev, "Can't allocate IRQ\n"); zy7_ehci_detach(dev); return (ENOMEM); } /* Add USB device */ sc->sc_bus.bdev = device_add_child(dev, "usbus", -1); if (!sc->sc_bus.bdev) { device_printf(dev, "Could not add USB device\n"); zy7_ehci_detach(dev); return (ENXIO); } device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); device_set_desc(sc->sc_bus.bdev, "Zynq-7000 ehci USB 2.0 controller"); strcpy(sc->sc_vendor, "Xilinx"); /* or IP vendor? */ /* Activate the interrupt */ err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); if (err) { device_printf(dev, "Cannot setup IRQ\n"); zy7_ehci_detach(dev); return (err); } /* Customization. */ sc->sc_flags |= EHCI_SCFLG_TT | EHCI_SCFLG_NORESTERM; sc->sc_vendor_post_reset = zy7_ehci_post_reset; sc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc; /* Modify FIFO burst threshold from 2 to 8. */ bus_space_write_4(sc->sc_io_tag, bsh, ZY7_USB_TXFILLTUNING, 8 << ZY7_USB_TXFILLTUNING_TXFIFOTHRES_SHFT); /* Handle PHY options. */ if (zy7_phy_config(dev, sc->sc_io_tag, bsh) < 0) { device_printf(dev, "Cannot config phy!\n"); zy7_ehci_detach(dev); return (EIO); } /* Init ehci. */ err = ehci_init(sc); if (!err) { sc->sc_flags |= EHCI_SCFLG_DONEINIT; err = device_probe_and_attach(sc->sc_bus.bdev); } if (err) { device_printf(dev, "USB init failed err=%d\n", err); zy7_ehci_detach(dev); return (err); } return (0); }
/** * omap_ehci_attach - driver entry point, sets up the ECHI controller/driver * @dev: the new device handle * * Sets up bus spaces, interrupt handles, etc for the EHCI controller. It also * parses the resource hints and calls omap_ehci_init() to initialise the * H/W. * * LOCKING: * none * * RETURNS: * 0 on success or a positive error code on failure. */ static int omap_ehci_attach(device_t dev) { struct omap_ehci_softc *isc = device_get_softc(dev); phandle_t node; /* 3 ports with 3 cells per port */ pcell_t phyconf[3 * 3]; pcell_t *phyconf_ptr; ehci_softc_t *sc = &isc->base; int err; int rid; int len, tuple_size; int i; /* initialise some bus fields */ sc->sc_bus.parent = dev; sc->sc_bus.devices = sc->sc_devices; sc->sc_bus.devices_max = EHCI_MAX_DEVICES; /* save the device */ isc->sc_dev = dev; /* get all DMA memory */ if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(dev), &ehci_iterate_hw_softc)) { return (ENOMEM); } /* When the EHCI driver is added to the tree it is expected that 3 * memory resources and 1 interrupt resource is assigned. The memory * resources should be: * 0 => EHCI register range * 1 => UHH register range * 2 => TLL register range * * The interrupt resource is just the single interupt for the controller. */ /* Allocate resource for the EHCI register set */ rid = 0; sc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->sc_io_res) { device_printf(dev, "Error: Could not map EHCI memory\n"); goto error; } /* Request an interrupt resource */ rid = 0; sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (sc->sc_irq_res == NULL) { device_printf(dev, "Error: could not allocate irq\n"); goto error; } /* Allocate resource for the UHH register set */ rid = 1; isc->uhh_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!isc->uhh_mem_res) { device_printf(dev, "Error: Could not map UHH memory\n"); goto error; } /* Allocate resource for the TLL register set */ rid = 2; isc->tll_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!isc->tll_mem_res) { device_printf(dev, "Error: Could not map TLL memory\n"); goto error; } /* Add this device as a child of the USBus device */ sc->sc_bus.bdev = device_add_child(dev, "usbus", -1); if (!sc->sc_bus.bdev) { device_printf(dev, "Error: could not add USB device\n"); goto error; } device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); device_set_desc(sc->sc_bus.bdev, OMAP_EHCI_HC_DEVSTR); /* Set the vendor name */ sprintf(sc->sc_vendor, "Texas Instruments"); /* Get the GPIO device, we may need this if the driver needs to toggle * some pins for external PHY resets. */ isc->sc_gpio_dev = devclass_get_device(devclass_find("gpio"), 0); if (isc->sc_gpio_dev == NULL) { device_printf(dev, "Error: failed to get the GPIO device\n"); goto error; } /* Set the defaults for the hints */ for (i = 0; i < 3; i++) { isc->phy_reset[i] = 0; isc->port_mode[i] = EHCI_HCD_OMAP_MODE_UNKNOWN; isc->reset_gpio_pin[i] = -1; } tuple_size = sizeof(pcell_t) * 3; node = ofw_bus_get_node(dev); len = OF_getprop(node, "phy-config", phyconf, sizeof(phyconf)); if (len > 0) { if (len % tuple_size) goto error; if ((len / tuple_size) != 3) goto error; phyconf_ptr = phyconf; for (i = 0; i < 3; i++) { isc->port_mode[i] = fdt32_to_cpu(*phyconf_ptr); isc->phy_reset[i] = fdt32_to_cpu(*(phyconf_ptr + 1)); isc->reset_gpio_pin[i] = fdt32_to_cpu(*(phyconf_ptr + 2)); phyconf_ptr += 3; } } /* Initialise the ECHI registers */ err = omap_ehci_init(isc); if (err) { device_printf(dev, "Error: could not setup OMAP EHCI, %d\n", err); goto error; } /* Set the tag and size of the register set in the EHCI context */ sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res); sc->sc_io_tag = rman_get_bustag(sc->sc_io_res); sc->sc_io_size = rman_get_size(sc->sc_io_res); /* Setup the interrupt */ err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); if (err) { device_printf(dev, "Error: could not setup irq, %d\n", err); sc->sc_intr_hdl = NULL; goto error; } /* Finally we are ready to kick off the ECHI host controller */ err = ehci_init(sc); if (err == 0) { err = device_probe_and_attach(sc->sc_bus.bdev); } if (err) { device_printf(dev, "Error: USB init failed err=%d\n", err); goto error; } return (0); error: omap_ehci_detach(dev); return (ENXIO); }
/* called during probe() after chip reset completes */ static int ehci_pci_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); u32 temp; int retval; ehci->caps = hcd->regs; ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase)); dbg_hcs_params(ehci, "reset"); dbg_hcc_params(ehci, "reset"); /* ehci_init() causes memory for DMA transfers to be * allocated. Thus, any vendor-specific workarounds based on * limiting the type of memory used for DMA transfers must * happen before ehci_init() is called. */ switch (pdev->vendor) { case PCI_VENDOR_ID_NVIDIA: /* NVidia reports that certain chips don't handle * QH, ITD, or SITD addresses above 2GB. (But TD, * data buffer, and periodic schedule are normal.) */ switch (pdev->device) { case 0x003c: /* MCP04 */ case 0x005b: /* CK804 */ case 0x00d8: /* CK8 */ case 0x00e8: /* CK8S */ if (pci_set_consistent_dma_mask(pdev, DMA_31BIT_MASK) < 0) ehci_warn(ehci, "can't enable NVidia " "workaround for >2GB RAM\n"); break; } break; } /* cache this readonly data; minimize chip reads */ ehci->hcs_params = readl(&ehci->caps->hcs_params); retval = ehci_halt(ehci); if (retval) return retval; /* data structure init */ retval = ehci_init(hcd); if (retval) return retval; switch (pdev->vendor) { case PCI_VENDOR_ID_TDI: if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { ehci->is_tdi_rh_tt = 1; tdi_reset(ehci); } break; case PCI_VENDOR_ID_AMD: /* AMD8111 EHCI doesn't work, according to AMD errata */ if (pdev->device == 0x7463) { ehci_info(ehci, "ignoring AMD8111 (errata)\n"); retval = -EIO; goto done; } break; case PCI_VENDOR_ID_NVIDIA: switch (pdev->device) { /* Some NForce2 chips have problems with selective suspend; * fixed in newer silicon. */ case 0x0068: pci_read_config_dword(pdev, PCI_REVISION_ID, &temp); if ((temp & 0xff) < 0xa4) ehci->no_selective_suspend = 1; break; } break; } if (ehci_is_TDI(ehci)) ehci_reset(ehci); /* at least the Genesys GL880S needs fixup here */ temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); temp &= 0x0f; if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) { ehci_dbg(ehci, "bogus port configuration: " "cc=%d x pcc=%d < ports=%d\n", HCS_N_CC(ehci->hcs_params), HCS_N_PCC(ehci->hcs_params), HCS_N_PORTS(ehci->hcs_params)); switch (pdev->vendor) { case 0x17a0: /* GENESYS */ /* GL880S: should be PORTS=2 */ temp |= (ehci->hcs_params & ~0xf); ehci->hcs_params = temp; break; case PCI_VENDOR_ID_NVIDIA: /* NF4: should be PCC=10 */ break; } } /* Serial Bus Release Number is at PCI 0x60 offset */ pci_read_config_byte(pdev, 0x60, &ehci->sbrn); /* Workaround current PCI init glitch: wakeup bits aren't * being set from PCI PM capability. */ if (!device_can_wakeup(&pdev->dev)) { u16 port_wake; pci_read_config_word(pdev, 0x62, &port_wake); if (port_wake & 0x0001) device_init_wakeup(&pdev->dev, 1); } #ifdef CONFIG_USB_SUSPEND /* REVISIT: the controller works fine for wakeup iff the root hub * itself is "globally" suspended, but usbcore currently doesn't * understand such things. * * System suspend currently expects to be able to suspend the entire * device tree, device-at-a-time. If we failed selective suspend * reports, system suspend would fail; so the root hub code must claim * success. That's lying to usbcore, and it matters for for runtime * PM scenarios with selective suspend and remote wakeup... */ if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev)) ehci_warn(ehci, "selective suspend/wakeup unavailable\n"); #endif retval = ehci_pci_reinit(ehci, pdev); done: return retval; }
static int ehci_xls_attach(device_t self) { ehci_softc_t *sc = device_get_softc(self); int err; int rid; sc->sc_bus.parent = self; sc->sc_bus.devices = sc->sc_devices; sc->sc_bus.devices_max = EHCI_MAX_DEVICES; /* get all DMA memory */ if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) { return (ENOMEM); } rid = 0; sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->sc_io_res) { device_printf(self, "Could not map memory\n"); goto error; } sc->sc_io_tag = rman_get_bustag(sc->sc_io_res); sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res); printf("IO Resource tag %lx, hdl %lx, size %lx\n", (u_long)sc->sc_io_tag, (u_long)sc->sc_io_hdl, (u_long)sc->sc_io_size); rid = 0; sc->sc_irq_res = bus_alloc_resource(self, SYS_RES_IRQ, &rid, PIC_USB_IRQ, PIC_USB_IRQ, 1, RF_SHAREABLE | RF_ACTIVE); if (sc->sc_irq_res == NULL) { device_printf(self, "Could not allocate irq\n"); goto error; } sc->sc_bus.bdev = device_add_child(self, "usbus", -1); if (!sc->sc_bus.bdev) { device_printf(self, "Could not add USB device\n"); goto error; } device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); device_set_desc(sc->sc_bus.bdev, xlr_usb_dev_desc); sprintf(sc->sc_vendor, xlr_vendor_desc); err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, NULL, (driver_intr_t *) ehci_interrupt, sc, &sc->sc_intr_hdl); if (err) { device_printf(self, "Could not setup irq, %d\n", err); sc->sc_intr_hdl = NULL; goto error; } err = ehci_init(sc); if (err) { device_printf(self, "USB init failed err=%d\n", err); goto error; } err = device_probe_and_attach(sc->sc_bus.bdev); if (err) { device_printf(self, "USB probe and attach failed err=%d\n", err); goto error; } return (0); error: ehci_xls_detach(self); return (ENXIO); }