static int err_intr(void *arg) { ehci_softc_t *sc = arg; unsigned int cause; cause = EREAD4(sc, USB_BRIDGE_INTR_CAUSE); if (cause) { printf("USB error: "); if (cause & MV_USB_ADDR_DECODE_ERR) { uint32_t addr; addr = EREAD4(sc, USB_BRIDGE_ERR_ADDR); printf("address decoding error (addr=%#x)\n", addr); } if (cause & MV_USB_HOST_UNDERFLOW) printf("host underflow\n"); if (cause & MV_USB_HOST_OVERFLOW) printf("host overflow\n"); if (cause & MV_USB_DEVICE_UNDERFLOW) printf("device underflow\n"); if (cause & ~(MV_USB_ADDR_DECODE_ERR | MV_USB_HOST_UNDERFLOW | MV_USB_HOST_OVERFLOW | MV_USB_DEVICE_UNDERFLOW)) printf("unknown cause (cause=%#x)\n", cause); EWRITE4(sc, USB_BRIDGE_INTR_CAUSE, 0); } return (FILTER_HANDLED); }
void eap1371_set_dac_rate(struct eap_softc *sc, int rate, int which) { int dac = which == 1 ? ESRC_DAC1 : ESRC_DAC2; int freq, r; int s; /* Whatever, it works, so I'll leave it :) */ if (rate > 48000) rate = 48000; if (rate < 4000) rate = 4000; freq = ((rate << 15) + 1500) / 3000; s = splaudio(); eap1371_src_wait(sc); r = EREAD4(sc, E1371_SRC) & (E1371_SRC_DISABLE | E1371_SRC_DISP2 | E1371_SRC_DISP1 | E1371_SRC_DISREC); r |= (which == 1) ? E1371_SRC_DISP1 : E1371_SRC_DISP2; EWRITE4(sc, E1371_SRC, r); r = eap1371_src_read(sc, dac + ESRC_IREGS) & 0x00ff; eap1371_src_write(sc, dac + ESRC_IREGS, r | ((freq >> 5) & 0xfc00)); eap1371_src_write(sc, dac + ESRC_VFF, freq & 0x7fff); r = EREAD4(sc, E1371_SRC) & (E1371_SRC_DISABLE | E1371_SRC_DISP2 | E1371_SRC_DISP1 | E1371_SRC_DISREC); r &= ~(which == 1 ? E1371_SRC_DISP1 : E1371_SRC_DISP2); EWRITE4(sc, E1371_SRC, r); splx(s); }
int eap1371_read_codec(void *sc_, u_int8_t a, u_int16_t *d) { struct eap_softc *sc = sc_; int to; u_int32_t t; eap1371_ready_codec(sc, a, E1371_SET_CODEC(a, 0) | E1371_CODEC_READ); for (to = 0; to < EAP_WRITE_TIMEOUT; to++) { if (!(EREAD4(sc, E1371_CODEC) & E1371_CODEC_WIP)) break; delay(1); } if (to == EAP_WRITE_TIMEOUT) printf("%s: eap1371_read_codec timeout 1\n", sc->sc_dev.dv_xname); for (to = 0; to < EAP_WRITE_TIMEOUT; to++) { t = EREAD4(sc, E1371_CODEC); if (t & E1371_CODEC_VALID) break; delay(1); } if (to == EAP_WRITE_TIMEOUT) printf("%s: eap1371_read_codec timeout 2\n", sc->sc_dev.dv_xname); *d = (u_int16_t)t; DPRINTFN(10, ("eap1371: reading codec (%x) = %x\n", a, *d)); return (0); }
static void ehci_pci_takecontroller(device_t self) { ehci_softc_t *sc = device_get_softc(self); u_int32_t cparams, eec; uint8_t bios_sem; int eecp, i; cparams = EREAD4(sc, EHCI_HCCPARAMS); /* Synchronise with the BIOS if it owns the controller. */ for (eecp = EHCI_HCC_EECP(cparams); eecp != 0; eecp = EHCI_EECP_NEXT(eec)) { eec = pci_read_config(self, eecp, 4); if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP) continue; bios_sem = pci_read_config(self, eecp + EHCI_LEGSUP_BIOS_SEM, 1); if (bios_sem) { pci_write_config(self, eecp + EHCI_LEGSUP_OS_SEM, 1, 1); printf("%s: waiting for BIOS to give up control\n", device_get_nameunit(sc->sc_bus.bdev)); for (i = 0; i < 5000; i++) { bios_sem = pci_read_config(self, eecp + EHCI_LEGSUP_BIOS_SEM, 1); if (bios_sem == 0) break; DELAY(1000); } if (bios_sem) printf("%s: timed out waiting for BIOS\n", device_get_nameunit(sc->sc_bus.bdev)); } } }
void ehci_pci_takecontroller(struct ehci_pci_softc *sc, int silent) { u_int32_t cparams, eec, legsup; int eecp, i; cparams = EREAD4(&sc->sc, EHCI_HCCPARAMS); /* Synchronise with the BIOS if it owns the controller. */ for (eecp = EHCI_HCC_EECP(cparams); eecp != 0; eecp = EHCI_EECP_NEXT(eec)) { eec = pci_conf_read(sc->sc_pc, sc->sc_tag, eecp); if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP) continue; legsup = eec; if (legsup & EHCI_LEGSUP_BIOSOWNED) { pci_conf_write(sc->sc_pc, sc->sc_tag, eecp, legsup | EHCI_LEGSUP_OSOWNED); DPRINTF(("%s: waiting for BIOS to give up control\n", sc->sc.sc_bus.bdev.dv_xname)); for (i = 0; i < 5000; i++) { legsup = pci_conf_read(sc->sc_pc, sc->sc_tag, eecp); if ((legsup & EHCI_LEGSUP_BIOSOWNED) == 0) break; DELAY(1000); } if (silent == 0 && (legsup & EHCI_LEGSUP_BIOSOWNED)) printf("%s: timed out waiting for BIOS\n", sc->sc.sc_bus.bdev.dv_xname); } } }
static __inline void eap1371_ready_codec(struct eap_softc *sc, u_int8_t a, u_int32_t wd) { int to, s; u_int32_t src, t; for (to = 0; to < EAP_WRITE_TIMEOUT; to++) { if (!(EREAD4(sc, E1371_CODEC) & E1371_CODEC_WIP)) break; delay(1); } if (to == EAP_WRITE_TIMEOUT) printf("%s: eap1371_ready_codec timeout 1\n", sc->sc_dev.dv_xname); s = splaudio(); src = eap1371_src_wait(sc) & E1371_SRC_CTLMASK; EWRITE4(sc, E1371_SRC, src | E1371_SRC_STATE_OK); for (to = 0; to < EAP_READ_TIMEOUT; to++) { t = EREAD4(sc, E1371_SRC); if ((t & E1371_SRC_STATE_MASK) == 0) break; delay(1); } if (to == EAP_READ_TIMEOUT) printf("%s: eap1371_ready_codec timeout 2\n", sc->sc_dev.dv_xname); for (to = 0; to < EAP_READ_TIMEOUT; to++) { t = EREAD4(sc, E1371_SRC); if ((t & E1371_SRC_STATE_MASK) == E1371_SRC_STATE_OK) break; delay(1); } if (to == EAP_READ_TIMEOUT) printf("%s: eap1371_ready_codec timeout 3\n", sc->sc_dev.dv_xname); EWRITE4(sc, E1371_CODEC, wd); eap1371_src_wait(sc); EWRITE4(sc, E1371_SRC, src); splx(s); }
int eap_intr(void *p) { struct eap_softc *sc = p; u_int32_t intr, sic; mtx_enter(&audio_lock); intr = EREAD4(sc, EAP_ICSS); if (!(intr & EAP_INTR)) { mtx_leave(&audio_lock); return (0); } sic = EREAD4(sc, EAP_SIC); DPRINTFN(5, ("eap_intr: ICSS=0x%08x, SIC=0x%08x\n", intr, sic)); if (intr & EAP_I_ADC) { #if 0 /* * XXX This is a hack! * The EAP chip sometimes generates the recording interrupt * while it is still transferring the data. To make sure * it has all arrived we busy wait until the count is right. * The transfer we are waiting for is 8 longwords. */ int s, nw, n; EWRITE4(sc, EAP_MEMPAGE, EAP_ADC_PAGE); s = EREAD4(sc, EAP_ADC_CSR); nw = ((s & 0xffff) + 1) >> 2; /* # of words in DMA */ n = 0; while (((EREAD4(sc, EAP_ADC_SIZE) >> 16) + 8) % nw == 0) { delay(10); if (++n > 100) { printf("eapintr: dma fix timeout"); break; } } /* Continue with normal interrupt handling. */ #endif EWRITE4(sc, EAP_SIC, sic & ~EAP_R1_INTR_EN); EWRITE4(sc, EAP_SIC, sic | EAP_R1_INTR_EN); if (sc->sc_rintr) sc->sc_rintr(sc->sc_rarg); }
u_int32_t eap1371_src_wait(struct eap_softc *sc) { int to; u_int32_t src; for (to = 0; to < EAP_READ_TIMEOUT; to++) { src = EREAD4(sc, E1371_SRC); if (!(src & E1371_SRC_RBUSY)) return (src); delay(1); } printf("%s: eap1371_src_wait timeout\n", sc->sc_dev.dv_xname); return (src); }
void eap1371_reset_codec(void *sc_) { struct eap_softc *sc = sc_; u_int32_t icsc; mtx_enter(&audio_lock); icsc = EREAD4(sc, EAP_ICSC); EWRITE4(sc, EAP_ICSC, icsc | E1371_SYNC_RES); delay(20); EWRITE4(sc, EAP_ICSC, icsc & ~E1371_SYNC_RES); delay(1); mtx_leave(&audio_lock); return; }
void ehci_pci_givecontroller(struct ehci_pci_softc *sc) { u_int32_t cparams, eec, legsup; int eecp; cparams = EREAD4(&sc->sc, EHCI_HCCPARAMS); for (eecp = EHCI_HCC_EECP(cparams); eecp != 0; eecp = EHCI_EECP_NEXT(eec)) { eec = pci_conf_read(sc->sc_pc, sc->sc_tag, eecp); if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP) continue; legsup = eec; pci_conf_write(sc->sc_pc, sc->sc_tag, eecp, legsup & ~EHCI_LEGSUP_OSOWNED); } }
void eap1371_reset_codec(void *sc_) { struct eap_softc *sc = sc_; u_int32_t icsc; int s; s = splaudio(); icsc = EREAD4(sc, EAP_ICSC); EWRITE4(sc, EAP_ICSC, icsc | E1371_SYNC_RES); delay(20); EWRITE4(sc, EAP_ICSC, icsc & ~E1371_SYNC_RES); delay(1); splx(s); return; }
void eap1370_write_codec(struct eap_softc *sc, int a, int d) { int icss, to; to = EAP_WRITE_TIMEOUT; do { icss = EREAD4(sc, EAP_ICSS); DPRINTFN(5,("eap: codec %d prog: icss=0x%08x\n", a, icss)); if (!to--) { printf("%s: timeout writing to codec\n", sc->sc_dev.dv_xname); return; } } while (icss & EAP_CWRIP); /* XXX could use CSTAT here */ EWRITE4(sc, EAP_CODEC, EAP_SET_CODEC(a, d)); }
static int ehci_pci_take_controller(device_t self) { ehci_softc_t *sc = device_get_softc(self); uint32_t cparams; uint32_t eec; uint16_t to; uint8_t eecp; uint8_t bios_sem; cparams = EREAD4(sc, EHCI_HCCPARAMS); /* Synchronise with the BIOS if it owns the controller. */ for (eecp = EHCI_HCC_EECP(cparams); eecp != 0; eecp = EHCI_EECP_NEXT(eec)) { eec = pci_read_config(self, eecp, 4); if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP) { continue; } bios_sem = pci_read_config(self, eecp + EHCI_LEGSUP_BIOS_SEM, 1); if (bios_sem == 0) { continue; } device_printf(sc->sc_bus.bdev, "waiting for BIOS " "to give up control\n"); pci_write_config(self, eecp + EHCI_LEGSUP_OS_SEM, 1, 1); to = 500; while (1) { bios_sem = pci_read_config(self, eecp + EHCI_LEGSUP_BIOS_SEM, 1); if (bios_sem == 0) break; if (--to == 0) { device_printf(sc->sc_bus.bdev, "timed out waiting for BIOS\n"); break; } usb_pause_mtx(NULL, hz / 100); /* wait 10ms */ } } return (0); }
static void ehci_pci_givecontroller(device_t self) { #if 0 ehci_softc_t *sc = device_get_softc(self); u_int32_t cparams, eec; int eecp; cparams = EREAD4(sc, EHCI_HCCPARAMS); for (eecp = EHCI_HCC_EECP(cparams); eecp != 0; eecp = EHCI_EECP_NEXT(eec)) { eec = pci_read_config(self, eecp, 4); if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP) continue; pci_write_config(self, eecp + EHCI_LEGSUP_OS_SEM, 0, 1); } #endif }
int eap1371_src_read(struct eap_softc *sc, int a) { int to; u_int32_t src, t; src = eap1371_src_wait(sc) & E1371_SRC_CTLMASK; src |= E1371_SRC_ADDR(a); EWRITE4(sc, E1371_SRC, src | E1371_SRC_STATE_OK); if ((eap1371_src_wait(sc) & E1371_SRC_STATE_MASK) != E1371_SRC_STATE_OK) { for (to = 0; to < EAP_READ_TIMEOUT; to++) { t = EREAD4(sc, E1371_SRC); if ((t & E1371_SRC_STATE_MASK) == E1371_SRC_STATE_OK) break; delay(1); } } EWRITE4(sc, E1371_SRC, src); return t & E1371_SRC_DATAMASK; }
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 = EHCI_SCFLG_SETMODE; 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; 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); }
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 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; }