phy: phy-imx8mq-usb: Add support for i.MX8MP USB PHY
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> Tested-By: Tim Harvey <tharvey@gateworks.com> #imx8mp-venice-gw74xx
This commit is contained in:
parent
7a2c3be95a
commit
77ee5d3508
2 changed files with 65 additions and 7 deletions
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue