* [PATCH] phy: phy-imx8mq-usb: Add support for i.MX8MP USB PHY
@ 2022-04-01 1:18 Marek Vasut
2022-04-07 22:21 ` Tim Harvey
0 siblings, 1 reply; 2+ messages in thread
From: Marek Vasut @ 2022-04-01 1:18 UTC (permalink / raw)
To: u-boot; +Cc: Marek Vasut, Fabio Estevam, Peng Fan, Stefano Babic
Add initial support for i.MX8MP USB PHY, i.MX8MP USB is similar to
the i.MX8MQ, except for clock and power domain design customization.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Fabio Estevam <festevam@gmail.com>
Cc: Peng Fan <peng.fan@nxp.com>
Cc: Stefano Babic <sbabic@denx.de>
---
drivers/phy/Kconfig | 6 ++--
drivers/phy/phy-imx8mq-usb.c | 66 +++++++++++++++++++++++++++++++++---
2 files changed, 65 insertions(+), 7 deletions(-)
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index d79798429b1..c01d9e09b90 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -275,11 +275,11 @@ config PHY_MTK_TPHY
so you can easily distinguish them by banks layout.
config PHY_IMX8MQ_USB
- bool "NXP i.MX8MQ USB PHY Driver"
+ bool "NXP i.MX8MQ/i.MX8MP USB PHY Driver"
depends on PHY
- depends on IMX8MQ
+ depends on IMX8MQ || IMX8MP
help
- Support the USB3.0 PHY in NXP i.MX8MQ SoC
+ Support the USB3.0 PHY in NXP i.MX8MQ or i.MX8MP SoC
config PHY_XILINX_ZYNQMP
tristate "Xilinx ZynqMP PHY driver"
diff --git a/drivers/phy/phy-imx8mq-usb.c b/drivers/phy/phy-imx8mq-usb.c
index afbc7ad8dd4..69f01de5553 100644
--- a/drivers/phy/phy-imx8mq-usb.c
+++ b/drivers/phy/phy-imx8mq-usb.c
@@ -9,7 +9,9 @@
#include <dm.h>
#include <errno.h>
#include <generic-phy.h>
+#include <linux/bitfield.h>
#include <linux/bitops.h>
+#include <linux/delay.h>
#include <linux/err.h>
#include <clk.h>
@@ -68,17 +70,22 @@
#define PHY_STS0_FSVPLUS BIT(3)
#define PHY_STS0_FSVMINUS BIT(2)
+enum imx8mpq_phy_type {
+ IMX8MQ_PHY,
+ IMX8MP_PHY,
+};
+
struct imx8mq_usb_phy {
#if CONFIG_IS_ENABLED(CLK)
struct clk phy_clk;
#endif
void __iomem *base;
+ enum imx8mpq_phy_type type;
};
static const struct udevice_id imx8mq_usb_phy_of_match[] = {
- {
- .compatible = "fsl,imx8mq-usb-phy",
- },
+ { .compatible = "fsl,imx8mq-usb-phy", .data = IMX8MQ_PHY },
+ { .compatible = "fsl,imx8mp-usb-phy", .data = IMX8MP_PHY },
{},
};
@@ -111,6 +118,56 @@ static int imx8mq_usb_phy_init(struct phy *usb_phy)
return 0;
}
+static int imx8mp_usb_phy_init(struct phy *usb_phy)
+{
+ struct udevice *dev = usb_phy->dev;
+ struct imx8mq_usb_phy *imx_phy = dev_get_priv(dev);
+ u32 value;
+
+ /* USB3.0 PHY signal fsel for 24M ref */
+ value = readl(imx_phy->base + PHY_CTRL0);
+ value &= ~PHY_CTRL0_FSEL_MASK;
+ value |= FIELD_PREP(PHY_CTRL0_FSEL_MASK, PHY_CTRL0_FSEL_24M);
+ writel(value, imx_phy->base + PHY_CTRL0);
+
+ /* Disable alt_clk_en and use internal MPLL clocks */
+ value = readl(imx_phy->base + PHY_CTRL6);
+ value &= ~(PHY_CTRL6_ALT_CLK_SEL | PHY_CTRL6_ALT_CLK_EN);
+ writel(value, imx_phy->base + PHY_CTRL6);
+
+ value = readl(imx_phy->base + PHY_CTRL1);
+ value &= ~(PHY_CTRL1_VDATSRCENB0 | PHY_CTRL1_VDATDETENB0);
+ value |= PHY_CTRL1_RESET | PHY_CTRL1_ATERESET;
+ writel(value, imx_phy->base + PHY_CTRL1);
+
+ value = readl(imx_phy->base + PHY_CTRL0);
+ value |= PHY_CTRL0_REF_SSP_EN;
+ writel(value, imx_phy->base + PHY_CTRL0);
+
+ value = readl(imx_phy->base + PHY_CTRL2);
+ value |= PHY_CTRL2_TXENABLEN0 | PHY_CTRL2_OTG_DISABLE;
+ writel(value, imx_phy->base + PHY_CTRL2);
+
+ udelay(10);
+
+ value = readl(imx_phy->base + PHY_CTRL1);
+ value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET);
+ writel(value, imx_phy->base + PHY_CTRL1);
+
+ return 0;
+}
+
+static int imx8mpq_usb_phy_init(struct phy *usb_phy)
+{
+ struct udevice *dev = usb_phy->dev;
+ struct imx8mq_usb_phy *imx_phy = dev_get_priv(dev);
+
+ if (imx_phy->type == IMX8MP_PHY)
+ return imx8mp_usb_phy_init(usb_phy);
+ else
+ return imx8mq_usb_phy_init(usb_phy);
+}
+
static int imx8mq_usb_phy_power_on(struct phy *usb_phy)
{
struct udevice *dev = usb_phy->dev;
@@ -158,7 +215,7 @@ static int imx8mq_usb_phy_exit(struct phy *usb_phy)
}
struct phy_ops imx8mq_usb_phy_ops = {
- .init = imx8mq_usb_phy_init,
+ .init = imx8mpq_usb_phy_init,
.power_on = imx8mq_usb_phy_power_on,
.power_off = imx8mq_usb_phy_power_off,
.exit = imx8mq_usb_phy_exit,
@@ -168,6 +225,7 @@ int imx8mq_usb_phy_probe(struct udevice *dev)
{
struct imx8mq_usb_phy *priv = dev_get_priv(dev);
+ priv->type = dev_get_driver_data(dev);
priv->base = dev_read_addr_ptr(dev);
if (!priv->base)
--
2.35.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] phy: phy-imx8mq-usb: Add support for i.MX8MP USB PHY
2022-04-01 1:18 [PATCH] phy: phy-imx8mq-usb: Add support for i.MX8MP USB PHY Marek Vasut
@ 2022-04-07 22:21 ` Tim Harvey
0 siblings, 0 replies; 2+ messages in thread
From: Tim Harvey @ 2022-04-07 22:21 UTC (permalink / raw)
To: Marek Vasut; +Cc: u-boot, Fabio Estevam, Peng Fan, Stefano Babic
On Thu, Mar 31, 2022 at 6:26 PM Marek Vasut <marex@denx.de> wrote:
>
> Add initial support for i.MX8MP USB PHY, i.MX8MP USB is similar to
> the i.MX8MQ, except for clock and power domain design customization.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Fabio Estevam <festevam@gmail.com>
> Cc: Peng Fan <peng.fan@nxp.com>
> Cc: Stefano Babic <sbabic@denx.de>
> ---
> drivers/phy/Kconfig | 6 ++--
> drivers/phy/phy-imx8mq-usb.c | 66 +++++++++++++++++++++++++++++++++---
> 2 files changed, 65 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index d79798429b1..c01d9e09b90 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -275,11 +275,11 @@ config PHY_MTK_TPHY
> so you can easily distinguish them by banks layout.
>
> config PHY_IMX8MQ_USB
> - bool "NXP i.MX8MQ USB PHY Driver"
> + bool "NXP i.MX8MQ/i.MX8MP USB PHY Driver"
> depends on PHY
> - depends on IMX8MQ
> + depends on IMX8MQ || IMX8MP
> help
> - Support the USB3.0 PHY in NXP i.MX8MQ SoC
> + Support the USB3.0 PHY in NXP i.MX8MQ or i.MX8MP SoC
>
> config PHY_XILINX_ZYNQMP
> tristate "Xilinx ZynqMP PHY driver"
> diff --git a/drivers/phy/phy-imx8mq-usb.c b/drivers/phy/phy-imx8mq-usb.c
> index afbc7ad8dd4..69f01de5553 100644
> --- a/drivers/phy/phy-imx8mq-usb.c
> +++ b/drivers/phy/phy-imx8mq-usb.c
> @@ -9,7 +9,9 @@
> #include <dm.h>
> #include <errno.h>
> #include <generic-phy.h>
> +#include <linux/bitfield.h>
> #include <linux/bitops.h>
> +#include <linux/delay.h>
> #include <linux/err.h>
> #include <clk.h>
>
> @@ -68,17 +70,22 @@
> #define PHY_STS0_FSVPLUS BIT(3)
> #define PHY_STS0_FSVMINUS BIT(2)
>
> +enum imx8mpq_phy_type {
> + IMX8MQ_PHY,
> + IMX8MP_PHY,
> +};
> +
> struct imx8mq_usb_phy {
> #if CONFIG_IS_ENABLED(CLK)
> struct clk phy_clk;
> #endif
> void __iomem *base;
> + enum imx8mpq_phy_type type;
> };
>
> static const struct udevice_id imx8mq_usb_phy_of_match[] = {
> - {
> - .compatible = "fsl,imx8mq-usb-phy",
> - },
> + { .compatible = "fsl,imx8mq-usb-phy", .data = IMX8MQ_PHY },
> + { .compatible = "fsl,imx8mp-usb-phy", .data = IMX8MP_PHY },
> {},
> };
>
> @@ -111,6 +118,56 @@ static int imx8mq_usb_phy_init(struct phy *usb_phy)
> return 0;
> }
>
> +static int imx8mp_usb_phy_init(struct phy *usb_phy)
> +{
> + struct udevice *dev = usb_phy->dev;
> + struct imx8mq_usb_phy *imx_phy = dev_get_priv(dev);
> + u32 value;
> +
> + /* USB3.0 PHY signal fsel for 24M ref */
> + value = readl(imx_phy->base + PHY_CTRL0);
> + value &= ~PHY_CTRL0_FSEL_MASK;
> + value |= FIELD_PREP(PHY_CTRL0_FSEL_MASK, PHY_CTRL0_FSEL_24M);
> + writel(value, imx_phy->base + PHY_CTRL0);
> +
> + /* Disable alt_clk_en and use internal MPLL clocks */
> + value = readl(imx_phy->base + PHY_CTRL6);
> + value &= ~(PHY_CTRL6_ALT_CLK_SEL | PHY_CTRL6_ALT_CLK_EN);
> + writel(value, imx_phy->base + PHY_CTRL6);
> +
> + value = readl(imx_phy->base + PHY_CTRL1);
> + value &= ~(PHY_CTRL1_VDATSRCENB0 | PHY_CTRL1_VDATDETENB0);
> + value |= PHY_CTRL1_RESET | PHY_CTRL1_ATERESET;
> + writel(value, imx_phy->base + PHY_CTRL1);
> +
> + value = readl(imx_phy->base + PHY_CTRL0);
> + value |= PHY_CTRL0_REF_SSP_EN;
> + writel(value, imx_phy->base + PHY_CTRL0);
> +
> + value = readl(imx_phy->base + PHY_CTRL2);
> + value |= PHY_CTRL2_TXENABLEN0 | PHY_CTRL2_OTG_DISABLE;
> + writel(value, imx_phy->base + PHY_CTRL2);
> +
> + udelay(10);
> +
> + value = readl(imx_phy->base + PHY_CTRL1);
> + value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET);
> + writel(value, imx_phy->base + PHY_CTRL1);
> +
> + return 0;
> +}
> +
> +static int imx8mpq_usb_phy_init(struct phy *usb_phy)
> +{
> + struct udevice *dev = usb_phy->dev;
> + struct imx8mq_usb_phy *imx_phy = dev_get_priv(dev);
> +
> + if (imx_phy->type == IMX8MP_PHY)
> + return imx8mp_usb_phy_init(usb_phy);
> + else
> + return imx8mq_usb_phy_init(usb_phy);
> +}
> +
> static int imx8mq_usb_phy_power_on(struct phy *usb_phy)
> {
> struct udevice *dev = usb_phy->dev;
> @@ -158,7 +215,7 @@ static int imx8mq_usb_phy_exit(struct phy *usb_phy)
> }
>
> struct phy_ops imx8mq_usb_phy_ops = {
> - .init = imx8mq_usb_phy_init,
> + .init = imx8mpq_usb_phy_init,
> .power_on = imx8mq_usb_phy_power_on,
> .power_off = imx8mq_usb_phy_power_off,
> .exit = imx8mq_usb_phy_exit,
> @@ -168,6 +225,7 @@ int imx8mq_usb_phy_probe(struct udevice *dev)
> {
> struct imx8mq_usb_phy *priv = dev_get_priv(dev);
>
> + priv->type = dev_get_driver_data(dev);
> priv->base = dev_read_addr_ptr(dev);
>
> if (!priv->base)
> --
> 2.35.1
>
Thanks for working on this!
This helps get DWC3 USB working on IMX8MP.
Tested-By: Tim Harvey <tharvey@gateworks.com> #imx8mp-venice-gw74xx
Best Regards,
Tim
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-04-07 22:22 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-01 1:18 [PATCH] phy: phy-imx8mq-usb: Add support for i.MX8MP USB PHY Marek Vasut
2022-04-07 22:21 ` Tim Harvey
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.