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@xxxxxxx> --- 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@xxxxxxx --- 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