summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/phy/Kconfig6
-rw-r--r--drivers/phy/phy-imx8mq-usb.c91
-rw-r--r--drivers/usb/common/dwc2_core.c2
-rw-r--r--drivers/usb/host/ehci-mx6.c2
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(&regs->global_regs.gotgctl) & GOTGCTL_CONID_B) ||
- (readl(&regs->global_regs.gusbcfg) & GUSBCFG_FORCEDEVMODE))
+ (readl(&regs->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);