diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/Kconfig | 4 | ||||
-rw-r--r-- | drivers/usb/host/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/host/dwc2.c | 1132 | ||||
-rw-r--r-- | drivers/usb/host/dwc2.h | 778 | ||||
-rw-r--r-- | drivers/usb/host/ehci-atmel.c | 37 | ||||
-rw-r--r-- | drivers/usb/host/ehci-core.h | 12 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 97 | ||||
-rw-r--r-- | drivers/usb/host/ehci-omap.c | 16 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 13 | ||||
-rw-r--r-- | drivers/usb/host/ohci-at91.c | 33 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hcd.c | 29 | ||||
-rw-r--r-- | drivers/usb/host/ohci.h | 1 | ||||
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 105 | ||||
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 222 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 107 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 34 |
16 files changed, 392 insertions, 2230 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 51697e109e..d38b4dcac4 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only config USB_EHCI bool "EHCI driver" depends on HAS_DMA @@ -21,9 +22,6 @@ config USB_OHCI_AT91 depends on ARCH_AT91 bool "AT91 OHCI driver" -config USB_DWC2_HOST - bool "DWC2 Host driver" - config USB_XHCI bool "xHCI driver" depends on HAS_DMA diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index d417410e90..e55dff4580 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -1,7 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_USB_EHCI) += ehci-hcd.o obj-$(CONFIG_USB_EHCI_OMAP) += ehci-omap.o obj-$(CONFIG_USB_EHCI_ATMEL) += ehci-atmel.o obj-$(CONFIG_USB_OHCI) += ohci-hcd.o obj-$(CONFIG_USB_OHCI_AT91) += ohci-at91.o -obj-$(CONFIG_USB_DWC2_HOST) += dwc2.o obj-$(CONFIG_USB_XHCI) += xhci.o xhci-mem.o xhci-ring.o diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c deleted file mode 100644 index 1df1149686..0000000000 --- a/drivers/usb/host/dwc2.c +++ /dev/null @@ -1,1132 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org> - * Copyright (C) 2014 Marek Vasut <marex@denx.de> - */ - -#include <common.h> -#include <usb/usb.h> -#include <usb/usbroothubdes.h> -#include <malloc.h> -#include <init.h> -#include <io.h> -#include <of.h> -#include <linux/iopoll.h> -#include <dma.h> - -#include "dwc2.h" - -/* Use only HC channel 0. */ -#define DWC2_HC_CHANNEL 0 - -#define DWC2_STATUS_BUF_SIZE 64 -#define DWC2_DATA_BUF_SIZE (16 * 1024) - -#define MAX_DEVICE 16 -#define MAX_ENDPOINT 16 - -struct dwc2_priv { - struct device_d *dev; - struct usb_host host; - uint8_t *dmabuf; - - u8 in_data_toggle[MAX_DEVICE][MAX_ENDPOINT]; - u8 out_data_toggle[MAX_DEVICE][MAX_ENDPOINT]; - struct dwc2_core_regs *regs; - int root_hub_devnum; - bool ext_vbus; - /* - * The hnp/srp capability must be disabled if the platform - * does't support hnp/srp. Otherwise the force mode can't work. - */ - bool hnp_srp_disable; - bool oc_disable; -}; - -/* - * Initializes the FSLSPClkSel field of the HCFG register - * depending on the PHY type. - */ -static void init_fslspclksel(struct dwc2_priv *priv) -{ - struct dwc2_core_regs *regs = priv->regs; - uint32_t phyclk; - - phyclk = DWC2_HCFG_FSLSPCLKSEL_48_MHZ; /* Full speed PHY */ - - clrsetbits_le32(®s->host_regs.hcfg, - DWC2_HCFG_FSLSPCLKSEL_MASK, - phyclk << DWC2_HCFG_FSLSPCLKSEL_OFFSET); -} - -/* - * Flush a Tx FIFO. - * - * @param regs Programming view of DWC_otg controller. - * @param num Tx FIFO to flush. - */ -static void dwc_otg_flush_tx_fifo(struct dwc2_priv *priv, const int num) -{ - struct dwc2_core_regs *regs = priv->regs; - struct device_d *dev = priv->dev; - int ret; - uint32_t val; - - writel(DWC2_GRSTCTL_TXFFLSH | (num << DWC2_GRSTCTL_TXFNUM_OFFSET), - ®s->grstctl); - ret = readl_poll_timeout(®s->grstctl, val, !(val & DWC2_GRSTCTL_TXFFLSH), - 1000000); - if (ret) - dev_err(dev, "%s: Timeout!\n", __func__); - - /* Wait for 3 PHY Clocks */ - udelay(1); -} - -/* - * Flush Rx FIFO. - * - * @param regs Programming view of DWC_otg controller. - */ -static void dwc_otg_flush_rx_fifo(struct dwc2_priv *priv) -{ - struct dwc2_core_regs *regs = priv->regs; - struct device_d *dev = priv->dev; - int ret; - uint32_t val; - - writel(DWC2_GRSTCTL_RXFFLSH, ®s->grstctl); - ret = readl_poll_timeout(®s->grstctl, val, !(val & DWC2_GRSTCTL_RXFFLSH), - 1000000); - if (ret) - dev_err(dev, "%s: Timeout!\n", __func__); - - /* Wait for 3 PHY Clocks */ - udelay(1); -} - -/* - * Do core a soft reset of the core. Be careful with this because it - * resets all the internal state machines of the core. - */ -static void dwc_otg_core_reset(struct dwc2_priv *priv) -{ - struct dwc2_core_regs *regs = priv->regs; - struct device_d *dev = priv->dev; - uint32_t val; - int ret; - - /* Wait for AHB master IDLE state. */ - ret = readl_poll_timeout(®s->grstctl, val, val & DWC2_GRSTCTL_AHBIDLE, - 1000000); - if (ret) - dev_err(dev, "%s: Timeout!\n", __func__); - - /* Core Soft Reset */ - writel(DWC2_GRSTCTL_CSFTRST, ®s->grstctl); - ret = readl_poll_timeout(®s->grstctl, val, !(val & DWC2_GRSTCTL_CSFTRST), - 1000000); - if (ret) - dev_err(dev, "%s: Timeout!\n", __func__); - - /* - * Wait for core to come out of reset. - * NOTE: This long sleep is _very_ important, otherwise the core will - * not stay in host mode after a connector ID change! - */ - mdelay(100); -} - -/* - * This function initializes the DWC_otg controller registers for - * host mode. - * - * This function flushes the Tx and Rx FIFOs and it flushes any entries in the - * request queues. Host channels are reset to ensure that they are ready for - * performing transfers. - * - * @param dev USB Device (NULL if driver model is not being used) - * @param regs Programming view of DWC_otg controller - * - */ -static void dwc_otg_core_host_init(struct dwc2_priv *priv) -{ - struct dwc2_core_regs *regs = priv->regs; - struct device_d *dev = priv->dev; - uint32_t nptxfifosize = 0; - uint32_t ptxfifosize = 0; - uint32_t hprt0 = 0; - uint32_t val; - int i, ret, num_channels; - - /* Restart the Phy Clock */ - writel(0, ®s->pcgcctl); - - /* Initialize Host Configuration Register */ - init_fslspclksel(priv); - - /* Configure data FIFO sizes */ - if (readl(®s->ghwcfg2) & DWC2_HWCFG2_DYNAMIC_FIFO) { - /* Rx FIFO */ - writel(CONFIG_DWC2_HOST_RX_FIFO_SIZE, ®s->grxfsiz); - - /* Non-periodic Tx FIFO */ - nptxfifosize |= CONFIG_DWC2_HOST_NPERIO_TX_FIFO_SIZE << - DWC2_FIFOSIZE_DEPTH_OFFSET; - nptxfifosize |= CONFIG_DWC2_HOST_RX_FIFO_SIZE << - DWC2_FIFOSIZE_STARTADDR_OFFSET; - writel(nptxfifosize, ®s->gnptxfsiz); - - /* Periodic Tx FIFO */ - ptxfifosize |= CONFIG_DWC2_HOST_PERIO_TX_FIFO_SIZE << - DWC2_FIFOSIZE_DEPTH_OFFSET; - ptxfifosize |= (CONFIG_DWC2_HOST_RX_FIFO_SIZE + - CONFIG_DWC2_HOST_NPERIO_TX_FIFO_SIZE) << - DWC2_FIFOSIZE_STARTADDR_OFFSET; - writel(ptxfifosize, ®s->hptxfsiz); - } - - /* Clear Host Set HNP Enable in the OTG Control Register */ - clrbits_le32(®s->gotgctl, DWC2_GOTGCTL_HSTSETHNPEN); - - /* Make sure the FIFOs are flushed. */ - dwc_otg_flush_tx_fifo(priv, 0x10); /* All Tx FIFOs */ - dwc_otg_flush_rx_fifo(priv); - - /* Flush out any leftover queued requests. */ - num_channels = readl(®s->ghwcfg2); - num_channels &= DWC2_HWCFG2_NUM_HOST_CHAN_MASK; - num_channels >>= DWC2_HWCFG2_NUM_HOST_CHAN_OFFSET; - num_channels += 1; - - for (i = 0; i < num_channels; i++) - clrsetbits_le32(®s->hc_regs[i].hcchar, - DWC2_HCCHAR_CHEN | DWC2_HCCHAR_EPDIR, - DWC2_HCCHAR_CHDIS); - - /* Halt all channels to put them into a known state. */ - for (i = 0; i < num_channels; i++) { - clrsetbits_le32(®s->hc_regs[i].hcchar, - DWC2_HCCHAR_EPDIR, - DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS); - ret = readl_poll_timeout(®s->hc_regs[i].hcchar, val, - !(val & DWC2_HCCHAR_CHEN), - 1000000); - if (ret) - dev_err(dev, "%s: Timeout!\n", __func__); - } - - /* Turn on the vbus power. */ - if (readl(®s->gintsts) & DWC2_GINTSTS_CURMODE_HOST) { - hprt0 = readl(®s->hprt0); - hprt0 &= ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET); - hprt0 &= ~(DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG); - if (!(hprt0 & DWC2_HPRT0_PRTPWR)) { - hprt0 |= DWC2_HPRT0_PRTPWR; - writel(hprt0, ®s->hprt0); - } - } -} - -/* - * This function initializes the DWC_otg controller registers and - * prepares the core for device mode or host mode operation. - * - * @param regs Programming view of the DWC_otg controller - */ -static void dwc_otg_core_init(struct dwc2_priv *priv) -{ - struct dwc2_core_regs *regs = priv->regs; - uint32_t ahbcfg = 0; - uint32_t usbcfg = 0; - uint8_t brst_sz = 32; - - /* Common Initialization */ - usbcfg = readl(®s->gusbcfg); - - /* Program the ULPI External VBUS bit if needed */ - if (priv->ext_vbus) { - usbcfg |= DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV; - if (!priv->oc_disable) { - usbcfg |= DWC2_GUSBCFG_ULPI_INT_VBUS_INDICATOR | - DWC2_GUSBCFG_INDICATOR_PASSTHROUGH; - } - } else { - usbcfg &= ~DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV; - } - - /* Set external TS Dline pulsing */ - usbcfg &= ~DWC2_GUSBCFG_TERM_SEL_DL_PULSE; - writel(usbcfg, ®s->gusbcfg); - - /* Reset the Controller */ - dwc_otg_core_reset(priv); - - /* High speed PHY. */ - - /* - * HS PHY parameters. These parameters are preserved during - * soft reset so only program the first time. Do a soft reset - * immediately after setting phyif. - */ - usbcfg &= ~(DWC2_GUSBCFG_ULPI_UTMI_SEL | DWC2_GUSBCFG_PHYIF); - usbcfg |= CONFIG_DWC2_PHY_TYPE << DWC2_GUSBCFG_ULPI_UTMI_SEL_OFFSET; - - if (usbcfg & DWC2_GUSBCFG_ULPI_UTMI_SEL) /* ULPI interface */ - usbcfg &= ~DWC2_GUSBCFG_DDRSEL; - - writel(usbcfg, ®s->gusbcfg); - - /* Reset after setting the PHY parameters */ - dwc_otg_core_reset(priv); - - usbcfg = readl(®s->gusbcfg); - usbcfg &= ~(DWC2_GUSBCFG_ULPI_FSLS | DWC2_GUSBCFG_ULPI_CLK_SUS_M); - - if (priv->hnp_srp_disable) - usbcfg |= DWC2_GUSBCFG_FORCEHOSTMODE; - - writel(usbcfg, ®s->gusbcfg); - - /* Program the GAHBCFG Register. */ - switch (readl(®s->ghwcfg2) & DWC2_HWCFG2_ARCHITECTURE_MASK) { - case DWC2_HWCFG2_ARCHITECTURE_SLAVE_ONLY: - break; - case DWC2_HWCFG2_ARCHITECTURE_EXT_DMA: - while (brst_sz > 1) { - ahbcfg |= ahbcfg + (1 << DWC2_GAHBCFG_HBURSTLEN_OFFSET); - ahbcfg &= DWC2_GAHBCFG_HBURSTLEN_MASK; - brst_sz >>= 1; - } - - ahbcfg |= DWC2_GAHBCFG_DMAENABLE; - break; - - case DWC2_HWCFG2_ARCHITECTURE_INT_DMA: - ahbcfg |= DWC2_GAHBCFG_HBURSTLEN_INCR4; - ahbcfg |= DWC2_GAHBCFG_DMAENABLE; - break; - } - - writel(ahbcfg, ®s->gahbcfg); - - /* Program the capabilities in GUSBCFG Register */ - usbcfg = 0; - - if (!priv->hnp_srp_disable) - usbcfg |= DWC2_GUSBCFG_HNPCAP | DWC2_GUSBCFG_SRPCAP; - - setbits_le32(®s->gusbcfg, usbcfg); -} - -/* - * Prepares a host channel for transferring packets to/from a specific - * endpoint. The HCCHARn register is set up with the characteristics specified - * in _hc. Host channel interrupts that may need to be serviced while this - * transfer is in progress are enabled. - * - * @param regs Programming view of DWC_otg controller - * @param hc Information needed to initialize the host channel - */ -static void dwc_otg_hc_init(struct dwc2_core_regs *regs, uint8_t hc_num, - struct usb_device *dev, uint8_t dev_addr, uint8_t ep_num, - uint8_t ep_is_in, uint8_t ep_type, uint16_t max_packet) -{ - struct dwc2_hc_regs *hc_regs = ®s->hc_regs[hc_num]; - uint32_t hcchar = (dev_addr << DWC2_HCCHAR_DEVADDR_OFFSET) | - (ep_num << DWC2_HCCHAR_EPNUM_OFFSET) | - (ep_is_in << DWC2_HCCHAR_EPDIR_OFFSET) | - (ep_type << DWC2_HCCHAR_EPTYPE_OFFSET) | - (max_packet << DWC2_HCCHAR_MPS_OFFSET); - - if (dev->speed == USB_SPEED_LOW) - hcchar |= DWC2_HCCHAR_LSPDDEV; - - /* - * Program the HCCHARn register with the endpoint characteristics - * for the current transfer. - */ - writel(hcchar, &hc_regs->hcchar); - - /* Program the HCSPLIT register, default to no SPLIT */ - writel(0, &hc_regs->hcsplt); -} - -static void dwc_otg_hc_init_split(struct dwc2_hc_regs *hc_regs, - uint8_t hub_devnum, uint8_t hub_port) -{ - uint32_t hcsplt = 0; - - hcsplt = DWC2_HCSPLT_SPLTENA; - hcsplt |= hub_devnum << DWC2_HCSPLT_HUBADDR_OFFSET; - hcsplt |= hub_port << DWC2_HCSPLT_PRTADDR_OFFSET; - - /* Program the HCSPLIT register for SPLITs */ - writel(hcsplt, &hc_regs->hcsplt); -} - -/* - * DWC2 to USB API interface - */ -/* Direction: In ; Request: Status */ -static int dwc_otg_submit_rh_msg_in_status(struct dwc2_core_regs *regs, - struct usb_device *dev, void *buffer, - int txlen, struct devrequest *cmd) -{ - uint32_t hprt0 = 0; - uint32_t port_status = 0; - uint32_t port_change = 0; - int len = 0; - int stat = 0; - - switch (cmd->requesttype & ~USB_DIR_IN) { - case 0: - *(uint16_t *)buffer = cpu_to_le16(1); - len = 2; - break; - case USB_RECIP_INTERFACE: - case USB_RECIP_ENDPOINT: - *(uint16_t *)buffer = cpu_to_le16(0); - len = 2; - break; - case USB_TYPE_CLASS: - *(uint32_t *)buffer = cpu_to_le32(0); - len = 4; - break; - case USB_RECIP_OTHER | USB_TYPE_CLASS: - hprt0 = readl(®s->hprt0); - if (hprt0 & DWC2_HPRT0_PRTCONNSTS) - port_status |= USB_PORT_STAT_CONNECTION; - if (hprt0 & DWC2_HPRT0_PRTENA) - port_status |= USB_PORT_STAT_ENABLE; - if (hprt0 & DWC2_HPRT0_PRTSUSP) - port_status |= USB_PORT_STAT_SUSPEND; - if (hprt0 & DWC2_HPRT0_PRTOVRCURRACT) - port_status |= USB_PORT_STAT_OVERCURRENT; - if (hprt0 & DWC2_HPRT0_PRTRST) - port_status |= USB_PORT_STAT_RESET; - if (hprt0 & DWC2_HPRT0_PRTPWR) - port_status |= USB_PORT_STAT_POWER; - - if ((hprt0 & DWC2_HPRT0_PRTSPD_MASK) == DWC2_HPRT0_PRTSPD_LOW) - port_status |= USB_PORT_STAT_LOW_SPEED; - else if ((hprt0 & DWC2_HPRT0_PRTSPD_MASK) == - DWC2_HPRT0_PRTSPD_HIGH) - port_status |= USB_PORT_STAT_HIGH_SPEED; - - if (hprt0 & DWC2_HPRT0_PRTENCHNG) - port_change |= USB_PORT_STAT_C_ENABLE; - if (hprt0 & DWC2_HPRT0_PRTCONNDET) - port_change |= USB_PORT_STAT_C_CONNECTION; - if (hprt0 & DWC2_HPRT0_PRTOVRCURRCHNG) - port_change |= USB_PORT_STAT_C_OVERCURRENT; - - *(uint32_t *)buffer = cpu_to_le32(port_status | - (port_change << 16)); - len = 4; - break; - default: - pr_err("%s: unsupported root hub command\n", __func__); - stat = USB_ST_STALLED; - } - - dev->act_len = min(len, txlen); - dev->status = stat; - - return stat; -} - -/* Direction: In ; Request: Descriptor */ -static int dwc_otg_submit_rh_msg_in_descriptor(struct usb_device *dev, - void *buffer, int txlen, - struct devrequest *cmd) -{ - unsigned char data[32]; - uint32_t dsc; - int len = 0; - int stat = 0; - uint16_t wValue = cpu_to_le16(cmd->value); - uint16_t wLength = cpu_to_le16(cmd->length); - - switch (cmd->requesttype & ~USB_DIR_IN) { - case 0: - switch (wValue & 0xff00) { - case 0x0100: /* device descriptor */ - len = min3(txlen, (int)sizeof(root_hub_dev_des), (int)wLength); - memcpy(buffer, root_hub_dev_des, len); - break; - case 0x0200: /* configuration descriptor */ - len = min3(txlen, (int)sizeof(root_hub_config_des), (int)wLength); - memcpy(buffer, root_hub_config_des, len); - break; - case 0x0300: /* string descriptors */ - switch (wValue & 0xff) { - case 0x00: - len = min3(txlen, (int)sizeof(root_hub_str_index0), - (int)wLength); - memcpy(buffer, root_hub_str_index0, len); - break; - case 0x01: - len = min3(txlen, (int)sizeof(root_hub_str_index1), - (int)wLength); - memcpy(buffer, root_hub_str_index1, len); - break; - } - break; - default: - stat = USB_ST_STALLED; - } - break; - - case USB_TYPE_CLASS: - /* Root port config, set 1 port and nothing else. */ - dsc = 0x00000001; - - data[0] = 9; /* min length; */ - data[1] = 0x29; - data[2] = dsc & RH_A_NDP; - data[3] = 0; - if (dsc & RH_A_PSM) - data[3] |= 0x1; - if (dsc & RH_A_NOCP) - data[3] |= 0x10; - else if (dsc & RH_A_OCPM) - data[3] |= 0x8; - - /* corresponds to data[4-7] */ - data[5] = (dsc & RH_A_POTPGT) >> 24; - data[7] = dsc & RH_B_DR; - if (data[2] < 7) { - data[8] = 0xff; - } else { - data[0] += 2; - data[8] = (dsc & RH_B_DR) >> 8; - data[9] = 0xff; - data[10] = data[9]; - } - - len = min3(txlen, (int)data[0], (int)wLength); - memcpy(buffer, data, len); - break; - default: - pr_err("%s: unsupported root hub command\n", __func__); - stat = USB_ST_STALLED; - } - - dev->act_len = min(len, txlen); - dev->status = stat; - - return stat; -} - -/* Direction: In ; Request: Configuration */ -static int dwc_otg_submit_rh_msg_in_configuration(struct usb_device *dev, - void *buffer, int txlen, - struct devrequest *cmd) -{ - int len = 0; - int stat = 0; - - switch (cmd->requesttype & ~USB_DIR_IN) { - case 0: - *(uint8_t *)buffer = 0x01; - len = 1; - break; - default: - pr_err("%s: unsupported root hub command\n", __func__); - stat = USB_ST_STALLED; - } - - dev->act_len = min(len, txlen); - dev->status = stat; - - return stat; -} - -/* Direction: In */ -static int dwc_otg_submit_rh_msg_in(struct dwc2_priv *priv, - struct usb_device *dev, void *buffer, - int txlen, struct devrequest *cmd) -{ - switch (cmd->request) { - case USB_REQ_GET_STATUS: - return dwc_otg_submit_rh_msg_in_status(priv->regs, dev, buffer, - txlen, cmd); - case USB_REQ_GET_DESCRIPTOR: - return dwc_otg_submit_rh_msg_in_descriptor(dev, buffer, - txlen, cmd); - case USB_REQ_GET_CONFIGURATION: - return dwc_otg_submit_rh_msg_in_configuration(dev, buffer, - txlen, cmd); - default: - pr_err("%s: unsupported root hub command\n", __func__); - return USB_ST_STALLED; - } -} - -/* Direction: Out */ -static int dwc_otg_submit_rh_msg_out(struct dwc2_priv *priv, - struct usb_device *dev, - void *buffer, int txlen, - struct devrequest *cmd) -{ - struct dwc2_core_regs *regs = priv->regs; - int len = 0; - int stat = 0; - uint16_t bmrtype_breq = cmd->requesttype | (cmd->request << 8); - uint16_t wValue = cpu_to_le16(cmd->value); - - switch (bmrtype_breq & ~USB_DIR_IN) { - case (USB_REQ_CLEAR_FEATURE << 8) | USB_RECIP_ENDPOINT: - case (USB_REQ_CLEAR_FEATURE << 8) | USB_TYPE_CLASS: - break; - - case (USB_REQ_CLEAR_FEATURE << 8) | USB_RECIP_OTHER | USB_TYPE_CLASS: - switch (wValue) { - case USB_PORT_FEAT_C_CONNECTION: - setbits_le32(®s->hprt0, DWC2_HPRT0_PRTCONNDET); - break; - } - break; - - case (USB_REQ_SET_FEATURE << 8) | USB_RECIP_OTHER | USB_TYPE_CLASS: - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - break; - - case USB_PORT_FEAT_RESET: - clrsetbits_le32(®s->hprt0, DWC2_HPRT0_PRTENA | - DWC2_HPRT0_PRTCONNDET | - DWC2_HPRT0_PRTENCHNG | - DWC2_HPRT0_PRTOVRCURRCHNG, - DWC2_HPRT0_PRTRST); - mdelay(50); - clrbits_le32(®s->hprt0, DWC2_HPRT0_PRTRST); - break; - - case USB_PORT_FEAT_POWER: - clrsetbits_le32(®s->hprt0, DWC2_HPRT0_PRTENA | - DWC2_HPRT0_PRTCONNDET | - DWC2_HPRT0_PRTENCHNG | - DWC2_HPRT0_PRTOVRCURRCHNG, - DWC2_HPRT0_PRTRST); - break; - - case USB_PORT_FEAT_ENABLE: - break; - } - break; - case (USB_REQ_SET_ADDRESS << 8): - priv->root_hub_devnum = wValue; - break; - case (USB_REQ_SET_CONFIGURATION << 8): - break; - default: - pr_err("%s: unsupported root hub command\n", __func__); - stat = USB_ST_STALLED; - } - - len = min(len, txlen); - - dev->act_len = len; - dev->status = stat; - - return stat; -} - -static int dwc_otg_submit_rh_msg(struct dwc2_priv *priv, struct usb_device *dev, - unsigned long pipe, void *buffer, int txlen, - struct devrequest *cmd) -{ - int stat = 0; - - if (usb_pipeint(pipe)) { - pr_err("Root-Hub submit IRQ: NOT implemented\n"); - return 0; - } - - if (cmd->requesttype & USB_DIR_IN) - stat = dwc_otg_submit_rh_msg_in(priv, dev, buffer, txlen, cmd); - else - stat = dwc_otg_submit_rh_msg_out(priv, dev, buffer, txlen, cmd); - - mdelay(1); - - return stat; -} - -static int wait_for_chhltd(struct dwc2_priv *priv, uint32_t *sub, - u8 *toggle, int timeout_ms) -{ - struct dwc2_core_regs *regs = priv->regs; - struct dwc2_hc_regs *hc_regs = ®s->hc_regs[DWC2_HC_CHANNEL]; - struct device_d *dev = priv->dev; - int ret; - uint32_t hcint, hctsiz; - uint32_t val; - int timeout_us = timeout_ms * 1000; - - ret = readl_poll_timeout(&hc_regs->hcint, val, - val & DWC2_HCINT_CHHLTD, timeout_us); - if (ret) { - clrsetbits_le32(&hc_regs->hcchar, 0, DWC2_HCCHAR_CHDIS); - readl_poll_timeout(&hc_regs->hcint, val, - val & DWC2_HCINT_CHHLTD, 10000); - - return ret; - } - - hcint = readl(&hc_regs->hcint); - hctsiz = readl(&hc_regs->hctsiz); - *sub = (hctsiz & DWC2_HCTSIZ_XFERSIZE_MASK) >> - DWC2_HCTSIZ_XFERSIZE_OFFSET; - *toggle = (hctsiz & DWC2_HCTSIZ_PID_MASK) >> DWC2_HCTSIZ_PID_OFFSET; - - dev_dbg(dev, "%s: HCINT=%08x sub=%u toggle=%d\n", __func__, hcint, *sub, - *toggle); - - if (hcint & DWC2_HCINT_XFERCOMP) - return 0; - - if (hcint & (DWC2_HCINT_NAK | DWC2_HCINT_FRMOVRUN)) - return -EAGAIN; - - dev_dbg(dev, "%s: Error (HCINT=%08x)\n", __func__, hcint); - - return -EINVAL; -} - -static int dwc2_eptype[] = { - DWC2_HCCHAR_EPTYPE_ISOC, - DWC2_HCCHAR_EPTYPE_INTR, - DWC2_HCCHAR_EPTYPE_CONTROL, - DWC2_HCCHAR_EPTYPE_BULK, -}; - -static int transfer_chunk(struct dwc2_priv *priv, u8 *pid, int in, void *buffer, - int num_packets, int xfer_len, int *actual_len, - int odd_frame, int timeout_ms) -{ - struct dwc2_core_regs *regs = priv->regs; - struct dwc2_hc_regs *hc_regs = ®s->hc_regs[DWC2_HC_CHANNEL]; - int ret = 0; - uint32_t sub = 0; - enum dma_data_direction dir; - dma_addr_t dma = 0; - - dev_dbg(priv->dev, "%s: chunk: pid %d xfer_len %u pkts %u\n", - __func__, *pid, xfer_len, num_packets); - - writel((xfer_len << DWC2_HCTSIZ_XFERSIZE_OFFSET) | - (num_packets << DWC2_HCTSIZ_PKTCNT_OFFSET) | - (*pid << DWC2_HCTSIZ_PID_OFFSET), - &hc_regs->hctsiz); - - if (xfer_len) { - if (in) { - dir = DMA_FROM_DEVICE; - } else { - memcpy(priv->dmabuf, buffer, xfer_len); - dir = DMA_TO_DEVICE; - } - dma = dma_map_single(priv->dev, priv->dmabuf, xfer_len, dir); - } - - writel(dma, &hc_regs->hcdma); - - /* Clear old interrupt conditions for this host channel. */ - writel(0x3fff, &hc_regs->hcint); - - /* Set host channel enable after all other setup is complete. */ - clrsetbits_le32(&hc_regs->hcchar, DWC2_HCCHAR_MULTICNT_MASK | - DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS | - DWC2_HCCHAR_ODDFRM, - (1 << DWC2_HCCHAR_MULTICNT_OFFSET) | - (odd_frame << DWC2_HCCHAR_ODDFRM_OFFSET) | - DWC2_HCCHAR_CHEN); - - ret = wait_for_chhltd(priv, &sub, pid, timeout_ms); - - if (xfer_len) - dma_unmap_single(priv->dev, dma, xfer_len, dir); - - if (in) { - xfer_len -= sub; - - memcpy(buffer, priv->dmabuf, xfer_len); - } - - if (!ret) - *actual_len = xfer_len; - - return ret; -} - -static int usb_find_usb2_hub_address_port(struct usb_device *udev, - uint8_t *hub_address, uint8_t *hub_port) -{ - /* Find out the nearest parent which is high speed */ - while (udev->parent->parent) { - if (udev->parent->speed != USB_SPEED_HIGH) { - udev = udev->parent; - } else { - *hub_address = udev->parent->devnum; - *hub_port = udev->portnr; - return 0; - } - } - - return -EINVAL; -} - -static int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev, - unsigned long pipe, u8 *pid, int in, void *buffer, int len, - int timeout_ms) -{ - struct dwc2_core_regs *regs = priv->regs; - struct dwc2_hc_regs *hc_regs = ®s->hc_regs[DWC2_HC_CHANNEL]; - struct dwc2_host_regs *host_regs = ®s->host_regs; - int devnum = usb_pipedevice(pipe); - int ep = usb_pipeendpoint(pipe); - int max = usb_maxpacket(dev, pipe); - int eptype = dwc2_eptype[usb_pipetype(pipe)]; - int done = 0; - int ret = 0; - int do_split = 0; - int complete_split = 0; - uint32_t xfer_len; - uint32_t num_packets; - int stop_transfer = 0; - uint32_t max_xfer_len; - int ssplit_frame_num = 0; - - dev_dbg(priv->dev, "%s: msg: pipe %lx pid %d in %d len %d\n", - __func__, pipe, *pid, in, len); - - max_xfer_len = CONFIG_DWC2_MAX_PACKET_COUNT * max; - if (max_xfer_len > CONFIG_DWC2_MAX_TRANSFER_SIZE) - max_xfer_len = CONFIG_DWC2_MAX_TRANSFER_SIZE; - if (max_xfer_len > DWC2_DATA_BUF_SIZE) - max_xfer_len = DWC2_DATA_BUF_SIZE; - - /* Make sure that max_xfer_len is a multiple of max packet size. */ - num_packets = max_xfer_len / max; - max_xfer_len = num_packets * max; - - /* Initialize channel */ - dwc_otg_hc_init(regs, DWC2_HC_CHANNEL, dev, devnum, ep, in, - eptype, max); - - /* Check if the target is a FS/LS device behind a HS hub */ - if (dev->speed != USB_SPEED_HIGH) { - uint8_t hub_addr; - uint8_t hub_port; - uint32_t hprt0 = readl(®s->hprt0); - - if ((hprt0 & DWC2_HPRT0_PRTSPD_MASK) == DWC2_HPRT0_PRTSPD_HIGH) { - ret = usb_find_usb2_hub_address_port(dev, &hub_addr, - &hub_port); - if (ret) - return ret; - dwc_otg_hc_init_split(hc_regs, hub_addr, hub_port); - - do_split = 1; - num_packets = 1; - max_xfer_len = max; - } - } - - do { - int actual_len = 0; - uint32_t hcint; - int odd_frame = 0; - xfer_len = len - done; - - if (xfer_len > max_xfer_len) - xfer_len = max_xfer_len; - else if (xfer_len > max) - num_packets = (xfer_len + max - 1) / max; - else - num_packets = 1; - - if (complete_split) - setbits_le32(&hc_regs->hcsplt, DWC2_HCSPLT_COMPSPLT); - else if (do_split) - clrbits_le32(&hc_regs->hcsplt, DWC2_HCSPLT_COMPSPLT); - - if (eptype == DWC2_HCCHAR_EPTYPE_INTR) { - int uframe_num = readl(&host_regs->hfnum); - if (!(uframe_num & 0x1)) - odd_frame = 1; - } - - ret = transfer_chunk(priv, pid, in, (char *)buffer + done, - num_packets, xfer_len, &actual_len, - odd_frame, timeout_ms); - - hcint = readl(&hc_regs->hcint); - if (complete_split) { - stop_transfer = 0; - if (hcint & DWC2_HCINT_NYET) { - int frame_num = DWC2_HFNUM_MAX_FRNUM & - readl(&host_regs->hfnum); - ret = 0; - if (((frame_num - ssplit_frame_num) & - DWC2_HFNUM_MAX_FRNUM) > 4) - ret = -EAGAIN; - } else - complete_split = 0; - } else if (do_split) { - if (hcint & DWC2_HCINT_ACK) { - ssplit_frame_num = DWC2_HFNUM_MAX_FRNUM & - readl(&host_regs->hfnum); - ret = 0; - complete_split = 1; - } - } - - if (ret) - break; - - if (actual_len < xfer_len) - stop_transfer = 1; - - done += actual_len; - - /* - * Transactions are done when when either all data is transferred or - * there is a short transfer. In case of a SPLIT make sure the CSPLIT - * is executed. - */ - } while (((done < len) && !stop_transfer) || complete_split); - - writel(0, &hc_regs->hcintmsk); - writel(0xFFFFFFFF, &hc_regs->hcint); - - dev->status = 0; - dev->act_len = done; - - return ret; -} - -#define to_dwc2(ptr) container_of(ptr, struct dwc2_priv, host) - -static int dwc2_init_common(struct usb_host *host) -{ - struct dwc2_priv *priv = to_dwc2(host); - struct dwc2_core_regs *regs = priv->regs; - int i, j; - - priv->ext_vbus = 0; - - dwc_otg_core_init(priv); - dwc_otg_core_host_init(priv); - - clrsetbits_le32(®s->hprt0, DWC2_HPRT0_PRTENA | - DWC2_HPRT0_PRTCONNDET | DWC2_HPRT0_PRTENCHNG | - DWC2_HPRT0_PRTOVRCURRCHNG, - DWC2_HPRT0_PRTRST); - mdelay(50); - clrbits_le32(®s->hprt0, DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | - DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG | - DWC2_HPRT0_PRTRST); - - for (i = 0; i < MAX_DEVICE; i++) { - for (j = 0; j < MAX_ENDPOINT; j++) { - priv->in_data_toggle[i][j] = DWC2_HC_PID_DATA0; - priv->out_data_toggle[i][j] = DWC2_HC_PID_DATA0; - } - } - - return 0; -} - -static void dwc2_uninit_common(struct dwc2_core_regs *regs) -{ - /* Put everything in reset. */ - clrsetbits_le32(®s->hprt0, DWC2_HPRT0_PRTENA | - DWC2_HPRT0_PRTCONNDET | DWC2_HPRT0_PRTENCHNG | - DWC2_HPRT0_PRTOVRCURRCHNG, - DWC2_HPRT0_PRTRST); -} - -static int dwc2_submit_control_msg(struct usb_device *udev, - unsigned long pipe, void *buffer, int len, - struct devrequest *setup, int timeout_ms) -{ - struct usb_host *host = udev->host; - struct dwc2_priv *priv = to_dwc2(host); - int devnum = usb_pipedevice(pipe); - int ret, act_len; - u8 pid; - /* For CONTROL endpoint pid should start with DATA1 */ - int status_direction; - - if (devnum == priv->root_hub_devnum) { - udev->status = 0; - udev->speed = USB_SPEED_HIGH; - return dwc_otg_submit_rh_msg(priv, udev, pipe, buffer, len, - setup); - } - - /* SETUP stage */ - pid = DWC2_HC_PID_SETUP; - do { - ret = chunk_msg(priv, udev, pipe, &pid, 0, setup, 8, timeout_ms); - } while (ret == -EAGAIN); - - if (ret) - return ret; - - /* DATA stage */ - act_len = 0; - if (buffer) { - pid = DWC2_HC_PID_DATA1; - do { - ret = chunk_msg(priv, udev, pipe, &pid, usb_pipein(pipe), - buffer, len, timeout_ms); - act_len += udev->act_len; - buffer += udev->act_len; - len -= udev->act_len; - } while (ret == -EAGAIN); - if (ret) - return ret; - status_direction = usb_pipeout(pipe); - } else { - /* No-data CONTROL always ends with an IN transaction */ - status_direction = 1; - } - - /* STATUS stage */ - pid = DWC2_HC_PID_DATA1; - do { - ret = chunk_msg(priv, udev, pipe, &pid, status_direction, - NULL, 0, timeout_ms); - } while (ret == -EAGAIN); - - if (ret) - return ret; - - udev->act_len = act_len; - - return 0; -} - -static int dwc2_submit_bulk_msg(struct usb_device *udev, unsigned long pipe, - void *buffer, int len, int timeout_ms) -{ - struct usb_host *host = udev->host; - struct dwc2_priv *priv = to_dwc2(host); - int devnum = usb_pipedevice(pipe); - int ep = usb_pipeendpoint(pipe); - u8* pid; - - if ((devnum >= MAX_DEVICE) || (devnum == priv->root_hub_devnum)) { - udev->status = 0; - return -EINVAL; - } - - if (usb_pipein(pipe)) - pid = &priv->in_data_toggle[devnum][ep]; - else - pid = &priv->out_data_toggle[devnum][ep]; - - return chunk_msg(priv, udev, pipe, pid, usb_pipein(pipe), buffer, len, - timeout_ms); -} - -static int dwc2_submit_int_msg(struct usb_device *udev, unsigned long pipe, - void *buffer, int len, int interval) -{ - uint64_t start; - int ret; - - start = get_time_ns(); - - while (1) { - ret = dwc2_submit_bulk_msg(udev, pipe, buffer, len, 0); - if (ret != -EAGAIN) - return ret; - if (is_timeout(start, USB_CNTL_TIMEOUT * MSECOND)) - return -ETIMEDOUT; - } -} - -static int dwc2_detect(struct device_d *dev) -{ - struct dwc2_priv *priv = dev->priv; - - return usb_host_detect(&priv->host); -} - -static int dwc2_probe(struct device_d *dev) -{ - struct resource *iores; - struct dwc2_priv *priv; - struct usb_host *host; - struct device_node *np = dev->device_node; - int ret; - uint32_t snpsid; - - priv = xzalloc(sizeof(*priv)); - - iores = dev_request_mem_resource(dev, 0); - if (IS_ERR(iores)) - return PTR_ERR(iores); - - priv->regs = IOMEM(iores->start); - priv->dev = dev; - - snpsid = readl(&priv->regs->gsnpsid); - dev_info(dev, "Core Release: %x.%03x\n", - snpsid >> 12 & 0xf, snpsid & 0xfff); - - if ((snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_2xx && - (snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_3xx) { - dev_info(dev, "SNPSID invalid (not DWC2 OTG device): %08x\n", - snpsid); - return -ENODEV; - } - - priv->oc_disable = of_property_read_bool(np, "disable-over-current"); - priv->hnp_srp_disable = of_property_read_bool(np, "hnp-srp-disable"); - priv->dmabuf = dma_alloc(DWC2_DATA_BUF_SIZE); - - host = &priv->host; - - host->init = dwc2_init_common; - host->submit_int_msg = dwc2_submit_int_msg; - host->submit_control_msg = dwc2_submit_control_msg; - host->submit_bulk_msg = dwc2_submit_bulk_msg; - - dev->priv = priv; - dev->detect = dwc2_detect; - - ret = usb_register_host(host); - if (ret) - return ret; - - return 0; -} - -static void dwc2_remove(struct device_d *dev) -{ - struct dwc2_priv *priv = dev->priv; - - dwc2_uninit_common(priv->regs); -} - -static const struct of_device_id dwc2_dt_ids[] = { - { .compatible = "brcm,bcm2835-usb" }, - { .compatible = "brcm,bcm2708-usb" }, - { .compatible = "snps,dwc2" }, - { /* sentinel */ } -}; - -static struct driver_d dwc2_driver = { - .name = "dwc2", - .probe = dwc2_probe, - .remove = dwc2_remove, - .of_compatible = DRV_OF_COMPAT(dwc2_dt_ids), -}; -device_platform_driver(dwc2_driver); diff --git a/drivers/usb/host/dwc2.h b/drivers/usb/host/dwc2.h deleted file mode 100644 index bdf338f1ed..0000000000 --- a/drivers/usb/host/dwc2.h +++ /dev/null @@ -1,778 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2014 Marek Vasut <marex@denx.de> - */ - -#ifndef __DWC2_H__ -#define __DWC2_H__ - -struct dwc2_hc_regs { - u32 hcchar; /* 0x00 */ - u32 hcsplt; - u32 hcint; - u32 hcintmsk; - u32 hctsiz; /* 0x10 */ - u32 hcdma; - u32 reserved; - u32 hcdmab; -}; - -struct dwc2_host_regs { - u32 hcfg; /* 0x00 */ - u32 hfir; - u32 hfnum; - u32 _pad_0x40c; - u32 hptxsts; /* 0x10 */ - u32 haint; - u32 haintmsk; - u32 hflbaddr; -}; - -struct dwc2_core_regs { - u32 gotgctl; /* 0x000 */ - u32 gotgint; - u32 gahbcfg; - u32 gusbcfg; - u32 grstctl; /* 0x010 */ - u32 gintsts; - u32 gintmsk; - u32 grxstsr; - u32 grxstsp; /* 0x020 */ - u32 grxfsiz; - u32 gnptxfsiz; - u32 gnptxsts; - u32 gi2cctl; /* 0x030 */ - u32 gpvndctl; - u32 ggpio; - u32 guid; - u32 gsnpsid; /* 0x040 */ - u32 ghwcfg1; - u32 ghwcfg2; - u32 ghwcfg3; - u32 ghwcfg4; /* 0x050 */ - u32 glpmcfg; - u32 _pad_0x58_0x9c[42]; - u32 hptxfsiz; /* 0x100 */ - u32 dptxfsiz_dieptxf[15]; - u32 _pad_0x140_0x3fc[176]; - struct dwc2_host_regs host_regs; /* 0x400 */ - u32 _pad_0x420_0x43c[8]; - u32 hprt0; /* 0x440 */ - u32 _pad_0x444_0x4fc[47]; - struct dwc2_hc_regs hc_regs[16]; /* 0x500 */ - u32 _pad_0x700_0xe00[448]; - u32 pcgcctl; /* 0xe00 */ -}; - -#define DWC2_GOTGCTL_SESREQSCS (1 << 0) -#define DWC2_GOTGCTL_SESREQSCS_OFFSET 0 -#define DWC2_GOTGCTL_SESREQ (1 << 1) -#define DWC2_GOTGCTL_SESREQ_OFFSET 1 -#define DWC2_GOTGCTL_HSTNEGSCS (1 << 8) -#define DWC2_GOTGCTL_HSTNEGSCS_OFFSET 8 -#define DWC2_GOTGCTL_HNPREQ (1 << 9) -#define DWC2_GOTGCTL_HNPREQ_OFFSET 9 -#define DWC2_GOTGCTL_HSTSETHNPEN (1 << 10) -#define DWC2_GOTGCTL_HSTSETHNPEN_OFFSET 10 -#define DWC2_GOTGCTL_DEVHNPEN (1 << 11) -#define DWC2_GOTGCTL_DEVHNPEN_OFFSET 11 -#define DWC2_GOTGCTL_CONIDSTS (1 << 16) -#define DWC2_GOTGCTL_CONIDSTS_OFFSET 16 -#define DWC2_GOTGCTL_DBNCTIME (1 << 17) -#define DWC2_GOTGCTL_DBNCTIME_OFFSET 17 -#define DWC2_GOTGCTL_ASESVLD (1 << 18) -#define DWC2_GOTGCTL_ASESVLD_OFFSET 18 -#define DWC2_GOTGCTL_BSESVLD (1 << 19) -#define DWC2_GOTGCTL_BSESVLD_OFFSET 19 -#define DWC2_GOTGCTL_OTGVER (1 << 20) -#define DWC2_GOTGCTL_OTGVER_OFFSET 20 -#define DWC2_GOTGINT_SESENDDET (1 << 2) -#define DWC2_GOTGINT_SESENDDET_OFFSET 2 -#define DWC2_GOTGINT_SESREQSUCSTSCHNG (1 << 8) -#define DWC2_GOTGINT_SESREQSUCSTSCHNG_OFFSET 8 -#define DWC2_GOTGINT_HSTNEGSUCSTSCHNG (1 << 9) -#define DWC2_GOTGINT_HSTNEGSUCSTSCHNG_OFFSET 9 -#define DWC2_GOTGINT_RESERVER10_16_MASK (0x7F << 10) -#define DWC2_GOTGINT_RESERVER10_16_OFFSET 10 -#define DWC2_GOTGINT_HSTNEGDET (1 << 17) -#define DWC2_GOTGINT_HSTNEGDET_OFFSET 17 -#define DWC2_GOTGINT_ADEVTOUTCHNG (1 << 18) -#define DWC2_GOTGINT_ADEVTOUTCHNG_OFFSET 18 -#define DWC2_GOTGINT_DEBDONE (1 << 19) -#define DWC2_GOTGINT_DEBDONE_OFFSET 19 -#define DWC2_GAHBCFG_GLBLINTRMSK (1 << 0) -#define DWC2_GAHBCFG_GLBLINTRMSK_OFFSET 0 -#define DWC2_GAHBCFG_HBURSTLEN_SINGLE (0 << 1) -#define DWC2_GAHBCFG_HBURSTLEN_INCR (1 << 1) -#define DWC2_GAHBCFG_HBURSTLEN_INCR4 (3 << 1) -#define DWC2_GAHBCFG_HBURSTLEN_INCR8 (5 << 1) -#define DWC2_GAHBCFG_HBURSTLEN_INCR16 (7 << 1) -#define DWC2_GAHBCFG_HBURSTLEN_MASK (0xF << 1) -#define DWC2_GAHBCFG_HBURSTLEN_OFFSET 1 -#define DWC2_GAHBCFG_DMAENABLE (1 << 5) -#define DWC2_GAHBCFG_DMAENABLE_OFFSET 5 -#define DWC2_GAHBCFG_NPTXFEMPLVL_TXFEMPLVL (1 << 7) -#define DWC2_GAHBCFG_NPTXFEMPLVL_TXFEMPLVL_OFFSET 7 -#define DWC2_GAHBCFG_PTXFEMPLVL (1 << 8) -#define DWC2_GAHBCFG_PTXFEMPLVL_OFFSET 8 -#define DWC2_GUSBCFG_TOUTCAL_MASK (0x7 << 0) -#define DWC2_GUSBCFG_TOUTCAL_OFFSET 0 -#define DWC2_GUSBCFG_PHYIF (1 << 3) -#define DWC2_GUSBCFG_PHYIF_OFFSET 3 -#define DWC2_GUSBCFG_ULPI_UTMI_SEL (1 << 4) -#define DWC2_GUSBCFG_ULPI_UTMI_SEL_OFFSET 4 -#define DWC2_GUSBCFG_FSINTF (1 << 5) -#define DWC2_GUSBCFG_FSINTF_OFFSET 5 -#define DWC2_GUSBCFG_PHYSEL (1 << 6) -#define DWC2_GUSBCFG_PHYSEL_OFFSET 6 -#define DWC2_GUSBCFG_DDRSEL (1 << 7) -#define DWC2_GUSBCFG_DDRSEL_OFFSET 7 -#define DWC2_GUSBCFG_SRPCAP (1 << 8) -#define DWC2_GUSBCFG_SRPCAP_OFFSET 8 -#define DWC2_GUSBCFG_HNPCAP (1 << 9) -#define DWC2_GUSBCFG_HNPCAP_OFFSET 9 -#define DWC2_GUSBCFG_USBTRDTIM_MASK (0xF << 10) -#define DWC2_GUSBCFG_USBTRDTIM_OFFSET 10 -#define DWC2_GUSBCFG_NPTXFRWNDEN (1 << 14) -#define DWC2_GUSBCFG_NPTXFRWNDEN_OFFSET 14 -#define DWC2_GUSBCFG_PHYLPWRCLKSEL (1 << 15) -#define DWC2_GUSBCFG_PHYLPWRCLKSEL_OFFSET 15 -#define DWC2_GUSBCFG_OTGUTMIFSSEL (1 << 16) -#define DWC2_GUSBCFG_OTGUTMIFSSEL_OFFSET 16 -#define DWC2_GUSBCFG_ULPI_FSLS (1 << 17) -#define DWC2_GUSBCFG_ULPI_FSLS_OFFSET 17 -#define DWC2_GUSBCFG_ULPI_AUTO_RES (1 << 18) -#define DWC2_GUSBCFG_ULPI_AUTO_RES_OFFSET 18 -#define DWC2_GUSBCFG_ULPI_CLK_SUS_M (1 << 19) -#define DWC2_GUSBCFG_ULPI_CLK_SUS_M_OFFSET 19 -#define DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV (1 << 20) -#define DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV_OFFSET 20 -#define DWC2_GUSBCFG_ULPI_INT_VBUS_INDICATOR (1 << 21) -#define DWC2_GUSBCFG_ULPI_INT_VBUS_INDICATOR_OFFSET 21 -#define DWC2_GUSBCFG_TERM_SEL_DL_PULSE (1 << 22) -#define DWC2_GUSBCFG_TERM_SEL_DL_PULSE_OFFSET 22 -#define DWC2_GUSBCFG_INDICATOR_PASSTHROUGH (1 << 24) -#define DWC2_GUSBCFG_INDICATOR_PASSTHROUGH_OFFSET 24 -#define DWC2_GUSBCFG_IC_USB_CAP (1 << 26) -#define DWC2_GUSBCFG_IC_USB_CAP_OFFSET 26 -#define DWC2_GUSBCFG_IC_TRAFFIC_PULL_REMOVE (1 << 27) -#define DWC2_GUSBCFG_IC_TRAFFIC_PULL_REMOVE_OFFSET 27 -#define DWC2_GUSBCFG_TX_END_DELAY (1 << 28) -#define DWC2_GUSBCFG_TX_END_DELAY_OFFSET 28 -#define DWC2_GUSBCFG_FORCEHOSTMODE (1 << 29) -#define DWC2_GUSBCFG_FORCEHOSTMODE_OFFSET 29 -#define DWC2_GUSBCFG_FORCEDEVMODE (1 << 30) -#define DWC2_GUSBCFG_FORCEDEVMODE_OFFSET 30 -#define DWC2_GLPMCTL_LPM_CAP_EN (1 << 0) -#define DWC2_GLPMCTL_LPM_CAP_EN_OFFSET 0 -#define DWC2_GLPMCTL_APPL_RESP (1 << 1) -#define DWC2_GLPMCTL_APPL_RESP_OFFSET 1 -#define DWC2_GLPMCTL_HIRD_MASK (0xF << 2) -#define DWC2_GLPMCTL_HIRD_OFFSET 2 -#define DWC2_GLPMCTL_REM_WKUP_EN (1 << 6) -#define DWC2_GLPMCTL_REM_WKUP_EN_OFFSET 6 -#define DWC2_GLPMCTL_EN_UTMI_SLEEP (1 << 7) -#define DWC2_GLPMCTL_EN_UTMI_SLEEP_OFFSET 7 -#define DWC2_GLPMCTL_HIRD_THRES_MASK (0x1F << 8) -#define DWC2_GLPMCTL_HIRD_THRES_OFFSET 8 -#define DWC2_GLPMCTL_LPM_RESP_MASK (0x3 << 13) -#define DWC2_GLPMCTL_LPM_RESP_OFFSET 13 -#define DWC2_GLPMCTL_PRT_SLEEP_STS (1 << 15) -#define DWC2_GLPMCTL_PRT_SLEEP_STS_OFFSET 15 -#define DWC2_GLPMCTL_SLEEP_STATE_RESUMEOK (1 << 16) -#define DWC2_GLPMCTL_SLEEP_STATE_RESUMEOK_OFFSET 16 -#define DWC2_GLPMCTL_LPM_CHAN_INDEX_MASK (0xF << 17) -#define DWC2_GLPMCTL_LPM_CHAN_INDEX_OFFSET 17 -#define DWC2_GLPMCTL_RETRY_COUNT_MASK (0x7 << 21) -#define DWC2_GLPMCTL_RETRY_COUNT_OFFSET 21 -#define DWC2_GLPMCTL_SEND_LPM (1 << 24) -#define DWC2_GLPMCTL_SEND_LPM_OFFSET 24 -#define DWC2_GLPMCTL_RETRY_COUNT_STS_MASK (0x7 << 25) -#define DWC2_GLPMCTL_RETRY_COUNT_STS_OFFSET 25 -#define DWC2_GLPMCTL_HSIC_CONNECT (1 << 30) -#define DWC2_GLPMCTL_HSIC_CONNECT_OFFSET 30 -#define DWC2_GLPMCTL_INV_SEL_HSIC (1 << 31) -#define DWC2_GLPMCTL_INV_SEL_HSIC_OFFSET 31 -#define DWC2_GRSTCTL_CSFTRST (1 << 0) -#define DWC2_GRSTCTL_CSFTRST_OFFSET 0 -#define DWC2_GRSTCTL_HSFTRST (1 << 1) -#define DWC2_GRSTCTL_HSFTRST_OFFSET 1 -#define DWC2_GRSTCTL_HSTFRM (1 << 2) -#define DWC2_GRSTCTL_HSTFRM_OFFSET 2 -#define DWC2_GRSTCTL_INTKNQFLSH (1 << 3) -#define DWC2_GRSTCTL_INTKNQFLSH_OFFSET 3 -#define DWC2_GRSTCTL_RXFFLSH (1 << 4) -#define DWC2_GRSTCTL_RXFFLSH_OFFSET 4 -#define DWC2_GRSTCTL_TXFFLSH (1 << 5) -#define DWC2_GRSTCTL_TXFFLSH_OFFSET 5 -#define DWC2_GRSTCTL_TXFNUM_MASK (0x1F << 6) -#define DWC2_GRSTCTL_TXFNUM_OFFSET 6 -#define DWC2_GRSTCTL_DMAREQ (1 << 30) -#define DWC2_GRSTCTL_DMAREQ_OFFSET 30 -#define DWC2_GRSTCTL_AHBIDLE (1 << 31) -#define DWC2_GRSTCTL_AHBIDLE_OFFSET 31 -#define DWC2_GINTMSK_MODEMISMATCH (1 << 1) -#define DWC2_GINTMSK_MODEMISMATCH_OFFSET 1 -#define DWC2_GINTMSK_OTGINTR (1 << 2) -#define DWC2_GINTMSK_OTGINTR_OFFSET 2 -#define DWC2_GINTMSK_SOFINTR (1 << 3) -#define DWC2_GINTMSK_SOFINTR_OFFSET 3 -#define DWC2_GINTMSK_RXSTSQLVL (1 << 4) -#define DWC2_GINTMSK_RXSTSQLVL_OFFSET 4 -#define DWC2_GINTMSK_NPTXFEMPTY (1 << 5) -#define DWC2_GINTMSK_NPTXFEMPTY_OFFSET 5 -#define DWC2_GINTMSK_GINNAKEFF (1 << 6) -#define DWC2_GINTMSK_GINNAKEFF_OFFSET 6 -#define DWC2_GINTMSK_GOUTNAKEFF (1 << 7) -#define DWC2_GINTMSK_GOUTNAKEFF_OFFSET 7 -#define DWC2_GINTMSK_I2CINTR (1 << 9) -#define DWC2_GINTMSK_I2CINTR_OFFSET 9 -#define DWC2_GINTMSK_ERLYSUSPEND (1 << 10) -#define DWC2_GINTMSK_ERLYSUSPEND_OFFSET 10 -#define DWC2_GINTMSK_USBSUSPEND (1 << 11) -#define DWC2_GINTMSK_USBSUSPEND_OFFSET 11 -#define DWC2_GINTMSK_USBRESET (1 << 12) -#define DWC2_GINTMSK_USBRESET_OFFSET 12 -#define DWC2_GINTMSK_ENUMDONE (1 << 13) -#define DWC2_GINTMSK_ENUMDONE_OFFSET 13 -#define DWC2_GINTMSK_ISOOUTDROP (1 << 14) -#define DWC2_GINTMSK_ISOOUTDROP_OFFSET 14 -#define DWC2_GINTMSK_EOPFRAME (1 << 15) -#define DWC2_GINTMSK_EOPFRAME_OFFSET 15 -#define DWC2_GINTMSK_EPMISMATCH (1 << 17) -#define DWC2_GINTMSK_EPMISMATCH_OFFSET 17 -#define DWC2_GINTMSK_INEPINTR (1 << 18) -#define DWC2_GINTMSK_INEPINTR_OFFSET 18 -#define DWC2_GINTMSK_OUTEPINTR (1 << 19) -#define DWC2_GINTMSK_OUTEPINTR_OFFSET 19 -#define DWC2_GINTMSK_INCOMPLISOIN (1 << 20) -#define DWC2_GINTMSK_INCOMPLISOIN_OFFSET 20 -#define DWC2_GINTMSK_INCOMPLISOOUT (1 << 21) -#define DWC2_GINTMSK_INCOMPLISOOUT_OFFSET 21 -#define DWC2_GINTMSK_PORTINTR (1 << 24) -#define DWC2_GINTMSK_PORTINTR_OFFSET 24 -#define DWC2_GINTMSK_HCINTR (1 << 25) -#define DWC2_GINTMSK_HCINTR_OFFSET 25 -#define DWC2_GINTMSK_PTXFEMPTY (1 << 26) -#define DWC2_GINTMSK_PTXFEMPTY_OFFSET 26 -#define DWC2_GINTMSK_LPMTRANRCVD (1 << 27) -#define DWC2_GINTMSK_LPMTRANRCVD_OFFSET 27 -#define DWC2_GINTMSK_CONIDSTSCHNG (1 << 28) -#define DWC2_GINTMSK_CONIDSTSCHNG_OFFSET 28 -#define DWC2_GINTMSK_DISCONNECT (1 << 29) -#define DWC2_GINTMSK_DISCONNECT_OFFSET 29 -#define DWC2_GINTMSK_SESSREQINTR (1 << 30) -#define DWC2_GINTMSK_SESSREQINTR_OFFSET 30 -#define DWC2_GINTMSK_WKUPINTR (1 << 31) -#define DWC2_GINTMSK_WKUPINTR_OFFSET 31 -#define DWC2_GINTSTS_CURMODE_DEVICE (0 << 0) -#define DWC2_GINTSTS_CURMODE_HOST (1 << 0) -#define DWC2_GINTSTS_CURMODE (1 << 0) -#define DWC2_GINTSTS_CURMODE_OFFSET 0 -#define DWC2_GINTSTS_MODEMISMATCH (1 << 1) -#define DWC2_GINTSTS_MODEMISMATCH_OFFSET 1 -#define DWC2_GINTSTS_OTGINTR (1 << 2) -#define DWC2_GINTSTS_OTGINTR_OFFSET 2 -#define DWC2_GINTSTS_SOFINTR (1 << 3) -#define DWC2_GINTSTS_SOFINTR_OFFSET 3 -#define DWC2_GINTSTS_RXSTSQLVL (1 << 4) -#define DWC2_GINTSTS_RXSTSQLVL_OFFSET 4 -#define DWC2_GINTSTS_NPTXFEMPTY (1 << 5) -#define DWC2_GINTSTS_NPTXFEMPTY_OFFSET 5 -#define DWC2_GINTSTS_GINNAKEFF (1 << 6) -#define DWC2_GINTSTS_GINNAKEFF_OFFSET 6 -#define DWC2_GINTSTS_GOUTNAKEFF (1 << 7) -#define DWC2_GINTSTS_GOUTNAKEFF_OFFSET 7 -#define DWC2_GINTSTS_I2CINTR (1 << 9) -#define DWC2_GINTSTS_I2CINTR_OFFSET 9 -#define DWC2_GINTSTS_ERLYSUSPEND (1 << 10) -#define DWC2_GINTSTS_ERLYSUSPEND_OFFSET 10 -#define DWC2_GINTSTS_USBSUSPEND (1 << 11) -#define DWC2_GINTSTS_USBSUSPEND_OFFSET 11 -#define DWC2_GINTSTS_USBRESET (1 << 12) -#define DWC2_GINTSTS_USBRESET_OFFSET 12 -#define DWC2_GINTSTS_ENUMDONE (1 << 13) -#define DWC2_GINTSTS_ENUMDONE_OFFSET 13 -#define DWC2_GINTSTS_ISOOUTDROP (1 << 14) -#define DWC2_GINTSTS_ISOOUTDROP_OFFSET 14 -#define DWC2_GINTSTS_EOPFRAME (1 << 15) -#define DWC2_GINTSTS_EOPFRAME_OFFSET 15 -#define DWC2_GINTSTS_INTOKENRX (1 << 16) -#define DWC2_GINTSTS_INTOKENRX_OFFSET 16 -#define DWC2_GINTSTS_EPMISMATCH (1 << 17) -#define DWC2_GINTSTS_EPMISMATCH_OFFSET 17 -#define DWC2_GINTSTS_INEPINT (1 << 18) -#define DWC2_GINTSTS_INEPINT_OFFSET 18 -#define DWC2_GINTSTS_OUTEPINTR (1 << 19) -#define DWC2_GINTSTS_OUTEPINTR_OFFSET 19 -#define DWC2_GINTSTS_INCOMPLISOIN (1 << 20) -#define DWC2_GINTSTS_INCOMPLISOIN_OFFSET 20 -#define DWC2_GINTSTS_INCOMPLISOOUT (1 << 21) -#define DWC2_GINTSTS_INCOMPLISOOUT_OFFSET 21 -#define DWC2_GINTSTS_PORTINTR (1 << 24) -#define DWC2_GINTSTS_PORTINTR_OFFSET 24 -#define DWC2_GINTSTS_HCINTR (1 << 25) -#define DWC2_GINTSTS_HCINTR_OFFSET 25 -#define DWC2_GINTSTS_PTXFEMPTY (1 << 26) -#define DWC2_GINTSTS_PTXFEMPTY_OFFSET 26 -#define DWC2_GINTSTS_LPMTRANRCVD (1 << 27) -#define DWC2_GINTSTS_LPMTRANRCVD_OFFSET 27 -#define DWC2_GINTSTS_CONIDSTSCHNG (1 << 28) -#define DWC2_GINTSTS_CONIDSTSCHNG_OFFSET 28 -#define DWC2_GINTSTS_DISCONNECT (1 << 29) -#define DWC2_GINTSTS_DISCONNECT_OFFSET 29 -#define DWC2_GINTSTS_SESSREQINTR (1 << 30) -#define DWC2_GINTSTS_SESSREQINTR_OFFSET 30 -#define DWC2_GINTSTS_WKUPINTR (1 << 31) -#define DWC2_GINTSTS_WKUPINTR_OFFSET 31 -#define DWC2_GRXSTS_EPNUM_MASK (0xF << 0) -#define DWC2_GRXSTS_EPNUM_OFFSET 0 -#define DWC2_GRXSTS_BCNT_MASK (0x7FF << 4) -#define DWC2_GRXSTS_BCNT_OFFSET 4 -#define DWC2_GRXSTS_DPID_MASK (0x3 << 15) -#define DWC2_GRXSTS_DPID_OFFSET 15 -#define DWC2_GRXSTS_PKTSTS_MASK (0xF << 17) -#define DWC2_GRXSTS_PKTSTS_OFFSET 17 -#define DWC2_GRXSTS_FN_MASK (0xF << 21) -#define DWC2_GRXSTS_FN_OFFSET 21 -#define DWC2_FIFOSIZE_STARTADDR_MASK (0xFFFF << 0) -#define DWC2_FIFOSIZE_STARTADDR_OFFSET 0 -#define DWC2_FIFOSIZE_DEPTH_MASK (0xFFFF << 16) -#define DWC2_FIFOSIZE_DEPTH_OFFSET 16 -#define DWC2_GNPTXSTS_NPTXFSPCAVAIL_MASK (0xFFFF << 0) -#define DWC2_GNPTXSTS_NPTXFSPCAVAIL_OFFSET 0 -#define DWC2_GNPTXSTS_NPTXQSPCAVAIL_MASK (0xFF << 16) -#define DWC2_GNPTXSTS_NPTXQSPCAVAIL_OFFSET 16 -#define DWC2_GNPTXSTS_NPTXQTOP_TERMINATE (1 << 24) -#define DWC2_GNPTXSTS_NPTXQTOP_TERMINATE_OFFSET 24 -#define DWC2_GNPTXSTS_NPTXQTOP_TOKEN_MASK (0x3 << 25) -#define DWC2_GNPTXSTS_NPTXQTOP_TOKEN_OFFSET 25 -#define DWC2_GNPTXSTS_NPTXQTOP_CHNEP_MASK (0xF << 27) -#define DWC2_GNPTXSTS_NPTXQTOP_CHNEP_OFFSET 27 -#define DWC2_DTXFSTS_TXFSPCAVAIL_MASK (0xFFFF << 0) -#define DWC2_DTXFSTS_TXFSPCAVAIL_OFFSET 0 -#define DWC2_GI2CCTL_RWDATA_MASK (0xFF << 0) -#define DWC2_GI2CCTL_RWDATA_OFFSET 0 -#define DWC2_GI2CCTL_REGADDR_MASK (0xFF << 8) -#define DWC2_GI2CCTL_REGADDR_OFFSET 8 -#define DWC2_GI2CCTL_ADDR_MASK (0x7F << 16) -#define DWC2_GI2CCTL_ADDR_OFFSET 16 -#define DWC2_GI2CCTL_I2CEN (1 << 23) -#define DWC2_GI2CCTL_I2CEN_OFFSET 23 -#define DWC2_GI2CCTL_ACK (1 << 24) -#define DWC2_GI2CCTL_ACK_OFFSET 24 -#define DWC2_GI2CCTL_I2CSUSPCTL (1 << 25) -#define DWC2_GI2CCTL_I2CSUSPCTL_OFFSET 25 -#define DWC2_GI2CCTL_I2CDEVADDR_MASK (0x3 << 26) -#define DWC2_GI2CCTL_I2CDEVADDR_OFFSET 26 -#define DWC2_GI2CCTL_RW (1 << 30) -#define DWC2_GI2CCTL_RW_OFFSET 30 -#define DWC2_GI2CCTL_BSYDNE (1 << 31) -#define DWC2_GI2CCTL_BSYDNE_OFFSET 31 -#define DWC2_HWCFG1_EP_DIR0_MASK (0x3 << 0) -#define DWC2_HWCFG1_EP_DIR0_OFFSET 0 -#define DWC2_HWCFG1_EP_DIR1_MASK (0x3 << 2) -#define DWC2_HWCFG1_EP_DIR1_OFFSET 2 -#define DWC2_HWCFG1_EP_DIR2_MASK (0x3 << 4) -#define DWC2_HWCFG1_EP_DIR2_OFFSET 4 -#define DWC2_HWCFG1_EP_DIR3_MASK (0x3 << 6) -#define DWC2_HWCFG1_EP_DIR3_OFFSET 6 -#define DWC2_HWCFG1_EP_DIR4_MASK (0x3 << 8) -#define DWC2_HWCFG1_EP_DIR4_OFFSET 8 -#define DWC2_HWCFG1_EP_DIR5_MASK (0x3 << 10) -#define DWC2_HWCFG1_EP_DIR5_OFFSET 10 -#define DWC2_HWCFG1_EP_DIR6_MASK (0x3 << 12) -#define DWC2_HWCFG1_EP_DIR6_OFFSET 12 -#define DWC2_HWCFG1_EP_DIR7_MASK (0x3 << 14) -#define DWC2_HWCFG1_EP_DIR7_OFFSET 14 -#define DWC2_HWCFG1_EP_DIR8_MASK (0x3 << 16) -#define DWC2_HWCFG1_EP_DIR8_OFFSET 16 -#define DWC2_HWCFG1_EP_DIR9_MASK (0x3 << 18) -#define DWC2_HWCFG1_EP_DIR9_OFFSET 18 -#define DWC2_HWCFG1_EP_DIR10_MASK (0x3 << 20) -#define DWC2_HWCFG1_EP_DIR10_OFFSET 20 -#define DWC2_HWCFG1_EP_DIR11_MASK (0x3 << 22) -#define DWC2_HWCFG1_EP_DIR11_OFFSET 22 -#define DWC2_HWCFG1_EP_DIR12_MASK (0x3 << 24) -#define DWC2_HWCFG1_EP_DIR12_OFFSET 24 -#define DWC2_HWCFG1_EP_DIR13_MASK (0x3 << 26) -#define DWC2_HWCFG1_EP_DIR13_OFFSET 26 -#define DWC2_HWCFG1_EP_DIR14_MASK (0x3 << 28) -#define DWC2_HWCFG1_EP_DIR14_OFFSET 28 -#define DWC2_HWCFG1_EP_DIR15_MASK (0x3 << 30) -#define DWC2_HWCFG1_EP_DIR15_OFFSET 30 -#define DWC2_HWCFG2_OP_MODE_MASK (0x7 << 0) -#define DWC2_HWCFG2_OP_MODE_OFFSET 0 -#define DWC2_HWCFG2_ARCHITECTURE_SLAVE_ONLY (0x0 << 3) -#define DWC2_HWCFG2_ARCHITECTURE_EXT_DMA (0x1 << 3) -#define DWC2_HWCFG2_ARCHITECTURE_INT_DMA (0x2 << 3) -#define DWC2_HWCFG2_ARCHITECTURE_MASK (0x3 << 3) -#define DWC2_HWCFG2_ARCHITECTURE_OFFSET 3 -#define DWC2_HWCFG2_POINT2POINT (1 << 5) -#define DWC2_HWCFG2_POINT2POINT_OFFSET 5 -#define DWC2_HWCFG2_HS_PHY_TYPE_MASK (0x3 << 6) -#define DWC2_HWCFG2_HS_PHY_TYPE_OFFSET 6 -#define DWC2_HWCFG2_FS_PHY_TYPE_MASK (0x3 << 8) -#define DWC2_HWCFG2_FS_PHY_TYPE_OFFSET 8 -#define DWC2_HWCFG2_NUM_DEV_EP_MASK (0xF << 10) -#define DWC2_HWCFG2_NUM_DEV_EP_OFFSET 10 -#define DWC2_HWCFG2_NUM_HOST_CHAN_MASK (0xF << 14) -#define DWC2_HWCFG2_NUM_HOST_CHAN_OFFSET 14 -#define DWC2_HWCFG2_PERIO_EP_SUPPORTED (1 << 18) -#define DWC2_HWCFG2_PERIO_EP_SUPPORTED_OFFSET 18 -#define DWC2_HWCFG2_DYNAMIC_FIFO (1 << 19) -#define DWC2_HWCFG2_DYNAMIC_FIFO_OFFSET 19 -#define DWC2_HWCFG2_MULTI_PROC_INT (1 << 20) -#define DWC2_HWCFG2_MULTI_PROC_INT_OFFSET 20 -#define DWC2_HWCFG2_NONPERIO_TX_Q_DEPTH_MASK (0x3 << 22) -#define DWC2_HWCFG2_NONPERIO_TX_Q_DEPTH_OFFSET 22 -#define DWC2_HWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK (0x3 << 24) -#define DWC2_HWCFG2_HOST_PERIO_TX_Q_DEPTH_OFFSET 24 -#define DWC2_HWCFG2_DEV_TOKEN_Q_DEPTH_MASK (0x1F << 26) -#define DWC2_HWCFG2_DEV_TOKEN_Q_DEPTH_OFFSET 26 -#define DWC2_HWCFG3_XFER_SIZE_CNTR_WIDTH_MASK (0xF << 0) -#define DWC2_HWCFG3_XFER_SIZE_CNTR_WIDTH_OFFSET 0 -#define DWC2_HWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK (0x7 << 4) -#define DWC2_HWCFG3_PACKET_SIZE_CNTR_WIDTH_OFFSET 4 -#define DWC2_HWCFG3_OTG_FUNC (1 << 7) -#define DWC2_HWCFG3_OTG_FUNC_OFFSET 7 -#define DWC2_HWCFG3_I2C (1 << 8) -#define DWC2_HWCFG3_I2C_OFFSET 8 -#define DWC2_HWCFG3_VENDOR_CTRL_IF (1 << 9) -#define DWC2_HWCFG3_VENDOR_CTRL_IF_OFFSET 9 -#define DWC2_HWCFG3_OPTIONAL_FEATURES (1 << 10) -#define DWC2_HWCFG3_OPTIONAL_FEATURES_OFFSET 10 -#define DWC2_HWCFG3_SYNCH_RESET_TYPE (1 << 11) -#define DWC2_HWCFG3_SYNCH_RESET_TYPE_OFFSET 11 -#define DWC2_HWCFG3_OTG_ENABLE_IC_USB (1 << 12) -#define DWC2_HWCFG3_OTG_ENABLE_IC_USB_OFFSET 12 -#define DWC2_HWCFG3_OTG_ENABLE_HSIC (1 << 13) -#define DWC2_HWCFG3_OTG_ENABLE_HSIC_OFFSET 13 -#define DWC2_HWCFG3_OTG_LPM_EN (1 << 15) -#define DWC2_HWCFG3_OTG_LPM_EN_OFFSET 15 -#define DWC2_HWCFG3_DFIFO_DEPTH_MASK (0xFFFF << 16) -#define DWC2_HWCFG3_DFIFO_DEPTH_OFFSET 16 -#define DWC2_HWCFG4_NUM_DEV_PERIO_IN_EP_MASK (0xF << 0) -#define DWC2_HWCFG4_NUM_DEV_PERIO_IN_EP_OFFSET 0 -#define DWC2_HWCFG4_POWER_OPTIMIZ (1 << 4) -#define DWC2_HWCFG4_POWER_OPTIMIZ_OFFSET 4 -#define DWC2_HWCFG4_MIN_AHB_FREQ_MASK (0x1FF << 5) -#define DWC2_HWCFG4_MIN_AHB_FREQ_OFFSET 5 -#define DWC2_HWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14) -#define DWC2_HWCFG4_UTMI_PHY_DATA_WIDTH_OFFSET 14 -#define DWC2_HWCFG4_NUM_DEV_MODE_CTRL_EP_MASK (0xF << 16) -#define DWC2_HWCFG4_NUM_DEV_MODE_CTRL_EP_OFFSET 16 -#define DWC2_HWCFG4_IDDIG_FILT_EN (1 << 20) -#define DWC2_HWCFG4_IDDIG_FILT_EN_OFFSET 20 -#define DWC2_HWCFG4_VBUS_VALID_FILT_EN (1 << 21) -#define DWC2_HWCFG4_VBUS_VALID_FILT_EN_OFFSET 21 -#define DWC2_HWCFG4_A_VALID_FILT_EN (1 << 22) -#define DWC2_HWCFG4_A_VALID_FILT_EN_OFFSET 22 -#define DWC2_HWCFG4_B_VALID_FILT_EN (1 << 23) -#define DWC2_HWCFG4_B_VALID_FILT_EN_OFFSET 23 -#define DWC2_HWCFG4_SESSION_END_FILT_EN (1 << 24) -#define DWC2_HWCFG4_SESSION_END_FILT_EN_OFFSET 24 -#define DWC2_HWCFG4_DED_FIFO_EN (1 << 25) -#define DWC2_HWCFG4_DED_FIFO_EN_OFFSET 25 -#define DWC2_HWCFG4_NUM_IN_EPS_MASK (0xF << 26) -#define DWC2_HWCFG4_NUM_IN_EPS_OFFSET 26 -#define DWC2_HWCFG4_DESC_DMA (1 << 30) -#define DWC2_HWCFG4_DESC_DMA_OFFSET 30 -#define DWC2_HWCFG4_DESC_DMA_DYN (1 << 31) -#define DWC2_HWCFG4_DESC_DMA_DYN_OFFSET 31 -#define DWC2_HCFG_FSLSPCLKSEL_30_60_MHZ 0 -#define DWC2_HCFG_FSLSPCLKSEL_48_MHZ 1 -#define DWC2_HCFG_FSLSPCLKSEL_6_MHZ 2 -#define DWC2_HCFG_FSLSPCLKSEL_MASK (0x3 << 0) -#define DWC2_HCFG_FSLSPCLKSEL_OFFSET 0 -#define DWC2_HCFG_FSLSSUPP (1 << 2) -#define DWC2_HCFG_FSLSSUPP_OFFSET 2 -#define DWC2_HCFG_DESCDMA (1 << 23) -#define DWC2_HCFG_DESCDMA_OFFSET 23 -#define DWC2_HCFG_FRLISTEN_MASK (0x3 << 24) -#define DWC2_HCFG_FRLISTEN_OFFSET 24 -#define DWC2_HCFG_PERSCHEDENA (1 << 26) -#define DWC2_HCFG_PERSCHEDENA_OFFSET 26 -#define DWC2_HCFG_PERSCHEDSTAT (1 << 27) -#define DWC2_HCFG_PERSCHEDSTAT_OFFSET 27 -#define DWC2_HFIR_FRINT_MASK (0xFFFF << 0) -#define DWC2_HFIR_FRINT_OFFSET 0 -#define DWC2_HFNUM_FRNUM_MASK (0xFFFF << 0) -#define DWC2_HFNUM_FRNUM_OFFSET 0 -#define DWC2_HFNUM_FRREM_MASK (0xFFFF << 16) -#define DWC2_HFNUM_FRREM_OFFSET 16 -#define DWC2_HFNUM_MAX_FRNUM 0x3FFF -#define DWC2_HPTXSTS_PTXFSPCAVAIL_MASK (0xFFFF << 0) -#define DWC2_HPTXSTS_PTXFSPCAVAIL_OFFSET 0 -#define DWC2_HPTXSTS_PTXQSPCAVAIL_MASK (0xFF << 16) -#define DWC2_HPTXSTS_PTXQSPCAVAIL_OFFSET 16 -#define DWC2_HPTXSTS_PTXQTOP_TERMINATE (1 << 24) -#define DWC2_HPTXSTS_PTXQTOP_TERMINATE_OFFSET 24 -#define DWC2_HPTXSTS_PTXQTOP_TOKEN_MASK (0x3 << 25) -#define DWC2_HPTXSTS_PTXQTOP_TOKEN_OFFSET 25 -#define DWC2_HPTXSTS_PTXQTOP_CHNUM_MASK (0xF << 27) -#define DWC2_HPTXSTS_PTXQTOP_CHNUM_OFFSET 27 -#define DWC2_HPTXSTS_PTXQTOP_ODD (1 << 31) -#define DWC2_HPTXSTS_PTXQTOP_ODD_OFFSET 31 -#define DWC2_HPRT0_PRTCONNSTS (1 << 0) -#define DWC2_HPRT0_PRTCONNSTS_OFFSET 0 -#define DWC2_HPRT0_PRTCONNDET (1 << 1) -#define DWC2_HPRT0_PRTCONNDET_OFFSET 1 -#define DWC2_HPRT0_PRTENA (1 << 2) -#define DWC2_HPRT0_PRTENA_OFFSET 2 -#define DWC2_HPRT0_PRTENCHNG (1 << 3) -#define DWC2_HPRT0_PRTENCHNG_OFFSET 3 -#define DWC2_HPRT0_PRTOVRCURRACT (1 << 4) -#define DWC2_HPRT0_PRTOVRCURRACT_OFFSET 4 -#define DWC2_HPRT0_PRTOVRCURRCHNG (1 << 5) -#define DWC2_HPRT0_PRTOVRCURRCHNG_OFFSET 5 -#define DWC2_HPRT0_PRTRES (1 << 6) -#define DWC2_HPRT0_PRTRES_OFFSET 6 -#define DWC2_HPRT0_PRTSUSP (1 << 7) -#define DWC2_HPRT0_PRTSUSP_OFFSET 7 -#define DWC2_HPRT0_PRTRST (1 << 8) -#define DWC2_HPRT0_PRTRST_OFFSET 8 -#define DWC2_HPRT0_PRTLNSTS_MASK (0x3 << 10) -#define DWC2_HPRT0_PRTLNSTS_OFFSET 10 -#define DWC2_HPRT0_PRTPWR (1 << 12) -#define DWC2_HPRT0_PRTPWR_OFFSET 12 -#define DWC2_HPRT0_PRTTSTCTL_MASK (0xF << 13) -#define DWC2_HPRT0_PRTTSTCTL_OFFSET 13 -#define DWC2_HPRT0_PRTSPD_HIGH (0 << 17) -#define DWC2_HPRT0_PRTSPD_FULL (1 << 17) -#define DWC2_HPRT0_PRTSPD_LOW (2 << 17) -#define DWC2_HPRT0_PRTSPD_MASK (0x3 << 17) -#define DWC2_HPRT0_PRTSPD_OFFSET 17 -#define DWC2_HAINT_CH0 (1 << 0) -#define DWC2_HAINT_CH0_OFFSET 0 -#define DWC2_HAINT_CH1 (1 << 1) -#define DWC2_HAINT_CH1_OFFSET 1 -#define DWC2_HAINT_CH2 (1 << 2) -#define DWC2_HAINT_CH2_OFFSET 2 -#define DWC2_HAINT_CH3 (1 << 3) -#define DWC2_HAINT_CH3_OFFSET 3 -#define DWC2_HAINT_CH4 (1 << 4) -#define DWC2_HAINT_CH4_OFFSET 4 -#define DWC2_HAINT_CH5 (1 << 5) -#define DWC2_HAINT_CH5_OFFSET 5 -#define DWC2_HAINT_CH6 (1 << 6) -#define DWC2_HAINT_CH6_OFFSET 6 -#define DWC2_HAINT_CH7 (1 << 7) -#define DWC2_HAINT_CH7_OFFSET 7 -#define DWC2_HAINT_CH8 (1 << 8) -#define DWC2_HAINT_CH8_OFFSET 8 -#define DWC2_HAINT_CH9 (1 << 9) -#define DWC2_HAINT_CH9_OFFSET 9 -#define DWC2_HAINT_CH10 (1 << 10) -#define DWC2_HAINT_CH10_OFFSET 10 -#define DWC2_HAINT_CH11 (1 << 11) -#define DWC2_HAINT_CH11_OFFSET 11 -#define DWC2_HAINT_CH12 (1 << 12) -#define DWC2_HAINT_CH12_OFFSET 12 -#define DWC2_HAINT_CH13 (1 << 13) -#define DWC2_HAINT_CH13_OFFSET 13 -#define DWC2_HAINT_CH14 (1 << 14) -#define DWC2_HAINT_CH14_OFFSET 14 -#define DWC2_HAINT_CH15 (1 << 15) -#define DWC2_HAINT_CH15_OFFSET 15 -#define DWC2_HAINT_CHINT_MASK 0xffff -#define DWC2_HAINT_CHINT_OFFSET 0 -#define DWC2_HAINTMSK_CH0 (1 << 0) -#define DWC2_HAINTMSK_CH0_OFFSET 0 -#define DWC2_HAINTMSK_CH1 (1 << 1) -#define DWC2_HAINTMSK_CH1_OFFSET 1 -#define DWC2_HAINTMSK_CH2 (1 << 2) -#define DWC2_HAINTMSK_CH2_OFFSET 2 -#define DWC2_HAINTMSK_CH3 (1 << 3) -#define DWC2_HAINTMSK_CH3_OFFSET 3 -#define DWC2_HAINTMSK_CH4 (1 << 4) -#define DWC2_HAINTMSK_CH4_OFFSET 4 -#define DWC2_HAINTMSK_CH5 (1 << 5) -#define DWC2_HAINTMSK_CH5_OFFSET 5 -#define DWC2_HAINTMSK_CH6 (1 << 6) -#define DWC2_HAINTMSK_CH6_OFFSET 6 -#define DWC2_HAINTMSK_CH7 (1 << 7) -#define DWC2_HAINTMSK_CH7_OFFSET 7 -#define DWC2_HAINTMSK_CH8 (1 << 8) -#define DWC2_HAINTMSK_CH8_OFFSET 8 -#define DWC2_HAINTMSK_CH9 (1 << 9) -#define DWC2_HAINTMSK_CH9_OFFSET 9 -#define DWC2_HAINTMSK_CH10 (1 << 10) -#define DWC2_HAINTMSK_CH10_OFFSET 10 -#define DWC2_HAINTMSK_CH11 (1 << 11) -#define DWC2_HAINTMSK_CH11_OFFSET 11 -#define DWC2_HAINTMSK_CH12 (1 << 12) -#define DWC2_HAINTMSK_CH12_OFFSET 12 -#define DWC2_HAINTMSK_CH13 (1 << 13) -#define DWC2_HAINTMSK_CH13_OFFSET 13 -#define DWC2_HAINTMSK_CH14 (1 << 14) -#define DWC2_HAINTMSK_CH14_OFFSET 14 -#define DWC2_HAINTMSK_CH15 (1 << 15) -#define DWC2_HAINTMSK_CH15_OFFSET 15 -#define DWC2_HAINTMSK_CHINT_MASK 0xffff -#define DWC2_HAINTMSK_CHINT_OFFSET 0 -#define DWC2_HCCHAR_MPS_MASK (0x7FF << 0) -#define DWC2_HCCHAR_MPS_OFFSET 0 -#define DWC2_HCCHAR_EPNUM_MASK (0xF << 11) -#define DWC2_HCCHAR_EPNUM_OFFSET 11 -#define DWC2_HCCHAR_EPDIR (1 << 15) -#define DWC2_HCCHAR_EPDIR_OFFSET 15 -#define DWC2_HCCHAR_LSPDDEV (1 << 17) -#define DWC2_HCCHAR_LSPDDEV_OFFSET 17 -#define DWC2_HCCHAR_EPTYPE_CONTROL 0 -#define DWC2_HCCHAR_EPTYPE_ISOC 1 -#define DWC2_HCCHAR_EPTYPE_BULK 2 -#define DWC2_HCCHAR_EPTYPE_INTR 3 -#define DWC2_HCCHAR_EPTYPE_MASK (0x3 << 18) -#define DWC2_HCCHAR_EPTYPE_OFFSET 18 -#define DWC2_HCCHAR_MULTICNT_MASK (0x3 << 20) -#define DWC2_HCCHAR_MULTICNT_OFFSET 20 -#define DWC2_HCCHAR_DEVADDR_MASK (0x7F << 22) -#define DWC2_HCCHAR_DEVADDR_OFFSET 22 -#define DWC2_HCCHAR_ODDFRM (1 << 29) -#define DWC2_HCCHAR_ODDFRM_OFFSET 29 -#define DWC2_HCCHAR_CHDIS (1 << 30) -#define DWC2_HCCHAR_CHDIS_OFFSET 30 -#define DWC2_HCCHAR_CHEN (1 << 31) -#define DWC2_HCCHAR_CHEN_OFFSET 31 -#define DWC2_HCSPLT_PRTADDR_MASK (0x7F << 0) -#define DWC2_HCSPLT_PRTADDR_OFFSET 0 -#define DWC2_HCSPLT_HUBADDR_MASK (0x7F << 7) -#define DWC2_HCSPLT_HUBADDR_OFFSET 7 -#define DWC2_HCSPLT_XACTPOS_MASK (0x3 << 14) -#define DWC2_HCSPLT_XACTPOS_OFFSET 14 -#define DWC2_HCSPLT_COMPSPLT (1 << 16) -#define DWC2_HCSPLT_COMPSPLT_OFFSET 16 -#define DWC2_HCSPLT_SPLTENA (1 << 31) -#define DWC2_HCSPLT_SPLTENA_OFFSET 31 -#define DWC2_HCINT_XFERCOMP (1 << 0) -#define DWC2_HCINT_XFERCOMP_OFFSET 0 -#define DWC2_HCINT_CHHLTD (1 << 1) -#define DWC2_HCINT_CHHLTD_OFFSET 1 -#define DWC2_HCINT_AHBERR (1 << 2) -#define DWC2_HCINT_AHBERR_OFFSET 2 -#define DWC2_HCINT_STALL (1 << 3) -#define DWC2_HCINT_STALL_OFFSET 3 -#define DWC2_HCINT_NAK (1 << 4) -#define DWC2_HCINT_NAK_OFFSET 4 -#define DWC2_HCINT_ACK (1 << 5) -#define DWC2_HCINT_ACK_OFFSET 5 -#define DWC2_HCINT_NYET (1 << 6) -#define DWC2_HCINT_NYET_OFFSET 6 -#define DWC2_HCINT_XACTERR (1 << 7) -#define DWC2_HCINT_XACTERR_OFFSET 7 -#define DWC2_HCINT_BBLERR (1 << 8) -#define DWC2_HCINT_BBLERR_OFFSET 8 -#define DWC2_HCINT_FRMOVRUN (1 << 9) -#define DWC2_HCINT_FRMOVRUN_OFFSET 9 -#define DWC2_HCINT_DATATGLERR (1 << 10) -#define DWC2_HCINT_DATATGLERR_OFFSET 10 -#define DWC2_HCINT_BNA (1 << 11) -#define DWC2_HCINT_BNA_OFFSET 11 -#define DWC2_HCINT_XCS_XACT (1 << 12) -#define DWC2_HCINT_XCS_XACT_OFFSET 12 -#define DWC2_HCINT_FRM_LIST_ROLL (1 << 13) -#define DWC2_HCINT_FRM_LIST_ROLL_OFFSET 13 -#define DWC2_HCINTMSK_XFERCOMPL (1 << 0) -#define DWC2_HCINTMSK_XFERCOMPL_OFFSET 0 -#define DWC2_HCINTMSK_CHHLTD (1 << 1) -#define DWC2_HCINTMSK_CHHLTD_OFFSET 1 -#define DWC2_HCINTMSK_AHBERR (1 << 2) -#define DWC2_HCINTMSK_AHBERR_OFFSET 2 -#define DWC2_HCINTMSK_STALL (1 << 3) -#define DWC2_HCINTMSK_STALL_OFFSET 3 -#define DWC2_HCINTMSK_NAK (1 << 4) -#define DWC2_HCINTMSK_NAK_OFFSET 4 -#define DWC2_HCINTMSK_ACK (1 << 5) -#define DWC2_HCINTMSK_ACK_OFFSET 5 -#define DWC2_HCINTMSK_NYET (1 << 6) -#define DWC2_HCINTMSK_NYET_OFFSET 6 -#define DWC2_HCINTMSK_XACTERR (1 << 7) -#define DWC2_HCINTMSK_XACTERR_OFFSET 7 -#define DWC2_HCINTMSK_BBLERR (1 << 8) -#define DWC2_HCINTMSK_BBLERR_OFFSET 8 -#define DWC2_HCINTMSK_FRMOVRUN (1 << 9) -#define DWC2_HCINTMSK_FRMOVRUN_OFFSET 9 -#define DWC2_HCINTMSK_DATATGLERR (1 << 10) -#define DWC2_HCINTMSK_DATATGLERR_OFFSET 10 -#define DWC2_HCINTMSK_BNA (1 << 11) -#define DWC2_HCINTMSK_BNA_OFFSET 11 -#define DWC2_HCINTMSK_XCS_XACT (1 << 12) -#define DWC2_HCINTMSK_XCS_XACT_OFFSET 12 -#define DWC2_HCINTMSK_FRM_LIST_ROLL (1 << 13) -#define DWC2_HCINTMSK_FRM_LIST_ROLL_OFFSET 13 -#define DWC2_HCTSIZ_XFERSIZE_MASK 0x7ffff -#define DWC2_HCTSIZ_XFERSIZE_OFFSET 0 -#define DWC2_HCTSIZ_SCHINFO_MASK 0xff -#define DWC2_HCTSIZ_SCHINFO_OFFSET 0 -#define DWC2_HCTSIZ_NTD_MASK (0xff << 8) -#define DWC2_HCTSIZ_NTD_OFFSET 8 -#define DWC2_HCTSIZ_PKTCNT_MASK (0x3ff << 19) -#define DWC2_HCTSIZ_PKTCNT_OFFSET 19 -#define DWC2_HCTSIZ_PID_MASK (0x3 << 29) -#define DWC2_HCTSIZ_PID_OFFSET 29 -#define DWC2_HCTSIZ_DOPNG (1 << 31) -#define DWC2_HCTSIZ_DOPNG_OFFSET 31 -#define DWC2_HCDMA_CTD_MASK (0xFF << 3) -#define DWC2_HCDMA_CTD_OFFSET 3 -#define DWC2_HCDMA_DMA_ADDR_MASK (0x1FFFFF << 11) -#define DWC2_HCDMA_DMA_ADDR_OFFSET 11 -#define DWC2_PCGCCTL_STOPPCLK (1 << 0) -#define DWC2_PCGCCTL_STOPPCLK_OFFSET 0 -#define DWC2_PCGCCTL_GATEHCLK (1 << 1) -#define DWC2_PCGCCTL_GATEHCLK_OFFSET 1 -#define DWC2_PCGCCTL_PWRCLMP (1 << 2) -#define DWC2_PCGCCTL_PWRCLMP_OFFSET 2 -#define DWC2_PCGCCTL_RSTPDWNMODULE (1 << 3) -#define DWC2_PCGCCTL_RSTPDWNMODULE_OFFSET 3 -#define DWC2_PCGCCTL_PHYSUSPENDED (1 << 4) -#define DWC2_PCGCCTL_PHYSUSPENDED_OFFSET 4 -#define DWC2_PCGCCTL_ENBL_SLEEP_GATING (1 << 5) -#define DWC2_PCGCCTL_ENBL_SLEEP_GATING_OFFSET 5 -#define DWC2_PCGCCTL_PHY_IN_SLEEP (1 << 6) -#define DWC2_PCGCCTL_PHY_IN_SLEEP_OFFSET 6 -#define DWC2_PCGCCTL_DEEP_SLEEP (1 << 7) -#define DWC2_PCGCCTL_DEEP_SLEEP_OFFSET 7 -#define DWC2_SNPSID_DEVID_VER_2xx (0x4f542 << 12) -#define DWC2_SNPSID_DEVID_VER_3xx (0x4f543 << 12) -#define DWC2_SNPSID_DEVID_MASK (0xfffff << 12) -#define DWC2_SNPSID_DEVID_OFFSET 12 - -/* Host controller specific */ -#define DWC2_HC_PID_DATA0 0 -#define DWC2_HC_PID_DATA2 1 -#define DWC2_HC_PID_DATA1 2 -#define DWC2_HC_PID_MDATA 3 -#define DWC2_HC_PID_SETUP 3 - -/* roothub.a masks */ -#define RH_A_NDP (0xff << 0) /* number of downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* over current protection mode */ -#define RH_A_NOCP (1 << 12) /* no over current protection */ -#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ - -/* roothub.b masks */ -#define RH_B_DR 0x0000ffff /* device removable flags */ -#define RH_B_PPCM 0xffff0000 /* port power control mask */ - -/* Default driver configuration */ -#define CONFIG_DWC2_MAX_CHANNELS 16 /* Max # of EPs */ -#define CONFIG_DWC2_HOST_RX_FIFO_SIZE (516 + CONFIG_DWC2_MAX_CHANNELS) -#define CONFIG_DWC2_HOST_NPERIO_TX_FIFO_SIZE 0x100 /* nPeriodic TX FIFO */ -#define CONFIG_DWC2_HOST_PERIO_TX_FIFO_SIZE 0x200 /* Periodic TX FIFO */ -#define CONFIG_DWC2_MAX_TRANSFER_SIZE 65535 -#define CONFIG_DWC2_MAX_PACKET_COUNT 511 - -#define DWC2_PHY_TYPE_FS 0 -#define DWC2_PHY_TYPE_UTMI 1 -#define DWC2_PHY_TYPE_ULPI 2 -#define CONFIG_DWC2_PHY_TYPE DWC2_PHY_TYPE_UTMI /* PHY type */ -#define CONFIG_DWC2_UTMI_WIDTH 8 /* UTMI bus width (8/16) */ - -#define CONFIG_DWC2_PHY_ULPI_EXT_VBUS /* ULPI PHY controls VBUS */ -#define CONFIG_DWC2_TX_THR_LENGTH 64 - -#endif /* __DWC2_H__ */ diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 192c5ef9d1..f176babfa7 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -1,16 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * (C) Copyright 2010 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; version 2 of - * the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include <common.h> @@ -18,9 +8,9 @@ #include <linux/err.h> #include <driver.h> #include <init.h> -#include <usb/usb.h> -#include <usb/usb_defs.h> -#include <usb/ehci.h> +#include <linux/usb/usb.h> +#include <linux/usb/usb_defs.h> +#include <linux/usb/ehci.h> #include <errno.h> #include <io.h> @@ -28,7 +18,7 @@ struct atmel_ehci_priv { struct ehci_host *ehci; - struct device_d *dev; + struct device *dev; struct clk *iclk; struct clk *uclk; }; @@ -57,14 +47,7 @@ static void atmel_stop_clock(struct atmel_ehci_priv *atehci) clk_disable(atehci->uclk); } -static int atmel_ehci_detect(struct device_d *dev) -{ - struct atmel_ehci_priv *atehci = dev->priv; - - return ehci_detect(atehci->ehci); -} - -static int atmel_ehci_probe(struct device_d *dev) +static int atmel_ehci_probe(struct device *dev) { int ret; struct resource *iores; @@ -73,12 +56,11 @@ static int atmel_ehci_probe(struct device_d *dev) const char *uclk_name; struct ehci_host *ehci; - uclk_name = (dev->device_node) ? "usb_clk" : "uhpck"; + uclk_name = (dev->of_node) ? "usb_clk" : "uhpck"; atehci = xzalloc(sizeof(*atehci)); atehci->dev = dev; dev->priv = atehci; - dev->detect = atmel_ehci_detect; atehci->iclk = clk_get(dev, "ehci_clk"); if (IS_ERR(atehci->iclk)) { @@ -115,7 +97,7 @@ static int atmel_ehci_probe(struct device_d *dev) return 0; } -static void atmel_ehci_remove(struct device_d *dev) +static void atmel_ehci_remove(struct device *dev) { struct atmel_ehci_priv *atehci = dev->priv; @@ -131,8 +113,9 @@ static const struct of_device_id atmel_ehci_dt_ids[] = { { .compatible = "atmel,at91sam9g45-ehci" }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, atmel_ehci_dt_ids); -static struct driver_d atmel_ehci_driver = { +static struct driver atmel_ehci_driver = { .name = "atmel-ehci", .probe = atmel_ehci_probe, .remove = atmel_ehci_remove, diff --git a/drivers/usb/host/ehci-core.h b/drivers/usb/host/ehci-core.h index 584dd541ad..8f43783f7e 100644 --- a/drivers/usb/host/ehci-core.h +++ b/drivers/usb/host/ehci-core.h @@ -1,18 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /*- * Copyright (c) 2007-2008, Juniper Networks, Inc. * Copyright (c) 2008, Excito Elektronik i SkÃ¥ne AB * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2 of - * the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #ifndef USB_EHCI_CORE_H diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index ead63b2c9f..7ae3a285a0 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1,26 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0-only /*- * Copyright (c) 2007-2008, Juniper Networks, Inc. * Copyright (c) 2008, Excito Elektronik i SkÃ¥ne AB * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it> * * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2 of - * the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ /*#define DEBUG */ #include <common.h> #include <dma.h> #include <asm/byteorder.h> -#include <usb/usb.h> +#include <linux/usb/usb.h> #include <io.h> #include <malloc.h> #include <driver.h> @@ -29,15 +19,17 @@ #include <clock.h> #include <errno.h> #include <of.h> -#include <usb/ehci.h> +#include <linux/usb/ehci.h> #include <linux/err.h> #include <linux/sizes.h> +#include <linux/clk.h> +#include <linux/phy/phy.h> #include "ehci.h" struct ehci_host { int rootdev; - struct device_d *dev; + struct device *dev; struct ehci_hccr *hccr; struct ehci_hcor *hcor; struct usb_host host; @@ -240,7 +232,7 @@ static int ehci_td_buffer(struct qTD *td, dma_addr_t addr, size_t sz) } if (idx == buffer_count) { - pr_debug("out of buffer pointers (%u bytes left)\n", sz); + pr_debug("out of buffer pointers (%zu bytes left)\n", sz); return -ENOMEM; } @@ -250,7 +242,7 @@ static int ehci_td_buffer(struct qTD *td, dma_addr_t addr, size_t sz) return 0; } -static int ehci_prepare_qtd(struct device_d *dev, +static int ehci_prepare_qtd(struct device *dev, struct qTD *td, uint32_t token, void *buffer, size_t length, dma_addr_t *buffer_dma, @@ -305,15 +297,17 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, struct usb_host *host = dev->host; struct ehci_host *ehci = to_ehci(host); const bool dir_in = usb_pipein(pipe); - dma_addr_t buffer_dma, req_dma; + dma_addr_t buffer_dma = DMA_ERROR_CODE, req_dma; struct QH *qh = &ehci->qh_list[1]; struct qTD *td; + volatile struct qTD *vtd; uint32_t *tdp; uint32_t endpt, token, usbsts; uint32_t status; uint32_t toggle; bool c; int ret; + uint64_t start, timeout_val; dev_dbg(ehci->dev, "pipe=%lx, buffer=%p, length=%d, req=%p\n", pipe, @@ -442,13 +436,18 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, return ret; } - ret = handshake(&ehci->hcor->or_usbsts, STS_USBINT, STS_USBINT, - timeout_ms * 1000); - if (ret < 0) { - ehci_enable_async_schedule(ehci, false); - ehci_writel(&qh->qt_token, 0); - return -ETIMEDOUT; - } + /* Wait for TDs to be processed. */ + timeout_val = timeout_ms * MSECOND; + start = get_time_ns(); + vtd = td; + do { + token = hc32_to_cpu(vtd->qt_token); + if (is_timeout_non_interruptible(start, timeout_val)) { + ehci_enable_async_schedule(ehci, false); + ehci_writel(&qh->qt_token, 0); + return -ETIMEDOUT; + } + } while (token & QT_TOKEN_STATUS_ACTIVE); if (req) dma_unmap_single(ehci->dev, req_dma, sizeof(*req), @@ -511,7 +510,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, } #if defined(CONFIG_MACH_EFIKA_MX_SMARTBOOK) && defined(CONFIG_USB_ULPI) -#include <usb/ulpi.h> +#include <linux/usb/ulpi.h> /* * Add support for setting CHRGVBUS to workaround a hardware bug on efika mx/sb * boards. @@ -1342,12 +1341,7 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, return result; } -int ehci_detect(struct ehci_host *ehci) -{ - return usb_host_detect(&ehci->host); -} - -struct ehci_host *ehci_register(struct device_d *dev, struct ehci_data *data) +struct ehci_host *ehci_register(struct device *dev, struct ehci_data *data) { struct usb_host *host; struct ehci_host *ehci; @@ -1404,20 +1398,16 @@ void ehci_unregister(struct ehci_host *ehci) free(ehci); } -static int ehci_dev_detect(struct device_d *dev) -{ - struct ehci_host *ehci = dev->priv; - - return ehci_detect(ehci); -} - -static int ehci_probe(struct device_d *dev) +static int ehci_probe(struct device *dev) { struct resource *iores; struct ehci_data data = {}; struct ehci_platform_data *pdata = dev->platform_data; - struct device_node *dn = dev->device_node; + struct device_node *dn = dev->of_node; struct ehci_host *ehci; + struct clk_bulk_data *clks; + int num_clocks, ret; + struct phy *usb2_generic_phy; if (pdata) data.flags = pdata->flags; @@ -1431,6 +1421,27 @@ static int ehci_probe(struct device_d *dev) */ data.flags = EHCI_HAS_TT; + usb2_generic_phy = phy_optional_get(dev, "usb"); + if (IS_ERR(usb2_generic_phy)) + return PTR_ERR(usb2_generic_phy); + + ret = phy_init(usb2_generic_phy); + if (ret) + return ret; + + ret = phy_power_on(usb2_generic_phy); + if (ret) + return ret; + + ret = clk_bulk_get_all(dev, &clks); + if (ret < 0) + return ret; + + num_clocks = ret; + ret = clk_bulk_enable(num_clocks, clks); + if (ret) + return ret; + iores = dev_request_mem_resource(dev, 0); if (IS_ERR(iores)) return PTR_ERR(iores); @@ -1450,12 +1461,11 @@ static int ehci_probe(struct device_d *dev) return PTR_ERR(ehci); dev->priv = ehci; - dev->detect = ehci_dev_detect; return 0; } -static void ehci_remove(struct device_d *dev) +static void ehci_remove(struct device *dev) { struct ehci_host *ehci = dev->priv; @@ -1469,8 +1479,9 @@ static __maybe_unused struct of_device_id ehci_platform_dt_ids[] = { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, ehci_platform_dt_ids); -static struct driver_d ehci_driver = { +static struct driver ehci_driver = { .name = "ehci", .probe = ehci_probe, .remove = ehci_remove, diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index fc5a54f671..e364796a1a 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -1,8 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2010 Michael Grzeschik <mgr@pengutronix.de> - * - * This file is released under the GPLv2 - * */ /* @@ -12,16 +10,16 @@ /*-------------------------------------------------------------------------*/ #include <mfd/twl4030.h> -#include <usb/twl4030.h> -#include <mach/ehci.h> +#include <linux/usb/twl4030.h> +#include <mach/omap/ehci.h> #include <common.h> #include <io.h> #include <clock.h> #include <gpio.h> -#include <mach/omap3-silicon.h> -#include <mach/omap3-clock.h> -#include <mach/cm-regbits-34xx.h> -#include <mach/sys_info.h> +#include <mach/omap/omap3-silicon.h> +#include <mach/omap/omap3-clock.h> +#include <mach/omap/cm-regbits-34xx.h> +#include <mach/omap/sys_info.h> void omap_usb_utmi_init(struct omap_hcd *omap, u8 tll_channel_mask) { diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index e88e37e14c..49196bfc7d 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -1,18 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /*- * Copyright (c) 2007-2008, Juniper Networks, Inc. * Copyright (c) 2008, Michael Trimarchi <trimarchimichael@yahoo.it> * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2 of - * the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #ifndef USB_EHCI_H @@ -53,7 +43,6 @@ struct ehci_hcor { #define STD_ASS (1 << 15) #define STS_PSS (1 << 14) #define STS_HALT (1 << 12) -#define STS_USBINT BIT(0) uint32_t or_usbintr; uint32_t or_frindex; uint32_t or_ctrldssegment; diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 05ed2876c6..867c0977be 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -1,30 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * (C) Copyright 2010 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; version 2 of - * the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include <common.h> #include <linux/clk.h> #include <driver.h> #include <init.h> -#include <usb/usb.h> -#include <usb/usb_defs.h> +#include <linux/usb/usb.h> +#include <linux/usb/usb_defs.h> #include <errno.h> #include <gpio.h> #include <of_gpio.h> #include <io.h> -#include <mach/board.h> +#include <mach/at91/board.h> #include "ohci.h" @@ -33,7 +23,7 @@ struct ohci_at91_priv { - struct device_d *dev; + struct device *dev; struct clk *iclk; struct clk *fclk; struct ohci_regs __iomem *regs; @@ -64,13 +54,13 @@ static void at91_stop_clock(struct ohci_at91_priv *ohci_at91) clk_disable(ohci_at91->iclk); } -static int at91_ohci_probe_dt(struct device_d *dev) +static int at91_ohci_probe_dt(struct device *dev) { u32 ports; int i, ret, gpio; enum of_gpio_flags flags; struct at91_usbh_data *pdata; - struct device_node *np = dev->device_node; + struct device_node *np = dev->of_node; pdata = xzalloc(sizeof(*pdata)); dev->platform_data = pdata; @@ -117,7 +107,7 @@ static int at91_ohci_probe_dt(struct device_d *dev) return 0; } -static int at91_ohci_probe(struct device_d *dev) +static int at91_ohci_probe(struct device *dev) { int ret; struct resource *io; @@ -126,7 +116,7 @@ static int at91_ohci_probe(struct device_d *dev) dev->priv = ohci_at91; ohci_at91->dev = dev; - if (dev->device_node) { + if (dev->of_node) { ret = at91_ohci_probe_dt(dev); if (ret < 0) return ret; @@ -169,7 +159,7 @@ static int at91_ohci_probe(struct device_d *dev) return 0; } -static void at91_ohci_remove(struct device_d *dev) +static void at91_ohci_remove(struct device *dev) { struct at91_usbh_data *pdata = dev->platform_data; struct ohci_at91_priv *ohci_at91 = dev->priv; @@ -204,8 +194,9 @@ static const struct of_device_id at91_ohci_dt_ids[] = { { .compatible = "atmel,at91rm9200-ohci" }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids); -static struct driver_d at91_ohci_driver = { +static struct driver at91_ohci_driver = { .name = "at91_ohci", .probe = at91_ohci_probe, .remove = at91_ohci_remove, diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index a28c48b4c8..ae4c34e818 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * URB OHCI HCD (Host Controller Driver) for USB on the AT91RM9200 and PCI bus. * @@ -16,18 +17,6 @@ * * Modified for the MP2USB by (C) Copyright 2005 Eric Benard * ebenard@eukrea.com - based on s3c24x0's driver - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * */ /* * IMPORTANT NOTES @@ -38,12 +27,11 @@ * to activate workaround for bug #41 or this driver will NOT work! */ #include <common.h> -#include <dma.h> #include <clock.h> #include <dma.h> #include <malloc.h> -#include <usb/usb.h> -#include <usb/usb_defs.h> +#include <linux/usb/usb.h> +#include <linux/usb/usb_defs.h> #include <init.h> #include <errno.h> #include <linux/err.h> @@ -854,7 +842,8 @@ static void td_fill(struct ohci *ohci, unsigned int info, td->hwNextTD = virt_to_phys((void *)m32_swap((unsigned long)td_pt)); - dma_sync_single_for_device((unsigned long)data, len, DMA_BIDIRECTIONAL); + dma_sync_single_for_device(ohci->host.hw_dev, (unsigned long)data, + len, DMA_BIDIRECTIONAL); /* append to queue */ td->ed->hwTailP = td->hwNextTD; @@ -1090,7 +1079,7 @@ static int dl_done_list(struct ohci *ohci) unsigned long ptdphys = virt_to_phys(ptd); struct td *td_list; - dma_sync_single_for_device((unsigned long)ptdphys, + dma_sync_single_for_device(ohci->host.hw_dev, (unsigned long)ptdphys, sizeof(struct td) * NUM_TD, DMA_BIDIRECTIONAL); td_list = dl_reverse_done_list(ohci); @@ -1527,7 +1516,7 @@ static int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *b dev->status = stat; dev->act_len = urb->actual_length; - dma_sync_single_for_cpu((unsigned long)buffer, transfer_len, + dma_sync_single_for_cpu(host->hw_dev, (unsigned long)buffer, transfer_len, DMA_BIDIRECTIONAL); pkt_print(urb, dev, pipe, buffer, transfer_len, @@ -1787,7 +1776,7 @@ static int ohci_init(struct usb_host *host) return 0; } -static int ohci_probe(struct device_d *dev) +static int ohci_probe(struct device *dev) { struct resource *iores; struct usb_host *host; @@ -1822,7 +1811,7 @@ static int ohci_probe(struct device_d *dev) return 0; } -static struct driver_d ohci_driver = { +static struct driver ohci_driver = { .name = "ohci", .probe = ohci_probe, }; diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 9c9b8375ce..7d70bcb719 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * URB OHCI HCD (Host Controller Driver) for USB. * diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index f66dadef12..e962bfde3f 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0-or-later /* * USB HOST XHCI Controller stack * @@ -20,8 +20,8 @@ #include <io.h> #include <linux/err.h> #include <linux/sizes.h> -#include <usb/usb.h> -#include <usb/xhci.h> +#include <linux/usb/usb.h> +#include <linux/usb/xhci.h> #include <asm/unaligned.h> #include "xhci.h" @@ -82,11 +82,11 @@ static void xhci_free(struct xhci_ctrl *ctrl, void *ptr) * @param size size of memory to be allocated * @return allocates the memory and returns the aligned pointer */ -static void *xhci_malloc(struct xhci_ctrl *ctrl, unsigned int size) +static void *xhci_malloc(struct xhci_ctrl *ctrl, unsigned int size, dma_addr_t *dma_addr) { void *ptr; - ptr = dma_alloc_coherent(size, DMA_ADDRESS_BROKEN); + ptr = dma_alloc_coherent(size, dma_addr); if (!ptr) return NULL; @@ -145,7 +145,7 @@ static void xhci_scratchpad_free(struct xhci_ctrl *ctrl) ctrl->dcbaa->dev_context_ptrs[0] = 0; - xhci_free(ctrl, (void *)(uintptr_t)ctrl->scratchpad->sp_array[0]); + xhci_free(ctrl, ctrl->scratchpad->scratchpad); xhci_free(ctrl, ctrl->scratchpad->sp_array); free(ctrl->scratchpad); ctrl->scratchpad = NULL; @@ -234,14 +234,13 @@ static void xhci_link_segments(struct xhci_segment *prev, struct xhci_segment *next, bool link_trbs) { u32 val; - u64 val_64 = 0; if (!prev || !next) return; prev->next = next; if (link_trbs) { - val_64 = (uintptr_t)next->trbs; - prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = val_64; + prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = + cpu_to_le64(next->dma); /* * Set the last TRB in the segment to @@ -249,8 +248,7 @@ static void xhci_link_segments(struct xhci_segment *prev, */ val = le32_to_cpu(prev->trbs[TRBS_PER_SEGMENT-1].link.control); val &= ~TRB_TYPE_BITMASK; - val |= (TRB_LINK << TRB_TYPE_SHIFT); - + val |= TRB_TYPE(TRB_LINK); prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val); } } @@ -295,7 +293,7 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_ctrl *ctrl) seg = xzalloc(sizeof(*seg)); - seg->trbs = xhci_malloc(ctrl, SEGMENT_SIZE); + seg->trbs = xhci_malloc(ctrl, SEGMENT_SIZE, &seg->dma); return seg; } @@ -365,6 +363,7 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl) struct xhci_hccr *hccr = ctrl->hccr; struct xhci_hcor *hcor = ctrl->hcor; struct xhci_scratchpad *scratchpad; + dma_addr_t val_64; int num_sp; uint32_t page_size; void *buf; @@ -379,11 +378,11 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl) goto fail_sp; ctrl->scratchpad = scratchpad; - scratchpad->sp_array = xhci_malloc(ctrl, num_sp * sizeof(u64)); + scratchpad->sp_array = xhci_malloc(ctrl, num_sp * sizeof(u64), &val_64); if (!scratchpad->sp_array) goto fail_sp2; - ctrl->dcbaa->dev_context_ptrs[0] = - cpu_to_le64((uintptr_t)scratchpad->sp_array); + + ctrl->dcbaa->dev_context_ptrs[0] = cpu_to_le64(val_64); xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[0], sizeof(ctrl->dcbaa->dev_context_ptrs[0])); @@ -397,17 +396,21 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl) BUG_ON(i == 16); page_size = 1 << (i + 12); - buf = xhci_malloc(ctrl, num_sp * page_size); + buf = xhci_malloc(ctrl, num_sp * page_size, &val_64); if (!buf) goto fail_sp3; xhci_flush_cache((uintptr_t)buf, num_sp * page_size); + scratchpad->scratchpad = buf; for (i = 0; i < num_sp; i++) { - uintptr_t ptr = (uintptr_t)buf + i * page_size; - scratchpad->sp_array[i] = cpu_to_le64(ptr); + scratchpad->sp_array[i] = cpu_to_le64(val_64); + val_64 += page_size; } + xhci_flush_cache((uintptr_t)scratchpad->sp_array, + sizeof(u64) * num_sp); + return 0; fail_sp3: @@ -438,11 +441,11 @@ static struct xhci_container_ctx BUG_ON((type != XHCI_CTX_TYPE_DEVICE) && (type != XHCI_CTX_TYPE_INPUT)); ctx->type = type; ctx->size = (MAX_EP_CTX_NUM + 1) * - CTX_SIZE(readl(&ctrl->hccr->cr_hccparams)); + CTX_SIZE(xhci_readl(&ctrl->hccr->cr_hccparams)); if (type == XHCI_CTX_TYPE_INPUT) - ctx->size += CTX_SIZE(readl(&ctrl->hccr->cr_hccparams)); + ctx->size += CTX_SIZE(xhci_readl(&ctrl->hccr->cr_hccparams)); - ctx->bytes = xhci_malloc(ctrl, ctx->size); + ctx->bytes = xhci_malloc(ctrl, ctx->size, &ctx->dma); return ctx; } @@ -464,8 +467,7 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id) return -EEXIST; } - ctrl->devs[slot_id] = (struct xhci_virt_device *) - malloc(sizeof(struct xhci_virt_device)); + ctrl->devs[slot_id] = malloc(sizeof(struct xhci_virt_device)); if (!ctrl->devs[slot_id]) { dev_err(ctrl->dev, "Failed to allocate virtual device\n"); @@ -494,10 +496,10 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id) /* Allocate endpoint 0 ring */ virt_dev->eps[0].ring = xhci_ring_alloc(ctrl, 1, true); - byte_64 = (uintptr_t)(virt_dev->out_ctx->bytes); + byte_64 = virt_dev->out_ctx->dma; /* Point to output device context in dcbaa. */ - ctrl->dcbaa->dev_context_ptrs[slot_id] = byte_64; + ctrl->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(byte_64); xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[slot_id], sizeof(__le64)); @@ -516,29 +518,27 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id) int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, struct xhci_hcor *hcor) { + dma_addr_t dma; uint64_t val_64; uint64_t trb_64; uint32_t val; - unsigned long deq; + uint64_t deq; int i; struct xhci_segment *seg; /* DCBAA initialization */ - ctrl->dcbaa = xhci_malloc(ctrl, sizeof(*ctrl->dcbaa)); - if (!ctrl->dcbaa) { - dev_err(ctrl->dev, "unable to allocate DCBA\n"); - return -ENOMEM; - } + ctrl->dcbaa = xhci_malloc(ctrl, sizeof(struct xhci_device_context_array), + &dma); + ctrl->dcbaa->dma = dma; - val_64 = (uintptr_t)ctrl->dcbaa; /* Set the pointer in DCBAA register */ - xhci_writeq(&hcor->or_dcbaap, val_64); + xhci_writeq(&hcor->or_dcbaap, dma); /* Command ring control pointer register initialization */ ctrl->cmd_ring = xhci_ring_alloc(ctrl, 1, true); /* Set the address in the Command Ring Control register */ - trb_64 = (uintptr_t)ctrl->cmd_ring->first_seg->trbs; + trb_64 = ctrl->cmd_ring->first_seg->dma; val_64 = xhci_readq(&hcor->or_crcr); val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) | (trb_64 & (u64) ~CMD_RING_RSVD_BITS) | @@ -560,8 +560,8 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, /* Event ring does not maintain link TRB */ ctrl->event_ring = xhci_ring_alloc(ctrl, ERST_NUM_SEGS, false); - ctrl->erst.entries = - xhci_malloc(ctrl, sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS); + ctrl->erst.entries = xhci_malloc(ctrl, sizeof(struct xhci_erst_entry) * + ERST_NUM_SEGS, &ctrl->erst.erst_dma_addr); ctrl->erst.num_entries = ERST_NUM_SEGS; @@ -570,9 +570,8 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, val++) { struct xhci_erst_entry *entry = &ctrl->erst.entries[val]; - trb_64 = 0; - trb_64 = (uintptr_t)seg->trbs; - xhci_writeq(&entry->seg_addr, trb_64); + trb_64 = seg->dma; + entry->seg_addr = cpu_to_le64(trb_64); entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT); entry->rsvd = 0; seg = seg->next; @@ -580,7 +579,8 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, xhci_flush_cache((uintptr_t)ctrl->erst.entries, ERST_NUM_SEGS * sizeof(struct xhci_erst_entry)); - deq = (unsigned long)ctrl->event_ring->dequeue; + deq = xhci_trb_virt_to_dma(ctrl->event_ring->deq_seg, + ctrl->event_ring->dequeue); /* Update HC event ring dequeue pointer */ xhci_writeq(&ctrl->ir_set->erst_dequeue, @@ -595,7 +595,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, /* this is the event ring segment table pointer */ val_64 = xhci_readq(&ctrl->ir_set->erst_base); val_64 &= ERST_PTR_MASK; - val_64 |= ((uintptr_t)(ctrl->erst.entries) & ~ERST_PTR_MASK); + val_64 |= ctrl->erst.erst_dma_addr & ~ERST_PTR_MASK; xhci_writeq(&ctrl->ir_set->erst_base, val_64); @@ -645,7 +645,7 @@ struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_ctrl *ctrl, return (struct xhci_slot_ctx *)ctx->bytes; return (struct xhci_slot_ctx *) - (ctx->bytes + CTX_SIZE(readl(&ctrl->hccr->cr_hccparams))); + (ctx->bytes + CTX_SIZE(xhci_readl(&ctrl->hccr->cr_hccparams))); } /** @@ -667,7 +667,7 @@ struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_ctrl *ctrl, return (struct xhci_ep_ctx *) (ctx->bytes + - (ep_index * CTX_SIZE(readl(&ctrl->hccr->cr_hccparams)))); + (ep_index * CTX_SIZE(xhci_readl(&ctrl->hccr->cr_hccparams)))); } /** @@ -776,7 +776,7 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, dev_dbg(&udev->dev, "route string 0x%x\n", route); - slot_ctx->dev_info |= route; + slot_ctx->dev_info |= cpu_to_le32(route); switch (speed) { case USB_SPEED_SUPER: @@ -824,25 +824,22 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, /* Step 4 - ring already allocated */ /* Step 5 */ - ep0_ctx->ep_info2 = cpu_to_le32(CTRL_EP << EP_TYPE_SHIFT); + ep0_ctx->ep_info2 = cpu_to_le32(EP_TYPE(CTRL_EP)); dev_dbg(&udev->dev, "SPEED = %d\n", speed); switch (speed) { case USB_SPEED_SUPER: - ep0_ctx->ep_info2 |= cpu_to_le32(((512 & MAX_PACKET_MASK) << - MAX_PACKET_SHIFT)); + ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(512)); dev_dbg(&udev->dev, "Setting Packet size = 512bytes\n"); break; case USB_SPEED_HIGH: /* USB core guesses at a 64-byte max packet first for FS devices */ case USB_SPEED_FULL: - ep0_ctx->ep_info2 |= cpu_to_le32(((64 & MAX_PACKET_MASK) << - MAX_PACKET_SHIFT)); + ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(64)); dev_dbg(&udev->dev, "Setting Packet size = 64bytes\n"); break; case USB_SPEED_LOW: - ep0_ctx->ep_info2 |= cpu_to_le32(((8 & MAX_PACKET_MASK) << - MAX_PACKET_SHIFT)); + ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(8)); dev_dbg(&udev->dev, "Setting Packet size = 8bytes\n"); break; default: @@ -851,11 +848,9 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, } /* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */ - ep0_ctx->ep_info2 |= - cpu_to_le32(((0 & MAX_BURST_MASK) << MAX_BURST_SHIFT) | - ((3 & ERROR_COUNT_MASK) << ERROR_COUNT_SHIFT)); + ep0_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(0) | ERROR_COUNT(3)); - trb_64 = (uintptr_t)virt_dev->eps[0].ring->first_seg->trbs; + trb_64 = virt_dev->eps[0].ring->first_seg->dma; ep0_ctx->deq = cpu_to_le64(trb_64 | virt_dev->eps[0].ring->cycle_state); /* diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 61b1b55a27..691d9c7463 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0-or-later /* * USB HOST XHCI Controller stack * @@ -19,12 +19,30 @@ #include <io.h> #include <linux/err.h> #include <linux/sizes.h> -#include <usb/usb.h> -#include <usb/xhci.h> +#include <linux/usb/usb.h> +#include <linux/usb/xhci.h> #include <asm/unaligned.h> #include "xhci.h" +/* + * Returns zero if the TRB isn't in this segment, otherwise it returns the DMA + * address of the TRB. + */ +dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, + union xhci_trb *trb) +{ + unsigned long segment_offset; + + BUG_ON(!seg || !trb || trb < seg->trbs); + + /* offset in TRBs */ + segment_offset = trb - seg->trbs; + BUG_ON(segment_offset >= TRBS_PER_SEGMENT); + + return seg->dma + (segment_offset * sizeof(*trb)); +} + /** * Is this TRB a link TRB or was the last TRB the last TRB in this event ring * segment? I.e. would the updated event TRB pointer step off the end of the @@ -181,12 +199,11 @@ static void inc_deq(struct xhci_ctrl *ctrl, struct xhci_ring *ring) * @param trb_fields pointer to trb field array containing TRB contents * @return pointer to the enqueued trb */ -static struct xhci_generic_trb *queue_trb(struct xhci_ctrl *ctrl, - struct xhci_ring *ring, - bool more_trbs_coming, - unsigned int *trb_fields) +static dma_addr_t queue_trb(struct xhci_ctrl *ctrl, struct xhci_ring *ring, + bool more_trbs_coming, unsigned int *trb_fields) { struct xhci_generic_trb *trb; + dma_addr_t addr; int i; trb = &ring->enqueue->generic; @@ -196,9 +213,11 @@ static struct xhci_generic_trb *queue_trb(struct xhci_ctrl *ctrl, xhci_flush_cache((uintptr_t)trb, sizeof(struct xhci_generic_trb)); + addr = xhci_trb_virt_to_dma(ring->enq_seg, (union xhci_trb *)trb); + inc_enq(ctrl, ring, more_trbs_coming); - return trb; + return addr; } /** @@ -273,16 +292,15 @@ static int prepare_ring(struct xhci_ctrl *ctrl, struct xhci_ring *ep_ring, * @param cmd Command type to enqueue * @return none */ -void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, u32 slot_id, +void xhci_queue_command(struct xhci_ctrl *ctrl, dma_addr_t addr, u32 slot_id, u32 ep_index, trb_type cmd) { u32 fields[4]; - u64 val_64 = (uintptr_t)ptr; BUG_ON(prepare_ring(ctrl, ctrl->cmd_ring, EP_STATE_RUNNING)); - fields[0] = lower_32_bits(val_64); - fields[1] = upper_32_bits(val_64); + fields[0] = lower_32_bits(addr); + fields[1] = upper_32_bits(addr); fields[2] = 0; fields[3] = TRB_TYPE(cmd) | SLOT_ID_FOR_TRB(slot_id) | ctrl->cmd_ring->cycle_state; @@ -396,12 +414,15 @@ static void giveback_first_trb(struct usb_device *udev, int ep_index, */ void xhci_acknowledge_event(struct xhci_ctrl *ctrl) { + dma_addr_t deq; + /* Advance our dequeue pointer to the next event */ inc_deq(ctrl, ctrl->event_ring); /* Inform the hardware */ - xhci_writeq(&ctrl->ir_set->erst_dequeue, - (uintptr_t)ctrl->event_ring->dequeue | ERST_EHB); + deq = xhci_trb_virt_to_dma(ctrl->event_ring->deq_seg, + ctrl->event_ring->dequeue); + xhci_writeq(&ctrl->ir_set->erst_dequeue, deq | ERST_EHB); } /** @@ -436,7 +457,8 @@ static int event_ready(struct xhci_ctrl *ctrl) * @param expected TRB type expected from Event TRB * @return pointer to event trb */ -union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected) +union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected, + unsigned int timeout_ms) { trb_type type; uint64_t start = get_time_ns(); @@ -448,7 +470,8 @@ union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected) continue; type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->event_cmd.flags)); - if (type == expected) + if (type == expected || + (expected == TRB_NONE && type != TRB_PORT_STATUS)) return event; if (type == TRB_PORT_STATUS) @@ -461,7 +484,7 @@ union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected) le32_to_cpu(event->generic.field[2])) != COMP_SUCCESS); else - dev_err(ctrl->dev, "Unexpected XHCI event TRB, skipping... " + dev_dbg(ctrl->dev, "Unexpected XHCI event TRB, skipping... " "(%08x %08x %08x %08x)\n", le32_to_cpu(event->generic.field[0]), le32_to_cpu(event->generic.field[1]), @@ -469,13 +492,50 @@ union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected) le32_to_cpu(event->generic.field[3])); xhci_acknowledge_event(ctrl); - } while (!is_timeout_non_interruptible(start, 5 * SECOND)); + } while (!is_timeout_non_interruptible(start, timeout_ms * MSECOND)); if (expected == TRB_TRANSFER) return NULL; - dev_err(ctrl->dev, "XHCI timeout on event type %d... cannot recover.\n", expected); - BUG(); + dev_warn(ctrl->dev, "XHCI timeout on event type %d...\n", expected); + + return NULL; +} + +/* + * Send reset endpoint command for given endpoint. This recovers from a + * halted endpoint (e.g. due to a stall error). + */ +static void reset_ep(struct usb_device *udev, int ep_index, unsigned int timeout_ms) +{ + struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); + struct xhci_ring *ring = ctrl->devs[udev->slot_id]->eps[ep_index].ring; + union xhci_trb *event; + u64 addr; + u32 field; + + dev_info(&udev->dev, "Resetting EP %d...\n", ep_index); + + xhci_queue_command(ctrl, 0, udev->slot_id, ep_index, TRB_RESET_EP); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, timeout_ms); + if (!event) + return; + + field = le32_to_cpu(event->trans_event.flags); + BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id); + xhci_acknowledge_event(ctrl); + + addr = xhci_trb_virt_to_dma(ring->enq_seg, + (void *)((uintptr_t)ring->enqueue | ring->cycle_state)); + xhci_queue_command(ctrl, addr, udev->slot_id, ep_index, TRB_SET_DEQ); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, timeout_ms); + if (!event) + return; + + BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) + != udev->slot_id || GET_COMP_CODE(le32_to_cpu( + event->event_cmd.status)) != COMP_SUCCESS); + xhci_acknowledge_event(ctrl); } /* @@ -491,27 +551,49 @@ static void abort_td(struct usb_device *udev, int ep_index) struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); struct xhci_ring *ring = ctrl->devs[udev->slot_id]->eps[ep_index].ring; union xhci_trb *event; + xhci_comp_code comp; + trb_type type; + dma_addr_t addr; u32 field; - xhci_queue_command(ctrl, NULL, udev->slot_id, ep_index, TRB_STOP_RING); + xhci_queue_command(ctrl, 0, udev->slot_id, ep_index, TRB_STOP_RING); - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); - field = le32_to_cpu(event->trans_event.flags); - BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id); - BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); - BUG_ON(GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len - != COMP_STOP))); - xhci_acknowledge_event(ctrl); + event = xhci_wait_for_event(ctrl, TRB_NONE, XHCI_TIMEOUT_DEFAULT); + if (!event) + return; - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); - BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) - != udev->slot_id || GET_COMP_CODE(le32_to_cpu( - event->event_cmd.status)) != COMP_SUCCESS); + type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->event_cmd.flags)); + if (type == TRB_TRANSFER) { + field = le32_to_cpu(event->trans_event.flags); + BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id); + BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); + BUG_ON(GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len + != COMP_STOP))); + xhci_acknowledge_event(ctrl); + + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT); + if (!event) + return; + type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->event_cmd.flags)); + + } else { + dev_warn(ctrl->dev, "abort_td: Expected a TRB_TRANSFER TRB first\n"); + } + + comp = GET_COMP_CODE(le32_to_cpu(event->event_cmd.status)); + BUG_ON(type != TRB_COMPLETION || + TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) + != udev->slot_id || (comp != COMP_SUCCESS && comp + != COMP_CTX_STATE)); xhci_acknowledge_event(ctrl); - xhci_queue_command(ctrl, (void *)((uintptr_t)ring->enqueue | - ring->cycle_state), udev->slot_id, ep_index, TRB_SET_DEQ); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + addr = xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue); + addr |= ring->cycle_state; + xhci_queue_command(ctrl, addr, udev->slot_id, ep_index, TRB_SET_DEQ); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT); + if (!event) + return; + BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) != udev->slot_id || GET_COMP_CODE(le32_to_cpu( event->event_cmd.status)) != COMP_SUCCESS); @@ -557,7 +639,7 @@ static void record_transfer_result(struct usb_device *udev, * @return returns 0 if successful else -1 on failure */ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, - int length, void *buffer) + int length, void *buffer, unsigned int timeout_ms) { int num_trbs = 0; struct xhci_generic_trb *start_trb; @@ -601,7 +683,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, memcpy(bounce, buffer, length); } - map = addr = dma_map_single(ctrl->dev, bounce, length, direction); + map = addr = dma_map_single(ctrl->host.hw_dev, bounce, length, direction); dev_dbg(&udev->dev, "pipe=0x%lx, buffer=%p, length=%d\n", pipe, buffer, length); @@ -614,6 +696,14 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, ep_ctx = xhci_get_ep_ctx(ctrl, virt_dev->out_ctx, ep_index); + /* + * If the endpoint was halted due to a prior error, resume it before + * the next transfer. It is the responsibility of the upper layer to + * have dealt with whatever caused the error. + */ + if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) == EP_STATE_HALTED) + reset_ep(udev, ep_index, timeout_ms); + ring = virt_dev->eps[ep_index].ring; /* * How much data is (potentially) left before the 64KB boundary? @@ -646,8 +736,10 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, */ ret = prepare_ring(ctrl, ring, le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK); - if (ret < 0) + if (ret < 0) { + dma_unmap_single(ctrl->host.hw_dev, map, length, direction); return ret; + } /* * Don't give the first TRB to the hardware (by toggling the cycle bit) @@ -667,6 +759,9 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, first_trb = true; + /* flush the buffer before use */ + xhci_flush_cache((uintptr_t)buffer, length); + /* Queue the first TRB, even if it's zero-length */ do { u32 remainder = 0; @@ -703,15 +798,14 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, maxpacketsize, num_trbs - 1); - length_field = ((trb_buff_len & TRB_LEN_MASK) | + length_field = (TRB_LEN(trb_buff_len) | remainder | - ((0 & TRB_INTR_TARGET_MASK) << - TRB_INTR_TARGET_SHIFT)); + TRB_INTR_TARGET(0)); trb_fields[0] = lower_32_bits(addr); trb_fields[1] = upper_32_bits(addr); trb_fields[2] = length_field; - trb_fields[3] = field | (TRB_NORMAL << TRB_TYPE_SHIFT); + trb_fields[3] = field | TRB_TYPE(TRB_NORMAL); queue_trb(ctrl, ring, (num_trbs > 1), trb_fields); @@ -726,12 +820,13 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, giveback_first_trb(udev, ep_index, start_cycle, start_trb); - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); + event = xhci_wait_for_event(ctrl, TRB_TRANSFER, timeout_ms); if (!event) { dev_dbg(&udev->dev, "XHCI bulk transfer timed out, aborting...\n"); abort_td(udev, ep_index); udev->status = USB_ST_NAK_REC; /* closest thing to a timeout */ udev->act_len = 0; + dma_unmap_single(ctrl->host.hw_dev, map, length, direction); return -ETIMEDOUT; } field = le32_to_cpu(event->trans_event.flags); @@ -747,7 +842,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, record_transfer_result(udev, event, length); xhci_acknowledge_event(ctrl); - dma_unmap_single(ctrl->dev, map, length, direction); + dma_unmap_single(ctrl->host.hw_dev, map, length, direction); if (usb_pipein(pipe)) memcpy(buffer, bounce, length); @@ -767,7 +862,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, */ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, struct devrequest *req, int length, - void *buffer) + void *buffer, unsigned int timeout_ms) { int ret; int start_cycle; @@ -846,7 +941,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, /* Queue setup TRB - see section 6.4.1.2.1 */ /* FIXME better way to translate setup_packet into two u32 fields? */ field = 0; - field |= TRB_IDT | (TRB_SETUP << TRB_TYPE_SHIFT); + field |= TRB_IDT | TRB_TYPE(TRB_SETUP); if (start_cycle == 0) field |= 0x1; @@ -854,9 +949,9 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, if (HC_VERSION(xhci_readl(&ctrl->hccr->cr_capbase)) >= 0x100) { if (length > 0) { if (req->requesttype & USB_DIR_IN) - field |= (TRB_DATA_IN << TRB_TX_TYPE_SHIFT); + field |= TRB_TX_TYPE(TRB_DATA_IN); else - field |= (TRB_DATA_OUT << TRB_TX_TYPE_SHIFT); + field |= TRB_TX_TYPE(TRB_DATA_OUT); } } @@ -872,8 +967,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, trb_fields[1] = le16_to_cpu(req->index) | le16_to_cpu(req->length) << 16; /* TRB_LEN | (TRB_INTR_TARGET) */ - trb_fields[2] = (8 | ((0 & TRB_INTR_TARGET_MASK) << - TRB_INTR_TARGET_SHIFT)); + trb_fields[2] = (TRB_LEN(8) | TRB_INTR_TARGET(0)); /* Immediate data in pointer */ trb_fields[3] = field; queue_trb(ctrl, ep_ring, true, trb_fields); @@ -883,15 +977,15 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, /* If there's data, queue data TRBs */ /* Only set interrupt on short packet for IN endpoints */ if (usb_pipein(pipe)) - field = TRB_ISP | (TRB_DATA << TRB_TYPE_SHIFT); + field = TRB_ISP | TRB_TYPE(TRB_DATA); else - field = (TRB_DATA << TRB_TYPE_SHIFT); + field = TRB_TYPE(TRB_DATA); - length_field = (length & TRB_LEN_MASK) | xhci_td_remainder(length) | + length_field = TRB_LEN(length) | xhci_td_remainder(length) | ((0 & TRB_INTR_TARGET_MASK) << TRB_INTR_TARGET_SHIFT); dev_dbg(&udev->dev, "length_field = %d, length = %d," "xhci_td_remainder(length) = %d , TRB_INTR_TARGET(0) = %d\n", - length_field, (length & TRB_LEN_MASK), + length_field, TRB_LEN(length), xhci_td_remainder(length), 0); if (req->requesttype & USB_DIR_IN) @@ -902,13 +996,14 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, if (length > 0) { if (req->requesttype & USB_DIR_IN) field |= TRB_DIR_IN; - map = buf_64 = dma_map_single(ctrl->dev, buffer, length, direction); + map = buf_64 = dma_map_single(ctrl->host.hw_dev, buffer, length, direction); trb_fields[0] = lower_32_bits(buf_64); trb_fields[1] = upper_32_bits(buf_64); trb_fields[2] = length_field; trb_fields[3] = field | ep_ring->cycle_state; + xhci_flush_cache((uintptr_t)buffer, length); queue_trb(ctrl, ep_ring, true, trb_fields); } @@ -926,17 +1021,16 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, trb_fields[0] = 0; trb_fields[1] = 0; - trb_fields[2] = ((0 & TRB_INTR_TARGET_MASK) << TRB_INTR_TARGET_SHIFT); + trb_fields[2] = TRB_INTR_TARGET(0); /* Event on completion */ trb_fields[3] = field | TRB_IOC | - (TRB_STATUS << TRB_TYPE_SHIFT) | - ep_ring->cycle_state; + TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state; queue_trb(ctrl, ep_ring, false, trb_fields); giveback_first_trb(udev, ep_index, start_cycle, start_trb); - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); + event = xhci_wait_for_event(ctrl, TRB_TRANSFER, timeout_ms); if (!event) goto abort; field = le32_to_cpu(event->trans_event.flags); @@ -954,12 +1048,17 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, /* Invalidate buffer to make it available to usb-core */ if (length > 0) - dma_unmap_single(ctrl->dev, map, length, direction); + dma_unmap_single(ctrl->host.hw_dev, map, length, direction); + + if (udev->status == USB_ST_STALLED) { + reset_ep(udev, ep_index, timeout_ms); + return -EPIPE; + } if (GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len)) == COMP_SHORT_TX) { /* Short data stage, clear up additional status stage event */ - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); + event = xhci_wait_for_event(ctrl, TRB_TRANSFER, timeout_ms); if (!event) goto abort; BUG_ON(TRB_TO_SLOT_ID(field) != slot_id); @@ -974,5 +1073,6 @@ abort: abort_td(udev, ep_index); udev->status = USB_ST_NAK_REC; udev->act_len = 0; + dma_unmap_single(ctrl->host.hw_dev, map, length, direction); return -ETIMEDOUT; } diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 317000d650..e7b8344181 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0-or-later /* * USB HOST XHCI Controller stack * @@ -24,13 +24,13 @@ #include <init.h> #include <io.h> #include <linux/err.h> -#include <usb/usb.h> -#include <usb/xhci.h> +#include <linux/usb/usb.h> +#include <linux/usb/xhci.h> #include <asm/unaligned.h> #include "xhci.h" -static struct descriptor { +static const struct descriptor { struct usb_hub_descriptor hub; struct usb_device_descriptor device; struct usb_config_descriptor config; @@ -151,6 +151,8 @@ static int xhci_start(struct xhci_ctrl *ctrl) u32 temp; int ret; + dev_dbg(ctrl->dev, "Starting the controller\n"); + temp = xhci_readl(&hcor->or_usbcmd); temp |= (CMD_RUN); xhci_writel(&hcor->or_usbcmd, temp); @@ -441,9 +443,12 @@ static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change) in_ctx = virt_dev->in_ctx; xhci_flush_cache((uintptr_t)in_ctx->bytes, in_ctx->size); - xhci_queue_command(ctrl, in_ctx->bytes, udev->slot_id, 0, + xhci_queue_command(ctrl, in_ctx->dma, udev->slot_id, 0, ctx_change ? TRB_EVAL_CONTEXT : TRB_CONFIG_EP); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT); + if (!event) + return -ETIMEDOUT; + BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) != udev->slot_id); @@ -566,8 +571,7 @@ static int xhci_set_configuration(struct usb_device *udev) cpu_to_le32(EP_MAX_ESIT_PAYLOAD_HI(max_esit_payload) | EP_INTERVAL(interval) | EP_MULT(mult)); - ep_ctx[ep_index]->ep_info2 = - cpu_to_le32(ep_type << EP_TYPE_SHIFT); + ep_ctx[ep_index]->ep_info2 = cpu_to_le32(EP_TYPE(ep_type)); ep_ctx[ep_index]->ep_info2 |= cpu_to_le32(MAX_PACKET (get_unaligned(&endpt_desc->wMaxPacketSize))); @@ -579,8 +583,8 @@ static int xhci_set_configuration(struct usb_device *udev) cpu_to_le32(MAX_BURST(max_burst) | ERROR_COUNT(err_count)); - trb_64 = (uintptr_t) - virt_dev->eps[ep_index].ring->enqueue; + trb_64 = xhci_trb_virt_to_dma(virt_dev->eps[ep_index].ring->enq_seg, + virt_dev->eps[ep_index].ring->enqueue); ep_ctx[ep_index]->deq = cpu_to_le64(trb_64 | virt_dev->eps[ep_index].ring->cycle_state); @@ -628,8 +632,12 @@ static int xhci_address_device(struct usb_device *udev, int root_portnr) ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG); ctrl_ctx->drop_flags = 0; - xhci_queue_command(ctrl, (void *)ctrl_ctx, slot_id, 0, TRB_ADDR_DEV); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + xhci_queue_command(ctrl, virt_dev->in_ctx->dma, + slot_id, 0, TRB_ADDR_DEV); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT); + if (!event) + return -ETIMEDOUT; + BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) != slot_id); switch (GET_COMP_CODE(le32_to_cpu(event->event_cmd.status))) { @@ -703,8 +711,11 @@ static int _xhci_alloc_device(struct usb_device *udev) return 0; } - xhci_queue_command(ctrl, NULL, 0, 0, TRB_ENABLE_SLOT); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + xhci_queue_command(ctrl, 0, 0, 0, TRB_ENABLE_SLOT); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT); + if (!event) + return -ETIMEDOUT; + BUG_ON(GET_COMP_CODE(le32_to_cpu(event->event_cmd.status)) != COMP_SUCCESS); @@ -764,8 +775,7 @@ int xhci_check_maxpacket(struct usb_device *udev) ctrl->devs[slot_id]->out_ctx, ep_index); in_ctx = ctrl->devs[slot_id]->in_ctx; ep_ctx = xhci_get_ep_ctx(ctrl, in_ctx, ep_index); - ep_ctx->ep_info2 &= cpu_to_le32(~((0xffff & MAX_PACKET_MASK) - << MAX_PACKET_SHIFT)); + ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET(MAX_PACKET_MASK)); ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size)); /* @@ -860,7 +870,7 @@ static int xhci_submit_root(struct usb_device *udev, unsigned long pipe, { uint8_t tmpbuf[4]; u16 typeReq; - void *srcptr = NULL; + const void *srcptr = NULL; int len, srclen; uint32_t reg; volatile uint32_t *status_reg; @@ -928,7 +938,7 @@ static int xhci_submit_root(struct usb_device *udev, unsigned long pipe, case USB_DT_HUB: case USB_DT_SS_HUB: dev_dbg(&udev->dev, "USB_DT_HUB config\n"); - srcptr = &descriptor.hub; + srcptr = &ctrl->hub_desc; srclen = 0x8; break; default: @@ -1088,8 +1098,10 @@ unknown: static int _xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe, void *buffer, int length, int interval) { - if (usb_pipetype(pipe) != PIPE_INTERRUPT) + if (usb_pipetype(pipe) != PIPE_INTERRUPT) { + dev_err(&udev->dev, "non-interrupt pipe (type=%lu)", usb_pipetype(pipe)); return -EINVAL; + } /* * xHCI uses normal TRBs for both bulk and interrupt. When the @@ -1097,7 +1109,7 @@ static int _xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe, * (at most) one TD. A TD (comprised of sg list entries) can * take several service intervals to transmit. */ - return xhci_bulk_tx(udev, pipe, length, buffer); + return xhci_bulk_tx(udev, pipe, length, buffer, 0); } /** @@ -1112,10 +1124,12 @@ static int _xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe, static int _xhci_submit_bulk_msg(struct usb_device *udev, unsigned long pipe, void *buffer, int length, int timeout_ms) { - if (usb_pipetype(pipe) != PIPE_BULK) + if (usb_pipetype(pipe) != PIPE_BULK) { + dev_err(&udev->dev, "non-bulk pipe (type=%lu)", usb_pipetype(pipe)); return -EINVAL; + } - return xhci_bulk_tx(udev, pipe, length, buffer); + return xhci_bulk_tx(udev, pipe, length, buffer, timeout_ms); } /** @@ -1131,13 +1145,16 @@ static int _xhci_submit_bulk_msg(struct usb_device *udev, unsigned long pipe, */ static int _xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe, void *buffer, int length, - struct devrequest *setup, int root_portnr) + struct devrequest *setup, int root_portnr, + unsigned int timeout_ms) { struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); int ret = 0; - if (usb_pipetype(pipe) != PIPE_CONTROL) + if (usb_pipetype(pipe) != PIPE_CONTROL) { + dev_err(&udev->dev, "non-control pipe (type=%lu)", usb_pipetype(pipe)); return -EINVAL; + } if (usb_pipedevice(pipe) == ctrl->rootdev) return xhci_submit_root(udev, pipe, buffer, setup); @@ -1155,7 +1172,7 @@ static int _xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe, } } - return xhci_ctrl_tx(udev, pipe, setup, length, buffer); + return xhci_ctrl_tx(udev, pipe, setup, length, buffer, timeout_ms); } static int xhci_lowlevel_init(struct xhci_ctrl *ctrl) @@ -1180,21 +1197,23 @@ static int xhci_lowlevel_init(struct xhci_ctrl *ctrl) /* initializing xhci data structures */ if (xhci_mem_init(ctrl, hccr, hcor) < 0) return -ENOMEM; + ctrl->hub_desc = descriptor.hub; reg = xhci_readl(&hccr->cr_hcsparams1); - descriptor.hub.bNbrPorts = ((reg & HCS_MAX_PORTS_MASK) >> - HCS_MAX_PORTS_SHIFT); + ctrl->hub_desc.bNbrPorts = HCS_MAX_PORTS(reg); + + dev_dbg(ctrl->dev, "Register 0x%x NbrPorts %d\n", reg, ctrl->hub_desc.bNbrPorts); /* Port Indicators */ reg = xhci_readl(&hccr->cr_hccparams); if (HCS_INDICATOR(reg)) - put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) - | 0x80, &descriptor.hub.wHubCharacteristics); + put_unaligned(get_unaligned(&ctrl->hub_desc.wHubCharacteristics) + | 0x80, &ctrl->hub_desc.wHubCharacteristics); /* Port Power Control */ if (HCC_PPC(reg)) - put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics) - | 0x01, &descriptor.hub.wHubCharacteristics); + put_unaligned(get_unaligned(&ctrl->hub_desc.wHubCharacteristics) + | 0x01, &ctrl->hub_desc.wHubCharacteristics); if (xhci_start(ctrl)) { xhci_reset(ctrl); @@ -1217,6 +1236,8 @@ static int xhci_lowlevel_stop(struct xhci_ctrl *ctrl) xhci_reset(ctrl); + dev_dbg(ctrl->dev, "Disabling event ring interrupts\n"); + temp = xhci_readl(&ctrl->hcor->or_usbsts); xhci_writel(&ctrl->hcor->or_usbsts, temp & ~STS_EINT); temp = xhci_readl(&ctrl->ir_set->irq_pending); @@ -1239,7 +1260,7 @@ static int xhci_submit_control_msg(struct usb_device *udev, } return _xhci_submit_control_msg(udev, pipe, buffer, length, setup, - root_portnr); + root_portnr, timeout_ms); } static int xhci_submit_bulk_msg(struct usb_device *udev, @@ -1343,7 +1364,7 @@ static __maybe_unused int xhci_get_max_xfer_size(size_t *size) int xhci_register(struct xhci_ctrl *ctrl) { struct usb_host *host; - struct device_d *dev = ctrl->dev; + struct device *dev = ctrl->dev; int ret; dev_dbg(dev, "%s: hccr=%p, hcor=%p\n", __func__, ctrl->hccr, ctrl->hcor); @@ -1358,7 +1379,11 @@ int xhci_register(struct xhci_ctrl *ctrl) */ host->no_desc_before_addr = true; - host->hw_dev = dev; + /* + * If xHCI doesn't have its own DT node, it'll be a child of a + * physical USB host controller device that should be used for DMA + */ + host->hw_dev = dev_of_node(dev) ? dev : dev->parent; host->submit_int_msg = xhci_submit_int_msg; host->submit_control_msg = xhci_submit_control_msg; host->submit_bulk_msg = xhci_submit_bulk_msg; @@ -1389,18 +1414,11 @@ int xhci_deregister(struct xhci_ctrl *ctrl) return 0; } -static int xhci_detect(struct device_d *dev) -{ - struct xhci_ctrl *ctrl = dev->priv; - - return usb_host_detect(&ctrl->host); -} - /* * xHCI platform driver */ -static int xhci_probe(struct device_d *dev) +static int xhci_probe(struct device *dev) { struct resource *iores; struct xhci_ctrl *ctrl; @@ -1417,19 +1435,18 @@ static int xhci_probe(struct device_d *dev) HC_LENGTH(xhci_readl(&(ctrl->hccr)->cr_capbase))); dev->priv = ctrl; - dev->detect = xhci_detect; return xhci_register(ctrl); } -static void xhci_remove(struct device_d *dev) +static void xhci_remove(struct device *dev) { struct xhci_ctrl *ctrl = dev->priv; xhci_deregister(ctrl); } -static struct driver_d xhci_driver = { +static struct driver xhci_driver = { .name = "xHCI", .probe = xhci_probe, .remove = xhci_remove, diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 9ffbb103d5..37e8cee843 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * USB HOST XHCI Controller * @@ -16,7 +16,7 @@ #ifndef HOST_XHCI_H_ #define HOST_XHCI_H_ -#include <asm/types.h> +#include <linux/types.h> #include <io.h> #include <io-64-nonatomic-lo-hi.h> #include <linux/list.h> @@ -30,8 +30,8 @@ /* Section 5.3.3 - MaxPorts */ #define MAX_HC_PORTS 255 -/* Up to 16 ms to halt an HC */ -#define XHCI_MAX_HALT_USEC (16*1000) +/* Up to 32 ms to halt an HC */ +#define XHCI_MAX_HALT_USEC (32*1000) #define XHCI_MAX_RESET_USEC (250*1000) @@ -490,6 +490,7 @@ struct xhci_container_ctx { int size; u8 *bytes; + dma_addr_t dma; }; /** @@ -691,6 +692,8 @@ struct xhci_input_control_ctx { struct xhci_device_context_array { /* 64-bit device addresses; we only write 32-bit addresses */ __le64 dev_context_ptrs[MAX_HC_SLOTS]; + /* private xHCD pointers */ + dma_addr_t dma; }; /* TODO: write function to set the 64-bit device DMA address */ /* @@ -903,6 +906,8 @@ union xhci_trb { /* TRB type IDs */ typedef enum { + /* reserved, used as a software sentinel */ + TRB_NONE = 0, /* bulk, interrupt, isoc scatter/gather, and control data stage */ TRB_NORMAL = 1, /* setup stage for control transfers */ @@ -1003,6 +1008,7 @@ struct xhci_segment { union xhci_trb *trbs; /* private to HCD */ struct xhci_segment *next; + dma_addr_t dma; }; struct xhci_ring { @@ -1031,11 +1037,14 @@ struct xhci_erst_entry { struct xhci_erst { struct xhci_erst_entry *entries; unsigned int num_entries; + /* xhci->event_ring keeps track of segment dma addresses */ + dma_addr_t erst_dma_addr; /* Num entries the ERST can contain */ unsigned int erst_size; }; struct xhci_scratchpad { + void *scratchpad; u64 *sp_array; }; @@ -1134,8 +1143,6 @@ void xhci_hcd_stop(int index); /************************************************************* EXTENDED CAPABILITY DEFINITIONS *************************************************************/ -/* Up to 16 ms to halt an HC */ -#define XHCI_MAX_HALT_USEC (16*1000) /* HC not running - set to 1 when run/stop bit is cleared. */ #define XHCI_STS_HALT (1 << 0) @@ -1203,7 +1210,7 @@ void xhci_hcd_stop(int index); struct xhci_ctrl { struct usb_host host; - struct device_d *dev; + struct device *dev; struct xhci_hccr *hccr; /* R/O registers, not need for volatile */ struct xhci_hcor *hcor; struct xhci_doorbell_array *dba; @@ -1218,6 +1225,7 @@ struct xhci_ctrl { struct xhci_erst_entry entry[ERST_NUM_SEGS]; struct xhci_scratchpad *scratchpad; struct xhci_virt_device *devs[MAX_HC_SLOTS]; + struct usb_hub_descriptor hub_desc; void *bounce_buffer; int rootdev; }; @@ -1227,7 +1235,7 @@ static inline struct xhci_ctrl *to_xhci(struct usb_host *host) return container_of(host, struct xhci_ctrl, host); } -unsigned long trb_addr(struct xhci_segment *seg, union xhci_trb *trb); +dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb); struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_container_ctx *ctx); struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_ctrl *ctrl, @@ -1244,14 +1252,16 @@ void xhci_slot_copy(struct xhci_ctrl *ctrl, struct xhci_container_ctx *out_ctx); void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, struct usb_device *udev, int hop_portnr); -void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, +void xhci_queue_command(struct xhci_ctrl *ctrl, dma_addr_t addr, u32 slot_id, u32 ep_index, trb_type cmd); void xhci_acknowledge_event(struct xhci_ctrl *ctrl); -union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected); +#define XHCI_TIMEOUT_DEFAULT 5000 +union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected, + unsigned int timeout_ms); int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, - int length, void *buffer); + int length, void *buffer, unsigned int timeout_ms); int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, - struct devrequest *req, int length, void *buffer); + struct devrequest *req, int length, void *buffer, unsigned int timeout_ms); int xhci_check_maxpacket(struct usb_device *udev); void xhci_flush_cache(uintptr_t addr, u32 type_len); void xhci_inval_cache(uintptr_t addr, u32 type_len); |