void imxehci_reset(struct imxehci_softc *sc) { uint32_t reg; int i; struct ehci_softc *hsc = &sc->sc_hsc; #define RESET_TIMEOUT 100 reg = EOREAD4(hsc, EHCI_USBCMD); reg &= ~EHCI_CMD_RS; EOWRITE4(hsc, EHCI_USBCMD, reg); for (i=0; i < RESET_TIMEOUT; ++i) { reg = EOREAD4(hsc, EHCI_USBCMD); if ((reg & EHCI_CMD_RS) == 0) break; usb_delay_ms(&hsc->sc_bus, 1); } EOWRITE4(hsc, EHCI_USBCMD, reg | EHCI_CMD_HCRESET); for (i = 0; i < RESET_TIMEOUT; i++) { reg = EOREAD4(hsc, EHCI_USBCMD); if ((reg & EHCI_CMD_HCRESET) == 0) break; usb_delay_ms(&hsc->sc_bus, 1); } if (i >= RESET_TIMEOUT) { aprint_error_dev(hsc->sc_dev, "reset timeout (%x)\n", reg); } usb_delay_ms(&hsc->sc_bus, 100); }
static void imxehci_select_interface(struct imxehci_softc *sc, enum imx_usb_if interface) { uint32_t reg; struct ehci_softc *hsc = &sc->sc_hsc; reg = EOREAD4(hsc, EHCI_PORTSC(1)); reg &= ~(PORTSC_PTS | PORTSC_PTW); switch (interface) { case IMXUSBC_IF_UTMI_WIDE: reg |= PORTSC_PTW_16; case IMXUSBC_IF_UTMI: reg |= PORTSC_PTS_UTMI; break; case IMXUSBC_IF_PHILIPS: reg |= PORTSC_PTS_PHILIPS; break; case IMXUSBC_IF_ULPI: reg |= PORTSC_PTS_ULPI; break; case IMXUSBC_IF_SERIAL: reg |= PORTSC_PTS_SERIAL; break; } EOWRITE4(hsc, EHCI_PORTSC(1), reg); }
static void ehci_ps3_post_reset(struct ehci_softc *ehci_softc) { uint32_t usbmode; /* Select big-endian mode */ usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM); usbmode |= EHCI_UM_ES_BE; EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode); }
static void zy7_ehci_post_reset(struct ehci_softc *ehci_softc) { uint32_t usbmode; /* Force HOST mode */ usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM); usbmode &= ~EHCI_UM_CM; usbmode |= EHCI_UM_CM_HOST; EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode); }
static void mvusb_vendor_init(struct ehci_softc *sc) { uint32_t mode; /* put TDI/ARC silicon into EHCI mode */ mode = EOREAD4(sc, MARVELL_USB_EHCI_USBMODE); mode &= ~MARVELL_USB_EHCI_MODE_HDMASK; /* Host/Device Mask */ mode |= MARVELL_USB_EHCI_MODE_HOST; mode |= MARVELL_USB_EHCI_MODE_STRMDIS; EOWRITE4(sc, MARVELL_USB_EHCI_USBMODE, mode); }
static void ehci_ixp_post_reset(struct ehci_softc *ehci_softc) { uint32_t usbmode; /* Force HOST mode, select big-endian mode */ usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM); usbmode &= ~EHCI_UM_CM; usbmode |= EHCI_UM_CM_HOST; usbmode |= EHCI_UM_ES_BE; EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode); }
static void zynqusb_init(struct ehci_softc *hsc) { struct zynqehci_softc *sc = device_private(hsc->sc_dev); uint32_t reg; reg = EOREAD4(hsc, EHCI_PORTSC(1)); reg &= ~(EHCI_PS_CSC | EHCI_PS_PEC | EHCI_PS_OCC); reg |= EHCI_PS_PP | EHCI_PS_PE; EOWRITE4(hsc, EHCI_PORTSC(1), reg); reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ZYNQUSB_OTGSC); reg |= OTGSC_IDPU; reg |= OTGSC_DPIE | OTGSC_IDIE; bus_space_write_4(sc->sc_iot, sc->sc_ioh, ZYNQUSB_OTGSC, reg); reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ZYNQUSB_USBMODE); reg &= ~USBMODE_CM; reg |= USBMODE_CM_HOST; bus_space_write_4(sc->sc_iot, sc->sc_ioh, ZYNQUSB_USBMODE, reg); }
static void imxehci_init(struct ehci_softc *hsc) { struct imxehci_softc *sc = device_private(hsc->sc_dev); uint32_t reg; reg = EOREAD4(hsc, EHCI_PORTSC(1)); reg &= ~(EHCI_PS_CSC | EHCI_PS_PEC | EHCI_PS_OCC); reg |= EHCI_PS_PP | EHCI_PS_PE; EOWRITE4(hsc, EHCI_PORTSC(1), reg); reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, IMXUSB_OTGSC); reg |= OTGSC_IDPU; /* disable IDIE not to conflict with SSP1_DETECT. */ //reg |= OTGSC_DPIE | OTGSC_IDIE; reg |= OTGSC_DPIE; bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXUSB_OTGSC, reg); reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, IMXUSB_USBMODE); reg &= ~USBMODE_CM; reg |= USBMODE_CM_HOST; bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXUSB_USBMODE, reg); }
void imxehci_attach(struct device *parent, struct device *self, void *aux) { struct imxehci_softc *sc = (struct imxehci_softc *)self; struct armv7_attach_args *aa = aux; usbd_status r; char *devname = sc->sc.sc_bus.bdev.dv_xname; sc->sc.iot = aa->aa_iot; sc->sc.sc_bus.dmatag = aa->aa_dmat; sc->sc.sc_size = aa->aa_dev->mem[0].size; /* Map I/O space */ if (bus_space_map(sc->sc.iot, aa->aa_dev->mem[0].addr, aa->aa_dev->mem[0].size, 0, &sc->sc.ioh)) { printf(": cannot map mem space\n"); goto out; } if (bus_space_map(sc->sc.iot, aa->aa_dev->mem[1].addr, aa->aa_dev->mem[1].size, 0, &sc->uh_ioh)) { printf(": cannot map mem space\n"); goto mem0; } if (bus_space_map(sc->sc.iot, aa->aa_dev->mem[2].addr, aa->aa_dev->mem[2].size, 0, &sc->ph_ioh)) { printf(": cannot map mem space\n"); goto mem1; } if (bus_space_map(sc->sc.iot, aa->aa_dev->mem[3].addr, aa->aa_dev->mem[3].size, 0, &sc->nc_ioh)) { printf(": cannot map mem space\n"); goto mem2; } printf("\n"); imxccm_enable_usboh3(); delay(1000); if (aa->aa_dev->mem[0].addr == USBUH1_EHCI_ADDR) { /* enable usb port power */ switch (board_id) { case BOARD_ID_IMX6_PHYFLEX: imxgpio_set_dir(EHCI_PHYFLEX_USB_H1_PWR, IMXGPIO_DIR_OUT); delay(10); imxgpio_set_bit(EHCI_PHYFLEX_USB_H1_PWR); delay(10); break; case BOARD_ID_IMX6_CUBOXI: case BOARD_ID_IMX6_HUMMINGBOARD: imxgpio_set_bit(EHCI_HUMMINGBOARD_USB_H1_PWR); imxgpio_set_dir(EHCI_HUMMINGBOARD_USB_H1_PWR, IMXGPIO_DIR_OUT); delay(10); break; case BOARD_ID_IMX6_SABRELITE: imxgpio_clear_bit(EHCI_NITROGEN6X_USB_HUB_RST); imxgpio_set_dir(EHCI_NITROGEN6X_USB_HUB_RST, IMXGPIO_DIR_OUT); delay(1000 * 2); imxgpio_set_bit(EHCI_NITROGEN6X_USB_HUB_RST); delay(10); break; case BOARD_ID_IMX6_SABRESD: imxgpio_set_bit(EHCI_SABRESD_USB_PWR); imxgpio_set_dir(EHCI_SABRESD_USB_PWR, IMXGPIO_DIR_OUT); delay(10); break; case BOARD_ID_IMX6_UTILITE: imxgpio_clear_bit(EHCI_UTILITE_USB_HUB_RST); imxgpio_set_dir(EHCI_UTILITE_USB_HUB_RST, IMXGPIO_DIR_OUT); delay(10); imxgpio_set_bit(EHCI_UTILITE_USB_HUB_RST); delay(1000); break; } /* disable the carger detection, else signal on DP will be poor */ imxccm_disable_usb2_chrg_detect(); /* power host 1 */ imxccm_enable_pll_usb2(); /* over current and polarity setting */ bus_space_write_4(sc->sc.iot, sc->nc_ioh, USBNC_USB_UH1_CTRL, bus_space_read_4(sc->sc.iot, sc->nc_ioh, USBNC_USB_UH1_CTRL) | (USBNC_USB_UH1_CTRL_OVER_CUR_POL | USBNC_USB_UH1_CTRL_OVER_CUR_DIS)); } else if (aa->aa_dev->mem[0].addr == USBOTG_EHCI_ADDR) { /* enable usb port power */ switch (board_id) { case BOARD_ID_IMX6_CUBOXI: case BOARD_ID_IMX6_HUMMINGBOARD: imxgpio_set_dir(EHCI_HUMMINGBOARD_USB_OTG_PWR, IMXGPIO_DIR_OUT); imxgpio_set_bit(EHCI_HUMMINGBOARD_USB_OTG_PWR); delay(10); break; } /* disable the carger detection, else signal on DP will be poor */ imxccm_disable_usb1_chrg_detect(); /* power host 0 */ imxccm_enable_pll_usb1(); /* over current and polarity setting */ bus_space_write_4(sc->sc.iot, sc->nc_ioh, USBNC_USB_OTG_CTRL, bus_space_read_4(sc->sc.iot, sc->nc_ioh, USBNC_USB_OTG_CTRL) | (USBNC_USB_OTG_CTRL_OVER_CUR_POL | USBNC_USB_OTG_CTRL_OVER_CUR_DIS)); } bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_CLR, USBPHY_CTRL_CLKGATE); /* Disable interrupts, so we don't get any spurious ones. */ sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH); EOWRITE2(&sc->sc, EHCI_USBINTR, 0); /* Stop then Reset */ uint32_t val = EOREAD4(&sc->sc, EHCI_USBCMD); val &= ~EHCI_CMD_RS; EOWRITE4(&sc->sc, EHCI_USBCMD, val); while (EOREAD4(&sc->sc, EHCI_USBCMD) & EHCI_CMD_RS) ; val = EOREAD4(&sc->sc, EHCI_USBCMD); val |= EHCI_CMD_HCRESET; EOWRITE4(&sc->sc, EHCI_USBCMD, val); while (EOREAD4(&sc->sc, EHCI_USBCMD) & EHCI_CMD_HCRESET) ; /* Reset USBPHY module */ bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_SET, USBPHY_CTRL_SFTRST); delay(10); /* Remove CLKGATE and SFTRST */ bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_CLR, USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); delay(10); /* Power up the PHY */ bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_PWD, 0); /* enable FS/LS device */ bus_space_write_4(sc->sc.iot, sc->ph_ioh, USBPHY_CTRL_SET, USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3); /* set host mode */ EWRITE4(&sc->sc, EHCI_USBMODE, EREAD4(&sc->sc, EHCI_USBMODE) | EHCI_USBMODE_HOST); /* set to UTMI mode */ EOWRITE4(&sc->sc, EHCI_PORTSC(1), EOREAD4(&sc->sc, EHCI_PORTSC(1)) & ~EHCI_PS_PTS_UTMI_MASK); sc->sc_ih = arm_intr_establish(aa->aa_dev->irq[0], IPL_USB, ehci_intr, &sc->sc, devname); if (sc->sc_ih == NULL) { printf(": unable to establish interrupt\n"); goto mem3; } strlcpy(sc->sc.sc_vendor, "i.MX6", sizeof(sc->sc.sc_vendor)); r = ehci_init(&sc->sc); if (r != USBD_NORMAL_COMPLETION) { printf("%s: init failed, error=%d\n", devname, r); goto intr; } config_found(self, &sc->sc.sc_bus, usbctlprint); goto out; intr: arm_intr_disestablish(sc->sc_ih); sc->sc_ih = NULL; mem3: bus_space_unmap(sc->sc.iot, sc->nc_ioh, aa->aa_dev->mem[3].addr); mem2: bus_space_unmap(sc->sc.iot, sc->ph_ioh, aa->aa_dev->mem[2].addr); mem1: bus_space_unmap(sc->sc.iot, sc->uh_ioh, aa->aa_dev->mem[1].addr); mem0: bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); sc->sc.sc_size = 0; out: return; }
static void imxehci_attach(device_t parent, device_t self, void *aux) { struct imxusbc_attach_args *aa = aux; struct imxusbc_softc *usbc = device_private(parent); struct imxehci_softc *sc = device_private(self); ehci_softc_t *hsc = &sc->sc_hsc; bus_space_tag_t iot; uint16_t hcirev; usbd_status r; uint32_t id, hwhost, hwdevice; const char *comma; sc->sc_hsc.sc_dev = self; iot = sc->sc_iot = sc->sc_hsc.iot = aa->aa_iot; sc->sc_unit = aa->aa_unit; sc->sc_usbc = usbc; hsc->sc_bus.hci_private = sc; hsc->sc_flags |= EHCIF_ETTF; hsc->sc_vendor_init = imxehci_init; aprint_naive("\n"); aprint_normal(": i.MX USB Controller\n"); /* per unit registers */ if (bus_space_subregion(iot, aa->aa_ioh, aa->aa_unit * IMXUSB_EHCI_SIZE, IMXUSB_EHCI_SIZE, &sc->sc_ioh) || bus_space_subregion(iot, aa->aa_ioh, aa->aa_unit * IMXUSB_EHCI_SIZE + IMXUSB_EHCIREGS, IMXUSB_EHCI_SIZE - IMXUSB_EHCIREGS, &sc->sc_hsc.ioh)) { aprint_error_dev(self, "can't subregion\n"); return; } id = bus_space_read_4(iot, sc->sc_ioh, IMXUSB_ID); hcirev = bus_space_read_2(iot, sc->sc_hsc.ioh, EHCI_HCIVERSION); aprint_normal_dev(self, "id=%d revision=%d HCI revision=0x%x\n", (int)__SHIFTOUT(id, IMXUSB_ID_ID), (int)__SHIFTOUT(id, IMXUSB_ID_REVISION), hcirev); hwhost = bus_space_read_4(iot, sc->sc_ioh, IMXUSB_HWHOST); hwdevice = bus_space_read_4(iot, sc->sc_ioh, IMXUSB_HWDEVICE); aprint_normal_dev(self, ""); comma = ""; if (hwhost & HWHOST_HC) { int n_ports = 1 + __SHIFTOUT(hwhost, HWHOST_NPORT); aprint_normal("%d host port%s", n_ports, n_ports > 1 ? "s" : ""); comma = ", "; } if (hwdevice & HWDEVICE_DC) { int n_endpoints = __SHIFTOUT(hwdevice, HWDEVICE_DEVEP); aprint_normal("%sdevice capable, %d endpoint%s", comma, n_endpoints, n_endpoints > 1 ? "s" : ""); } aprint_normal("\n"); sc->sc_hsc.sc_bus.dmatag = aa->aa_dmat; sc->sc_hsc.sc_offs = bus_space_read_1(iot, sc->sc_hsc.ioh, EHCI_CAPLENGTH); /* Platform dependent setup */ if (usbc->sc_init_md_hook) usbc->sc_init_md_hook(sc); imxehci_reset(sc); imxehci_select_interface(sc, sc->sc_iftype); if (sc->sc_iftype == IMXUSBC_IF_ULPI) { bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXUSB_ULPIVIEW, 0); aprint_normal_dev(hsc->sc_dev, "ULPI phy VID 0x%04x PID 0x%04x\n", (imxusb_ulpi_read(sc, ULPI_VENDOR_ID_LOW) | imxusb_ulpi_read(sc, ULPI_VENDOR_ID_HIGH) << 8), (imxusb_ulpi_read(sc, ULPI_PRODUCT_ID_LOW) | imxusb_ulpi_read(sc, ULPI_PRODUCT_ID_HIGH) << 8)); ulpi_reset(sc); } if (usbc->sc_setup_md_hook) usbc->sc_setup_md_hook(sc, IMXUSB_HOST); if (sc->sc_iftype == IMXUSBC_IF_ULPI) { #if 0 if(hsc->sc_bus.usbrev == USBREV_2_0) ulpi_write(hsc, ULPI_FUNCTION_CONTROL + ULPI_REG_CLEAR, (1 << 0)); else ulpi_write(hsc, ULPI_FUNCTION_CONTROL + ULPI_REG_SET, (1 << 2)); #endif imxusb_ulpi_write(sc, ULPI_FUNCTION_CONTROL + ULPI_REG_CLEAR, OTG_CONTROL_IDPULLUP); imxusb_ulpi_write(sc, ULPI_OTG_CONTROL + ULPI_REG_SET, OTG_CONTROL_USEEXTVBUSIND | OTG_CONTROL_DRVVBUSEXT | OTG_CONTROL_DRVVBUS | OTG_CONTROL_CHRGVBUS ); } /* Disable interrupts, so we don't get any spurious ones. */ EOWRITE4(hsc, EHCI_USBINTR, 0); intr_establish(aa->aa_irq, IPL_USB, IST_LEVEL, ehci_intr, hsc); /* Figure out vendor for root hub descriptor. */ strlcpy(hsc->sc_vendor, "i.MX", sizeof(hsc->sc_vendor)); r = ehci_init(hsc); if (r != USBD_NORMAL_COMPLETION) { aprint_error_dev(self, "init failed, error=%d\n", r); return; } /* Attach usb device. */ hsc->sc_child = config_found(self, &hsc->sc_bus, usbctlprint); }
void imxehci_attach(struct device *parent, struct device *self, void *aux) { struct imxehci_softc *sc = (struct imxehci_softc *)self; struct ehci_softc *esc; struct armv7_attach_args *aa = aux; struct fdt_memory hmem, pmem, mmem; int irq, r; sc->iot = aa->aa_iot; sc->sc_dmat = aa->aa_dmat; if (aa->aa_node) { uint32_t ints[3]; void *node; if (fdt_get_memory_address(aa->aa_node, 0, &hmem)) panic("%s: could not extract memory data from FDT", __func__); node = fdt_find_node_by_phandle_prop(aa->aa_node, "fsl,usbphy"); if (node == NULL || fdt_get_memory_address(node, 0, &pmem)) panic("%s: could not extract phy data from FDT", __func__); node = fdt_find_node_by_phandle_prop(aa->aa_node, "fsl,usbmisc"); if (node == NULL || fdt_get_memory_address(node, 0, &mmem)) panic("%s: could not extract phy data from FDT", __func__); /* TODO: Add interrupt FDT API. */ if (fdt_node_property_ints(aa->aa_node, "interrupts", ints, 3) != 3) panic("%s: could not extract interrupt data from FDT", __func__); irq = ints[1]; } else { hmem.addr = aa->aa_dev->mem[0].addr; hmem.size = aa->aa_dev->mem[0].size; pmem.addr = aa->aa_dev->mem[1].addr; pmem.size = aa->aa_dev->mem[1].size; mmem.addr = aa->aa_dev->mem[2].addr; mmem.size = aa->aa_dev->mem[2].size; irq = aa->aa_dev->irq[0]; } /* Map I/O space */ if (bus_space_map(sc->iot, hmem.addr, hmem.size, 0, &sc->uh_ioh)) { printf(": cannot map mem space\n"); goto hmem; } sc->ioh = sc->uh_ioh + 0x100; sc->sc_size = hmem.size; if (bus_space_map(sc->iot, pmem.addr, pmem.size, 0, &sc->ph_ioh)) { printf(": cannot map mem space\n"); goto pmem; } if (bus_space_map(sc->iot, mmem.addr, mmem.size, 0, &sc->nc_ioh)) { printf(": cannot map mem space\n"); goto mmem; } clk_enable(clk_get("usboh3")); delay(1000); if (hmem.addr == USBUH1_ADDR) { /* enable usb port power */ switch (board_id) { case BOARD_ID_IMX6_CUBOXI: case BOARD_ID_IMX6_HUMMINGBOARD: imxgpio_set_bit(EHCI_HUMMINGBOARD_USB_H1_PWR); imxgpio_set_dir(EHCI_HUMMINGBOARD_USB_H1_PWR, IMXGPIO_DIR_OUT); delay(10); break; case BOARD_ID_IMX6_SABRELITE: imxgpio_clear_bit(EHCI_NITROGEN6X_USB_HUB_RST); imxgpio_set_dir(EHCI_NITROGEN6X_USB_HUB_RST, IMXGPIO_DIR_OUT); delay(1000 * 2); imxgpio_set_bit(EHCI_NITROGEN6X_USB_HUB_RST); delay(10); break; case BOARD_ID_IMX6_SABRESD: imxgpio_set_bit(EHCI_SABRESD_USB_PWR); imxgpio_set_dir(EHCI_SABRESD_USB_PWR, IMXGPIO_DIR_OUT); delay(10); break; case BOARD_ID_IMX6_UTILITE: imxgpio_clear_bit(EHCI_UTILITE_USB_HUB_RST); imxgpio_set_dir(EHCI_UTILITE_USB_HUB_RST, IMXGPIO_DIR_OUT); delay(10); imxgpio_set_bit(EHCI_UTILITE_USB_HUB_RST); delay(1000); break; } /* disable the carger detection, else signal on DP will be poor */ imxccm_disable_usb2_chrg_detect(); /* power host 1 */ clk_enable(clk_get("pll7_usb_host")); clk_enable(clk_get("usbphy2_gate")); /* over current and polarity setting */ bus_space_write_4(sc->iot, sc->nc_ioh, USBNC_USB_UH1_CTRL, bus_space_read_4(sc->iot, sc->nc_ioh, USBNC_USB_UH1_CTRL) | (USBNC_USB_UH1_CTRL_OVER_CUR_POL | USBNC_USB_UH1_CTRL_OVER_CUR_DIS)); } else if (hmem.addr == USBOTG_ADDR) { /* enable usb port power */ switch (board_id) { case BOARD_ID_IMX6_CUBOXI: case BOARD_ID_IMX6_HUMMINGBOARD: imxgpio_set_bit(EHCI_HUMMINGBOARD_USB_OTG_PWR); imxgpio_set_dir(EHCI_HUMMINGBOARD_USB_OTG_PWR, IMXGPIO_DIR_OUT); delay(10); break; } /* disable the carger detection, else signal on DP will be poor */ imxccm_disable_usb1_chrg_detect(); /* power host 0 */ clk_enable(clk_get("pll3_usb_otg")); clk_enable(clk_get("usbphy1_gate")); /* over current and polarity setting */ bus_space_write_4(sc->iot, sc->nc_ioh, USBNC_USB_OTG_CTRL, bus_space_read_4(sc->iot, sc->nc_ioh, USBNC_USB_OTG_CTRL) | (USBNC_USB_OTG_CTRL_OVER_CUR_POL | USBNC_USB_OTG_CTRL_OVER_CUR_DIS)); } bus_space_write_4(sc->iot, sc->ph_ioh, USBPHY_CTRL_CLR, USBPHY_CTRL_CLKGATE); /* Disable interrupts, so we don't get any spurious ones. */ sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH); EOWRITE2(sc, EHCI_USBINTR, 0); /* Stop then Reset */ uint32_t val = EOREAD4(sc, EHCI_USBCMD); val &= ~EHCI_CMD_RS; EOWRITE4(sc, EHCI_USBCMD, val); while (EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_RS) ; val = EOREAD4(sc, EHCI_USBCMD); val |= EHCI_CMD_HCRESET; EOWRITE4(sc, EHCI_USBCMD, val); while (EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET) ; /* Reset USBPHY module */ bus_space_write_4(sc->iot, sc->ph_ioh, USBPHY_CTRL_SET, USBPHY_CTRL_SFTRST); delay(10); /* Remove CLKGATE and SFTRST */ bus_space_write_4(sc->iot, sc->ph_ioh, USBPHY_CTRL_CLR, USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); delay(10); /* Power up the PHY */ bus_space_write_4(sc->iot, sc->ph_ioh, USBPHY_PWD, 0); /* enable FS/LS device */ bus_space_write_4(sc->iot, sc->ph_ioh, USBPHY_CTRL_SET, USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3); /* set host mode */ EWRITE4(sc, EHCI_USBMODE, EREAD4(sc, EHCI_USBMODE) | EHCI_USBMODE_HOST); /* set to UTMI mode */ EOWRITE4(sc, EHCI_PORTSC(1), EOREAD4(sc, EHCI_PORTSC(1)) & ~EHCI_PS_PTS_UTMI_MASK); printf("\n"); if ((esc = (struct ehci_softc *)config_found(self, NULL, NULL)) == NULL) goto mmem; esc->iot = sc->iot; esc->ioh = sc->ioh; esc->sc_bus.dmatag = sc->sc_dmat; esc->sc_offs = sc->sc_offs; sc->sc_ih = arm_intr_establish(irq, IPL_USB, ehci_intr, esc, esc->sc_bus.bdev.dv_xname); if (sc->sc_ih == NULL) { printf(": unable to establish interrupt\n"); return; } strlcpy(esc->sc_vendor, "i.MX6", sizeof(esc->sc_vendor)); r = ehci_init(esc); if (r != USBD_NORMAL_COMPLETION) { printf("%s: init failed, error=%d\n", esc->sc_bus.bdev.dv_xname, r); goto intr; } printf("\n"); config_found((struct device *)esc, &esc->sc_bus, usbctlprint); goto out; intr: arm_intr_disestablish(sc->sc_ih); sc->sc_ih = NULL; mmem: bus_space_unmap(sc->iot, sc->nc_ioh, mmem.size); pmem: bus_space_unmap(sc->iot, sc->ph_ioh, pmem.size); hmem: bus_space_unmap(sc->iot, sc->uh_ioh, sc->sc_size); sc->sc_size = 0; out: return; }
void zynqusb_attach_common(device_t parent, device_t self, bus_space_tag_t iot, bus_dma_tag_t dmat, paddr_t iobase, size_t size, int intr, int flags, enum zynq_usb_if type, enum zynq_usb_role role) { struct zynqehci_softc *sc = device_private(self); ehci_softc_t *hsc = &sc->sc_hsc; uint16_t hcirev; usbd_status r; uint32_t id, hwhost, hwdevice; const char *comma; sc->sc_hsc.sc_dev = self; sc->sc_iot = sc->sc_hsc.iot = iot; sc->sc_iftype = type; sc->sc_role = role; hsc->sc_bus.hci_private = sc; hsc->sc_bus.usbrev = USBREV_2_0; hsc->sc_flags |= EHCIF_ETTF; hsc->sc_vendor_init = zynqusb_init; aprint_normal("\n"); if (bus_space_map(iot, iobase, size, 0, &sc->sc_ioh)) { aprint_error_dev(self, "unable to map device\n"); return; } if (bus_space_subregion(iot, sc->sc_ioh, ZYNQUSB_EHCIREGS, ZYNQUSB_EHCI_SIZE - ZYNQUSB_EHCIREGS, &sc->sc_hsc.ioh)) { aprint_error_dev(self, "unable to map subregion\n"); return; } id = bus_space_read_4(iot, sc->sc_ioh, ZYNQUSB_ID); hcirev = bus_space_read_2(iot, sc->sc_hsc.ioh, EHCI_HCIVERSION); aprint_normal_dev(self, "Zynq USB Controller id=%d revision=%d version=%d\n", (int)__SHIFTOUT(id, ZYNQUSB_ID_ID), (int)__SHIFTOUT(id, ZYNQUSB_ID_REVISION), (int)__SHIFTOUT(id, ZYNQUSB_ID_VERSION)); aprint_normal_dev(self, "HCI revision=0x%x\n", hcirev); hwhost = bus_space_read_4(iot, sc->sc_ioh, ZYNQUSB_HWHOST); hwdevice = bus_space_read_4(iot, sc->sc_ioh, ZYNQUSB_HWDEVICE); aprint_normal_dev(self, ""); comma = ""; if (hwhost & HWHOST_HC) { int n_ports = 1 + __SHIFTOUT(hwhost, HWHOST_NPORT); aprint_normal("%d host port%s", n_ports, n_ports > 1 ? "s" : ""); comma = ", "; } if (hwdevice & HWDEVICE_DC) { int n_endpoints = __SHIFTOUT(hwdevice, HWDEVICE_DEVEP); aprint_normal("%sdevice capable, %d endpoint%s", comma, n_endpoints, n_endpoints > 1 ? "s" : ""); } aprint_normal("\n"); sc->sc_hsc.sc_bus.dmatag = dmat; sc->sc_hsc.sc_offs = bus_space_read_1(iot, sc->sc_hsc.ioh, EHCI_CAPLENGTH); zynqusb_reset(sc); zynqusb_select_interface(sc, sc->sc_iftype); if (sc->sc_iftype == ZYNQUSBC_IF_ULPI) { bus_space_write_4(sc->sc_iot, sc->sc_ioh, ZYNQUSB_ULPIVIEW, 0); aprint_normal_dev(hsc->sc_dev, "ULPI phy VID 0x%04x PID 0x%04x\n", (ulpi_read(sc, ULPI_VENDOR_ID_LOW) | ulpi_read(sc, ULPI_VENDOR_ID_HIGH) << 8), (ulpi_read(sc, ULPI_PRODUCT_ID_LOW) | ulpi_read(sc, ULPI_PRODUCT_ID_HIGH) << 8)); ulpi_reset(sc); } if (sc->sc_iftype == ZYNQUSBC_IF_ULPI) { if(hsc->sc_bus.usbrev == USBREV_2_0) { ulpi_write(sc, ULPI_FUNCTION_CONTROL + ULPI_REG_CLEAR, FUNCTION_CONTROL_XCVRSELECT); ulpi_write(sc, ULPI_FUNCTION_CONTROL + ULPI_REG_SET, FUNCTION_CONTROL_TERMSELECT); } else { ulpi_write(sc, ULPI_FUNCTION_CONTROL + ULPI_REG_SET, XCVRSELECT_FSLS); ulpi_write(sc, ULPI_FUNCTION_CONTROL + ULPI_REG_CLEAR, FUNCTION_CONTROL_TERMSELECT); } ulpi_write(sc, ULPI_OTG_CONTROL + ULPI_REG_SET, OTG_CONTROL_USEEXTVBUSIND | OTG_CONTROL_DRVVBUSEXT | OTG_CONTROL_DRVVBUS | OTG_CONTROL_CHRGVBUS); } /* Disable interrupts, so we don't get any spurious ones. */ EOWRITE4(hsc, EHCI_USBINTR, 0); intr_establish(intr, IPL_USB, IST_LEVEL, ehci_intr, hsc); /* Figure out vendor for root hub descriptor. */ strlcpy(hsc->sc_vendor, "Xilinx", sizeof(hsc->sc_vendor)); r = ehci_init(hsc); if (r != USBD_NORMAL_COMPLETION) { aprint_error_dev(self, "init failed, error=%d\n", r); return; } /* Attach usb device. */ hsc->sc_child = config_found(self, &hsc->sc_bus, usbctlprint); }
static void pq3ehci_attach(device_t parent, device_t self, void *aux) { struct cpunode_softc * const psc = device_private(parent); struct pq3ehci_softc * const sc = device_private(self); struct cpunode_attach_args * const cna = aux; struct cpunode_locators * const cnl = &cna->cna_locs; int error; psc->sc_children |= cna->cna_childmask; sc->sc.iot = cna->cna_le_memt; /* EHCI registers are little endian */ sc->sc.sc_dev = self; sc->sc.sc_bus.ub_dmatag = cna->cna_dmat; sc->sc.sc_bus.ub_hcpriv = sc; sc->sc.sc_bus.ub_revision = USBREV_2_0; sc->sc.sc_ncomp = 0; sc->sc.sc_flags |= EHCIF_ETTF; sc->sc.sc_vendor_init = pq3ehci_init; aprint_naive(": USB controller\n"); aprint_normal(": USB controller\n"); error = bus_space_map(sc->sc.iot, cnl->cnl_addr, cnl->cnl_size, 0, &sc->sc.ioh); if (error) { aprint_error_dev(self, "can't map registers for %s#%u: %d\n", cnl->cnl_name, cnl->cnl_instance, error); return; } sc->sc.sc_size = cnl->cnl_size; /* * We need to tell the USB interface to snoop all off RAM starting * at 0. Since it can do it by powers of 2, get the highest RAM * address and roughly round it to the next power of 2 and find * the number of leading zero bits. */ cpu_write_4(cnl->cnl_addr + USB_SNOOP1, SNOOP_2GB - __builtin_clz(curcpu()->ci_softc->cpu_highmem * 2 - 1)); cpu_write_4(cnl->cnl_addr + USB_CONTROL, USB_EN); sc->sc_ih = intr_establish(cnl->cnl_intrs[0], IPL_USB, IST_ONCHIP, ehci_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(self, "failed to establish interrupt %d\n", cnl->cnl_intrs[0]); goto fail; } aprint_normal_dev(self, "interrupting on irq %d\n", cnl->cnl_intrs[0]); /* offs is needed for EOWRITEx */ sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH); /* Disable interrupts, so we don't get any spurious ones. */ DPRINTF(("%s: offs=%d\n", device_xname(self), sc->sc.sc_offs)); EOWRITE4(&sc->sc, EHCI_USBINTR, 0); error = ehci_init(&sc->sc); if (error) { aprint_error_dev(self, "init failed, error=%d\n", error); goto fail; } /* Attach usb device. */ sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint); return; fail: if (sc->sc_ih) { intr_disestablish(sc->sc_ih); sc->sc_ih = NULL; } if (sc->sc.sc_size) { bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); sc->sc.sc_size = 0; } return; }
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); }