Hi Ahmad,

On Mon, Nov 03, 2025 at 04:19:31PM +0100, Ahmad Fatoum wrote:
> Commit e213627bbe ("usb: dwc3: of-simple: add i.MX8MP compatible")
> added i.MX8MP support by matching the i.MX8MP glue in dwc3-of-simple.
> 
> This is unlike what the kernel was doing, because "Linux uses this wrapper
> for wakeup handling, but we don't need this functionality in Barebox".
> 
> Looking at Linux v6.18-rc3, this is not accurate anymore:
> The upstream i.MX8MP glue driver handles a number of device tree properties
> that we do not handle in barebox:
> 
>   * fsl,permanently-attached
>   * fsl,disable-port-power-control
>   * fsl,over-current-active-low
>   * fsl,power-active-low
> 
> The Linux driver also sets two software properies:

Nitpick

s/properies/properties/

>   * xhci-missing-cas-quirk
>   * xhci-skip-phy-init-quirk
> 
> But both are unneeded for barebox as the former only matters when
> resuming from runtime suspend and the latter is the only behavior we
> currently have in barebox, because the XHCI driver itself doesn't yet
> use the PHY API.
> 
> Thus import the Linux driver without the software property bits to add
> support for the OF bindings.
> 
> Reported-by: Marc Kleine-Budde <[email protected]>
> Reported-by: Holger Assmann <[email protected]>

This series works on our board using v2025.03.0 + backport of

    332e3542e5ed ("Port Linux __cleanup() based guard infrastructure") .

Tested-by: Thorsten Scherer <[email protected]>

> Signed-off-by: Ahmad Fatoum <[email protected]>
> ---
>  drivers/usb/dwc3/Kconfig          |  10 ++
>  drivers/usb/dwc3/Makefile         |   1 +
>  drivers/usb/dwc3/dwc3-imx8mp.c    | 160 ++++++++++++++++++++++++++++++
>  drivers/usb/dwc3/dwc3-of-simple.c |   1 -
>  4 files changed, 171 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/usb/dwc3/dwc3-imx8mp.c
> 
> diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
> index de5f0ef6f3eb..bed629776227 100644
> --- a/drivers/usb/dwc3/Kconfig
> +++ b/drivers/usb/dwc3/Kconfig
> @@ -48,6 +48,16 @@ config USB_DWC3_OF_SIMPLE
>        Currently supports Xilinx and Qualcomm DWC USB3 IP.
>        Say 'Y' or 'M' if you have one such device.
>  
> +config USB_DWC3_IMX8MP
> +     tristate "NXP iMX8MP Platform"
> +     depends on OF && COMMON_CLK
> +     depends on ARCH_IMX8MP || COMPILE_TEST
> +     default USB_DWC3
> +     help
> +       NXP iMX8M Plus SoC use DesignWare Core IP for USB2/3
> +       functionality.
> +       Say 'Y' or 'M' if you have one such device.
> +
>  config USB_DWC3_AM62
>       tristate "Texas Instruments AM62 Platforms"
>       depends on ARCH_K3 || COMPILE_TEST
> diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
> index 30097da367d9..31acda1825f5 100644
> --- a/drivers/usb/dwc3/Makefile
> +++ b/drivers/usb/dwc3/Makefile
> @@ -14,3 +14,4 @@ endif
>  
>  obj-$(CONFIG_USB_DWC3_OF_SIMPLE)     += dwc3-of-simple.o
>  obj-$(CONFIG_USB_DWC3_AM62)          += dwc3-am62.o
> +obj-$(CONFIG_USB_DWC3_IMX8MP)                += dwc3-imx8mp.o
> diff --git a/drivers/usb/dwc3/dwc3-imx8mp.c b/drivers/usb/dwc3/dwc3-imx8mp.c
> new file mode 100644
> index 000000000000..d7f2795dc504
> --- /dev/null
> +++ b/drivers/usb/dwc3/dwc3-imx8mp.c
> @@ -0,0 +1,160 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * dwc3-imx8mp.c - NXP imx8mp Specific Glue layer
> + *
> + * Copyright (c) 2020 NXP.
> + */
> +
> +#include <linux/cleanup.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <of.h>
> +#include <linux/device.h>
> +
> +/* USB wakeup registers */
> +#define USB_WAKEUP_CTRL                      0x00
> +
> +/* Global wakeup interrupt enable, also used to clear interrupt */
> +#define USB_WAKEUP_EN                        BIT(31)
> +/* Wakeup from connect or disconnect, only for superspeed */
> +#define USB_WAKEUP_SS_CONN           BIT(5)
> +/* 0 select vbus_valid, 1 select sessvld */
> +#define USB_WAKEUP_VBUS_SRC_SESS_VAL BIT(4)
> +/* Enable signal for wake up from u3 state */
> +#define USB_WAKEUP_U3_EN             BIT(3)
> +/* Enable signal for wake up from id change */
> +#define USB_WAKEUP_ID_EN             BIT(2)
> +/* Enable signal for wake up from vbus change */
> +#define      USB_WAKEUP_VBUS_EN              BIT(1)
> +/* Enable signal for wake up from dp/dm change */
> +#define USB_WAKEUP_DPDM_EN           BIT(0)
> +
> +#define USB_WAKEUP_EN_MASK           GENMASK(5, 0)
> +
> +/* USB glue registers */
> +#define USB_CTRL0            0x00
> +#define USB_CTRL1            0x04
> +
> +#define USB_CTRL0_PORTPWR_EN BIT(12) /* 1 - PPC enabled (default) */
> +#define USB_CTRL0_USB3_FIXED BIT(22) /* 1 - USB3 permanent attached */
> +#define USB_CTRL0_USB2_FIXED BIT(23) /* 1 - USB2 permanent attached */
> +
> +#define USB_CTRL1_OC_POLARITY        BIT(16) /* 0 - HIGH / 1 - LOW */
> +#define USB_CTRL1_PWR_POLARITY       BIT(17) /* 0 - HIGH / 1 - LOW */
> +
> +struct dwc3_imx8mp {
> +     struct device                   *dev;
> +     struct platform_device          *dwc3;
> +     void __iomem                    *hsio_blk_base;
> +     void __iomem                    *glue_base;
> +     struct clk                      *hsio_clk;
> +     struct clk                      *suspend_clk;
> +     bool                            wakeup_pending;
> +};
> +
> +static void imx8mp_configure_glue(struct dwc3_imx8mp *dwc3_imx)
> +{
> +     struct device *dev = dwc3_imx->dev;
> +     struct device_node *np = dev_of_node(dev);
> +     u32 value;
> +
> +     if (!dwc3_imx->glue_base)
> +             return;
> +
> +     value = readl(dwc3_imx->glue_base + USB_CTRL0);
> +
> +     if (of_property_read_bool(np, "fsl,permanently-attached"))
> +             value |= (USB_CTRL0_USB2_FIXED | USB_CTRL0_USB3_FIXED);
> +     else
> +             value &= ~(USB_CTRL0_USB2_FIXED | USB_CTRL0_USB3_FIXED);
> +
> +     if (of_property_read_bool(np, "fsl,disable-port-power-control"))
> +             value &= ~(USB_CTRL0_PORTPWR_EN);
> +     else
> +             value |= USB_CTRL0_PORTPWR_EN;
> +
> +     writel(value, dwc3_imx->glue_base + USB_CTRL0);
> +
> +     value = readl(dwc3_imx->glue_base + USB_CTRL1);
> +     if (of_property_read_bool(np, "fsl,over-current-active-low"))
> +             value |= USB_CTRL1_OC_POLARITY;
> +     else
> +             value &= ~USB_CTRL1_OC_POLARITY;
> +
> +     if (of_property_read_bool(np, "fsl,power-active-low"))
> +             value |= USB_CTRL1_PWR_POLARITY;
> +     else
> +             value &= ~USB_CTRL1_PWR_POLARITY;
> +
> +     writel(value, dwc3_imx->glue_base + USB_CTRL1);
> +}
> +
> +static int dwc3_imx8mp_probe(struct device *dev)
> +{
> +     struct device_node      *node = dev->of_node;
> +     struct dwc3_imx8mp      *dwc3_imx;
> +     struct resource         *res;
> +     int                     err;
> +
> +     if (!node) {
> +             dev_err(dev, "device node not found\n");
> +             return -EINVAL;
> +     }
> +
> +     dwc3_imx = devm_kzalloc(dev, sizeof(*dwc3_imx), GFP_KERNEL);
> +     if (!dwc3_imx)
> +             return -ENOMEM;
> +
> +     dwc3_imx->dev = dev;
> +
> +     dwc3_imx->hsio_blk_base = dev_platform_ioremap_resource(dev, 0);
> +     if (IS_ERR(dwc3_imx->hsio_blk_base))
> +             return PTR_ERR(dwc3_imx->hsio_blk_base);
> +
> +     res = dev_request_mem_resource(dev, 1);
> +     if (!res)
> +             dev_warn(dev, "Base address for glue layer missing. Continuing 
> without, some features are missing though.");
> +     else
> +             dwc3_imx->glue_base = IOMEM(res->start);
> +
> +     dwc3_imx->hsio_clk = clk_get_enabled(dev, "hsio");
> +     if (IS_ERR(dwc3_imx->hsio_clk))
> +             return dev_err_probe(dev, PTR_ERR(dwc3_imx->hsio_clk),
> +                                  "Failed to get hsio clk\n");
> +
> +     dwc3_imx->suspend_clk = clk_get_enabled(dev, "suspend");
> +     if (IS_ERR(dwc3_imx->suspend_clk))
> +             return dev_err_probe(dev, PTR_ERR(dwc3_imx->suspend_clk),
> +                                  "Failed to get suspend clk\n");
> +
> +     imx8mp_configure_glue(dwc3_imx);
> +
> +     err = of_platform_populate(node, NULL, dev);
> +     if (err) {
> +             dev_err(dev, "failed to create dwc3 core\n");
> +             return err;
> +     }
> +
> +     return 0;
> +}
> +
> +static const struct of_device_id dwc3_imx8mp_of_match[] = {
> +     { .compatible = "fsl,imx8mp-dwc3", },
> +     {},
> +};
> +MODULE_DEVICE_TABLE(of, dwc3_imx8mp_of_match);
> +
> +static struct driver dwc3_imx8mp_driver = {
> +     .probe          = dwc3_imx8mp_probe,
> +     .name   = "imx8mp-dwc3",
> +     .of_match_table = dwc3_imx8mp_of_match,
> +};
> +
> +device_platform_driver(dwc3_imx8mp_driver);
> +
> +MODULE_ALIAS("platform:imx8mp-dwc3");
> +MODULE_AUTHOR("[email protected]");
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("DesignWare USB3 imx8mp Glue Layer");
> diff --git a/drivers/usb/dwc3/dwc3-of-simple.c 
> b/drivers/usb/dwc3/dwc3-of-simple.c
> index 1e622240152e..b2b8ea9f23ce 100644
> --- a/drivers/usb/dwc3/dwc3-of-simple.c
> +++ b/drivers/usb/dwc3/dwc3-of-simple.c
> @@ -67,7 +67,6 @@ static void dwc3_of_simple_remove(struct device *dev)
>  static const struct of_device_id of_dwc3_simple_match[] = {
>       {.compatible = "rockchip,rk3399-dwc3"},
>       {.compatible = "xlnx,zynqmp-dwc3"},
> -     {.compatible = "fsl,imx8mp-dwc3"},
>       {/* Sentinel */}};
>  MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
>  
> -- 
> 2.47.3
> 
> 

Best regards
Thorsten

Reply via email to