Quoting kernel commit d504bfa6cfd1 ("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. We don't operate the ZynqMP in cache-coherent mode in barebox, but we do operate the 64-bit Layerscape SoCs in this mode, so prepare for being able to set this register. Signed-off-by: Ahmad Fatoum <[email protected]> --- drivers/usb/dwc3/core.c | 37 +++++++++++++++++++++++++++++++++++++ drivers/usb/dwc3/core.h | 8 ++++++++ drivers/usb/dwc3/glue.h | 14 ++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 472630c95392..cb22f19e39cc 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -445,6 +445,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; @@ -903,6 +915,8 @@ static int dwc3_core_init(struct dwc3 *dwc) dwc3_set_incr_burst_type(dwc); + dwc3_config_soc_bus(dwc); + usb_phy_set_suspend(dwc->usb2_phy, 0); usb_phy_set_suspend(dwc->usb3_phy, 0); ret = phy_power_on(dwc->usb2_generic_phy); @@ -1147,6 +1161,26 @@ 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, + const struct dwc3_properties *properties) +{ + dwc->gsbuscfg0_reqinfo = DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED; + + if (properties->gsbuscfg0_reqinfo != + DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED) { + dwc->gsbuscfg0_reqinfo = properties->gsbuscfg0_reqinfo; + return; + } + + /* + * TODO: Iterate over all parent nodes for finding swnode properties + * and non-DT (non-ABI) properties once we have device properties.. + * + * In Linux, this is used for Xilinx ZynqMP, which we don't configure + * here. + */ +} + static void dwc3_get_properties(struct dwc3 *dwc) { struct device *dev = dwc->dev; @@ -1416,6 +1450,8 @@ int dwc3_core_probe(const struct dwc3_probe_data *data) dwc3_get_properties(dwc); + dwc3_get_software_properties(dwc, &data->properties); + if (!data->ignore_clocks_and_resets) { if (dev->of_node) { ret = clk_bulk_get_all(dev, &dwc->clks); @@ -1497,6 +1533,7 @@ static int dwc3_probe(struct device *dev) probe_data.dwc = dwc; probe_data.res = res; + probe_data.properties = DWC3_DEFAULT_PROPERTIES; return dwc3_core_probe(&probe_data); } diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 52853a4370ce..d49feb9918b7 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -168,6 +168,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) @@ -1103,6 +1107,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; @@ -1318,6 +1325,7 @@ struct dwc3 { int last_fifo_depth; int num_ep_resized; struct dentry *debug_root; + u32 gsbuscfg0_reqinfo; }; #define INCRX_BURST_MODE 0 diff --git a/drivers/usb/dwc3/glue.h b/drivers/usb/dwc3/glue.h index 05d6d2723d19..f7842b42dfac 100644 --- a/drivers/usb/dwc3/glue.h +++ b/drivers/usb/dwc3/glue.h @@ -9,17 +9,31 @@ #include <linux/types.h> #include "core.h" +/** + * dwc3_properties: DWC3 core properties + * @gsbuscfg0_reqinfo: Value to be programmed in the GSBUSCFG0.REQINFO field + */ +struct dwc3_properties { + u32 gsbuscfg0_reqinfo; +}; + +#define DWC3_DEFAULT_PROPERTIES ((struct dwc3_properties){ \ + .gsbuscfg0_reqinfo = DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED, \ + }) + /** * dwc3_probe_data: Initialization parameters passed to dwc3_core_probe() * @dwc: Reference to dwc3 context structure * @res: resource for the DWC3 core mmio region * @ignore_clocks_and_resets: clocks and resets defined for the device should * be ignored by the DWC3 core, as they are managed by the glue + * @properties: dwc3 software manage properties */ struct dwc3_probe_data { struct dwc3 *dwc; struct resource *res; bool ignore_clocks_and_resets; + struct dwc3_properties properties; }; /** -- 2.47.3
