]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
usb: dwc3: xilinx: set coherency mode for AMD versal adaptive platform
authorRadhey Shyam Pandey <radhey.shyam.pandey@amd.com>
Tue, 3 Jun 2025 18:53:38 +0000 (00:23 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 19 Jun 2025 10:25:50 +0000 (12:25 +0200)
If device is coherent or if DMA (direct memory access) is translated by
an IOMMU then program USB2.0 IP to route transactions through the CCI for
coherency even if the target of transaction is in low power domain (LPD).

Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://lore.kernel.org/r/1748976818-710088-1-git-send-email-radhey.shyam.pandey@amd.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/dwc3/dwc3-xilinx.c

index 09c3c5c226ab401997548e0ba9a53169f6c7f955..1e28d6f50ed07ad09a7ffa43673ae129c564f5f3 100644 (file)
@@ -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;
 }