Commit d504bfa6 authored by Radhey Shyam Pandey's avatar Radhey Shyam Pandey Committed by Greg Kroah-Hartman
Browse files

usb: dwc3: enable CCI support for AMD-xilinx DWC3 controller



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: default avatarRadhey Shyam Pandey <radhey.shyam.pandey@amd.com>
Reviewed-by: default avatarFrank Li <Frank.Li@nxp.com>
Acked-by: default avatarThinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://lore.kernel.org/r/1720548651-726412-1-git-send-email-radhey.shyam.pandey@amd.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 5af43708
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -604,6 +604,18 @@ 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 (dwc->gsbuscfg0_reqinfo != DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED) {
		u32 reg;

		reg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0);
		reg &= ~DWC3_GSBUSCFG0_REQINFO(~0);
		reg |= DWC3_GSBUSCFG0_REQINFO(dwc->gsbuscfg0_reqinfo);
		dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, reg);
	}
}

static int dwc3_core_ulpi_init(struct dwc3 *dwc)
{
	int intf;
@@ -1343,6 +1355,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;
@@ -1581,6 +1595,27 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)
	dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);
}

static void dwc3_get_software_properties(struct dwc3 *dwc)
{
	struct device *tmpdev;
	u16 gsbuscfg0_reqinfo;
	int ret;

	dwc->gsbuscfg0_reqinfo = DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED;

	/*
	 * Iterate over all parent nodes for finding swnode properties
	 * and non-DT (non-ABI) properties.
	 */
	for (tmpdev = dwc->dev; tmpdev; tmpdev = tmpdev->parent) {
		ret = device_property_read_u16(tmpdev,
					       "snps,gsbuscfg0-reqinfo",
					       &gsbuscfg0_reqinfo);
		if (!ret)
			dwc->gsbuscfg0_reqinfo = gsbuscfg0_reqinfo;
	}
}

static void dwc3_get_properties(struct dwc3 *dwc)
{
	struct device		*dev = dwc->dev;
@@ -2095,6 +2130,8 @@ static int dwc3_probe(struct platform_device *pdev)

	dwc3_get_properties(dwc);

	dwc3_get_software_properties(dwc);

	dwc->reset = devm_reset_control_array_get_optional_shared(dev);
	if (IS_ERR(dwc->reset)) {
		ret = PTR_ERR(dwc->reset);
+8 −0
Original line number Diff line number Diff line
@@ -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_REQINFO(n)	(((n) & 0xffff) << 16)
#define DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED	0xffffffff

/* 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.
 * @gsbuscfg0_reqinfo: 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;
	u32			gsbuscfg0_reqinfo;
};

#define INCRX_BURST_MODE 0
+29 −0
Original line number Diff line number Diff line
@@ -246,6 +246,31 @@ static const struct of_device_id dwc3_xlnx_of_match[] = {
};
MODULE_DEVICE_TABLE(of, dwc3_xlnx_of_match);

static int dwc3_set_swnode(struct device *dev)
{
	struct device_node *np = dev->of_node, *dwc3_np;
	struct property_entry props[2];
	int prop_idx = 0, ret = 0;

	dwc3_np = of_get_compatible_child(np, "snps,dwc3");
	if (!dwc3_np) {
		ret = -ENODEV;
		dev_err(dev, "failed to find dwc3 core child\n");
		return ret;
	}

	memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props));
	if (of_dma_is_coherent(dwc3_np))
		props[prop_idx++] = PROPERTY_ENTRY_U16("snps,gsbuscfg0-reqinfo",
						       0xffff);
	of_node_put(dwc3_np);

	if (prop_idx)
		ret = device_create_managed_software_node(dev, props, NULL);

	return ret;
}

static int dwc3_xlnx_probe(struct platform_device *pdev)
{
	struct dwc3_xlnx		*priv_data;
@@ -288,6 +313,10 @@ static int dwc3_xlnx_probe(struct platform_device *pdev)
	if (ret)
		goto err_clk_put;

	ret = dwc3_set_swnode(dev);
	if (ret)
		goto err_clk_put;

	ret = of_platform_populate(np, NULL, NULL, dev);
	if (ret)
		goto err_clk_put;