diff options
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r-- | drivers/usb/dwc3/dwc3-xilinx.c | 34 | ||||
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 16 |
2 files changed, 29 insertions, 21 deletions
diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c index 09c3c5c226ab..1e28d6f50ed0 100644 --- a/drivers/usb/dwc3/dwc3-xilinx.c +++ b/drivers/usb/dwc3/dwc3-xilinx.c @@ -32,6 +32,9 @@ #define XLNX_USB_TRAFFIC_ROUTE_CONFIG 0x005C #define XLNX_USB_TRAFFIC_ROUTE_FPD 0x1 +/* USB 2.0 IP Register */ +#define XLNX_USB2_TRAFFIC_ROUTE_CONFIG 0x0044 + #define XLNX_USB_FPD_PIPE_CLK 0x7c #define PIPE_CLK_DESELECT 1 #define PIPE_CLK_SELECT 0 @@ -66,6 +69,23 @@ static void dwc3_xlnx_mask_phy_rst(struct dwc3_xlnx *priv_data, bool mask) writel(reg, priv_data->regs + XLNX_USB_PHY_RST_EN); } +static void dwc3_xlnx_set_coherency(struct dwc3_xlnx *priv_data, u32 coherency_offset) +{ + struct device *dev = priv_data->dev; + u32 reg; + + /* + * This routes the USB DMA traffic to go through FPD path instead + * of reaching DDR directly. This traffic routing is needed to + * make SMMU and CCI work with USB DMA. + */ + if (of_dma_is_coherent(dev->of_node) || device_iommu_mapped(dev)) { + reg = readl(priv_data->regs + coherency_offset); + reg |= XLNX_USB_TRAFFIC_ROUTE_FPD; + writel(reg, priv_data->regs + coherency_offset); + } +} + static int dwc3_xlnx_init_versal(struct dwc3_xlnx *priv_data) { struct device *dev = priv_data->dev; @@ -92,6 +112,7 @@ static int dwc3_xlnx_init_versal(struct dwc3_xlnx *priv_data) } dwc3_xlnx_mask_phy_rst(priv_data, true); + dwc3_xlnx_set_coherency(priv_data, XLNX_USB2_TRAFFIC_ROUTE_CONFIG); return 0; } @@ -102,7 +123,6 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data) struct reset_control *crst, *hibrst, *apbrst; struct gpio_desc *reset_gpio; int ret = 0; - u32 reg; priv_data->usb3_phy = devm_phy_optional_get(dev, "usb3-phy"); if (IS_ERR(priv_data->usb3_phy)) { @@ -219,17 +239,7 @@ skip_usb3_phy: usleep_range(5000, 10000); } - /* - * This routes the USB DMA traffic to go through FPD path instead - * of reaching DDR directly. This traffic routing is needed to - * make SMMU and CCI work with USB DMA. - */ - if (of_dma_is_coherent(dev->of_node) || device_iommu_mapped(dev)) { - reg = readl(priv_data->regs + XLNX_USB_TRAFFIC_ROUTE_CONFIG); - reg |= XLNX_USB_TRAFFIC_ROUTE_FPD; - writel(reg, priv_data->regs + XLNX_USB_TRAFFIC_ROUTE_CONFIG); - } - + dwc3_xlnx_set_coherency(priv_data, XLNX_USB_TRAFFIC_ROUTE_CONFIG); err: return ret; } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 6ab6c9f163b8..554f997eb8c4 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -924,11 +924,9 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action) if (ret) return ret; - if (!(dep->flags & DWC3_EP_RESOURCE_ALLOCATED)) { - ret = dwc3_gadget_set_xfer_resource(dep); - if (ret) - return ret; - } + ret = dwc3_gadget_set_xfer_resource(dep); + if (ret) + return ret; if (!(dep->flags & DWC3_EP_ENABLED)) { struct dwc3_trb *trb_st_hw; @@ -3501,7 +3499,7 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc) static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep, struct dwc3_request *req, struct dwc3_trb *trb, - const struct dwc3_event_depevt *event, int status, int chain) + const struct dwc3_event_depevt *event, int status) { unsigned int count; @@ -3553,7 +3551,8 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep, if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN) return 1; - if (event->status & DEPEVT_STATUS_SHORT && !chain) + if (event->status & DEPEVT_STATUS_SHORT && + !(trb->ctrl & DWC3_TRB_CTRL_CHN)) return 1; if ((trb->ctrl & DWC3_TRB_CTRL_ISP_IMI) && @@ -3580,8 +3579,7 @@ static int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep, trb = &dep->trb_pool[dep->trb_dequeue]; ret = dwc3_gadget_ep_reclaim_completed_trb(dep, req, - trb, event, status, - !!(trb->ctrl & DWC3_TRB_CTRL_CHN)); + trb, event, status); if (ret) break; } |