From: Ghennadi Procopciuc <ghennadi.procopciuc@nxp.com>
Enable USB driver for s32g2. This chip has an errata ERR050474,
so we need to set S32G_UCMALLBE for it to handle packages which
aren't 4 byte aligned correctly.
Signed-off-by: Ghennadi Procopciuc <ghennadi.procopciuc@nxp.com>
Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
---
Changes since v1:
* Update the copyright
* Use the .power_lost_check callback.
drivers/usb/chipidea/ci_hdrc_imx.c | 6 +++
drivers/usb/chipidea/usbmisc_imx.c | 74 ++++++++++++++++++++++++++++++
2 files changed, 80 insertions(+)
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 780f4d151345..e8c847eab8e3 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2025 NXP
* Copyright (C) 2012 Marek Vasut <marex@denx.de>
* on behalf of DENX Software Engineering GmbH
*/
@@ -78,6 +79,10 @@ static const struct ci_hdrc_imx_platform_flag imx8ulp_usb_data = {
CI_HDRC_HAS_PORTSC_PEC_MISSED,
};
+static const struct ci_hdrc_imx_platform_flag s32g_usb_data = {
+ .flags = CI_HDRC_DISABLE_HOST_STREAMING,
+};
+
static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
{ .compatible = "fsl,imx23-usb", .data = &imx23_usb_data},
{ .compatible = "fsl,imx28-usb", .data = &imx28_usb_data},
@@ -89,6 +94,7 @@ static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
{ .compatible = "fsl,imx7d-usb", .data = &imx7d_usb_data},
{ .compatible = "fsl,imx7ulp-usb", .data = &imx7ulp_usb_data},
{ .compatible = "fsl,imx8ulp-usb", .data = &imx8ulp_usb_data},
+ { .compatible = "nxp,s32g2-usb", .data = &s32g_usb_data},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index 118b9a68496b..67ff073ad806 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2025 NXP
*/
#include <linux/module.h>
@@ -155,6 +156,18 @@
BLKCTL_OTG_VBUS_WAKEUP_EN | \
BLKCTL_OTG_DPDM_WAKEUP_EN)
+#define S32G_WAKEUP_IE BIT(0)
+#define S32G_CORE_IE BIT(1)
+#define S32G_PWRFLTEN BIT(7)
+#define S32G_WAKEUPCTRL BIT(10)
+#define S32G_WAKEUPEN BIT(11)
+
+/* Workaround errata ERR050474 (handle packages that aren't 4 byte aligned) */
+#define S32G_UCMALLBE BIT(15)
+
+#define S32G_WAKEUP_BITS (S32G_WAKEUP_IE | S32G_CORE_IE | S32G_WAKEUPEN | \
+ S32G_WAKEUPCTRL)
+
struct usbmisc_ops {
/* It's called once when probe a usb device */
int (*init)(struct imx_usbmisc_data *data);
@@ -614,6 +627,52 @@ static int usbmisc_vf610_init(struct imx_usbmisc_data *data)
return 0;
}
+static int usbmisc_s32g_set_wakeup(struct imx_usbmisc_data *data, bool enabled)
+{
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&usbmisc->lock, flags);
+
+ reg = readl(usbmisc->base);
+ if (enabled)
+ reg |= S32G_WAKEUP_BITS;
+ else
+ reg &= ~S32G_WAKEUP_BITS;
+
+ writel(reg, usbmisc->base);
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+
+ return 0;
+}
+
+static int usbmisc_s32g_init(struct imx_usbmisc_data *data, u32 extra_flags)
+{
+ struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&usbmisc->lock, flags);
+
+ reg = readl(usbmisc->base);
+
+ reg |= S32G_PWRFLTEN;
+ reg |= extra_flags;
+
+ writel(reg, usbmisc->base);
+
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+ usbmisc_s32g_set_wakeup(data, false);
+
+ return 0;
+}
+
+static int usbmisc_s32g2_init(struct imx_usbmisc_data *data)
+{
+ return usbmisc_s32g_init(data, S32G_UCMALLBE);
+}
+
static int usbmisc_imx7d_set_wakeup
(struct imx_usbmisc_data *data, bool enabled)
{
@@ -1033,6 +1092,11 @@ static int usbmisc_imx6sx_power_lost_check(struct imx_usbmisc_data *data)
return 0;
}
+static int usbmisc_s32g_power_lost_check(struct imx_usbmisc_data *data)
+{
+ return 1;
+}
+
static u32 usbmisc_blkctl_wakeup_setting(struct imx_usbmisc_data *data)
{
u32 wakeup_setting = BLKCTL_WAKEUP_SOURCE;
@@ -1131,6 +1195,12 @@ static const struct usbmisc_ops imx95_usbmisc_ops = {
.vbus_comparator_on = usbmisc_imx7d_vbus_comparator_on,
};
+static const struct usbmisc_ops s32g2_usbmisc_ops = {
+ .init = usbmisc_s32g2_init,
+ .set_wakeup = usbmisc_s32g_set_wakeup,
+ .power_lost_check = usbmisc_s32g_power_lost_check,
+};
+
static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data)
{
struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
@@ -1356,6 +1426,10 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = {
.compatible = "fsl,imx95-usbmisc",
.data = &imx95_usbmisc_ops,
},
+ {
+ .compatible = "nxp,s32g2-usbmisc",
+ .data = &s32g2_usbmisc_ops,
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
--
2.47.2
On Thu, Jun 12, 2025 at 09:50:59PM +0300, Dan Carpenter wrote: > From: Ghennadi Procopciuc <ghennadi.procopciuc@nxp.com> > > Enable USB driver for s32g2. This chip has an errata ERR050474, Can you provide errata link here? > so we need to set S32G_UCMALLBE for it to handle packages which > aren't 4 byte aligned correctly. > > Signed-off-by: Ghennadi Procopciuc <ghennadi.procopciuc@nxp.com> > Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> > --- > Changes since v1: > * Update the copyright > * Use the .power_lost_check callback. > > drivers/usb/chipidea/ci_hdrc_imx.c | 6 +++ > drivers/usb/chipidea/usbmisc_imx.c | 74 ++++++++++++++++++++++++++++++ > 2 files changed, 80 insertions(+) > > diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c > index 780f4d151345..e8c847eab8e3 100644 > --- a/drivers/usb/chipidea/ci_hdrc_imx.c > +++ b/drivers/usb/chipidea/ci_hdrc_imx.c > @@ -1,6 +1,7 @@ > // SPDX-License-Identifier: GPL-2.0+ > /* > * Copyright 2012 Freescale Semiconductor, Inc. > + * Copyright 2025 NXP > * Copyright (C) 2012 Marek Vasut <marex@denx.de> > * on behalf of DENX Software Engineering GmbH > */ > @@ -78,6 +79,10 @@ static const struct ci_hdrc_imx_platform_flag imx8ulp_usb_data = { > CI_HDRC_HAS_PORTSC_PEC_MISSED, > }; > > +static const struct ci_hdrc_imx_platform_flag s32g_usb_data = { > + .flags = CI_HDRC_DISABLE_HOST_STREAMING, > +}; > + > static const struct of_device_id ci_hdrc_imx_dt_ids[] = { > { .compatible = "fsl,imx23-usb", .data = &imx23_usb_data}, > { .compatible = "fsl,imx28-usb", .data = &imx28_usb_data}, > @@ -89,6 +94,7 @@ static const struct of_device_id ci_hdrc_imx_dt_ids[] = { > { .compatible = "fsl,imx7d-usb", .data = &imx7d_usb_data}, > { .compatible = "fsl,imx7ulp-usb", .data = &imx7ulp_usb_data}, > { .compatible = "fsl,imx8ulp-usb", .data = &imx8ulp_usb_data}, > + { .compatible = "nxp,s32g2-usb", .data = &s32g_usb_data}, > { /* sentinel */ } > }; > MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids); > diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c > index 118b9a68496b..67ff073ad806 100644 > --- a/drivers/usb/chipidea/usbmisc_imx.c > +++ b/drivers/usb/chipidea/usbmisc_imx.c > @@ -1,6 +1,7 @@ > // SPDX-License-Identifier: GPL-2.0+ > /* > * Copyright 2012 Freescale Semiconductor, Inc. > + * Copyright 2025 NXP > */ > > #include <linux/module.h> > @@ -155,6 +156,18 @@ > BLKCTL_OTG_VBUS_WAKEUP_EN | \ > BLKCTL_OTG_DPDM_WAKEUP_EN) > > +#define S32G_WAKEUP_IE BIT(0) > +#define S32G_CORE_IE BIT(1) > +#define S32G_PWRFLTEN BIT(7) > +#define S32G_WAKEUPCTRL BIT(10) > +#define S32G_WAKEUPEN BIT(11) > + > +/* Workaround errata ERR050474 (handle packages that aren't 4 byte aligned) */ > +#define S32G_UCMALLBE BIT(15) > + > +#define S32G_WAKEUP_BITS (S32G_WAKEUP_IE | S32G_CORE_IE | S32G_WAKEUPEN | \ > + S32G_WAKEUPCTRL) > + > struct usbmisc_ops { > /* It's called once when probe a usb device */ > int (*init)(struct imx_usbmisc_data *data); > @@ -614,6 +627,52 @@ static int usbmisc_vf610_init(struct imx_usbmisc_data *data) > return 0; > } > > +static int usbmisc_s32g_set_wakeup(struct imx_usbmisc_data *data, bool enabled) > +{ > + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); > + unsigned long flags; > + u32 reg; > + > + spin_lock_irqsave(&usbmisc->lock, flags); > + > + reg = readl(usbmisc->base); > + if (enabled) > + reg |= S32G_WAKEUP_BITS; > + else > + reg &= ~S32G_WAKEUP_BITS; > + > + writel(reg, usbmisc->base); > + spin_unlock_irqrestore(&usbmisc->lock, flags); > + > + return 0; > +} > + > +static int usbmisc_s32g_init(struct imx_usbmisc_data *data, u32 extra_flags) > +{ > + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); > + unsigned long flags; > + u32 reg; > + > + spin_lock_irqsave(&usbmisc->lock, flags); > + > + reg = readl(usbmisc->base); > + > + reg |= S32G_PWRFLTEN; > + reg |= extra_flags; > + > + writel(reg, usbmisc->base); > + > + spin_unlock_irqrestore(&usbmisc->lock, flags); > + usbmisc_s32g_set_wakeup(data, false); > + > + return 0; > +} > + > +static int usbmisc_s32g2_init(struct imx_usbmisc_data *data) > +{ > + return usbmisc_s32g_init(data, S32G_UCMALLBE); > +} > + > static int usbmisc_imx7d_set_wakeup > (struct imx_usbmisc_data *data, bool enabled) > { > @@ -1033,6 +1092,11 @@ static int usbmisc_imx6sx_power_lost_check(struct imx_usbmisc_data *data) > return 0; > } > > +static int usbmisc_s32g_power_lost_check(struct imx_usbmisc_data *data) > +{ > + return 1; > +} > + > static u32 usbmisc_blkctl_wakeup_setting(struct imx_usbmisc_data *data) > { > u32 wakeup_setting = BLKCTL_WAKEUP_SOURCE; > @@ -1131,6 +1195,12 @@ static const struct usbmisc_ops imx95_usbmisc_ops = { > .vbus_comparator_on = usbmisc_imx7d_vbus_comparator_on, > }; > > +static const struct usbmisc_ops s32g2_usbmisc_ops = { > + .init = usbmisc_s32g2_init, > + .set_wakeup = usbmisc_s32g_set_wakeup, > + .power_lost_check = usbmisc_s32g_power_lost_check, > +}; > + > static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data) > { > struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); > @@ -1356,6 +1426,10 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = { > .compatible = "fsl,imx95-usbmisc", > .data = &imx95_usbmisc_ops, > }, > + { > + .compatible = "nxp,s32g2-usbmisc", > + .data = &s32g2_usbmisc_ops, > + }, > { /* sentinel */ } > }; > MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids); > -- > 2.47.2 >
© 2016 - 2025 Red Hat, Inc.