diff options
-rw-r--r-- | drivers/phy/Kconfig | 6 | ||||
-rw-r--r-- | drivers/phy/phy-imx8mq-usb.c | 91 | ||||
-rw-r--r-- | drivers/usb/common/dwc2_core.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ehci-mx6.c | 2 |
4 files changed, 95 insertions, 6 deletions
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index c297fa03ea7..d36a5f00ef8 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -289,11 +289,11 @@ config PHY_NPCM_USB Support the USB PHY in NPCM SoCs config PHY_IMX8MQ_USB - bool "NXP i.MX8MQ/i.MX8MP USB PHY Driver" + bool "NXP i.MX8MQ/i.MX8MP/i.MX95 USB PHY Driver" depends on PHY - depends on IMX8MQ || IMX8MP + depends on IMX8MQ || IMX8MP || IMX95 help - Support the USB3.0 PHY in NXP i.MX8MQ or i.MX8MP SoC + Support the USB3.0 PHY in NXP i.MX8MQ, i.MX8MP, and i.MX95 SoC config PHY_IMX8M_PCIE bool "NXP i.MX8MM/i.MX8MP PCIe PHY Driver" diff --git a/drivers/phy/phy-imx8mq-usb.c b/drivers/phy/phy-imx8mq-usb.c index 75763046adc..387db843c50 100644 --- a/drivers/phy/phy-imx8mq-usb.c +++ b/drivers/phy/phy-imx8mq-usb.c @@ -71,9 +71,57 @@ #define PHY_STS0_FSVPLUS BIT(3) #define PHY_STS0_FSVMINUS BIT(2) +#define TCA_CLK_RST 0x00 +#define TCA_CLK_RST_SW BIT(9) +#define TCA_CLK_RST_REF_CLK_EN BIT(1) +#define TCA_CLK_RST_SUSPEND_CLK_EN BIT(0) + +#define TCA_INTR_EN 0x04 +#define TCA_INTR_STS 0x08 + +#define TCA_GCFG 0x10 +#define TCA_GCFG_ROLE_HSTDEV BIT(4) +#define TCA_GCFG_OP_MODE GENMASK(1, 0) +#define TCA_GCFG_OP_MODE_SYSMODE 0 +#define TCA_GCFG_OP_MODE_SYNCMODE 1 + +#define TCA_TCPC 0x14 +#define TCA_TCPC_VALID BIT(4) +#define TCA_TCPC_LOW_POWER_EN BIT(3) +#define TCA_TCPC_ORIENTATION_NORMAL BIT(2) +#define TCA_TCPC_MUX_CONTRL GENMASK(1, 0) +#define TCA_TCPC_MUX_CONTRL_NO_CONN 0 +#define TCA_TCPC_MUX_CONTRL_USB_CONN 1 + +#define TCA_SYSMODE_CFG 0x18 +#define TCA_SYSMODE_TCPC_DISABLE BIT(3) +#define TCA_SYSMODE_TCPC_FLIP BIT(2) + +#define TCA_CTRLSYNCMODE_CFG0 0x20 +#define TCA_CTRLSYNCMODE_CFG1 0x20 + +#define TCA_PSTATE 0x30 +#define TCA_PSTATE_CM_STS BIT(4) +#define TCA_PSTATE_TX_STS BIT(3) +#define TCA_PSTATE_RX_PLL_STS BIT(2) +#define TCA_PSTATE_PIPE0_POWER_DOWN GENMASK(1, 0) + +#define TCA_GEN_STATUS 0x34 +#define TCA_GEN_DEV_POR BIT(12) +#define TCA_GEN_REF_CLK_SEL BIT(8) +#define TCA_GEN_TYPEC_FLIP_INVERT BIT(4) +#define TCA_GEN_PHY_TYPEC_DISABLE BIT(3) +#define TCA_GEN_PHY_TYPEC_FLIP BIT(2) + +#define TCA_VBUS_CTRL 0x40 +#define TCA_VBUS_STATUS 0x44 + +#define TCA_INFO 0xfc + enum imx8mpq_phy_type { IMX8MQ_PHY, IMX8MP_PHY, + IMX95_PHY, }; struct imx8mq_usb_phy { @@ -81,14 +129,49 @@ struct imx8mq_usb_phy { void __iomem *base; enum imx8mpq_phy_type type; struct udevice *vbus_supply; + void __iomem *tca_base; }; static const struct udevice_id imx8mq_usb_phy_of_match[] = { { .compatible = "fsl,imx8mq-usb-phy", .data = IMX8MQ_PHY }, { .compatible = "fsl,imx8mp-usb-phy", .data = IMX8MP_PHY }, + { .compatible = "fsl,imx95-usb-phy", .data = IMX95_PHY }, {}, }; +static void tca_blk_init(struct phy *usb_phy) +{ + struct udevice *dev = usb_phy->dev; + struct imx8mq_usb_phy *imx_phy = dev_get_priv(dev); + void __iomem *base = imx_phy->tca_base; + u32 val; + + /* reset XBar block */ + val = readl(base + TCA_CLK_RST); + val &= ~TCA_CLK_RST_SW; + writel(val, base + TCA_CLK_RST); + + udelay(100); + + /* clear reset */ + val |= TCA_CLK_RST_SW; + writel(val, base + TCA_CLK_RST); + + /* + * use Controller Synced Mode for TCA low power enable and + * put PHY to USB safe state. + */ + val = FIELD_PREP(TCA_GCFG_OP_MODE, TCA_GCFG_OP_MODE_SYNCMODE); + writel(val, base + TCA_GCFG); + + val = TCA_TCPC_VALID | TCA_TCPC_LOW_POWER_EN; + writel(val, base + TCA_TCPC); + + /* use System Configuration Mode for TCA mux control. */ + val = FIELD_PREP(TCA_GCFG_OP_MODE, TCA_GCFG_OP_MODE_SYSMODE); + writel(val, base + TCA_GCFG); +} + static int imx8mq_usb_phy_init(struct phy *usb_phy) { struct udevice *dev = usb_phy->dev; @@ -154,6 +237,9 @@ static int imx8mp_usb_phy_init(struct phy *usb_phy) value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET); writel(value, imx_phy->base + PHY_CTRL1); + if (imx_phy->tca_base) + tca_blk_init(usb_phy); + return 0; } @@ -162,7 +248,7 @@ 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) + if (imx_phy->type == IMX8MP_PHY || imx_phy->type == IMX95_PHY) return imx8mp_usb_phy_init(usb_phy); else return imx8mq_usb_phy_init(usb_phy); @@ -264,6 +350,9 @@ int imx8mq_usb_phy_probe(struct udevice *dev) } } + if (priv->type == IMX95_PHY) + priv->tca_base = dev_read_addr_index_ptr(dev, 1); + return 0; } diff --git a/drivers/usb/common/dwc2_core.c b/drivers/usb/common/dwc2_core.c index 63062d5cc94..37007134e5b 100644 --- a/drivers/usb/common/dwc2_core.c +++ b/drivers/usb/common/dwc2_core.c @@ -17,7 +17,7 @@ int dwc2_core_reset(struct dwc2_core_regs *regs) bool host_mode = false; if (!(readl(®s->global_regs.gotgctl) & GOTGCTL_CONID_B) || - (readl(®s->global_regs.gusbcfg) & GUSBCFG_FORCEDEVMODE)) + (readl(®s->global_regs.gusbcfg) & GUSBCFG_FORCEHOSTMODE)) host_mode = true; /* Core Soft Reset */ diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index a8748cef7ad..25907f22612 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -537,7 +537,7 @@ static int ehci_usb_phy_mode(struct udevice *dev) plat->init_type = USB_INIT_DEVICE; else plat->init_type = USB_INIT_HOST; - } else if (is_mx7() || is_imx8mm() || is_imx8mn() || is_imx93()) { + } else if (is_mx7() || is_imx8mm() || is_imx8mn() || is_imx9()) { phy_status = (void __iomem *)(addr + USBNC_PHY_STATUS_OFFSET); val = readl(phy_status); |