[PATCH v3] usb: dwc3: enable CCI support for AMD-xilinx DWC3 controller

Radhey Shyam Pandey radhey.shyam.pandey at amd.com
Thu Jun 6 00:01:19 PDT 2024


The GSBUSCFG0 register bits [31:16] are used to configure the cache type
settings of the descriptor and data write/read transfers (Cacheable,
Bufferable/Posted). When CCI is enabled in the design, DWC3 core GSBUSCFG0
cache bits must be updated to support CCI enabled transfers in USB.

To program GSBUSCFG0 cache bits create a software node property
in AMD-xilinx dwc3 glue driver and pass it to dwc3 core. The core
then reads this property value and configures it in dwc3_core_init()
sequence.

Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey at amd.com>
---
Changes for v3:
In v2 review as suggested by Thinh Nguyen, switch to swnode implementation
for passing GSBUSCFG0 cache bits from AMD-xilinx dwc3 glue driver to
core driver.

Changes for v2:
Make GSBUSCFG0 configuration specific to AMD-xilinx platform.
Taken reference from existing commit ec5eb43813a4 ("usb: dwc3: core:
add support for realtek SoCs custom's global register start address")

v1 link:
https://lore.kernel.org/all/20231013053448.11056-1-piyush.mehta@amd.com
---
 drivers/usb/dwc3/core.c        | 24 ++++++++++++++++++++++++
 drivers/usb/dwc3/core.h        |  8 ++++++++
 drivers/usb/dwc3/dwc3-xilinx.c | 18 +++++++++++++++++-
 3 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 7ee61a89520b..159d21b25629 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -23,6 +23,7 @@
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_graph.h>
 #include <linux/acpi.h>
 #include <linux/pinctrl/consumer.h>
@@ -599,6 +600,19 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)
 		parms->hwparams9 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS9);
 }
 
+static void dwc3_config_soc_bus(struct dwc3 *dwc)
+{
+	if (of_dma_is_coherent(dwc->dev->of_node)) {
+		u32 reg;
+
+		reg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0);
+		reg &= ~DWC3_GSBUSCFG0_DAT_DES_RD_WR_REQINFO_MASK;
+		reg |= (dwc->acache_data_rd_wr_info <<
+			DWC3_GSBUSCFG0_DAT_DES_RD_WR_REQINFO_SHIFT);
+		dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, reg);
+	}
+}
+
 static int dwc3_core_ulpi_init(struct dwc3 *dwc)
 {
 	int intf;
@@ -1320,6 +1334,8 @@ static int dwc3_core_init(struct dwc3 *dwc)
 
 	dwc3_set_incr_burst_type(dwc);
 
+	dwc3_config_soc_bus(dwc);
+
 	ret = dwc3_phy_power_on(dwc);
 	if (ret)
 		goto err_exit_phy;
@@ -1574,6 +1590,7 @@ static void dwc3_get_properties(struct dwc3 *dwc)
 	u8			tx_max_burst_prd = 0;
 	u8			tx_fifo_resize_max_num;
 	const char		*usb_psy_name;
+	struct device		*tmpdev;
 	int			ret;
 
 	/* default to highest possible threshold */
@@ -1716,6 +1733,13 @@ static void dwc3_get_properties(struct dwc3 *dwc)
 	dwc->dis_split_quirk = device_property_read_bool(dev,
 				"snps,dis-split-quirk");
 
+	/* Iterate over all parent nodes for finding swnode properties */
+	for (tmpdev = dwc->dev; tmpdev; tmpdev = tmpdev->parent) {
+		device_property_read_u16(tmpdev,
+					 "snps,acache-data-rd-wr-info",
+					  &dwc->acache_data_rd_wr_info);
+	}
+
 	dwc->lpm_nyet_threshold = lpm_nyet_threshold;
 	dwc->tx_de_emphasis = tx_de_emphasis;
 
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 3781c736c1a1..57b3cb739353 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -194,6 +194,10 @@
 #define DWC3_GSBUSCFG0_INCRBRSTENA	(1 << 0) /* undefined length enable */
 #define DWC3_GSBUSCFG0_INCRBRST_MASK	0xff
 
+/* Global SoC Bus Configuration Register: AHB-prot/AXI-cache/OCP-ReqInfo */
+#define DWC3_GSBUSCFG0_DAT_DES_RD_WR_REQINFO_MASK	GENMASK(31, 16)
+#define DWC3_GSBUSCFG0_DAT_DES_RD_WR_REQINFO_SHIFT	16
+
 /* Global Debug LSP MUX Select */
 #define DWC3_GDBGLSPMUX_ENDBC		BIT(15)	/* Host only */
 #define DWC3_GDBGLSPMUX_HOSTSELECT(n)	((n) & 0x3fff)
@@ -1153,6 +1157,9 @@ struct dwc3_scratchpad_array {
  * @num_ep_resized: carries the current number endpoints which have had its tx
  *		    fifo resized.
  * @debug_root: root debugfs directory for this device to put its files in.
+ * @acache_data_rd_wr_info: store GSBUSCFG0.DATRDREQINFO, DESRDREQINFO,
+ *                          DATWRREQINFO, and DESWRREQINFO value passed from
+ *                          glue driver.
  */
 struct dwc3 {
 	struct work_struct	drd_work;
@@ -1380,6 +1387,7 @@ struct dwc3 {
 	int			last_fifo_depth;
 	int			num_ep_resized;
 	struct dentry		*debug_root;
+	u16			acache_data_rd_wr_info;
 };
 
 #define INCRX_BURST_MODE 0
diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
index 6095f4dee6ce..f3757bfbd650 100644
--- a/drivers/usb/dwc3/dwc3-xilinx.c
+++ b/drivers/usb/dwc3/dwc3-xilinx.c
@@ -47,6 +47,15 @@ struct dwc3_xlnx {
 	struct phy			*usb3_phy;
 };
 
+static const struct property_entry dwc3_xilinx_properties[] = {
+	PROPERTY_ENTRY_U16("snps,acache-data-rd-wr-info", 0xffff),
+	{},
+};
+
+static const struct software_node dwc3_xilinx_swnode = {
+	.properties = dwc3_xilinx_properties,
+};
+
 static void dwc3_xlnx_mask_phy_rst(struct dwc3_xlnx *priv_data, bool mask)
 {
 	u32 reg;
@@ -288,10 +297,14 @@ static int dwc3_xlnx_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_clk_put;
 
-	ret = of_platform_populate(np, NULL, NULL, dev);
+	ret = device_add_software_node(dev, &dwc3_xilinx_swnode);
 	if (ret)
 		goto err_clk_put;
 
+	ret = of_platform_populate(np, NULL, NULL, dev);
+	if (ret)
+		goto err_remove_swnode;
+
 	pm_runtime_set_active(dev);
 	ret = devm_pm_runtime_enable(dev);
 	if (ret < 0)
@@ -303,6 +316,9 @@ static int dwc3_xlnx_probe(struct platform_device *pdev)
 err_pm_set_suspended:
 	pm_runtime_set_suspended(dev);
 
+err_remove_swnode:
+	device_remove_software_node(dev);
+
 err_clk_put:
 	clk_bulk_disable_unprepare(priv_data->num_clocks, priv_data->clks);
 
-- 
2.34.1




More information about the linux-arm-kernel mailing list