diff options
Diffstat (limited to 'drivers/staging/dwc2')
-rw-r--r-- | drivers/staging/dwc2/Kconfig | 1 | ||||
-rw-r--r-- | drivers/staging/dwc2/core.c | 449 | ||||
-rw-r--r-- | drivers/staging/dwc2/core.h | 221 | ||||
-rw-r--r-- | drivers/staging/dwc2/core_intr.c | 4 | ||||
-rw-r--r-- | drivers/staging/dwc2/hcd.c | 281 | ||||
-rw-r--r-- | drivers/staging/dwc2/hcd.h | 45 | ||||
-rw-r--r-- | drivers/staging/dwc2/hcd_ddma.c | 31 | ||||
-rw-r--r-- | drivers/staging/dwc2/hcd_intr.c | 129 | ||||
-rw-r--r-- | drivers/staging/dwc2/hcd_queue.c | 22 | ||||
-rw-r--r-- | drivers/staging/dwc2/hw.h | 156 | ||||
-rw-r--r-- | drivers/staging/dwc2/pci.c | 4 |
11 files changed, 761 insertions, 582 deletions
diff --git a/drivers/staging/dwc2/Kconfig b/drivers/staging/dwc2/Kconfig index d15d9d5..be947d6 100644 --- a/drivers/staging/dwc2/Kconfig +++ b/drivers/staging/dwc2/Kconfig @@ -1,7 +1,6 @@ config USB_DWC2 tristate "DesignWare USB2 DRD Core Support" depends on USB - depends on VIRT_TO_BUS help Say Y or M here if your system has a Dual Role HighSpeed USB controller based on the DesignWare HSOTG IP Core. diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c index e3a0e77..06dae67 100644 --- a/drivers/staging/dwc2/core.c +++ b/drivers/staging/dwc2/core.c @@ -90,12 +90,10 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) */ static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg) { - u32 hs_phy_type = hsotg->hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK; - u32 fs_phy_type = hsotg->hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK; u32 hcfg, val; - if ((hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && - fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED && + if ((hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && + hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED && hsotg->core_params->ulpi_fs_ls > 0) || hsotg->core_params->phy_type == DWC2_PHY_TYPE_PARAM_FS) { /* Full speed PHY */ @@ -108,7 +106,7 @@ static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "Initializing HCFG.FSLSPClkSel to %08x\n", val); hcfg = readl(hsotg->regs + HCFG); hcfg &= ~HCFG_FSLSPCLKSEL_MASK; - hcfg |= val; + hcfg |= val << HCFG_FSLSPCLKSEL_SHIFT; writel(hcfg, hsotg->regs + HCFG); } @@ -245,7 +243,7 @@ static void dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) { - u32 usbcfg, hs_phy_type, fs_phy_type; + u32 usbcfg; if (hsotg->core_params->speed == DWC2_SPEED_PARAM_FULL && hsotg->core_params->phy_type == DWC2_PHY_TYPE_PARAM_FS) { @@ -256,11 +254,8 @@ static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) dwc2_hs_phy_init(hsotg, select_phy); } - hs_phy_type = hsotg->hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK; - fs_phy_type = hsotg->hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK; - - if (hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && - fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED && + if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && + hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED && hsotg->core_params->ulpi_fs_ls > 0) { dev_dbg(hsotg->dev, "Setting ULPI FSLS\n"); usbcfg = readl(hsotg->regs + GUSBCFG); @@ -277,20 +272,20 @@ static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) { - u32 ahbcfg = 0; + u32 ahbcfg = readl(hsotg->regs + GAHBCFG); - switch (hsotg->hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) { + switch (hsotg->hw_params.arch) { case GHWCFG2_EXT_DMA_ARCH: dev_err(hsotg->dev, "External DMA Mode not supported\n"); return -EINVAL; case GHWCFG2_INT_DMA_ARCH: dev_dbg(hsotg->dev, "Internal DMA Mode\n"); - /* - * Old value was GAHBCFG_HBSTLEN_INCR - done for - * Host mode ISOC in issue fix - vahrama - */ - ahbcfg |= GAHBCFG_HBSTLEN_INCR4; + if (hsotg->core_params->ahbcfg != -1) { + ahbcfg &= GAHBCFG_CTRL_MASK; + ahbcfg |= hsotg->core_params->ahbcfg & + ~GAHBCFG_CTRL_MASK; + } break; case GHWCFG2_SLAVE_ONLY_ARCH: @@ -313,9 +308,6 @@ static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) hsotg->core_params->dma_desc_enable = 0; } - if (hsotg->core_params->ahb_single > 0) - ahbcfg |= GAHBCFG_AHB_SINGLE; - if (hsotg->core_params->dma_enable > 0) ahbcfg |= GAHBCFG_DMA_EN; @@ -331,7 +323,7 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg) usbcfg = readl(hsotg->regs + GUSBCFG); usbcfg &= ~(GUSBCFG_HNPCAP | GUSBCFG_SRPCAP); - switch (hsotg->hwcfg2 & GHWCFG2_OP_MODE_MASK) { + switch (hsotg->hw_params.op_mode) { case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE: if (hsotg->core_params->otg_cap == DWC2_CAP_PARAM_HNP_SRP_CAPABLE) @@ -392,21 +384,6 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq) /* Reset the Controller */ dwc2_core_reset(hsotg); - dev_dbg(hsotg->dev, "num_dev_perio_in_ep=%d\n", - hsotg->hwcfg4 >> GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT & - GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK >> - GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT); - - hsotg->total_fifo_size = hsotg->hwcfg3 >> GHWCFG3_DFIFO_DEPTH_SHIFT & - GHWCFG3_DFIFO_DEPTH_MASK >> GHWCFG3_DFIFO_DEPTH_SHIFT; - hsotg->rx_fifo_size = readl(hsotg->regs + GRXFSIZ); - hsotg->nperio_tx_fifo_size = - readl(hsotg->regs + GNPTXFSIZ) >> 16 & 0xffff; - - dev_dbg(hsotg->dev, "Total FIFO SZ=%d\n", hsotg->total_fifo_size); - dev_dbg(hsotg->dev, "RxFIFO SZ=%d\n", hsotg->rx_fifo_size); - dev_dbg(hsotg->dev, "NP TxFIFO SZ=%d\n", hsotg->nperio_tx_fifo_size); - /* * This needs to happen in FS mode before any other programming occurs */ @@ -504,22 +481,18 @@ void dwc2_disable_host_interrupts(struct dwc2_hsotg *hsotg) static void dwc2_config_fifos(struct dwc2_hsotg *hsotg) { struct dwc2_core_params *params = hsotg->core_params; - u32 rxfsiz, nptxfsiz, ptxfsiz, hptxfsiz, dfifocfg; + u32 nptxfsiz, hptxfsiz, dfifocfg, grxfsiz; if (!params->enable_dynamic_fifo) return; - dev_dbg(hsotg->dev, "Total FIFO Size=%d\n", hsotg->total_fifo_size); - dev_dbg(hsotg->dev, "Rx FIFO Size=%d\n", params->host_rx_fifo_size); - dev_dbg(hsotg->dev, "NP Tx FIFO Size=%d\n", - params->host_nperio_tx_fifo_size); - dev_dbg(hsotg->dev, "P Tx FIFO Size=%d\n", - params->host_perio_tx_fifo_size); - /* Rx FIFO */ - dev_dbg(hsotg->dev, "initial grxfsiz=%08x\n", - readl(hsotg->regs + GRXFSIZ)); - writel(params->host_rx_fifo_size, hsotg->regs + GRXFSIZ); + grxfsiz = readl(hsotg->regs + GRXFSIZ); + dev_dbg(hsotg->dev, "initial grxfsiz=%08x\n", grxfsiz); + grxfsiz &= ~GRXFSIZ_DEPTH_MASK; + grxfsiz |= params->host_rx_fifo_size << + GRXFSIZ_DEPTH_SHIFT & GRXFSIZ_DEPTH_MASK; + writel(grxfsiz, hsotg->regs + GRXFSIZ); dev_dbg(hsotg->dev, "new grxfsiz=%08x\n", readl(hsotg->regs + GRXFSIZ)); /* Non-periodic Tx FIFO */ @@ -536,27 +509,26 @@ static void dwc2_config_fifos(struct dwc2_hsotg *hsotg) /* Periodic Tx FIFO */ dev_dbg(hsotg->dev, "initial hptxfsiz=%08x\n", readl(hsotg->regs + HPTXFSIZ)); - ptxfsiz = params->host_perio_tx_fifo_size << - FIFOSIZE_DEPTH_SHIFT & FIFOSIZE_DEPTH_MASK; - ptxfsiz |= (params->host_rx_fifo_size + - params->host_nperio_tx_fifo_size) << - FIFOSIZE_STARTADDR_SHIFT & FIFOSIZE_STARTADDR_MASK; - writel(ptxfsiz, hsotg->regs + HPTXFSIZ); + hptxfsiz = params->host_perio_tx_fifo_size << + FIFOSIZE_DEPTH_SHIFT & FIFOSIZE_DEPTH_MASK; + hptxfsiz |= (params->host_rx_fifo_size + + params->host_nperio_tx_fifo_size) << + FIFOSIZE_STARTADDR_SHIFT & FIFOSIZE_STARTADDR_MASK; + writel(hptxfsiz, hsotg->regs + HPTXFSIZ); dev_dbg(hsotg->dev, "new hptxfsiz=%08x\n", readl(hsotg->regs + HPTXFSIZ)); if (hsotg->core_params->en_multiple_tx_fifo > 0 && - hsotg->snpsid <= DWC2_CORE_REV_2_94a) { + hsotg->hw_params.snpsid <= DWC2_CORE_REV_2_94a) { /* * Global DFIFOCFG calculation for Host mode - * include RxFIFO, NPTXFIFO and HPTXFIFO */ dfifocfg = readl(hsotg->regs + GDFIFOCFG); - rxfsiz = readl(hsotg->regs + GRXFSIZ) & 0x0000ffff; - nptxfsiz = readl(hsotg->regs + GNPTXFSIZ) >> 16 & 0xffff; - hptxfsiz = readl(hsotg->regs + HPTXFSIZ) >> 16 & 0xffff; dfifocfg &= ~GDFIFOCFG_EPINFOBASE_MASK; - dfifocfg |= (rxfsiz + nptxfsiz + hptxfsiz) << + dfifocfg |= (params->host_rx_fifo_size + + params->host_nperio_tx_fifo_size + + params->host_perio_tx_fifo_size) << GDFIFOCFG_EPINFOBASE_SHIFT & GDFIFOCFG_EPINFOBASE_MASK; writel(dfifocfg, hsotg->regs + GDFIFOCFG); @@ -602,10 +574,9 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg) } if (hsotg->core_params->dma_desc_enable > 0) { - u32 op_mode = hsotg->hwcfg2 & GHWCFG2_OP_MODE_MASK; - - if (hsotg->snpsid < DWC2_CORE_REV_2_90a || - !(hsotg->hwcfg4 & GHWCFG4_DESC_DMA) || + u32 op_mode = hsotg->hw_params.op_mode; + if (hsotg->hw_params.snpsid < DWC2_CORE_REV_2_90a || + !hsotg->hw_params.dma_desc_enable || op_mode == GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE || op_mode == GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE || op_mode == GHWCFG2_OP_MODE_UNDEFINED) { @@ -883,26 +854,20 @@ void dwc2_hc_init(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) dev_vdbg(hsotg->dev, "set HCCHAR(%d) to %08x\n", hc_num, hcchar); - dev_vdbg(hsotg->dev, "%s: Channel %d\n", __func__, hc_num); + dev_vdbg(hsotg->dev, "%s: Channel %d\n", + __func__, hc_num); dev_vdbg(hsotg->dev, " Dev Addr: %d\n", - hcchar >> HCCHAR_DEVADDR_SHIFT & - HCCHAR_DEVADDR_MASK >> HCCHAR_DEVADDR_SHIFT); + chan->dev_addr); dev_vdbg(hsotg->dev, " Ep Num: %d\n", - hcchar >> HCCHAR_EPNUM_SHIFT & - HCCHAR_EPNUM_MASK >> HCCHAR_EPNUM_SHIFT); + chan->ep_num); dev_vdbg(hsotg->dev, " Is In: %d\n", - !!(hcchar & HCCHAR_EPDIR)); + chan->ep_is_in); dev_vdbg(hsotg->dev, " Is Low Speed: %d\n", - !!(hcchar & HCCHAR_LSPDDEV)); + chan->speed == USB_SPEED_LOW); dev_vdbg(hsotg->dev, " Ep Type: %d\n", - hcchar >> HCCHAR_EPTYPE_SHIFT & - HCCHAR_EPTYPE_MASK >> HCCHAR_EPTYPE_SHIFT); + chan->ep_type); dev_vdbg(hsotg->dev, " Max Pkt: %d\n", - hcchar >> HCCHAR_MPS_SHIFT & - HCCHAR_MPS_MASK >> HCCHAR_MPS_SHIFT); - dev_vdbg(hsotg->dev, " Multi Cnt: %d\n", - hcchar >> HCCHAR_MULTICNT_SHIFT & - HCCHAR_MULTICNT_MASK >> HCCHAR_MULTICNT_SHIFT); + chan->max_packet); } /* Program the HCSPLT register for SPLITs */ @@ -932,8 +897,7 @@ void dwc2_hc_init(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) dev_vdbg(hsotg->dev, " is_in %d\n", chan->ep_is_in); dev_vdbg(hsotg->dev, " Max Pkt %d\n", - hcchar >> HCCHAR_MPS_SHIFT & - HCCHAR_MPS_MASK >> HCCHAR_MPS_SHIFT); + chan->max_packet); dev_vdbg(hsotg->dev, " xferlen %d\n", chan->xfer_len); } @@ -1382,14 +1346,14 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg, dev_vdbg(hsotg->dev, "%s: Channel %d\n", __func__, chan->hc_num); dev_vdbg(hsotg->dev, " Xfer Size: %d\n", - hctsiz >> TSIZ_XFERSIZE_SHIFT & - TSIZ_XFERSIZE_MASK >> TSIZ_XFERSIZE_SHIFT); + (hctsiz & TSIZ_XFERSIZE_MASK) >> + TSIZ_XFERSIZE_SHIFT); dev_vdbg(hsotg->dev, " Num Pkts: %d\n", - hctsiz >> TSIZ_PKTCNT_SHIFT & - TSIZ_PKTCNT_MASK >> TSIZ_PKTCNT_SHIFT); + (hctsiz & TSIZ_PKTCNT_MASK) >> + TSIZ_PKTCNT_SHIFT); dev_vdbg(hsotg->dev, " Start PID: %d\n", - hctsiz >> TSIZ_SC_MC_PID_SHIFT & - TSIZ_SC_MC_PID_MASK >> TSIZ_SC_MC_PID_SHIFT); + (hctsiz & TSIZ_SC_MC_PID_MASK) >> + TSIZ_SC_MC_PID_SHIFT); } if (hsotg->core_params->dma_enable > 0) { @@ -1433,8 +1397,8 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg, if (dbg_hc(chan)) dev_vdbg(hsotg->dev, " Multi Cnt: %d\n", - hcchar >> HCCHAR_MULTICNT_SHIFT & - HCCHAR_MULTICNT_MASK >> HCCHAR_MULTICNT_SHIFT); + (hcchar & HCCHAR_MULTICNT_MASK) >> + HCCHAR_MULTICNT_SHIFT); writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); if (dbg_hc(chan)) @@ -1522,8 +1486,8 @@ void dwc2_hc_start_transfer_ddma(struct dwc2_hsotg *hsotg, if (dbg_hc(chan)) dev_vdbg(hsotg->dev, " Multi Cnt: %d\n", - hcchar >> HCCHAR_MULTICNT_SHIFT & - HCCHAR_MULTICNT_MASK >> HCCHAR_MULTICNT_SHIFT); + (hcchar & HCCHAR_MULTICNT_MASK) >> + HCCHAR_MULTICNT_SHIFT); writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num)); if (dbg_hc(chan)) @@ -1658,18 +1622,16 @@ void dwc2_hc_do_ping(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg) { u32 usbcfg; - u32 hwcfg2; u32 hprt0; int clock = 60; /* default value */ usbcfg = readl(hsotg->regs + GUSBCFG); - hwcfg2 = readl(hsotg->regs + GHWCFG2); hprt0 = readl(hsotg->regs + HPRT0); if (!(usbcfg & GUSBCFG_PHYSEL) && (usbcfg & GUSBCFG_ULPI_UTMI_SEL) && !(usbcfg & GUSBCFG_PHYIF16)) clock = 60; - if ((usbcfg & GUSBCFG_PHYSEL) && (hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) == + if ((usbcfg & GUSBCFG_PHYSEL) && hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_SHARED_ULPI) clock = 48; if (!(usbcfg & GUSBCFG_PHY_LP_CLK_SEL) && !(usbcfg & GUSBCFG_PHYSEL) && @@ -1682,14 +1644,13 @@ u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg) !(usbcfg & GUSBCFG_ULPI_UTMI_SEL) && (usbcfg & GUSBCFG_PHYIF16)) clock = 48; if ((usbcfg & GUSBCFG_PHYSEL) && !(usbcfg & GUSBCFG_PHYIF16) && - (hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) == - GHWCFG2_FS_PHY_TYPE_SHARED_UTMI) + hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_SHARED_UTMI) clock = 48; - if ((usbcfg & GUSBCFG_PHYSEL) && (hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) == - GHWCFG2_FS_PHY_TYPE_DEDICATED) + if ((usbcfg & GUSBCFG_PHYSEL) && + hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED) clock = 48; - if ((hprt0 & HPRT0_SPD_MASK) == HPRT0_SPD_HIGH_SPEED) + if ((hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT == HPRT0_SPD_HIGH_SPEED) /* High speed case */ return 125 * clock; else @@ -1958,17 +1919,14 @@ int dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val) { int valid = 1; int retval = 0; - u32 op_mode; - - op_mode = hsotg->hwcfg2 & GHWCFG2_OP_MODE_MASK; switch (val) { case DWC2_CAP_PARAM_HNP_SRP_CAPABLE: - if (op_mode != GHWCFG2_OP_MODE_HNP_SRP_CAPABLE) + if (hsotg->hw_params.op_mode != GHWCFG2_OP_MODE_HNP_SRP_CAPABLE) valid = 0; break; case DWC2_CAP_PARAM_SRP_ONLY_CAPABLE: - switch (op_mode) { + switch (hsotg->hw_params.op_mode) { case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE: case GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE: case GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE: @@ -1992,7 +1950,7 @@ int dwc2_set_param_otg_cap(struct dwc2_hsotg *hsotg, int val) dev_err(hsotg->dev, "%d invalid for otg_cap parameter. Check HW configuration.\n", val); - switch (op_mode) { + switch (hsotg->hw_params.op_mode) { case GHWCFG2_OP_MODE_HNP_SRP_CAPABLE: val = DWC2_CAP_PARAM_HNP_SRP_CAPABLE; break; @@ -2018,8 +1976,7 @@ int dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val) int valid = 1; int retval = 0; - if (val > 0 && (hsotg->hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) == - GHWCFG2_SLAVE_ONLY_ARCH) + if (val > 0 && hsotg->hw_params.arch == GHWCFG2_SLAVE_ONLY_ARCH) valid = 0; if (val < 0) valid = 0; @@ -2029,8 +1986,7 @@ int dwc2_set_param_dma_enable(struct dwc2_hsotg *hsotg, int val) dev_err(hsotg->dev, "%d invalid for dma_enable parameter. Check HW configuration.\n", val); - val = (hsotg->hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) != - GHWCFG2_SLAVE_ONLY_ARCH; + val = hsotg->hw_params.arch != GHWCFG2_SLAVE_ONLY_ARCH; dev_dbg(hsotg->dev, "Setting dma_enable to %d\n", val); retval = -EINVAL; } @@ -2045,7 +2001,7 @@ int dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val) int retval = 0; if (val > 0 && (hsotg->core_params->dma_enable <= 0 || - !(hsotg->hwcfg4 & GHWCFG4_DESC_DMA))) + !hsotg->hw_params.dma_desc_enable)) valid = 0; if (val < 0) valid = 0; @@ -2056,7 +2012,7 @@ int dwc2_set_param_dma_desc_enable(struct dwc2_hsotg *hsotg, int val) "%d invalid for dma_desc_enable parameter. Check HW configuration.\n", val); val = (hsotg->core_params->dma_enable > 0 && - (hsotg->hwcfg4 & GHWCFG4_DESC_DMA)); + hsotg->hw_params.dma_desc_enable); dev_dbg(hsotg->dev, "Setting dma_desc_enable to %d\n", val); retval = -EINVAL; } @@ -2092,7 +2048,7 @@ int dwc2_set_param_enable_dynamic_fifo(struct dwc2_hsotg *hsotg, int val) int valid = 1; int retval = 0; - if (val > 0 && !(hsotg->hwcfg2 & GHWCFG2_DYNAMIC_FIFO)) + if (val > 0 && !hsotg->hw_params.enable_dynamic_fifo) valid = 0; if (val < 0) valid = 0; @@ -2102,7 +2058,7 @@ int dwc2_set_param_enable_dynamic_fifo(struct dwc2_hsotg *hsotg, int val) dev_err(hsotg->dev, "%d invalid for enable_dynamic_fifo parameter. Check HW configuration.\n", val); - val = !!(hsotg->hwcfg2 & GHWCFG2_DYNAMIC_FIFO); + val = hsotg->hw_params.enable_dynamic_fifo; dev_dbg(hsotg->dev, "Setting enable_dynamic_fifo to %d\n", val); retval = -EINVAL; } @@ -2116,7 +2072,7 @@ int dwc2_set_param_host_rx_fifo_size(struct dwc2_hsotg *hsotg, int val) int valid = 1; int retval = 0; - if (val < 16 || val > readl(hsotg->regs + GRXFSIZ)) + if (val < 16 || val > hsotg->hw_params.host_rx_fifo_size) valid = 0; if (!valid) { @@ -2124,7 +2080,7 @@ int dwc2_set_param_host_rx_fifo_size(struct dwc2_hsotg *hsotg, int val) dev_err(hsotg->dev, "%d invalid for host_rx_fifo_size. Check HW configuration.\n", val); - val = readl(hsotg->regs + GRXFSIZ); + val = hsotg->hw_params.host_rx_fifo_size; dev_dbg(hsotg->dev, "Setting host_rx_fifo_size to %d\n", val); retval = -EINVAL; } @@ -2138,7 +2094,7 @@ int dwc2_set_param_host_nperio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val) int valid = 1; int retval = 0; - if (val < 16 || val > (readl(hsotg->regs + GNPTXFSIZ) >> 16 & 0xffff)) + if (val < 16 || val > hsotg->hw_params.host_nperio_tx_fifo_size) valid = 0; if (!valid) { @@ -2146,7 +2102,7 @@ int dwc2_set_param_host_nperio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val) dev_err(hsotg->dev, "%d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n", val); - val = readl(hsotg->regs + GNPTXFSIZ) >> 16 & 0xffff; + val = hsotg->hw_params.host_nperio_tx_fifo_size; dev_dbg(hsotg->dev, "Setting host_nperio_tx_fifo_size to %d\n", val); retval = -EINVAL; @@ -2161,7 +2117,7 @@ int dwc2_set_param_host_perio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val) int valid = 1; int retval = 0; - if (val < 16 || val > (hsotg->hptxfsiz >> 16)) + if (val < 16 || val > hsotg->hw_params.host_perio_tx_fifo_size) valid = 0; if (!valid) { @@ -2169,7 +2125,7 @@ int dwc2_set_param_host_perio_tx_fifo_size(struct dwc2_hsotg *hsotg, int val) dev_err(hsotg->dev, "%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n", val); - val = hsotg->hptxfsiz >> 16; + val = hsotg->hw_params.host_perio_tx_fifo_size; dev_dbg(hsotg->dev, "Setting host_perio_tx_fifo_size to %d\n", val); retval = -EINVAL; @@ -2183,11 +2139,8 @@ int dwc2_set_param_max_transfer_size(struct dwc2_hsotg *hsotg, int val) { int valid = 1; int retval = 0; - int width = hsotg->hwcfg3 >> GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT & - GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK >> - GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT; - if (val < 2047 || val >= (1 << (width + 11))) + if (val < 2047 || val > hsotg->hw_params.max_transfer_size) valid = 0; if (!valid) { @@ -2195,7 +2148,7 @@ int dwc2_set_param_max_transfer_size(struct dwc2_hsotg *hsotg, int val) dev_err(hsotg->dev, "%d invalid for max_transfer_size. Check HW configuration.\n", val); - val = (1 << (width + 11)) - 1; + val = hsotg->hw_params.max_transfer_size; dev_dbg(hsotg->dev, "Setting max_transfer_size to %d\n", val); retval = -EINVAL; } @@ -2208,11 +2161,8 @@ int dwc2_set_param_max_packet_count(struct dwc2_hsotg *hsotg, int val) { int valid = 1; int retval = 0; - int width = hsotg->hwcfg3 >> GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT & - GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK >> - GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT; - if (val < 15 || val > (1 << (width + 4))) + if (val < 15 || val > hsotg->hw_params.max_packet_count) valid = 0; if (!valid) { @@ -2220,7 +2170,7 @@ int dwc2_set_param_max_packet_count(struct dwc2_hsotg *hsotg, int val) dev_err(hsotg->dev, "%d invalid for max_packet_count. Check HW configuration.\n", val); - val = (1 << (width + 4)) - 1; + val = hsotg->hw_params.max_packet_count; dev_dbg(hsotg->dev, "Setting max_packet_count to %d\n", val); retval = -EINVAL; } @@ -2233,10 +2183,8 @@ int dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val) { int valid = 1; int retval = 0; - int num_chan = hsotg->hwcfg2 >> GHWCFG2_NUM_HOST_CHAN_SHIFT & - GHWCFG2_NUM_HOST_CHAN_MASK >> GHWCFG2_NUM_HOST_CHAN_SHIFT; - if (val < 1 || val > num_chan + 1) + if (val < 1 || val > hsotg->hw_params.host_channels) valid = 0; if (!valid) { @@ -2244,7 +2192,7 @@ int dwc2_set_param_host_channels(struct dwc2_hsotg *hsotg, int val) dev_err(hsotg->dev, "%d invalid for host_channels. Check HW configuration.\n", val); - val = num_chan + 1; + val = hsotg->hw_params.host_channels; dev_dbg(hsotg->dev, "Setting host_channels to %d\n", val); retval = -EINVAL; } @@ -2257,8 +2205,7 @@ int dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val) { #ifndef NO_FS_PHY_HW_CHECKS int valid = 0; - u32 hs_phy_type; - u32 fs_phy_type; + u32 hs_phy_type, fs_phy_type; #endif int retval = 0; @@ -2279,9 +2226,8 @@ int dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val) } #ifndef NO_FS_PHY_HW_CHECKS - hs_phy_type = hsotg->hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK; - fs_phy_type = hsotg->hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK; - + hs_phy_type = hsotg->hw_params.hs_phy_type; + fs_phy_type = hsotg->hw_params.fs_phy_type; if (val == DWC2_PHY_TYPE_PARAM_UTMI && (hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI || hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI_ULPI)) @@ -2430,14 +2376,29 @@ int dwc2_set_param_phy_ulpi_ext_vbus(struct dwc2_hsotg *hsotg, int val) int dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg, int val) { + int valid = 0; int retval = 0; - if (DWC2_PARAM_TEST(val, 8, 8) && DWC2_PARAM_TEST(val, 16, 16)) { + switch (hsotg->hw_params.utmi_phy_data_width) { + case GHWCFG4_UTMI_PHY_DATA_WIDTH_8: + valid = (val == 8); + break; + case GHWCFG4_UTMI_PHY_DATA_WIDTH_16: + valid = (val == 16); + break; + case GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16: + valid = (val == 8 || val == 16); + break; + } + + if (!valid) { if (val >= 0) { - dev_err(hsotg->dev, "Wrong value for phy_utmi_width\n"); - dev_err(hsotg->dev, "phy_utmi_width must be 8 or 16\n"); + dev_err(hsotg->dev, + "%d invalid for phy_utmi_width. Check HW configuration.\n", + val); } - val = 8; + val = (hsotg->hw_params.utmi_phy_data_width == + GHWCFG4_UTMI_PHY_DATA_WIDTH_8) ? 8 : 16; dev_dbg(hsotg->dev, "Setting phy_utmi_width to %d\n", val); retval = -EINVAL; } @@ -2505,7 +2466,7 @@ int dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val) } #ifndef NO_FS_PHY_HW_CHECKS - if (val == 1 && !(hsotg->hwcfg3 & GHWCFG3_I2C)) + if (val == 1 && !(hsotg->hw_params.i2c_enable)) valid = 0; if (!valid) { @@ -2513,7 +2474,7 @@ int dwc2_set_param_i2c_enable(struct dwc2_hsotg *hsotg, int val) dev_err(hsotg->dev, "%d invalid for i2c_enable. Check HW configuration.\n", val); - val = !!(hsotg->hwcfg3 & GHWCFG3_I2C); + val = hsotg->hw_params.i2c_enable; dev_dbg(hsotg->dev, "Setting i2c_enable to %d\n", val); retval = -EINVAL; } @@ -2538,7 +2499,7 @@ int dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, int val) valid = 0; } - if (val == 1 && !(hsotg->hwcfg4 & GHWCFG4_DED_FIFO_EN)) + if (val == 1 && !hsotg->hw_params.en_multiple_tx_fifo) valid = 0; if (!valid) { @@ -2546,7 +2507,7 @@ int dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, int val) dev_err(hsotg->dev, "%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n", val); - val = !!(hsotg->hwcfg4 & GHWCFG4_DED_FIFO_EN); + val = hsotg->hw_params.en_multiple_tx_fifo; dev_dbg(hsotg->dev, "Setting en_multiple_tx_fifo to %d\n", val); retval = -EINVAL; } @@ -2569,7 +2530,7 @@ int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val) valid = 0; } - if (val == 1 && hsotg->snpsid < DWC2_CORE_REV_2_92a) + if (val == 1 && hsotg->hw_params.snpsid < DWC2_CORE_REV_2_92a) valid = 0; if (!valid) { @@ -2577,7 +2538,7 @@ int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val) dev_err(hsotg->dev, "%d invalid for parameter reload_ctl. Check HW configuration.\n", val); - val = hsotg->snpsid >= DWC2_CORE_REV_2_92a; + val = hsotg->hw_params.snpsid >= DWC2_CORE_REV_2_92a; dev_dbg(hsotg->dev, "Setting reload_ctl to %d\n", val); retval = -EINVAL; } @@ -2586,35 +2547,14 @@ int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val) return retval; } -int dwc2_set_param_ahb_single(struct dwc2_hsotg *hsotg, int val) +int dwc2_set_param_ahbcfg(struct dwc2_hsotg *hsotg, int val) { - int valid = 1; - int retval = 0; - - if (DWC2_PARAM_TEST(val, 0, 1)) { - if (val >= 0) { - dev_err(hsotg->dev, - "'%d' invalid for parameter ahb_single\n", val); - dev_err(hsotg->dev, "ahb_single must be 0 or 1\n"); - } - valid = 0; - } - - if (val > 0 && hsotg->snpsid < DWC2_CORE_REV_2_94a) - valid = 0; - - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for parameter ahb_single. Check HW configuration.\n", - val); - val = 0; - dev_dbg(hsotg->dev, "Setting ahb_single to %d\n", val); - retval = -EINVAL; - } - - hsotg->core_params->ahb_single = val; - return retval; + if (val != -1) + hsotg->core_params->ahbcfg = val; + else + hsotg->core_params->ahbcfg = GAHBCFG_HBSTLEN_INCR4 << + GAHBCFG_HBSTLEN_SHIFT; + return 0; } int dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val) @@ -2637,6 +2577,165 @@ int dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val) return retval; } +/** + * During device initialization, read various hardware configuration + * registers and interpret the contents. + */ +int dwc2_get_hwparams(struct dwc2_hsotg *hsotg) +{ + struct dwc2_hw_params *hw = &hsotg->hw_params; + unsigned width; + u32 hwcfg1, hwcfg2, hwcfg3, hwcfg4; + u32 hptxfsiz, grxfsiz, gnptxfsiz; + u32 gusbcfg; + + /* + * Attempt to ensure this device is really a DWC_otg Controller. + * Read and verify the GSNPSID register contents. The value should be + * 0x45f42xxx or 0x45f43xxx, which corresponds to either "OT2" or "OT3", + * as in "OTG version 2.xx" or "OTG version 3.xx". + */ + hw->snpsid = readl(hsotg->regs + GSNPSID); + if ((hw->snpsid & 0xfffff000) != 0x4f542000 && + (hw->snpsid & 0xfffff000) != 0x4f543000) { + dev_err(hsotg->dev, "Bad value for GSNPSID: 0x%08x\n", + hw->snpsid); + return -ENODEV; + } + + dev_dbg(hsotg->dev, "Core Release: %1x.%1x%1x%1x (snpsid=%x)\n", + hw->snpsid >> 12 & 0xf, hw->snpsid >> 8 & 0xf, + hw->snpsid >> 4 & 0xf, hw->snpsid & 0xf, hw->snpsid); + + hwcfg1 = readl(hsotg->regs + GHWCFG1); + hwcfg2 = readl(hsotg->regs + GHWCFG2); + hwcfg3 = readl(hsotg->regs + GHWCFG3); + hwcfg4 = readl(hsotg->regs + GHWCFG4); + gnptxfsiz = readl(hsotg->regs + GNPTXFSIZ); + grxfsiz = readl(hsotg->regs + GRXFSIZ); + + dev_dbg(hsotg->dev, "hwcfg1=%08x\n", hwcfg1); + dev_dbg(hsotg->dev, "hwcfg2=%08x\n", hwcfg2); + dev_dbg(hsotg->dev, "hwcfg3=%08x\n", hwcfg3); + dev_dbg(hsotg->dev, "hwcfg4=%08x\n", hwcfg4); + dev_dbg(hsotg->dev, "gnptxfsiz=%08x\n", gnptxfsiz); + dev_dbg(hsotg->dev, "grxfsiz=%08x\n", grxfsiz); + + /* Force host mode to get HPTXFSIZ exact power on value */ + gusbcfg = readl(hsotg->regs + GUSBCFG); + gusbcfg |= GUSBCFG_FORCEHOSTMODE; + writel(gusbcfg, hsotg->regs + GUSBCFG); + usleep_range(100000, 150000); + + hptxfsiz = readl(hsotg->regs + HPTXFSIZ); + dev_dbg(hsotg->dev, "hptxfsiz=%08x\n", hptxfsiz); + gusbcfg = readl(hsotg->regs + GUSBCFG); + gusbcfg &= ~GUSBCFG_FORCEHOSTMODE; + writel(gusbcfg, hsotg->regs + GUSBCFG); + usleep_range(100000, 150000); + + /* hwcfg2 */ + hw->op_mode = (hwcfg2 & GHWCFG2_OP_MODE_MASK) >> + GHWCFG2_OP_MODE_SHIFT; + hw->arch = (hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) >> + GHWCFG2_ARCHITECTURE_SHIFT; + hw->enable_dynamic_fifo = !!(hwcfg2 & GHWCFG2_DYNAMIC_FIFO); + hw->host_channels = 1 + ((hwcfg2 & GHWCFG2_NUM_HOST_CHAN_MASK) >> + GHWCFG2_NUM_HOST_CHAN_SHIFT); + hw->hs_phy_type = (hwcfg2 & GHWCFG2_HS_PHY_TYPE_MASK) >> + GHWCFG2_HS_PHY_TYPE_SHIFT; + hw->fs_phy_type = (hwcfg2 & GHWCFG2_FS_PHY_TYPE_MASK) >> + GHWCFG2_FS_PHY_TYPE_SHIFT; + hw->num_dev_ep = (hwcfg2 & GHWCFG2_NUM_DEV_EP_MASK) >> + GHWCFG2_NUM_DEV_EP_SHIFT; + hw->nperio_tx_q_depth = + (hwcfg2 & GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK) >> + GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT << 1; + hw->host_perio_tx_q_depth = + (hwcfg2 & GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK) >> + GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT << 1; + hw->dev_token_q_depth = + (hwcfg2 & GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK) >> + GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT; + + /* hwcfg3 */ + width = (hwcfg3 & GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK) >> + GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT; + hw->max_transfer_size = (1 << (width + 11)) - 1; + width = (hwcfg3 & GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK) >> + GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT; + hw->max_packet_count = (1 << (width + 4)) - 1; + hw->i2c_enable = !!(hwcfg3 & GHWCFG3_I2C); + hw->total_fifo_size = (hwcfg3 & GHWCFG3_DFIFO_DEPTH_MASK) >> + GHWCFG3_DFIFO_DEPTH_SHIFT; + + /* hwcfg4 */ + hw->en_multiple_tx_fifo = !!(hwcfg4 & GHWCFG4_DED_FIFO_EN); + hw->num_dev_perio_in_ep = (hwcfg4 & GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK) >> + GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT; + hw->dma_desc_enable = !!(hwcfg4 & GHWCFG4_DESC_DMA); + hw->power_optimized = !!(hwcfg4 & GHWCFG4_POWER_OPTIMIZ); + hw->utmi_phy_data_width = (hwcfg4 & GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK) >> + GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT; + + /* fifo sizes */ + hw->host_rx_fifo_size = (grxfsiz & GRXFSIZ_DEPTH_MASK) >> + GRXFSIZ_DEPTH_SHIFT; + hw->host_nperio_tx_fifo_size = (gnptxfsiz & FIFOSIZE_DEPTH_MASK) >> + FIFOSIZE_DEPTH_SHIFT; + hw->host_perio_tx_fifo_size = (hptxfsiz & FIFOSIZE_DEPTH_MASK) >> + FIFOSIZE_DEPTH_SHIFT; + + dev_dbg(hsotg->dev, "Detected values from hardware:\n"); + dev_dbg(hsotg->dev, " op_mode=%d\n", + hw->op_mode); + dev_dbg(hsotg->dev, " arch=%d\n", + hw->arch); + dev_dbg(hsotg->dev, " dma_desc_enable=%d\n", + hw->dma_desc_enable); + dev_dbg(hsotg->dev, " power_optimized=%d\n", + hw->power_optimized); + dev_dbg(hsotg->dev, " i2c_enable=%d\n", + hw->i2c_enable); + dev_dbg(hsotg->dev, " hs_phy_type=%d\n", + hw->hs_phy_type); + dev_dbg(hsotg->dev, " fs_phy_type=%d\n", + hw->fs_phy_type); + dev_dbg(hsotg->dev, " utmi_phy_data_wdith=%d\n", + hw->utmi_phy_data_width); + dev_dbg(hsotg->dev, " num_dev_ep=%d\n", + hw->num_dev_ep); + dev_dbg(hsotg->dev, " num_dev_perio_in_ep=%d\n", + hw->num_dev_perio_in_ep); + dev_dbg(hsotg->dev, " host_channels=%d\n", + hw->host_channels); + dev_dbg(hsotg->dev, " max_transfer_size=%d\n", + hw->max_transfer_size); + dev_dbg(hsotg->dev, " max_packet_count=%d\n", + hw->max_packet_count); + dev_dbg(hsotg->dev, " nperio_tx_q_depth=0x%0x\n", + hw->nperio_tx_q_depth); + dev_dbg(hsotg->dev, " host_perio_tx_q_depth=0x%0x\n", + hw->host_perio_tx_q_depth); + dev_dbg(hsotg->dev, " dev_token_q_depth=0x%0x\n", + hw->dev_token_q_depth); + dev_dbg(hsotg->dev, " enable_dynamic_fifo=%d\n", + hw->enable_dynamic_fifo); + dev_dbg(hsotg->dev, " en_multiple_tx_fifo=%d\n", + hw->en_multiple_tx_fifo); + dev_dbg(hsotg->dev, " total_fifo_size=%d\n", + hw->total_fifo_size); + dev_dbg(hsotg->dev, " host_rx_fifo_size=%d\n", + hw->host_rx_fifo_size); + dev_dbg(hsotg->dev, " host_nperio_tx_fifo_size=%d\n", + hw->host_nperio_tx_fifo_size); + dev_dbg(hsotg->dev, " host_perio_tx_fifo_size=%d\n", + hw->host_perio_tx_fifo_size); + dev_dbg(hsotg->dev, "\n"); + + return 0; +} + /* * This function is called during module intialization to pass module parameters * for the DWC_otg core. It returns non-0 if any parameters are invalid. @@ -2681,7 +2780,7 @@ int dwc2_set_parameters(struct dwc2_hsotg *hsotg, retval |= dwc2_set_param_en_multiple_tx_fifo(hsotg, params->en_multiple_tx_fifo); retval |= dwc2_set_param_reload_ctl(hsotg, params->reload_ctl); - retval |= dwc2_set_param_ahb_single(hsotg, params->ahb_single); + retval |= dwc2_set_param_ahbcfg(hsotg, params->ahbcfg); retval |= dwc2_set_param_otg_ver(hsotg, params->otg_ver); return retval; diff --git a/drivers/staging/dwc2/core.h b/drivers/staging/dwc2/core.h index fc075a7..9102f66 100644 --- a/drivers/staging/dwc2/core.h +++ b/drivers/staging/dwc2/core.h @@ -68,16 +68,18 @@ enum dwc2_lx_state { /** * struct dwc2_core_params - Parameters for configuring the core * - * @otg_cap: Specifies the OTG capabilities. The driver will - * automatically detect the value for this parameter if - * none is specified. - * 0 - HNP and SRP capable (default) + * @otg_cap: Specifies the OTG capabilities. + * 0 - HNP and SRP capable * 1 - SRP Only capable - * 2 - No HNP/SRP capable + * 2 - No HNP/SRP capable (always available) + * Defaults to best available option (0, 1, then 2) + * @otg_ver: OTG version supported + * 0 - 1.3 (default) + * 1 - 2.0 * @dma_enable: Specifies whether to use slave or DMA mode for accessing * the data FIFOs. The driver will automatically detect the * value for this parameter if none is specified. - * 0 - Slave + * 0 - Slave (always available) * 1 - DMA (default, if available) * @dma_desc_enable: When DMA mode is enabled, specifies whether to use * address DMA mode or descriptor DMA mode for accessing @@ -88,39 +90,47 @@ enum dwc2_lx_state { * @speed: Specifies the maximum speed of operation in host and * device mode. The actual speed depends on the speed of * the attached device and the value of phy_type. - * 0 - High Speed (default) + * 0 - High Speed + * (default when phy_type is UTMI+ or ULPI) * 1 - Full Speed - * @host_support_fs_ls_low_power: Specifies whether low power mode is supported - * when attached to a Full Speed or Low Speed device in - * host mode. - * 0 - Don't support low power mode (default) - * 1 - Support low power mode - * @host_ls_low_power_phy_clk: Specifies the PHY clock rate in low power mode - * when connected to a Low Speed device in host mode. This - * parameter is applicable only if - * host_support_fs_ls_low_power is enabled. If phy_type is - * set to FS then defaults to 6 MHZ otherwise 48 MHZ. - * 0 - 48 MHz - * 1 - 6 MHz + * (default when phy_type is Full Speed) * @enable_dynamic_fifo: 0 - Use coreConsultant-specified FIFO size parameters - * 1 - Allow dynamic FIFO sizing (default) + * 1 - Allow dynamic FIFO sizing (default, if available) + * @en_multiple_tx_fifo: Specifies whether dedicated per-endpoint transmit FIFOs + * are enabled * @host_rx_fifo_size: Number of 4-byte words in the Rx FIFO in host mode when * dynamic FIFO sizing is enabled - * 16 to 32768 (default 1024) + * 16 to 32768 + * Actual maximum value is autodetected and also + * the default. * @host_nperio_tx_fifo_size: Number of 4-byte words in the non-periodic Tx FIFO * in host mode when dynamic FIFO sizing is enabled - * 16 to 32768 (default 1024) + * 16 to 32768 + * Actual maximum value is autodetected and also + * the default. * @host_perio_tx_fifo_size: Number of 4-byte words in the periodic Tx FIFO in * host mode when dynamic FIFO sizing is enabled - * 16 to 32768 (default 1024) + * 16 to 32768 + * Actual maximum value is autodetected and also + * the default. * @max_transfer_size: The maximum transfer size supported, in bytes - * 2047 to 65,535 (default 65,535) + * 2047 to 65,535 + * Actual maximum value is autodetected and also + * the default. * @max_packet_count: The maximum number of packets in a transfer - * 15 to 511 (default 511) + * 15 to 511 + * Actual maximum value is autodetected and also + * the default. * @host_channels: The number of host channel registers to use - * 1 to 16 (default 12) + * 1 to 16 + * Actual maximum value is autodetected and also + * the default. * @phy_type: Specifies the type of PHY interface to use. By default, * the driver will automatically detect the phy_type. + * 0 - Full Speed Phy + * 1 - UTMI+ Phy + * 2 - ULPI Phy + * Defaults to best available option (2, 1, then 0) * @phy_utmi_width: Specifies the UTMI+ Data Width (in bits). This parameter * is applicable for a phy_type of UTMI+ or ULPI. (For a * ULPI phy_type, this parameter indicates the data width @@ -129,7 +139,7 @@ enum dwc2_lx_state { * parameter was set to "8 and 16 bits", meaning that the * core has been configured to work at either data path * width. - * 8 or 16 (default 16) + * 8 or 16 (default 16 if available) * @phy_ulpi_ddr: Specifies whether the ULPI operates at double or single * data rate. This parameter is only applicable if phy_type * is ULPI. @@ -139,27 +149,51 @@ enum dwc2_lx_state { * data bus * @phy_ulpi_ext_vbus: For a ULPI phy, specifies whether to use the internal or * external supply to drive the VBus + * 0 - Internal supply (default) + * 1 - External supply * @i2c_enable: Specifies whether to use the I2Cinterface for a full * speed PHY. This parameter is only applicable if phy_type * is FS. * 0 - No (default) * 1 - Yes - * @ulpi_fs_ls: True to make ULPI phy operate in FS/LS mode only - * @ts_dline: True to enable Term Select Dline pulsing - * @en_multiple_tx_fifo: Specifies whether dedicated per-endpoint transmit FIFOs - * are enabled - * @reload_ctl: True to allow dynamic reloading of HFIR register during - * runtime - * @ahb_single: This bit enables SINGLE transfers for remainder data in - * a transfer for DMA mode of operation. - * 0 - remainder data will be sent using INCR burst size - * 1 - remainder data will be sent using SINGLE burst size - * @otg_ver: OTG version supported - * 0 - 1.3 - * 1 - 2.0 + * @ulpi_fs_ls: Make ULPI phy operate in FS/LS mode only + * 0 - No (default) + * 1 - Yes + * @host_support_fs_ls_low_power: Specifies whether low power mode is supported + * when attached to a Full Speed or Low Speed device in + * host mode. + * 0 - Don't support low power mode (default) + * 1 - Support low power mode + * @host_ls_low_power_phy_clk: Specifies the PHY clock rate in low power mode + * when connected to a Low Speed device in host + * mode. This parameter is applicable only if + * host_support_fs_ls_low_power is enabled. + * 0 - 48 MHz + * (default when phy_type is UTMI+ or ULPI) + * 1 - 6 MHz + * (default when phy_type is Full Speed) + * @ts_dline: Enable Term Select Dline pulsing + * 0 - No (default) + * 1 - Yes + * @reload_ctl: Allow dynamic reloading of HFIR register during runtime + * 0 - No (default for core < 2.92a) + * 1 - Yes (default for core >= 2.92a) + * @ahbcfg: This field allows the default value of the GAHBCFG + * register to be overridden + * -1 - GAHBCFG value will be set to 0x06 + * (INCR4, default) + * all others - GAHBCFG value will be overridden with + * this value + * Not all bits can be controlled like this, the + * bits defined by GAHBCFG_CTRL_MASK are controlled + * by the driver and are ignored in this + * configuration value. * * The following parameters may be specified when starting the module. These - * parameters define how the DWC_otg controller should be configured. + * parameters define how the DWC_otg controller should be configured. A + * value of -1 (or any other out of range value) for any parameter means + * to read the value from hardware (if possible) or use the builtin + * default described above. */ struct dwc2_core_params { /* @@ -189,7 +223,85 @@ struct dwc2_core_params { int host_ls_low_power_phy_clk; int ts_dline; int reload_ctl; - int ahb_single; + int ahbcfg; +}; + +/** + * struct dwc2_hw_params - Autodetected parameters. + * + * These parameters are the various parameters read from hardware + * registers during initialization. They typically contain the best + * supported or maximum value that can be configured in the + * corresponding dwc2_core_params value. + * + * The values that are not in dwc2_core_params are documented below. + * + * @op_mode Mode of Operation + * 0 - HNP- and SRP-Capable OTG (Host & Device) + * 1 - SRP-Capable OTG (Host & Device) + * 2 - Non-HNP and Non-SRP Capable OTG (Host & Device) + * 3 - SRP-Capable Device + * 4 - Non-OTG Device + * 5 - SRP-Capable Host + * 6 - Non-OTG Host + * @arch Architecture + * 0 - Slave only + * 1 - External DMA + * 2 - Internal DMA + * @power_optimized Are power optimizations enabled? + * @num_dev_ep Number of device endpoints available + * @num_dev_perio_in_ep Number of device periodic IN endpoints + * avaialable + * @dev_token_q_depth Device Mode IN Token Sequence Learning Queue + * Depth + * 0 to 30 + * @host_perio_tx_q_depth + * Host Mode Periodic Request Queue Depth + * 2, 4 or 8 + * @nperio_tx_q_depth + * Non-Periodic Request Queue Depth + * 2, 4 or 8 + * @hs_phy_type High-speed PHY interface type + * 0 - High-speed interface not supported + * 1 - UTMI+ + * 2 - ULPI + * 3 - UTMI+ and ULPI + * @fs_phy_type Full-speed PHY interface type + * 0 - Full speed interface not supported + * 1 - Dedicated full speed interface + * 2 - FS pins shared with UTMI+ pins + * 3 - FS pins shared with ULPI pins + * @total_fifo_size: Total internal RAM for FIFOs (bytes) + * @utmi_phy_data_width UTMI+ PHY data width + * 0 - 8 bits + * 1 - 16 bits + * 2 - 8 or 16 bits + * @snpsid: Value from SNPSID register + */ +struct dwc2_hw_params { + unsigned op_mode:3; + unsigned arch:2; + unsigned dma_desc_enable:1; + unsigned enable_dynamic_fifo:1; + unsigned en_multiple_tx_fifo:1; + unsigned host_rx_fifo_size:16; + unsigned host_nperio_tx_fifo_size:16; + unsigned host_perio_tx_fifo_size:16; + unsigned nperio_tx_q_depth:3; + unsigned host_perio_tx_q_depth:3; + unsigned dev_token_q_depth:5; + unsigned max_transfer_size:26; + unsigned max_packet_count:11; + unsigned host_channels:4; + unsigned hs_phy_type:2; + unsigned fs_phy_type:2; + unsigned i2c_enable:1; + unsigned num_dev_ep:4; + unsigned num_dev_perio_in_ep:4; + unsigned total_fifo_size:16; + unsigned power_optimized:1; + unsigned utmi_phy_data_width:2; + u32 snpsid; }; /** @@ -199,15 +311,8 @@ struct dwc2_core_params { * @dev: The struct device pointer * @regs: Pointer to controller regs * @core_params: Parameters that define how the core should be configured - * @hwcfg1: Hardware Configuration - stored here for convenience - * @hwcfg2: Hardware Configuration - stored here for convenience - * @hwcfg3: Hardware Configuration - stored here for convenience - * @hwcfg4: Hardware Configuration - stored here for convenience - * @hptxfsiz: Hardware Configuration - stored here for convenience - * @snpsid: Value from SNPSID register - * @total_fifo_size: Total internal RAM for FIFOs (bytes) - * @rx_fifo_size: Size of Rx FIFO (bytes) - * @nperio_tx_fifo_size: Size of Non-periodic Tx FIFO (Bytes) + * @hw_params: Parameters that were autodetected from the + * hardware registers * @op_state: The operational State, during transitions (a_host=> * a_peripheral and b_device=>b_host) this may not match * the core, but allows the software to determine @@ -295,16 +400,10 @@ struct dwc2_core_params { struct dwc2_hsotg { struct device *dev; void __iomem *regs; + /** Params detected from hardware */ + struct dwc2_hw_params hw_params; + /** Params to actually use */ struct dwc2_core_params *core_params; - u32 hwcfg1; - u32 hwcfg2; - u32 hwcfg3; - u32 hwcfg4; - u32 hptxfsiz; - u32 snpsid; - u16 total_fifo_size; - u16 rx_fifo_size; - u16 nperio_tx_fifo_size; enum usb_otg_state op_state; unsigned int queuing_high_bandwidth:1; @@ -643,7 +742,7 @@ extern int dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, extern int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val); -extern int dwc2_set_param_ahb_single(struct dwc2_hsotg *hsotg, int val); +extern int dwc2_set_param_ahbcfg(struct dwc2_hsotg *hsotg, int val); extern int dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val); diff --git a/drivers/staging/dwc2/core_intr.c b/drivers/staging/dwc2/core_intr.c index 98c51bb..07cfa2f 100644 --- a/drivers/staging/dwc2/core_intr.c +++ b/drivers/staging/dwc2/core_intr.c @@ -166,7 +166,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg) * WA for 3.00a- HW is not setting cur_mode, even sometimes * this does not help */ - if (hsotg->snpsid >= DWC2_CORE_REV_3_00a) + if (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a) udelay(100); if (gotgctl & GOTGCTL_HSTNEGSCS) { if (dwc2_is_host_mode(hsotg)) { @@ -380,7 +380,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, "DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d\n", !!(dsts & DSTS_SUSPSTS), - !!(hsotg->hwcfg4 & GHWCFG4_POWER_OPTIMIZ)); + hsotg->hw_params.power_optimized); } else { if (hsotg->op_state == OTG_STATE_A_PERIPHERAL) { dev_dbg(hsotg->dev, "a_peripheral->a_host\n"); diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c index 2ed54b1..da0d35c 100644 --- a/drivers/staging/dwc2/hcd.c +++ b/drivers/staging/dwc2/hcd.c @@ -134,11 +134,8 @@ static void dwc2_kill_urbs_in_qh_list(struct dwc2_hsotg *hsotg, list_for_each_entry_safe(qh, qh_tmp, qh_list, qh_list_entry) { list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { - if (qtd->urb != NULL) { - dwc2_host_complete(hsotg, qtd->urb->priv, - qtd->urb, -ETIMEDOUT); - dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); - } + dwc2_host_complete(hsotg, qtd, -ETIMEDOUT); + dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); } } } @@ -421,6 +418,8 @@ static int dwc2_hcd_urb_dequeue(struct dwc2_hsotg *hsotg, return -EINVAL; } + urb->priv = NULL; + if (urb_qtd->in_process && qh->channel) { dwc2_dump_channel_info(hsotg, qh->channel); @@ -1006,10 +1005,10 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) dev_vdbg(hsotg->dev, "Queue periodic transactions\n"); tx_status = readl(hsotg->regs + HPTXSTS); - qspcavail = tx_status >> TXSTS_QSPCAVAIL_SHIFT & - TXSTS_QSPCAVAIL_MASK >> TXSTS_QSPCAVAIL_SHIFT; - fspcavail = tx_status >> TXSTS_FSPCAVAIL_SHIFT & - TXSTS_FSPCAVAIL_MASK >> TXSTS_FSPCAVAIL_SHIFT; + qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> + TXSTS_QSPCAVAIL_SHIFT; + fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >> + TXSTS_FSPCAVAIL_SHIFT; if (dbg_perio()) { dev_vdbg(hsotg->dev, " P Tx Req Queue Space Avail (before queue): %d\n", @@ -1021,7 +1020,9 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) qh_ptr = hsotg->periodic_sched_assigned.next; while (qh_ptr != &hsotg->periodic_sched_assigned) { tx_status = readl(hsotg->regs + HPTXSTS); - if ((tx_status & TXSTS_QSPCAVAIL_MASK) == 0) { + qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> + TXSTS_QSPCAVAIL_SHIFT; + if (qspcavail == 0) { no_queue_space = 1; break; } @@ -1047,8 +1048,8 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) qh->channel->multi_count > 1) hsotg->queuing_high_bandwidth = 1; - fspcavail = tx_status >> TXSTS_FSPCAVAIL_SHIFT & - TXSTS_FSPCAVAIL_MASK >> TXSTS_FSPCAVAIL_SHIFT; + fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >> + TXSTS_FSPCAVAIL_SHIFT; status = dwc2_queue_transaction(hsotg, qh->channel, fspcavail); if (status < 0) { no_fifo_space = 1; @@ -1079,10 +1080,10 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg) if (hsotg->core_params->dma_enable <= 0) { tx_status = readl(hsotg->regs + HPTXSTS); - qspcavail = tx_status >> TXSTS_QSPCAVAIL_SHIFT & - TXSTS_QSPCAVAIL_MASK >> TXSTS_QSPCAVAIL_SHIFT; - fspcavail = tx_status >> TXSTS_FSPCAVAIL_SHIFT & - TXSTS_FSPCAVAIL_MASK >> TXSTS_FSPCAVAIL_SHIFT; + qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> + TXSTS_QSPCAVAIL_SHIFT; + fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >> + TXSTS_FSPCAVAIL_SHIFT; if (dbg_perio()) { dev_vdbg(hsotg->dev, " P Tx Req Queue Space Avail (after queue): %d\n", @@ -1144,10 +1145,10 @@ static void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg) dev_vdbg(hsotg->dev, "Queue non-periodic transactions\n"); tx_status = readl(hsotg->regs + GNPTXSTS); - qspcavail = tx_status >> TXSTS_QSPCAVAIL_SHIFT & - TXSTS_QSPCAVAIL_MASK >> TXSTS_QSPCAVAIL_SHIFT; - fspcavail = tx_status >> TXSTS_FSPCAVAIL_SHIFT & - TXSTS_FSPCAVAIL_MASK >> TXSTS_FSPCAVAIL_SHIFT; + qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> + TXSTS_QSPCAVAIL_SHIFT; + fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >> + TXSTS_FSPCAVAIL_SHIFT; dev_vdbg(hsotg->dev, " NP Tx Req Queue Space Avail (before queue): %d\n", qspcavail); dev_vdbg(hsotg->dev, " NP Tx FIFO Space Avail (before queue): %d\n", @@ -1167,8 +1168,8 @@ static void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg) */ do { tx_status = readl(hsotg->regs + GNPTXSTS); - qspcavail = tx_status >> TXSTS_QSPCAVAIL_SHIFT & - TXSTS_QSPCAVAIL_MASK >> TXSTS_QSPCAVAIL_SHIFT; + qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> + TXSTS_QSPCAVAIL_SHIFT; if (hsotg->core_params->dma_enable <= 0 && qspcavail == 0) { no_queue_space = 1; break; @@ -1183,8 +1184,8 @@ static void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg) if (qh->tt_buffer_dirty) goto next; - fspcavail = tx_status >> TXSTS_FSPCAVAIL_SHIFT & - TXSTS_FSPCAVAIL_MASK >> TXSTS_FSPCAVAIL_SHIFT; + fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >> + TXSTS_FSPCAVAIL_SHIFT; status = dwc2_queue_transaction(hsotg, qh->channel, fspcavail); if (status > 0) { @@ -1204,10 +1205,10 @@ next: if (hsotg->core_params->dma_enable <= 0) { tx_status = readl(hsotg->regs + GNPTXSTS); - qspcavail = tx_status >> TXSTS_QSPCAVAIL_SHIFT & - TXSTS_QSPCAVAIL_MASK >> TXSTS_QSPCAVAIL_SHIFT; - fspcavail = tx_status >> TXSTS_FSPCAVAIL_SHIFT & - TXSTS_FSPCAVAIL_MASK >> TXSTS_FSPCAVAIL_SHIFT; + qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >> + TXSTS_QSPCAVAIL_SHIFT; + fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >> + TXSTS_FSPCAVAIL_SHIFT; dev_vdbg(hsotg->dev, " NP Tx Req Queue Space Avail (after queue): %d\n", qspcavail); @@ -1613,7 +1614,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, if (hprt0 & HPRT0_PWR) port_status |= USB_PORT_STAT_POWER; - speed = hprt0 & HPRT0_SPD_MASK; + speed = (hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT; if (speed == HPRT0_SPD_HIGH_SPEED) port_status |= USB_PORT_STAT_HIGH_SPEED; else if (speed == HPRT0_SPD_LOW_SPEED) @@ -1762,11 +1763,9 @@ int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg) #ifdef DWC2_DEBUG_SOF dev_vdbg(hsotg->dev, "DWC OTG HCD GET FRAME NUMBER %d\n", - hfnum >> HFNUM_FRNUM_SHIFT & - HFNUM_FRNUM_MASK >> HFNUM_FRNUM_SHIFT); + (hfnum & HFNUM_FRNUM_MASK) >> HFNUM_FRNUM_SHIFT); #endif - return hfnum >> HFNUM_FRNUM_SHIFT & - HFNUM_FRNUM_MASK >> HFNUM_FRNUM_SHIFT; + return (hfnum & HFNUM_FRNUM_MASK) >> HFNUM_FRNUM_SHIFT; } int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg) @@ -1917,18 +1916,14 @@ void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg) dev_dbg(hsotg->dev, " periodic_usecs: %d\n", hsotg->periodic_usecs); np_tx_status = readl(hsotg->regs + GNPTXSTS); dev_dbg(hsotg->dev, " NP Tx Req Queue Space Avail: %d\n", - np_tx_status >> TXSTS_QSPCAVAIL_SHIFT & - TXSTS_QSPCAVAIL_MASK >> TXSTS_QSPCAVAIL_SHIFT); + (np_tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT); dev_dbg(hsotg->dev, " NP Tx FIFO Space Avail: %d\n", - np_tx_status >> TXSTS_FSPCAVAIL_SHIFT & - TXSTS_FSPCAVAIL_MASK >> TXSTS_FSPCAVAIL_SHIFT); + (np_tx_status & TXSTS_FSPCAVAIL_MASK) >> TXSTS_FSPCAVAIL_SHIFT); p_tx_status = readl(hsotg->regs + HPTXSTS); dev_dbg(hsotg->dev, " P Tx Req Queue Space Avail: %d\n", - p_tx_status >> TXSTS_QSPCAVAIL_SHIFT & - TXSTS_QSPCAVAIL_MASK >> TXSTS_QSPCAVAIL_SHIFT); + (p_tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT); dev_dbg(hsotg->dev, " P Tx FIFO Space Avail: %d\n", - p_tx_status >> TXSTS_FSPCAVAIL_SHIFT & - TXSTS_FSPCAVAIL_MASK >> TXSTS_FSPCAVAIL_SHIFT); + (p_tx_status & TXSTS_FSPCAVAIL_MASK) >> TXSTS_FSPCAVAIL_SHIFT); dwc2_hcd_dump_frrem(hsotg); dwc2_dump_global_registers(hsotg); dwc2_dump_host_registers(hsotg); @@ -2088,23 +2083,29 @@ static void dwc2_free_bus_bandwidth(struct usb_hcd *hcd, u16 bw, * * Must be called with interrupt disabled and spinlock held */ -void dwc2_host_complete(struct dwc2_hsotg *hsotg, void *context, - struct dwc2_hcd_urb *dwc2_urb, int status) +void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, + int status) { - struct urb *urb = context; + struct urb *urb; int i; - if (!urb) { - dev_dbg(hsotg->dev, "## %s: context is NULL ##\n", __func__); + if (!qtd) { + dev_dbg(hsotg->dev, "## %s: qtd is NULL ##\n", __func__); return; } - if (!dwc2_urb) { - dev_dbg(hsotg->dev, "## %s: dwc2_urb is NULL ##\n", __func__); + if (!qtd->urb) { + dev_dbg(hsotg->dev, "## %s: qtd->urb is NULL ##\n", __func__); + return; + } + + urb = qtd->urb->priv; + if (!urb) { + dev_dbg(hsotg->dev, "## %s: urb->priv is NULL ##\n", __func__); return; } - urb->actual_length = dwc2_hcd_urb_get_actual_length(dwc2_urb); + urb->actual_length = dwc2_hcd_urb_get_actual_length(qtd->urb); if (dbg_urb(urb)) dev_vdbg(hsotg->dev, @@ -2121,18 +2122,17 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, void *context, } if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - urb->error_count = dwc2_hcd_urb_get_error_count(dwc2_urb); + urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb); for (i = 0; i < urb->number_of_packets; ++i) { urb->iso_frame_desc[i].actual_length = dwc2_hcd_urb_get_iso_desc_actual_length( - dwc2_urb, i); + qtd->urb, i); urb->iso_frame_desc[i].status = - dwc2_hcd_urb_get_iso_desc_status(dwc2_urb, i); + dwc2_hcd_urb_get_iso_desc_status(qtd->urb, i); } } urb->status = status; - urb->hcpriv = NULL; if (!status) { if ((urb->transfer_flags & URB_SHORT_NOT_OK) && urb->actual_length < urb->transfer_buffer_length) @@ -2149,7 +2149,10 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, void *context, urb); } - kfree(dwc2_urb); + usb_hcd_unlink_urb_from_ep(dwc2_hsotg_to_hcd(hsotg), urb); + urb->hcpriv = NULL; + kfree(qtd->urb); + qtd->urb = NULL; spin_unlock(&hsotg->lock); usb_hcd_giveback_urb(dwc2_hsotg_to_hcd(hsotg), urb, status); @@ -2337,8 +2340,8 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, struct usb_host_endpoint *ep = urb->ep; struct dwc2_hcd_urb *dwc2_urb; int i; + int retval; int alloc_bandwidth = 0; - int retval = 0; u8 ep_type = 0; u32 tflags = 0; void *buf; @@ -2389,14 +2392,15 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, !(usb_pipein(urb->pipe)))); buf = urb->transfer_buffer; + if (hcd->self.uses_dma) { - /* - * Calculate virtual address from physical address, because - * some class driver may not fill transfer_buffer. - * In Buffer DMA mode virtual address is used, when handling - * non-DWORD aligned buffers. - */ - buf = bus_to_virt(urb->transfer_dma); + if (!buf && (urb->transfer_dma & 3)) { + dev_err(hsotg->dev, + "%s: unaligned transfer with no transfer_buffer", + __func__); + retval = -EINVAL; + goto fail1; + } } if (!(urb->transfer_flags & URB_NO_INTERRUPT)) @@ -2420,21 +2424,36 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, urb->iso_frame_desc[i].length); urb->hcpriv = dwc2_urb; - retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, &ep->hcpriv, - mem_flags); - if (retval) { - urb->hcpriv = NULL; - kfree(dwc2_urb); - } else { - if (alloc_bandwidth) { - spin_lock_irqsave(&hsotg->lock, flags); - dwc2_allocate_bus_bandwidth(hcd, - dwc2_hcd_get_ep_bandwidth(hsotg, ep), - urb); - spin_unlock_irqrestore(&hsotg->lock, flags); - } + + spin_lock_irqsave(&hsotg->lock, flags); + retval = usb_hcd_link_urb_to_ep(hcd, urb); + spin_unlock_irqrestore(&hsotg->lock, flags); + if (retval) + goto fail1; + + retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, &ep->hcpriv, mem_flags); + if (retval) + goto fail2; + + if (alloc_bandwidth) { + spin_lock_irqsave(&hsotg->lock, flags); + dwc2_allocate_bus_bandwidth(hcd, + dwc2_hcd_get_ep_bandwidth(hsotg, ep), + urb); + spin_unlock_irqrestore(&hsotg->lock, flags); } + return 0; + +fail2: + spin_lock_irqsave(&hsotg->lock, flags); + dwc2_urb->priv = NULL; + usb_hcd_unlink_urb_from_ep(hcd, urb); + spin_unlock_irqrestore(&hsotg->lock, flags); +fail1: + urb->hcpriv = NULL; + kfree(dwc2_urb); + return retval; } @@ -2445,7 +2464,7 @@ static int _dwc2_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) { struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); - int rc = 0; + int rc; unsigned long flags; dev_dbg(hsotg->dev, "DWC OTG HCD URB Dequeue\n"); @@ -2453,6 +2472,10 @@ static int _dwc2_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, spin_lock_irqsave(&hsotg->lock, flags); + rc = usb_hcd_check_unlink_urb(hcd, urb, status); + if (rc) + goto out; + if (!urb->hcpriv) { dev_dbg(hsotg->dev, "## urb->hcpriv is NULL ##\n"); goto out; @@ -2460,6 +2483,8 @@ static int _dwc2_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, rc = dwc2_hcd_urb_dequeue(hsotg, urb->hcpriv); + usb_hcd_unlink_urb_from_ep(hcd, urb); + kfree(urb->hcpriv); urb->hcpriv = NULL; @@ -2653,7 +2678,7 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg) writel(ahbcfg, hsotg->regs + GAHBCFG); writel(0, hsotg->regs + GINTMSK); - if (hsotg->snpsid >= DWC2_CORE_REV_3_00a) { + if (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a) { dctl = readl(hsotg->regs + DCTL); dctl |= DCTL_SFTDISCON; writel(dctl, hsotg->regs + DCTL); @@ -2690,7 +2715,7 @@ void dwc2_set_all_params(struct dwc2_core_params *params, int value) int i; for (i = 0; i < size; i++) - p[i] = -1; + p[i] = value; } EXPORT_SYMBOL_GPL(dwc2_set_all_params); @@ -2705,79 +2730,22 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, { struct usb_hcd *hcd; struct dwc2_host_chan *channel; - u32 snpsid, gusbcfg, hcfg; + u32 hcfg; int i, num_channels; - int retval = -ENOMEM; + int retval; dev_dbg(hsotg->dev, "DWC OTG HCD INIT\n"); - /* - * Attempt to ensure this device is really a DWC_otg Controller. - * Read and verify the GSNPSID register contents. The value should be - * 0x45f42xxx or 0x45f43xxx, which corresponds to either "OT2" or "OT3", - * as in "OTG version 2.xx" or "OTG version 3.xx". - */ - snpsid = readl(hsotg->regs + GSNPSID); - if ((snpsid & 0xfffff000) != 0x4f542000 && - (snpsid & 0xfffff000) != 0x4f543000) { - dev_err(hsotg->dev, "Bad value for GSNPSID: 0x%08x\n", snpsid); - retval = -ENODEV; - goto error1; - } + /* Detect config values from hardware */ + retval = dwc2_get_hwparams(hsotg); - /* - * Store the contents of the hardware configuration registers here for - * easy access later - */ - hsotg->hwcfg1 = readl(hsotg->regs + GHWCFG1); - hsotg->hwcfg2 = readl(hsotg->regs + GHWCFG2); - hsotg->hwcfg3 = readl(hsotg->regs + GHWCFG3); - hsotg->hwcfg4 = readl(hsotg->regs + GHWCFG4); - - dev_dbg(hsotg->dev, "hwcfg1=%08x\n", hsotg->hwcfg1); - dev_dbg(hsotg->dev, "hwcfg2=%08x\n", hsotg->hwcfg2); - dev_dbg(hsotg->dev, "hwcfg3=%08x\n", hsotg->hwcfg3); - dev_dbg(hsotg->dev, "hwcfg4=%08x\n", hsotg->hwcfg4); - - /* Force host mode to get HPTXFSIZ exact power on value */ - gusbcfg = readl(hsotg->regs + GUSBCFG); - gusbcfg |= GUSBCFG_FORCEHOSTMODE; - writel(gusbcfg, hsotg->regs + GUSBCFG); - usleep_range(100000, 150000); - - hsotg->hptxfsiz = readl(hsotg->regs + HPTXFSIZ); - dev_dbg(hsotg->dev, "hptxfsiz=%08x\n", hsotg->hptxfsiz); - gusbcfg = readl(hsotg->regs + GUSBCFG); - gusbcfg &= ~GUSBCFG_FORCEHOSTMODE; - writel(gusbcfg, hsotg->regs + GUSBCFG); - usleep_range(100000, 150000); + if (retval) + return retval; + + retval = -ENOMEM; hcfg = readl(hsotg->regs + HCFG); dev_dbg(hsotg->dev, "hcfg=%08x\n", hcfg); - dev_dbg(hsotg->dev, "op_mode=%0x\n", - hsotg->hwcfg2 >> GHWCFG2_OP_MODE_SHIFT & - GHWCFG2_OP_MODE_MASK >> GHWCFG2_OP_MODE_SHIFT); - dev_dbg(hsotg->dev, "arch=%0x\n", - hsotg->hwcfg2 >> GHWCFG2_ARCHITECTURE_SHIFT & - GHWCFG2_ARCHITECTURE_MASK >> GHWCFG2_ARCHITECTURE_SHIFT); - dev_dbg(hsotg->dev, "num_dev_ep=%d\n", - hsotg->hwcfg2 >> GHWCFG2_NUM_DEV_EP_SHIFT & - GHWCFG2_NUM_DEV_EP_MASK >> GHWCFG2_NUM_DEV_EP_SHIFT); - dev_dbg(hsotg->dev, "max_host_chan=%d\n", - hsotg->hwcfg2 >> GHWCFG2_NUM_HOST_CHAN_SHIFT & - GHWCFG2_NUM_HOST_CHAN_MASK >> GHWCFG2_NUM_HOST_CHAN_SHIFT); - dev_dbg(hsotg->dev, "nonperio_tx_q_depth=0x%0x\n", - hsotg->hwcfg2 >> GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT & - GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK >> - GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT); - dev_dbg(hsotg->dev, "host_perio_tx_q_depth=0x%0x\n", - hsotg->hwcfg2 >> GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT & - GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK >> - GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT); - dev_dbg(hsotg->dev, "dev_token_q_depth=0x%0x\n", - hsotg->hwcfg2 >> GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT & - GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK >> - GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT); #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS hsotg->frame_num_array = kzalloc(sizeof(*hsotg->frame_num_array) * @@ -2801,22 +2769,30 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, /* Validate parameter values */ dwc2_set_parameters(hsotg, params); + /* Check if the bus driver or platform code has setup a dma_mask */ + if (hsotg->core_params->dma_enable > 0 && + hsotg->dev->dma_mask == NULL) { + dev_warn(hsotg->dev, + "dma_mask not set, disabling DMA\n"); + hsotg->core_params->dma_enable = 0; + hsotg->core_params->dma_desc_enable = 0; + } + /* Set device flags indicating whether the HCD supports DMA */ if (hsotg->core_params->dma_enable > 0) { if (dma_set_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0) dev_warn(hsotg->dev, "can't set DMA mask\n"); - if (dma_set_coherent_mask(hsotg->dev, DMA_BIT_MASK(31)) < 0) - dev_warn(hsotg->dev, - "can't enable workaround for >2GB RAM\n"); - } else { - dma_set_mask(hsotg->dev, 0); - dma_set_coherent_mask(hsotg->dev, 0); + if (dma_set_coherent_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0) + dev_warn(hsotg->dev, "can't set coherent DMA mask\n"); } hcd = usb_create_hcd(&dwc2_hc_driver, hsotg->dev, dev_name(hsotg->dev)); if (!hcd) goto error1; + if (hsotg->core_params->dma_enable <= 0) + hcd->self.uses_dma = 0; + hcd->has_tt = 1; spin_lock_init(&hsotg->lock); @@ -2843,11 +2819,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, } INIT_WORK(&hsotg->wf_otg, dwc2_conn_id_status_change); - hsotg->snpsid = readl(hsotg->regs + GSNPSID); - dev_dbg(hsotg->dev, "Core Release: %1x.%1x%1x%1x\n", - hsotg->snpsid >> 12 & 0xf, hsotg->snpsid >> 8 & 0xf, - hsotg->snpsid >> 4 & 0xf, hsotg->snpsid & 0xf); - setup_timer(&hsotg->wkp_timer, dwc2_wakeup_detected, (unsigned long)hsotg); @@ -2922,8 +2893,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, if (retval < 0) goto error3; - dwc2_dump_global_registers(hsotg); - dwc2_dump_host_registers(hsotg); dwc2_hcd_dump_state(hsotg); dwc2_enable_global_interrupts(hsotg); diff --git a/drivers/staging/dwc2/hcd.h b/drivers/staging/dwc2/hcd.h index cf6c055..cc0a117 100644 --- a/drivers/staging/dwc2/hcd.h +++ b/drivers/staging/dwc2/hcd.h @@ -122,11 +122,11 @@ struct dwc2_host_chan { unsigned ep_type:2; unsigned max_packet:11; unsigned data_pid_start:2; -#define DWC2_HC_PID_DATA0 (TSIZ_SC_MC_PID_DATA0 >> TSIZ_SC_MC_PID_SHIFT) -#define DWC2_HC_PID_DATA2 (TSIZ_SC_MC_PID_DATA2 >> TSIZ_SC_MC_PID_SHIFT) -#define DWC2_HC_PID_DATA1 (TSIZ_SC_MC_PID_DATA1 >> TSIZ_SC_MC_PID_SHIFT) -#define DWC2_HC_PID_MDATA (TSIZ_SC_MC_PID_MDATA >> TSIZ_SC_MC_PID_SHIFT) -#define DWC2_HC_PID_SETUP (TSIZ_SC_MC_PID_SETUP >> TSIZ_SC_MC_PID_SHIFT) +#define DWC2_HC_PID_DATA0 TSIZ_SC_MC_PID_DATA0 +#define DWC2_HC_PID_DATA2 TSIZ_SC_MC_PID_DATA2 +#define DWC2_HC_PID_DATA1 TSIZ_SC_MC_PID_DATA1 +#define DWC2_HC_PID_MDATA TSIZ_SC_MC_PID_MDATA +#define DWC2_HC_PID_SETUP TSIZ_SC_MC_PID_SETUP unsigned multi_count:2; @@ -146,10 +146,10 @@ struct dwc2_host_chan { u8 hub_addr; u8 hub_port; u8 xact_pos; -#define DWC2_HCSPLT_XACTPOS_MID (HCSPLT_XACTPOS_MID >> HCSPLT_XACTPOS_SHIFT) -#define DWC2_HCSPLT_XACTPOS_END (HCSPLT_XACTPOS_END >> HCSPLT_XACTPOS_SHIFT) -#define DWC2_HCSPLT_XACTPOS_BEGIN (HCSPLT_XACTPOS_BEGIN >> HCSPLT_XACTPOS_SHIFT) -#define DWC2_HCSPLT_XACTPOS_ALL (HCSPLT_XACTPOS_ALL >> HCSPLT_XACTPOS_SHIFT) +#define DWC2_HCSPLT_XACTPOS_MID HCSPLT_XACTPOS_MID +#define DWC2_HCSPLT_XACTPOS_END HCSPLT_XACTPOS_END +#define DWC2_HCSPLT_XACTPOS_BEGIN HCSPLT_XACTPOS_BEGIN +#define DWC2_HCSPLT_XACTPOS_ALL HCSPLT_XACTPOS_ALL u8 requests; u8 schinfo; @@ -232,16 +232,19 @@ enum dwc2_transaction_type { * - DWC2_HC_PID_DATA1 * @ping_state: Ping state * @do_split: Full/low speed endpoint on high-speed hub requires split - * @qtd_list: List of QTDs for this QH - * @channel: Host channel currently processing transfers for this QH + * @td_first: Index of first activated isochronous transfer descriptor + * @td_last: Index of last activated isochronous transfer descriptor * @usecs: Bandwidth in microseconds per (micro)frame * @interval: Interval between transfers in (micro)frames - * @sched_frame: (micro)frame to initialize a periodic transfer. + * @sched_frame: (Micro)frame to initialize a periodic transfer. * The transfer executes in the following (micro)frame. * @start_split_frame: (Micro)frame at which last start split was initialized + * @ntd: Actual number of transfer descriptors in a list * @dw_align_buf: Used instead of original buffer if its physical address * is not dword-aligned * @dw_align_buf_dma: DMA address for align_buf + * @qtd_list: List of QTDs for this QH + * @channel: Host channel currently processing transfers for this QH * @qh_list_entry: Entry for QH in either the periodic or non-periodic * schedule * @desc_list: List of transfer descriptors @@ -249,9 +252,6 @@ enum dwc2_transaction_type { * @n_bytes: Xfer Bytes array. Each element corresponds to a transfer * descriptor and indicates original XferSize value for the * descriptor - * @ntd: Actual number of transfer descriptors in a list - * @td_first: Index of first activated isochronous transfer descriptor - * @td_last: Index of last activated isochronous transfer descriptor * @tt_buffer_dirty True if clear_tt_buffer_complete is pending * * A Queue Head (QH) holds the static characteristics of an endpoint and @@ -266,21 +266,21 @@ struct dwc2_qh { u8 data_toggle; u8 ping_state; u8 do_split; - struct list_head qtd_list; - struct dwc2_host_chan *channel; + u8 td_first; + u8 td_last; u16 usecs; u16 interval; u16 sched_frame; u16 start_split_frame; + u16 ntd; u8 *dw_align_buf; dma_addr_t dw_align_buf_dma; + struct list_head qtd_list; + struct dwc2_host_chan *channel; struct list_head qh_list_entry; struct dwc2_hcd_dma_desc *desc_list; dma_addr_t desc_list_dma; u32 *n_bytes; - u16 ntd; - u8 td_first; - u8 td_last; unsigned tt_buffer_dirty:1; }; @@ -453,6 +453,7 @@ extern void dwc2_hcd_remove(struct dwc2_hsotg *hsotg); extern int dwc2_set_parameters(struct dwc2_hsotg *hsotg, const struct dwc2_core_params *params); extern void dwc2_set_all_params(struct dwc2_core_params *params, int value); +extern int dwc2_get_hwparams(struct dwc2_hsotg *hsotg); /* Transaction Execution Functions */ extern enum dwc2_transaction_type dwc2_hcd_select_transactions( @@ -716,8 +717,8 @@ extern void dwc2_host_disconnect(struct dwc2_hsotg *hsotg); extern void dwc2_host_hub_info(struct dwc2_hsotg *hsotg, void *context, int *hub_addr, int *hub_port); extern int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context); -extern void dwc2_host_complete(struct dwc2_hsotg *hsotg, void *context, - struct dwc2_hcd_urb *dwc2_urb, int status); +extern void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, + int status); #ifdef DEBUG /* diff --git a/drivers/staging/dwc2/hcd_ddma.c b/drivers/staging/dwc2/hcd_ddma.c index 5c0fd27..69070f4 100644 --- a/drivers/staging/dwc2/hcd_ddma.c +++ b/drivers/staging/dwc2/hcd_ddma.c @@ -800,11 +800,14 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, u16 remain = 0; int rc = 0; + if (!qtd->urb) + return -EINVAL; + frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last]; dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset); if (chan->ep_is_in) - remain = dma_desc->status >> HOST_DMA_ISOC_NBYTES_SHIFT & - HOST_DMA_ISOC_NBYTES_MASK >> HOST_DMA_ISOC_NBYTES_SHIFT; + remain = (dma_desc->status & HOST_DMA_ISOC_NBYTES_MASK) >> + HOST_DMA_ISOC_NBYTES_SHIFT; if ((dma_desc->status & HOST_DMA_STS_MASK) == HOST_DMA_STS_PKTERR) { /* @@ -826,7 +829,7 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, * urb->status is not used for isoc transfers here. The * individual frame_desc status are used instead. */ - dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, 0); + dwc2_host_complete(hsotg, qtd, 0); dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); /* @@ -884,13 +887,16 @@ static void dwc2_complete_isoc_xfer_ddma(struct dwc2_hsotg *hsotg, list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { - for (idx = 0; idx < qtd->urb->packet_count; idx++) { - frame_desc = &qtd->urb->iso_descs[idx]; - frame_desc->status = err; + if (qtd->urb) { + for (idx = 0; idx < qtd->urb->packet_count; + idx++) { + frame_desc = &qtd->urb->iso_descs[idx]; + frame_desc->status = err; + } + + dwc2_host_complete(hsotg, qtd, err); } - dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, - err); dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); } @@ -929,8 +935,8 @@ static int dwc2_update_non_isoc_urb_state_ddma(struct dwc2_hsotg *hsotg, u16 remain = 0; if (chan->ep_is_in) - remain = dma_desc->status >> HOST_DMA_NBYTES_SHIFT & - HOST_DMA_NBYTES_MASK >> HOST_DMA_NBYTES_SHIFT; + remain = (dma_desc->status & HOST_DMA_NBYTES_MASK) >> + HOST_DMA_NBYTES_SHIFT; dev_vdbg(hsotg->dev, "remain=%d dwc2_urb=%p\n", remain, urb); @@ -1015,6 +1021,9 @@ static int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg, dev_vdbg(hsotg->dev, "%s()\n", __func__); + if (!urb) + return -EINVAL; + dma_desc = &qh->desc_list[desc_num]; n_bytes = qh->n_bytes[desc_num]; dev_vdbg(hsotg->dev, @@ -1024,7 +1033,7 @@ static int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg, halt_status, n_bytes, xfer_done); if (failed || (*xfer_done && urb->status != -EINPROGRESS)) { - dwc2_host_complete(hsotg, urb->priv, urb, urb->status); + dwc2_host_complete(hsotg, qtd, urb->status); dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); dev_vdbg(hsotg->dev, "failed=%1x xfer_done=%1x status=%08x\n", failed, *xfer_done, urb->status); diff --git a/drivers/staging/dwc2/hcd_intr.c b/drivers/staging/dwc2/hcd_intr.c index e75dccb..e143f69 100644 --- a/drivers/staging/dwc2/hcd_intr.c +++ b/drivers/staging/dwc2/hcd_intr.c @@ -89,15 +89,20 @@ static void dwc2_hc_handle_tt_clear(struct dwc2_hsotg *hsotg, { struct urb *usb_urb; - if (!chan->qh || !qtd->urb) + if (!chan->qh) + return; + + if (chan->qh->dev_speed == USB_SPEED_HIGH) + return; + + if (!qtd->urb) return; usb_urb = qtd->urb->priv; - if (!usb_urb || !usb_urb->dev) + if (!usb_urb || !usb_urb->dev || !usb_urb->dev->tt) return; - if (chan->qh->dev_speed != USB_SPEED_HIGH && - qtd->urb->status != -EPIPE && qtd->urb->status != -EREMOTEIO) { + if (qtd->urb->status != -EPIPE && qtd->urb->status != -EREMOTEIO) { chan->qh->tt_buffer_dirty = 1; if (usb_hub_clear_tt_buffer(usb_urb)) /* Clear failed; let's hope things work anyway */ @@ -160,19 +165,16 @@ static void dwc2_rx_fifo_level_intr(struct dwc2_hsotg *hsotg) dev_vdbg(hsotg->dev, "--RxFIFO Level Interrupt--\n"); grxsts = readl(hsotg->regs + GRXSTSP); - chnum = grxsts >> GRXSTS_HCHNUM_SHIFT & - GRXSTS_HCHNUM_MASK >> GRXSTS_HCHNUM_SHIFT; + chnum = (grxsts & GRXSTS_HCHNUM_MASK) >> GRXSTS_HCHNUM_SHIFT; chan = hsotg->hc_ptr_array[chnum]; if (!chan) { dev_err(hsotg->dev, "Unable to get corresponding channel\n"); return; } - bcnt = grxsts >> GRXSTS_BYTECNT_SHIFT & - GRXSTS_BYTECNT_MASK >> GRXSTS_BYTECNT_SHIFT; - dpid = grxsts >> GRXSTS_DPID_SHIFT & - GRXSTS_DPID_MASK >> GRXSTS_DPID_SHIFT; - pktsts = grxsts & GRXSTS_PKTSTS_MASK; + bcnt = (grxsts & GRXSTS_BYTECNT_MASK) >> GRXSTS_BYTECNT_SHIFT; + dpid = (grxsts & GRXSTS_DPID_MASK) >> GRXSTS_DPID_SHIFT; + pktsts = (grxsts & GRXSTS_PKTSTS_MASK) >> GRXSTS_PKTSTS_SHIFT; /* Packet Status */ if (dbg_perio()) { @@ -180,9 +182,7 @@ static void dwc2_rx_fifo_level_intr(struct dwc2_hsotg *hsotg) dev_vdbg(hsotg->dev, " Count = %d\n", bcnt); dev_vdbg(hsotg->dev, " DPID = %d, chan.dpid = %d\n", dpid, chan->data_pid_start); - dev_vdbg(hsotg->dev, " PStatus = %d\n", - pktsts >> GRXSTS_PKTSTS_SHIFT & - GRXSTS_PKTSTS_MASK >> GRXSTS_PKTSTS_SHIFT); + dev_vdbg(hsotg->dev, " PStatus = %d\n", pktsts); } switch (pktsts) { @@ -261,7 +261,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, } usbcfg = readl(hsotg->regs + GUSBCFG); - prtspd = hprt0 & HPRT0_SPD_MASK; + prtspd = (hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT; if (prtspd == HPRT0_SPD_LOW_SPEED || prtspd == HPRT0_SPD_FULL_SPEED) { /* Low power */ @@ -273,7 +273,8 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, } hcfg = readl(hsotg->regs + HCFG); - fslspclksel = hcfg & HCFG_FSLSPCLKSEL_MASK; + fslspclksel = (hcfg & HCFG_FSLSPCLKSEL_MASK) >> + HCFG_FSLSPCLKSEL_SHIFT; if (prtspd == HPRT0_SPD_LOW_SPEED && params->host_ls_low_power_phy_clk == @@ -282,8 +283,9 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, dev_vdbg(hsotg->dev, "FS_PHY programming HCFG to 6 MHz\n"); if (fslspclksel != HCFG_FSLSPCLKSEL_6_MHZ) { + fslspclksel = HCFG_FSLSPCLKSEL_6_MHZ; hcfg &= ~HCFG_FSLSPCLKSEL_MASK; - hcfg |= HCFG_FSLSPCLKSEL_6_MHZ; + hcfg |= fslspclksel << HCFG_FSLSPCLKSEL_SHIFT; writel(hcfg, hsotg->regs + HCFG); do_reset = 1; } @@ -292,8 +294,9 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0, dev_vdbg(hsotg->dev, "FS_PHY programming HCFG to 48 MHz\n"); if (fslspclksel != HCFG_FSLSPCLKSEL_48_MHZ) { + fslspclksel = HCFG_FSLSPCLKSEL_48_MHZ; hcfg &= ~HCFG_FSLSPCLKSEL_MASK; - hcfg |= HCFG_FSLSPCLKSEL_48_MHZ; + hcfg |= fslspclksel << HCFG_FSLSPCLKSEL_SHIFT; writel(hcfg, hsotg->regs + HCFG); do_reset = 1; } @@ -406,8 +409,8 @@ static u32 dwc2_get_actual_xfer_length(struct dwc2_hsotg *hsotg, if (halt_status == DWC2_HC_XFER_COMPLETE) { if (chan->ep_is_in) { - count = hctsiz >> TSIZ_XFERSIZE_SHIFT & - TSIZ_XFERSIZE_MASK >> TSIZ_XFERSIZE_SHIFT; + count = (hctsiz & TSIZ_XFERSIZE_MASK) >> + TSIZ_XFERSIZE_SHIFT; length = chan->xfer_len - count; if (short_read != NULL) *short_read = (count != 0); @@ -426,8 +429,7 @@ static u32 dwc2_get_actual_xfer_length(struct dwc2_hsotg *hsotg, * hctsiz.xfersize field because that reflects the number of * bytes transferred via the AHB, not the USB). */ - count = hctsiz >> TSIZ_PKTCNT_SHIFT & - TSIZ_PKTCNT_MASK >> TSIZ_PKTCNT_SHIFT; + count = (hctsiz & TSIZ_PKTCNT_MASK) >> TSIZ_PKTCNT_SHIFT; length = (chan->start_pkt_count - count) * chan->max_packet; } @@ -462,7 +464,7 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg, /* Non DWORD-aligned buffer case handling */ if (chan->align_buf && xfer_length && chan->ep_is_in) { - dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); + dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); dma_sync_single_for_cpu(hsotg->dev, urb->dma, urb->length, DMA_FROM_DEVICE); memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf, @@ -490,8 +492,7 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg, __func__, (chan->ep_is_in ? "IN" : "OUT"), chnum); dev_vdbg(hsotg->dev, " chan->xfer_len %d\n", chan->xfer_len); dev_vdbg(hsotg->dev, " hctsiz.xfersize %d\n", - hctsiz >> TSIZ_XFERSIZE_SHIFT & - TSIZ_XFERSIZE_MASK >> TSIZ_XFERSIZE_SHIFT); + (hctsiz & TSIZ_XFERSIZE_MASK) >> TSIZ_XFERSIZE_SHIFT); dev_vdbg(hsotg->dev, " urb->transfer_buffer_length %d\n", urb->length); dev_vdbg(hsotg->dev, " urb->actual_length %d\n", urb->actual_length); dev_vdbg(hsotg->dev, " short_read %d, xfer_done %d\n", short_read, @@ -510,7 +511,7 @@ void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd) { u32 hctsiz = readl(hsotg->regs + HCTSIZ(chnum)); - u32 pid = hctsiz & TSIZ_SC_MC_PID_MASK; + u32 pid = (hctsiz & TSIZ_SC_MC_PID_MASK) >> TSIZ_SC_MC_PID_SHIFT; if (chan->ep_type != USB_ENDPOINT_XFER_CONTROL) { if (pid == TSIZ_SC_MC_PID_DATA0) @@ -557,8 +558,8 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state( /* Non DWORD-aligned buffer case handling */ if (chan->align_buf && frame_desc->actual_length && chan->ep_is_in) { - dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", - __func__); + dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", + __func__); dma_sync_single_for_cpu(hsotg->dev, urb->dma, urb->length, DMA_FROM_DEVICE); memcpy(urb->buf + frame_desc->offset + @@ -591,8 +592,8 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state( /* Non DWORD-aligned buffer case handling */ if (chan->align_buf && frame_desc->actual_length && chan->ep_is_in) { - dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", - __func__); + dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", + __func__); dma_sync_single_for_cpu(hsotg->dev, urb->dma, urb->length, DMA_FROM_DEVICE); memcpy(urb->buf + frame_desc->offset + @@ -623,7 +624,7 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state( * urb->status is not used for isoc transfers. The individual * frame_desc statuses are used instead. */ - dwc2_host_complete(hsotg, urb->priv, urb, 0); + dwc2_host_complete(hsotg, qtd, 0); halt_status = DWC2_HC_XFER_URB_COMPLETE; } else { halt_status = DWC2_HC_XFER_COMPLETE; @@ -714,11 +715,7 @@ static void dwc2_release_channel(struct dwc2_hsotg *hsotg, dev_vdbg(hsotg->dev, " Complete URB with transaction error\n"); free_qtd = 1; - if (qtd->urb) { - qtd->urb->status = -EPROTO; - dwc2_host_complete(hsotg, qtd->urb->priv, - qtd->urb, -EPROTO); - } + dwc2_host_complete(hsotg, qtd, -EPROTO); } break; case DWC2_HC_XFER_URB_DEQUEUE: @@ -731,11 +728,7 @@ static void dwc2_release_channel(struct dwc2_hsotg *hsotg, case DWC2_HC_XFER_PERIODIC_INCOMPLETE: dev_vdbg(hsotg->dev, " Complete URB with I/O error\n"); free_qtd = 1; - if (qtd && qtd->urb) { - qtd->urb->status = -EIO; - dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, - -EIO); - } + dwc2_host_complete(hsotg, qtd, -EIO); break; case DWC2_HC_XFER_NO_HALT_STATUS: default: @@ -938,7 +931,7 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg, frame_desc->actual_length += len; if (chan->align_buf && len) { - dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); + dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); dma_sync_single_for_cpu(hsotg->dev, qtd->urb->dma, qtd->urb->length, DMA_FROM_DEVICE); memcpy(qtd->urb->buf + frame_desc->offset + @@ -957,7 +950,7 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg, } if (qtd->isoc_frame_index == qtd->urb->packet_count) { - dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, 0); + dwc2_host_complete(hsotg, qtd, 0); dwc2_release_channel(hsotg, chan, qtd, DWC2_HC_XFER_URB_COMPLETE); } else { @@ -1040,7 +1033,7 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg, dev_vdbg(hsotg->dev, " Control transfer complete\n"); if (urb->status == -EINPROGRESS) urb->status = 0; - dwc2_host_complete(hsotg, urb->priv, urb, urb->status); + dwc2_host_complete(hsotg, qtd, urb->status); halt_status = DWC2_HC_XFER_URB_COMPLETE; break; } @@ -1053,7 +1046,7 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg, urb_xfer_done = dwc2_update_urb_state(hsotg, chan, chnum, urb, qtd); if (urb_xfer_done) { - dwc2_host_complete(hsotg, urb->priv, urb, urb->status); + dwc2_host_complete(hsotg, qtd, urb->status); halt_status = DWC2_HC_XFER_URB_COMPLETE; } else { halt_status = DWC2_HC_XFER_COMPLETE; @@ -1073,11 +1066,10 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg, * interrupt */ if (urb_xfer_done) { - dwc2_host_complete(hsotg, urb->priv, urb, - urb->status); - halt_status = DWC2_HC_XFER_URB_COMPLETE; + dwc2_host_complete(hsotg, qtd, urb->status); + halt_status = DWC2_HC_XFER_URB_COMPLETE; } else { - halt_status = DWC2_HC_XFER_COMPLETE; + halt_status = DWC2_HC_XFER_COMPLETE; } dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd); @@ -1123,11 +1115,11 @@ static void dwc2_hc_stall_intr(struct dwc2_hsotg *hsotg, goto handle_stall_halt; if (pipe_type == USB_ENDPOINT_XFER_CONTROL) - dwc2_host_complete(hsotg, urb->priv, urb, -EPIPE); + dwc2_host_complete(hsotg, qtd, -EPIPE); if (pipe_type == USB_ENDPOINT_XFER_BULK || pipe_type == USB_ENDPOINT_XFER_INT) { - dwc2_host_complete(hsotg, urb->priv, urb, -EPIPE); + dwc2_host_complete(hsotg, qtd, -EPIPE); /* * USB protocol requires resetting the data toggle for bulk * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT) @@ -1168,7 +1160,7 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg, /* Non DWORD-aligned buffer case handling */ if (chan->align_buf && xfer_length && chan->ep_is_in) { - dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); + dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); dma_sync_single_for_cpu(hsotg->dev, urb->dma, urb->length, DMA_FROM_DEVICE); memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf, @@ -1185,8 +1177,7 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg, dev_vdbg(hsotg->dev, " chan->start_pkt_count %d\n", chan->start_pkt_count); dev_vdbg(hsotg->dev, " hctsiz.pktcnt %d\n", - hctsiz >> TSIZ_PKTCNT_SHIFT & - TSIZ_PKTCNT_MASK >> TSIZ_PKTCNT_SHIFT); + (hctsiz & TSIZ_PKTCNT_MASK) >> TSIZ_PKTCNT_SHIFT); dev_vdbg(hsotg->dev, " chan->max_packet %d\n", chan->max_packet); dev_vdbg(hsotg->dev, " bytes_transferred %d\n", xfer_length); @@ -1372,10 +1363,10 @@ static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg, hsotg->core_params->dma_enable > 0) { qtd->complete_split = 0; qtd->isoc_split_offset = 0; + qtd->isoc_frame_index++; if (qtd->urb && - ++qtd->isoc_frame_index == qtd->urb->packet_count) { - dwc2_host_complete(hsotg, qtd->urb->priv, - qtd->urb, 0); + qtd->isoc_frame_index == qtd->urb->packet_count) { + dwc2_host_complete(hsotg, qtd, 0); dwc2_release_channel(hsotg, chan, qtd, DWC2_HC_XFER_URB_COMPLETE); } else { @@ -1445,16 +1436,16 @@ static void dwc2_hc_babble_intr(struct dwc2_hsotg *hsotg, dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: Babble Error--\n", chnum); + dwc2_hc_handle_tt_clear(hsotg, chan, qtd); + if (hsotg->core_params->dma_desc_enable > 0) { dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, DWC2_HC_XFER_BABBLE_ERR); - goto handle_babble_done; + goto disable_int; } if (chan->ep_type != USB_ENDPOINT_XFER_ISOC) { - if (qtd->urb) - dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, - -EOVERFLOW); + dwc2_host_complete(hsotg, qtd, -EOVERFLOW); dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_BABBLE_ERR); } else { enum dwc2_halt_status halt_status; @@ -1464,8 +1455,7 @@ static void dwc2_hc_babble_intr(struct dwc2_hsotg *hsotg, dwc2_halt_channel(hsotg, chan, qtd, halt_status); } -handle_babble_done: - dwc2_hc_handle_tt_clear(hsotg, chan, qtd); +disable_int: disable_hc_int(hsotg, chnum, HCINTMSK_BBLERR); } @@ -1490,6 +1480,8 @@ static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg, if (!urb) goto handle_ahberr_halt; + dwc2_hc_handle_tt_clear(hsotg, chan, qtd); + hcchar = readl(hsotg->regs + HCCHAR(chnum)); hcsplt = readl(hsotg->regs + HCSPLT(chnum)); hctsiz = readl(hsotg->regs + HCTSIZ(chnum)); @@ -1557,7 +1549,7 @@ static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg, goto handle_ahberr_done; } - dwc2_host_complete(hsotg, urb->priv, urb, -EIO); + dwc2_host_complete(hsotg, qtd, -EIO); handle_ahberr_halt: /* @@ -1567,7 +1559,6 @@ handle_ahberr_halt: dwc2_hc_halt(hsotg, chan, DWC2_HC_XFER_AHB_ERR); handle_ahberr_done: - dwc2_hc_handle_tt_clear(hsotg, chan, qtd); disable_hc_int(hsotg, chnum, HCINTMSK_AHBERR); } @@ -1582,6 +1573,8 @@ static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg, dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: Transaction Error--\n", chnum); + dwc2_hc_handle_tt_clear(hsotg, chan, qtd); + if (hsotg->core_params->dma_desc_enable > 0) { dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, DWC2_HC_XFER_XACT_ERR); @@ -1625,7 +1618,6 @@ static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg, } handle_xacterr_done: - dwc2_hc_handle_tt_clear(hsotg, chan, qtd); disable_hc_int(hsotg, chnum, HCINTMSK_XACTERR); } @@ -1643,6 +1635,8 @@ static void dwc2_hc_frmovrun_intr(struct dwc2_hsotg *hsotg, dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: Frame Overrun--\n", chnum); + dwc2_hc_handle_tt_clear(hsotg, chan, qtd); + switch (dwc2_hcd_get_pipe_type(&qtd->urb->pipe_info)) { case USB_ENDPOINT_XFER_CONTROL: case USB_ENDPOINT_XFER_BULK: @@ -1657,7 +1651,6 @@ static void dwc2_hc_frmovrun_intr(struct dwc2_hsotg *hsotg, break; } - dwc2_hc_handle_tt_clear(hsotg, chan, qtd); disable_hc_int(hsotg, chnum, HCINTMSK_FRMOVRUN); } @@ -1766,7 +1759,7 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg, * For core with OUT NAK enhancement, the flow for high-speed * CONTROL/BULK OUT is handled a little differently */ - if (hsotg->snpsid >= DWC2_CORE_REV_2_71a) { + if (hsotg->hw_params.snpsid >= DWC2_CORE_REV_2_71a) { if (chan->speed == USB_SPEED_HIGH && !chan->ep_is_in && (chan->ep_type == USB_ENDPOINT_XFER_CONTROL || chan->ep_type == USB_ENDPOINT_XFER_BULK)) { diff --git a/drivers/staging/dwc2/hcd_queue.c b/drivers/staging/dwc2/hcd_queue.c index b36f783..b1980ef 100644 --- a/drivers/staging/dwc2/hcd_queue.c +++ b/drivers/staging/dwc2/hcd_queue.c @@ -116,7 +116,7 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, qh->interval = 8; #endif hprt = readl(hsotg->regs + HPRT0); - prtspd = hprt & HPRT0_SPD_MASK; + prtspd = (hprt & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT; if (prtspd == HPRT0_SPD_HIGH_SPEED && (dev_speed == USB_SPEED_LOW || dev_speed == USB_SPEED_FULL)) { @@ -197,6 +197,9 @@ static struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, { struct dwc2_qh *qh; + if (!urb->priv) + return NULL; + /* Allocate memory */ qh = kzalloc(sizeof(*qh), mem_flags); if (!qh) @@ -638,7 +641,7 @@ int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb = qtd->urb; unsigned long flags; int allocated = 0; - int retval = 0; + int retval; /* * Get the QH which holds the QTD-list to insert to. Create QH if it @@ -652,8 +655,19 @@ int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, } spin_lock_irqsave(&hsotg->lock, flags); + retval = dwc2_hcd_qh_add(hsotg, *qh); - if (retval && allocated) { + if (retval) + goto fail; + + qtd->qh = *qh; + list_add_tail(&qtd->qtd_list_entry, &(*qh)->qtd_list); + spin_unlock_irqrestore(&hsotg->lock, flags); + + return 0; + +fail: + if (allocated) { struct dwc2_qtd *qtd2, *qtd2_tmp; struct dwc2_qh *qh_tmp = *qh; @@ -668,8 +682,6 @@ int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, spin_unlock_irqrestore(&hsotg->lock, flags); dwc2_hcd_qh_free(hsotg, qh_tmp); } else { - qtd->qh = *qh; - list_add_tail(&qtd->qtd_list_entry, &(*qh)->qtd_list); spin_unlock_irqrestore(&hsotg->lock, flags); } diff --git a/drivers/staging/dwc2/hw.h b/drivers/staging/dwc2/hw.h index 382a1d7..9c92a3c 100644 --- a/drivers/staging/dwc2/hw.h +++ b/drivers/staging/dwc2/hw.h @@ -72,12 +72,16 @@ #define GAHBCFG_DMA_EN (1 << 5) #define GAHBCFG_HBSTLEN_MASK (0xf << 1) #define GAHBCFG_HBSTLEN_SHIFT 1 -#define GAHBCFG_HBSTLEN_SINGLE (0 << 1) -#define GAHBCFG_HBSTLEN_INCR (1 << 1) -#define GAHBCFG_HBSTLEN_INCR4 (3 << 1) -#define GAHBCFG_HBSTLEN_INCR8 (5 << 1) -#define GAHBCFG_HBSTLEN_INCR16 (7 << 1) +#define GAHBCFG_HBSTLEN_SINGLE 0 +#define GAHBCFG_HBSTLEN_INCR 1 +#define GAHBCFG_HBSTLEN_INCR4 3 +#define GAHBCFG_HBSTLEN_INCR8 5 +#define GAHBCFG_HBSTLEN_INCR16 7 #define GAHBCFG_GLBL_INTR_EN (1 << 0) +#define GAHBCFG_CTRL_MASK (GAHBCFG_P_TXF_EMP_LVL | \ + GAHBCFG_NP_TXF_EMP_LVL | \ + GAHBCFG_DMA_EN | \ + GAHBCFG_GLBL_INTR_EN) #define GUSBCFG HSOTG_REG(0x00C) #define GUSBCFG_FORCEDEVMODE (1 << 30) @@ -165,15 +169,15 @@ #define GRXSTS_FN_SHIFT 25 #define GRXSTS_PKTSTS_MASK (0xf << 17) #define GRXSTS_PKTSTS_SHIFT 17 -#define GRXSTS_PKTSTS_GLOBALOUTNAK (1 << 17) -#define GRXSTS_PKTSTS_OUTRX (2 << 17) -#define GRXSTS_PKTSTS_HCHIN (2 << 17) -#define GRXSTS_PKTSTS_OUTDONE (3 << 17) -#define GRXSTS_PKTSTS_HCHIN_XFER_COMP (3 << 17) -#define GRXSTS_PKTSTS_SETUPDONE (4 << 17) -#define GRXSTS_PKTSTS_DATATOGGLEERR (5 << 17) -#define GRXSTS_PKTSTS_SETUPRX (6 << 17) -#define GRXSTS_PKTSTS_HCHHALTED (7 << 17) +#define GRXSTS_PKTSTS_GLOBALOUTNAK 1 +#define GRXSTS_PKTSTS_OUTRX 2 +#define GRXSTS_PKTSTS_HCHIN 2 +#define GRXSTS_PKTSTS_OUTDONE 3 +#define GRXSTS_PKTSTS_HCHIN_XFER_COMP 3 +#define GRXSTS_PKTSTS_SETUPDONE 4 +#define GRXSTS_PKTSTS_DATATOGGLEERR 5 +#define GRXSTS_PKTSTS_SETUPRX 6 +#define GRXSTS_PKTSTS_HCHHALTED 7 #define GRXSTS_HCHNUM_MASK (0xf << 0) #define GRXSTS_HCHNUM_SHIFT 0 #define GRXSTS_DPID_MASK (0x3 << 15) @@ -184,16 +188,11 @@ #define GRXSTS_EPNUM_SHIFT 0 #define GRXFSIZ HSOTG_REG(0x024) +#define GRXFSIZ_DEPTH_MASK (0xffff << 0) +#define GRXFSIZ_DEPTH_SHIFT 0 #define GNPTXFSIZ HSOTG_REG(0x028) -#define GNPTXFSIZ_NP_TXF_DEP_MASK (0xffff << 16) -#define GNPTXFSIZ_NP_TXF_DEP_SHIFT 16 -#define GNPTXFSIZ_NP_TXF_DEP_LIMIT 0xffff -#define GNPTXFSIZ_NP_TXF_DEP(_x) ((_x) << 16) -#define GNPTXFSIZ_NP_TXF_ST_ADDR_MASK (0xffff << 0) -#define GNPTXFSIZ_NP_TXF_ST_ADDR_SHIFT 0 -#define GNPTXFSIZ_NP_TXF_ST_ADDR_LIMIT 0xffff -#define GNPTXFSIZ_NP_TXF_ST_ADDR(_x) ((_x) << 0) +/* Use FIFOSIZE_* constants to access this register */ #define GNPTXSTS HSOTG_REG(0x02C) #define GNPTXSTS_NP_TXQ_TOP_MASK (0x7f << 24) @@ -244,32 +243,32 @@ #define GHWCFG2_NUM_DEV_EP_SHIFT 10 #define GHWCFG2_FS_PHY_TYPE_MASK (0x3 << 8) #define GHWCFG2_FS_PHY_TYPE_SHIFT 8 -#define GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED (0 << 8) -#define GHWCFG2_FS_PHY_TYPE_DEDICATED (1 << 8) -#define GHWCFG2_FS_PHY_TYPE_SHARED_UTMI (2 << 8) -#define GHWCFG2_FS_PHY_TYPE_SHARED_ULPI (3 << 8) +#define GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED 0 +#define GHWCFG2_FS_PHY_TYPE_DEDICATED 1 +#define GHWCFG2_FS_PHY_TYPE_SHARED_UTMI 2 +#define GHWCFG2_FS_PHY_TYPE_SHARED_ULPI 3 #define GHWCFG2_HS_PHY_TYPE_MASK (0x3 << 6) #define GHWCFG2_HS_PHY_TYPE_SHIFT 6 -#define GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED (0 << 6) -#define GHWCFG2_HS_PHY_TYPE_UTMI (1 << 6) -#define GHWCFG2_HS_PHY_TYPE_ULPI (2 << 6) -#define GHWCFG2_HS_PHY_TYPE_UTMI_ULPI (3 << 6) +#define GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0 +#define GHWCFG2_HS_PHY_TYPE_UTMI 1 +#define GHWCFG2_HS_PHY_TYPE_ULPI 2 +#define GHWCFG2_HS_PHY_TYPE_UTMI_ULPI 3 #define GHWCFG2_POINT2POINT (1 << 5) #define GHWCFG2_ARCHITECTURE_MASK (0x3 << 3) #define GHWCFG2_ARCHITECTURE_SHIFT 3 -#define GHWCFG2_SLAVE_ONLY_ARCH (0 << 3) -#define GHWCFG2_EXT_DMA_ARCH (1 << 3) -#define GHWCFG2_INT_DMA_ARCH (2 << 3) +#define GHWCFG2_SLAVE_ONLY_ARCH 0 +#define GHWCFG2_EXT_DMA_ARCH 1 +#define GHWCFG2_INT_DMA_ARCH 2 #define GHWCFG2_OP_MODE_MASK (0x7 << 0) #define GHWCFG2_OP_MODE_SHIFT 0 -#define GHWCFG2_OP_MODE_HNP_SRP_CAPABLE (0 << 0) -#define GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE (1 << 0) -#define GHWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE (2 << 0) -#define GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE (3 << 0) -#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE (4 << 0) -#define GHWCFG2_OP_MODE_SRP_CAPABLE_HOST (5 << 0) -#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST (6 << 0) -#define GHWCFG2_OP_MODE_UNDEFINED (7 << 0) +#define GHWCFG2_OP_MODE_HNP_SRP_CAPABLE 0 +#define GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE 1 +#define GHWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE 2 +#define GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3 +#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4 +#define GHWCFG2_OP_MODE_SRP_CAPABLE_HOST 5 +#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6 +#define GHWCFG2_OP_MODE_UNDEFINED 7 #define GHWCFG3 HSOTG_REG(0x004c) #define GHWCFG3_DFIFO_DEPTH_MASK (0xffff << 16) @@ -303,6 +302,9 @@ #define GHWCFG4_NUM_DEV_MODE_CTRL_EP_SHIFT 16 #define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14) #define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT 14 +#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0 +#define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1 +#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2 #define GHWCFG4_XHIBER (1 << 7) #define GHWCFG4_HIBER (1 << 6) #define GHWCFG4_MIN_AHB_FREQ (1 << 5) @@ -391,16 +393,12 @@ #define ADPCTL_PRB_DSCHRG_SHIFT 0 #define HPTXFSIZ HSOTG_REG(0x100) +/* Use FIFOSIZE_* constants to access this register */ #define DPTXFSIZN(_a) HSOTG_REG(0x104 + (((_a) - 1) * 4)) -#define DPTXFSIZN_DP_TXF_SIZE_MASK (0xffff << 16) -#define DPTXFSIZN_DP_TXF_SIZE_SHIFT 16 -#define DPTXFSIZN_DP_TXF_SIZE_GET(_v) (((_v) >> 16) & 0xffff) -#define DPTXFSIZN_DP_TXF_SIZE_LIMIT 0xffff -#define DPTXFSIZN_DP_TXF_SIZE(_x) ((_x) << 16) -#define DPTXFSIZN_DP_TXF_ST_ADDR_MASK (0xffff << 0) -#define DPTXFSIZN_DP_TXF_ST_ADDR_SHIFT 0 +/* Use FIFOSIZE_* constants to access this register */ +/* These apply to the GNPTXFSIZ, HPTXFSIZ and DPTXFSIZN registers */ #define FIFOSIZE_DEPTH_MASK (0xffff << 16) #define FIFOSIZE_DEPTH_SHIFT 16 #define FIFOSIZE_STARTADDR_MASK (0xffff << 0) @@ -424,10 +422,10 @@ #define DCFG_NZ_STS_OUT_HSHK (1 << 2) #define DCFG_DEVSPD_MASK (0x3 << 0) #define DCFG_DEVSPD_SHIFT 0 -#define DCFG_DEVSPD_HS (0 << 0) -#define DCFG_DEVSPD_FS (1 << 0) -#define DCFG_DEVSPD_LS (2 << 0) -#define DCFG_DEVSPD_FS48 (3 << 0) +#define DCFG_DEVSPD_HS 0 +#define DCFG_DEVSPD_FS 1 +#define DCFG_DEVSPD_LS 2 +#define DCFG_DEVSPD_FS48 3 #define DCTL HSOTG_REG(0x804) #define DCTL_PWRONPRGDONE (1 << 11) @@ -450,10 +448,10 @@ #define DSTS_ERRATICERR (1 << 3) #define DSTS_ENUMSPD_MASK (0x3 << 1) #define DSTS_ENUMSPD_SHIFT 1 -#define DSTS_ENUMSPD_HS (0 << 1) -#define DSTS_ENUMSPD_FS (1 << 1) -#define DSTS_ENUMSPD_LS (2 << 1) -#define DSTS_ENUMSPD_FS48 (3 << 1) +#define DSTS_ENUMSPD_HS 0 +#define DSTS_ENUMSPD_FS 1 +#define DSTS_ENUMSPD_LS 2 +#define DSTS_ENUMSPD_FS48 3 #define DSTS_SUSPSTS (1 << 0) #define DIEPMSK HSOTG_REG(0x810) @@ -501,10 +499,10 @@ */ #define D0EPCTL_MPS_MASK (0x3 << 0) #define D0EPCTL_MPS_SHIFT 0 -#define D0EPCTL_MPS_64 (0 << 0) -#define D0EPCTL_MPS_32 (1 << 0) -#define D0EPCTL_MPS_16 (2 << 0) -#define D0EPCTL_MPS_8 (3 << 0) +#define D0EPCTL_MPS_64 0 +#define D0EPCTL_MPS_32 1 +#define D0EPCTL_MPS_16 2 +#define D0EPCTL_MPS_8 3 #define DXEPCTL_EPENA (1 << 31) #define DXEPCTL_EPDIS (1 << 30) @@ -522,10 +520,10 @@ #define DXEPCTL_SNP (1 << 20) #define DXEPCTL_EPTYPE_MASK (0x3 << 18) #define DXEPCTL_EPTYPE_SHIFT 18 -#define DXEPCTL_EPTYPE_CONTROL (0 << 18) -#define DXEPCTL_EPTYPE_ISO (1 << 18) -#define DXEPCTL_EPTYPE_BULK (2 << 18) -#define DXEPCTL_EPTYPE_INTTERUPT (3 << 18) +#define DXEPCTL_EPTYPE_CONTROL 0 +#define DXEPCTL_EPTYPE_ISO 1 +#define DXEPCTL_EPTYPE_BULK 2 +#define DXEPCTL_EPTYPE_INTTERUPT 3 #define DXEPCTL_NAKSTS (1 << 17) #define DXEPCTL_DPID (1 << 16) #define DXEPCTL_EOFRNUM (1 << 16) @@ -645,9 +643,9 @@ #define HCFG_FSLSSUPP (1 << 2) #define HCFG_FSLSPCLKSEL_MASK (0x3 << 0) #define HCFG_FSLSPCLKSEL_SHIFT 0 -#define HCFG_FSLSPCLKSEL_30_60_MHZ (0 << 0) -#define HCFG_FSLSPCLKSEL_48_MHZ (1 << 0) -#define HCFG_FSLSPCLKSEL_6_MHZ (2 << 0) +#define HCFG_FSLSPCLKSEL_30_60_MHZ 0 +#define HCFG_FSLSPCLKSEL_48_MHZ 1 +#define HCFG_FSLSPCLKSEL_6_MHZ 2 #define HFIR HSOTG_REG(0x0404) #define HFIR_FRINT_MASK (0xffff << 0) @@ -680,9 +678,9 @@ #define HPRT0 HSOTG_REG(0x0440) #define HPRT0_SPD_MASK (0x3 << 17) #define HPRT0_SPD_SHIFT 17 -#define HPRT0_SPD_HIGH_SPEED (0 << 17) -#define HPRT0_SPD_FULL_SPEED (1 << 17) -#define HPRT0_SPD_LOW_SPEED (2 << 17) +#define HPRT0_SPD_HIGH_SPEED 0 +#define HPRT0_SPD_FULL_SPEED 1 +#define HPRT0_SPD_LOW_SPEED 2 #define HPRT0_TSTCTL_MASK (0xf << 13) #define HPRT0_TSTCTL_SHIFT 13 #define HPRT0_PWR (1 << 12) @@ -720,10 +718,10 @@ #define HCSPLT_COMPSPLT (1 << 16) #define HCSPLT_XACTPOS_MASK (0x3 << 14) #define HCSPLT_XACTPOS_SHIFT 14 -#define HCSPLT_XACTPOS_MID (0 << 14) -#define HCSPLT_XACTPOS_END (1 << 14) -#define HCSPLT_XACTPOS_BEGIN (2 << 14) -#define HCSPLT_XACTPOS_ALL (3 << 14) +#define HCSPLT_XACTPOS_MID 0 +#define HCSPLT_XACTPOS_END 1 +#define HCSPLT_XACTPOS_BEGIN 2 +#define HCSPLT_XACTPOS_ALL 3 #define HCSPLT_HUBADDR_MASK (0x7f << 7) #define HCSPLT_HUBADDR_SHIFT 7 #define HCSPLT_PRTADDR_MASK (0x7f << 0) @@ -751,11 +749,11 @@ #define TSIZ_DOPNG (1 << 31) #define TSIZ_SC_MC_PID_MASK (0x3 << 29) #define TSIZ_SC_MC_PID_SHIFT 29 -#define TSIZ_SC_MC_PID_DATA0 (0 << 29) -#define TSIZ_SC_MC_PID_DATA2 (1 << 29) -#define TSIZ_SC_MC_PID_DATA1 (2 << 29) -#define TSIZ_SC_MC_PID_MDATA (3 << 29) -#define TSIZ_SC_MC_PID_SETUP (3 << 29) +#define TSIZ_SC_MC_PID_DATA0 0 +#define TSIZ_SC_MC_PID_DATA2 1 +#define TSIZ_SC_MC_PID_DATA1 2 +#define TSIZ_SC_MC_PID_MDATA 3 +#define TSIZ_SC_MC_PID_SETUP 3 #define TSIZ_PKTCNT_MASK (0x3ff << 19) #define TSIZ_PKTCNT_SHIFT 19 #define TSIZ_NTD_MASK (0xff << 8) diff --git a/drivers/staging/dwc2/pci.c b/drivers/staging/dwc2/pci.c index 3ca54d6..9020260 100644 --- a/drivers/staging/dwc2/pci.c +++ b/drivers/staging/dwc2/pci.c @@ -74,7 +74,7 @@ static const struct dwc2_core_params dwc2_module_params = { .max_packet_count = 511, .host_channels = -1, .phy_type = -1, - .phy_utmi_width = 16, /* 16 bits - NOT DETECTABLE */ + .phy_utmi_width = -1, .phy_ulpi_ddr = -1, .phy_ulpi_ext_vbus = -1, .i2c_enable = -1, @@ -83,7 +83,7 @@ static const struct dwc2_core_params dwc2_module_params = { .host_ls_low_power_phy_clk = -1, .ts_dline = -1, .reload_ctl = -1, - .ahb_single = -1, + .ahbcfg = -1, }; /** |