[PATCH v3 3/4] usb: dwc3: xilinx: Add Versal2 MMI USB 3.2 controller support
Radhey Shyam Pandey
radhey.shyam.pandey at amd.com
Wed Apr 29 10:30:49 PDT 2026
Multimedia integrated (MMI) USB3.2 DRD IP is usb3.1 gen2 controller
which support following speed SSP (10-Gbps), SuperSpeed(5-Gbps),
high-speed(480-Mbps), full-speed(12-Mbps), and low-speed(1.5-Mbps)
operation modes.
USB2 and USB3 PHY support physical connectivity via the Type-C
connectivity. The MMI USB controller does not have a dedicated wrapper
register space, so ioremap is skipped via the config flag.
The driver handles clock and reset initialization. In this initial
version typec reversibility is not implemented and it is assumed that
USB3 PHY TCA mux programming is done by MMI configuration data object
(CDOs) and TI PD controller is configured using external tiva programmer
on VEK385 evaluation board.
Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey at amd.com>
---
Changes for v3:
- Remove mention of xlnx,usb-syscon phandle from version history.
- Rename map_resource to no_mem_map.
- Add assert delay.
- Rephrase commit description.
Changes for v2:
- Split config struct refactoring into separate patch (2/4).
- Remove unused regmap/syscon fields and parsing code; defer to
patch that first consumes them.
- Fix error message capitalization to lowercase ("reset", "deassert").
---
drivers/usb/dwc3/dwc3-xilinx.c | 56 ++++++++++++++++++++++++++++++----
1 file changed, 50 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
index af0ccd060c8b..b601cca485ed 100644
--- a/drivers/usb/dwc3/dwc3-xilinx.c
+++ b/drivers/usb/dwc3/dwc3-xilinx.c
@@ -46,6 +46,7 @@ struct dwc3_xlnx;
struct dwc3_xlnx_config {
int (*pltfm_init)(struct dwc3_xlnx *data);
+ bool no_mem_map;
};
struct dwc3_xlnx {
@@ -93,6 +94,35 @@ static void dwc3_xlnx_set_coherency(struct dwc3_xlnx *priv_data, u32 coherency_o
}
}
+static int dwc3_xlnx_init_versal2(struct dwc3_xlnx *priv_data)
+{
+ struct device *dev = priv_data->dev;
+ struct reset_control *crst;
+ int ret;
+
+ crst = devm_reset_control_get_optional_exclusive(dev, NULL);
+ if (IS_ERR(crst))
+ return dev_err_probe(dev, PTR_ERR(crst),
+ "failed to get reset signal\n");
+
+ /* assert and deassert reset */
+ ret = reset_control_assert(crst);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to assert reset\n");
+
+ /*
+ * PHY databook requires >= 10 ns warm reset assert time; 1 us provides
+ * safe margin for bus latency variations.
+ */
+ udelay(1);
+
+ ret = reset_control_deassert(crst);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to deassert reset\n");
+
+ return 0;
+}
+
static int dwc3_xlnx_init_versal(struct dwc3_xlnx *priv_data)
{
struct device *dev = priv_data->dev;
@@ -256,6 +286,11 @@ static const struct dwc3_xlnx_config versal_config = {
.pltfm_init = dwc3_xlnx_init_versal,
};
+static const struct dwc3_xlnx_config versal2_config = {
+ .pltfm_init = dwc3_xlnx_init_versal2,
+ .no_mem_map = true,
+};
+
static const struct of_device_id dwc3_xlnx_of_match[] = {
{
.compatible = "xlnx,zynqmp-dwc3",
@@ -265,6 +300,10 @@ static const struct of_device_id dwc3_xlnx_of_match[] = {
.compatible = "xlnx,versal-dwc3",
.data = &versal_config,
},
+ {
+ .compatible = "xlnx,versal2-mmi-dwc3",
+ .data = &versal2_config,
+ },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, dwc3_xlnx_of_match);
@@ -299,22 +338,27 @@ static int dwc3_xlnx_probe(struct platform_device *pdev)
struct dwc3_xlnx *priv_data;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
- void __iomem *regs;
int ret;
priv_data = devm_kzalloc(dev, sizeof(*priv_data), GFP_KERNEL);
if (!priv_data)
return -ENOMEM;
- regs = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(regs))
- return dev_err_probe(dev, PTR_ERR(regs), "failed to map registers\n");
-
priv_data->dwc3_config = device_get_match_data(dev);
if (!priv_data->dwc3_config)
return dev_err_probe(dev, -ENODEV,
"missing dwc3 platform configuration\n");
- priv_data->regs = regs;
+
+ if (!priv_data->dwc3_config->no_mem_map) {
+ void __iomem *regs;
+
+ regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(regs))
+ return dev_err_probe(dev, PTR_ERR(regs),
+ "failed to map registers\n");
+ priv_data->regs = regs;
+ }
+
priv_data->dev = dev;
platform_set_drvdata(pdev, priv_data);
--
2.43.0
More information about the linux-arm-kernel
mailing list