aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2024-09-09 15:54:56 -0600
committerTom Rini <trini@konsulko.com>2024-09-09 15:54:56 -0600
commitca55cf8104c0dd78aae45fa66dd8400ef1b3d0ac (patch)
tree90aa093631b4cbda08e4ef9244d3e51b192377cd
parent48038bfb4dc2ef8ddb67c1301ffcd633fd1afa22 (diff)
parente72e683e36a83214dbb2547d88d553b5fd816dc8 (diff)
downloadu-boot-ca55cf8104c0dd78aae45fa66dd8400ef1b3d0ac.tar.gz
Merge branch 'next' of https://source.denx.de/u-boot/custodians/u-boot-usb into nextWIP/09Sep2024-next
-rw-r--r--drivers/phy/phy-rcar-gen3.c90
-rw-r--r--drivers/phy/phy-uclass.c13
-rw-r--r--drivers/phy/sandbox-phy.c13
-rw-r--r--drivers/usb/host/ehci-generic.c2
-rw-r--r--drivers/usb/host/ehci-msm.c2
-rw-r--r--drivers/usb/host/ehci-mx6.c2
-rw-r--r--drivers/usb/host/ehci-pci.c2
-rw-r--r--drivers/usb/host/ohci-generic.c2
-rw-r--r--include/generic-phy.h8
-rw-r--r--test/dm/phy.c15
10 files changed, 131 insertions, 18 deletions
diff --git a/drivers/phy/phy-rcar-gen3.c b/drivers/phy/phy-rcar-gen3.c
index 7c292cae0e2..b278f995f37 100644
--- a/drivers/phy/phy-rcar-gen3.c
+++ b/drivers/phy/phy-rcar-gen3.c
@@ -8,6 +8,7 @@
#include <clk.h>
#include <div64.h>
#include <dm.h>
+#include <dm/device_compat.h>
#include <fdtdec.h>
#include <generic-phy.h>
#include <malloc.h>
@@ -31,8 +32,13 @@
#define USB2_LINECTRL1 0x610
#define USB2_ADPCTRL 0x630
+/* INT_ENABLE */
+#define USB2_INT_ENABLE_UCOM_INTEN BIT(3)
+#define USB2_INT_ENABLE_USBH_INTB_EN BIT(2)
+#define USB2_INT_ENABLE_USBH_INTA_EN BIT(1)
+
/* USBCTR */
-#define USB2_USBCTR_PLL_RST BIT(1)
+#define USB2_USBCTR_PLL_RST BIT(1)
/* SPD_RSM_TIMSET */
#define USB2_SPD_RSM_TIMSET_INIT 0x014e029b
@@ -43,11 +49,23 @@
/* COMMCTRL */
#define USB2_COMMCTRL_OTG_PERI BIT(31) /* 1 = Peripheral mode */
+/* OBINTSTA and OBINTEN */
+#define USB2_OBINT_SESSVLDCHG BIT(12)
+#define USB2_OBINT_IDDIGCHG BIT(11)
+
+/* VBCTRL */
+#define USB2_VBCTRL_DRVVBUSSEL BIT(8)
+
/* LINECTRL1 */
+#define USB2_LINECTRL1_DPRPD_EN BIT(19)
#define USB2_LINECTRL1_DP_RPD BIT(18)
+#define USB2_LINECTRL1_DMRPD_EN BIT(17)
#define USB2_LINECTRL1_DM_RPD BIT(16)
/* ADPCTRL */
+#define USB2_ADPCTRL_OTGSESSVLD BIT(20)
+#define USB2_ADPCTRL_IDDIG BIT(19)
+#define USB2_ADPCTRL_IDPULLUP BIT(5) /* 1 = ID sampling is enabled */
#define USB2_ADPCTRL_DRVVBUS BIT(4)
struct rcar_gen3_phy {
@@ -65,12 +83,14 @@ static int rcar_gen3_phy_phy_init(struct phy *phy)
writel(USB2_SPD_RSM_TIMSET_INIT, priv->regs + USB2_SPD_RSM_TIMSET);
writel(USB2_OC_TIMSET_INIT, priv->regs + USB2_OC_TIMSET);
- setbits_le32(priv->regs + USB2_LINECTRL1,
- USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD);
+ return 0;
+}
- clrbits_le32(priv->regs + USB2_COMMCTRL, USB2_COMMCTRL_OTG_PERI);
+static int rcar_gen3_phy_phy_exit(struct phy *phy)
+{
+ struct rcar_gen3_phy *priv = dev_get_priv(phy->dev);
- setbits_le32(priv->regs + USB2_ADPCTRL, USB2_ADPCTRL_DRVVBUS);
+ writel(0, priv->regs + USB2_INT_ENABLE);
return 0;
}
@@ -102,10 +122,70 @@ static int rcar_gen3_phy_phy_power_off(struct phy *phy)
return regulator_set_enable(priv->vbus_supply, false);
}
+static int rcar_gen3_phy_phy_set_mode(struct phy *phy, enum phy_mode mode,
+ int submode)
+{
+ const u32 adpdevmask = USB2_ADPCTRL_IDDIG | USB2_ADPCTRL_OTGSESSVLD;
+ struct rcar_gen3_phy *priv = dev_get_priv(phy->dev);
+ u32 adpctrl;
+
+ if (mode == PHY_MODE_USB_OTG) {
+ if (submode) {
+ /* OTG submode is used as initialization indicator */
+ writel(USB2_INT_ENABLE_UCOM_INTEN |
+ USB2_INT_ENABLE_USBH_INTB_EN |
+ USB2_INT_ENABLE_USBH_INTA_EN,
+ priv->regs + USB2_INT_ENABLE);
+ setbits_le32(priv->regs + USB2_VBCTRL,
+ USB2_VBCTRL_DRVVBUSSEL);
+ writel(USB2_OBINT_SESSVLDCHG | USB2_OBINT_IDDIGCHG,
+ priv->regs + USB2_OBINTSTA);
+ setbits_le32(priv->regs + USB2_OBINTEN,
+ USB2_OBINT_SESSVLDCHG |
+ USB2_OBINT_IDDIGCHG);
+ setbits_le32(priv->regs + USB2_ADPCTRL,
+ USB2_ADPCTRL_IDPULLUP);
+ clrsetbits_le32(priv->regs + USB2_LINECTRL1,
+ USB2_LINECTRL1_DP_RPD |
+ USB2_LINECTRL1_DM_RPD |
+ USB2_LINECTRL1_DPRPD_EN |
+ USB2_LINECTRL1_DMRPD_EN,
+ USB2_LINECTRL1_DPRPD_EN |
+ USB2_LINECTRL1_DMRPD_EN);
+ }
+
+ adpctrl = readl(priv->regs + USB2_ADPCTRL);
+ if ((adpctrl & adpdevmask) == adpdevmask)
+ mode = PHY_MODE_USB_DEVICE;
+ else
+ mode = PHY_MODE_USB_HOST;
+ }
+
+ if (mode == PHY_MODE_USB_HOST) {
+ clrbits_le32(priv->regs + USB2_COMMCTRL, USB2_COMMCTRL_OTG_PERI);
+ setbits_le32(priv->regs + USB2_LINECTRL1,
+ USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD);
+ setbits_le32(priv->regs + USB2_ADPCTRL, USB2_ADPCTRL_DRVVBUS);
+ } else if (mode == PHY_MODE_USB_DEVICE) {
+ setbits_le32(priv->regs + USB2_COMMCTRL, USB2_COMMCTRL_OTG_PERI);
+ clrsetbits_le32(priv->regs + USB2_LINECTRL1,
+ USB2_LINECTRL1_DP_RPD | USB2_LINECTRL1_DM_RPD,
+ USB2_LINECTRL1_DM_RPD);
+ clrbits_le32(priv->regs + USB2_ADPCTRL, USB2_ADPCTRL_DRVVBUS);
+ } else {
+ dev_err(phy->dev, "Unknown mode %d\n", mode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static const struct phy_ops rcar_gen3_phy_phy_ops = {
.init = rcar_gen3_phy_phy_init,
+ .exit = rcar_gen3_phy_phy_exit,
.power_on = rcar_gen3_phy_phy_power_on,
.power_off = rcar_gen3_phy_phy_power_off,
+ .set_mode = rcar_gen3_phy_phy_set_mode,
};
static int rcar_gen3_phy_probe(struct udevice *dev)
diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c
index acdcda15b5b..777d952b041 100644
--- a/drivers/phy/phy-uclass.c
+++ b/drivers/phy/phy-uclass.c
@@ -508,7 +508,8 @@ int generic_phy_power_off_bulk(struct phy_bulk *bulk)
return ret;
}
-int generic_setup_phy(struct udevice *dev, struct phy *phy, int index)
+int generic_setup_phy(struct udevice *dev, struct phy *phy, int index,
+ enum phy_mode mode, int submode)
{
int ret;
@@ -520,10 +521,18 @@ int generic_setup_phy(struct udevice *dev, struct phy *phy, int index)
if (ret)
return ret;
+ ret = generic_phy_set_mode(phy, mode, submode);
+ if (ret)
+ goto phys_mode_err;
+
ret = generic_phy_power_on(phy);
if (ret)
- generic_phy_exit(phy);
+ goto phys_mode_err;
+
+ return 0;
+phys_mode_err:
+ generic_phy_exit(phy);
return ret;
}
diff --git a/drivers/phy/sandbox-phy.c b/drivers/phy/sandbox-phy.c
index b159147a765..e70d20432e0 100644
--- a/drivers/phy/sandbox-phy.c
+++ b/drivers/phy/sandbox-phy.c
@@ -72,6 +72,18 @@ static int sandbox_phy_exit(struct phy *phy)
return 0;
}
+static int
+sandbox_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+ if (submode)
+ return -EOPNOTSUPP;
+
+ if (mode != PHY_MODE_USB_HOST)
+ return -EINVAL;
+
+ return 0;
+}
+
static int sandbox_phy_bind(struct udevice *dev)
{
if (dev_get_driver_data(dev) != DRIVER_DATA)
@@ -96,6 +108,7 @@ static struct phy_ops sandbox_phy_ops = {
.power_off = sandbox_phy_power_off,
.init = sandbox_phy_init,
.exit = sandbox_phy_exit,
+ .set_mode = sandbox_phy_set_mode,
};
static const struct udevice_id sandbox_phy_ids[] = {
diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c
index 23c3ed25554..1ae3619ce25 100644
--- a/drivers/usb/host/ehci-generic.c
+++ b/drivers/usb/host/ehci-generic.c
@@ -94,7 +94,7 @@ static int ehci_usb_probe(struct udevice *dev)
if (err)
goto reset_err;
- err = generic_setup_phy(dev, &priv->phy, 0);
+ err = generic_setup_phy(dev, &priv->phy, 0, PHY_MODE_USB_HOST, 0);
if (err)
goto regulator_err;
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index ff336082e3a..a759aea9db3 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -80,7 +80,7 @@ static int ehci_usb_probe(struct udevice *dev)
hcor = (struct ehci_hcor *)((phys_addr_t)hccr +
HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
- ret = generic_setup_phy(dev, &p->phy, 0);
+ ret = generic_setup_phy(dev, &p->phy, 0, PHY_MODE_USB_HOST, 0);
if (ret)
goto cleanup_iface;
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index 31cd8a50f4a..a93fa5d5455 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -703,7 +703,7 @@ static int ehci_usb_probe(struct udevice *dev)
usb_phy_enable(ehci, priv->phy_addr);
#endif
#else
- ret = generic_setup_phy(dev, &priv->phy, 0);
+ ret = generic_setup_phy(dev, &priv->phy, 0, PHY_MODE_USB_HOST, 0);
if (ret)
goto err_regulator;
#endif
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 572686580cd..8d05b14e898 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -30,7 +30,7 @@ static int ehci_pci_init(struct udevice *dev, struct ehci_hccr **ret_hccr,
int ret;
u32 cmd;
- ret = generic_setup_phy(dev, &priv->phy, 0);
+ ret = generic_setup_phy(dev, &priv->phy, 0, PHY_MODE_USB_HOST, 0);
if (ret)
return ret;
diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c
index f1325cd4953..cc44226f5e0 100644
--- a/drivers/usb/host/ohci-generic.c
+++ b/drivers/usb/host/ohci-generic.c
@@ -50,7 +50,7 @@ static int ohci_usb_probe(struct udevice *dev)
goto reset_err;
}
- err = generic_setup_phy(dev, &priv->phy, 0);
+ err = generic_setup_phy(dev, &priv->phy, 0, PHY_MODE_USB_HOST, 0);
if (err)
goto reset_err;
diff --git a/include/generic-phy.h b/include/generic-phy.h
index eaab7491660..ba3321f4849 100644
--- a/include/generic-phy.h
+++ b/include/generic-phy.h
@@ -415,10 +415,13 @@ int generic_phy_power_off_bulk(struct phy_bulk *bulk);
* @dev: The consumer device.
* @phy: A pointer to the PHY port
* @index: The index in the list of available PHYs
+ * @mode: PHY mode
+ * @submode: PHY submode
*
* Return: 0 if OK, or negative error code.
*/
-int generic_setup_phy(struct udevice *dev, struct phy *phy, int index);
+int generic_setup_phy(struct udevice *dev, struct phy *phy, int index,
+ enum phy_mode mode, int submode);
/**
* generic_shutdown_phy() - Power off and de-initialize phy.
@@ -509,7 +512,8 @@ static inline int generic_phy_power_off_bulk(struct phy_bulk *bulk)
return 0;
}
-static inline int generic_setup_phy(struct udevice *dev, struct phy *phy, int index)
+static inline int generic_setup_phy(struct udevice *dev, struct phy *phy, int index,
+ enum phy_mode mode, int submode)
{
return 0;
}
diff --git a/test/dm/phy.c b/test/dm/phy.c
index 9b4cff60e6a..194cad0bf70 100644
--- a/test/dm/phy.c
+++ b/test/dm/phy.c
@@ -243,20 +243,27 @@ static int dm_test_phy_setup(struct unit_test_state *uts)
"gen_phy_user", &parent));
/* normal */
- ut_assertok(generic_setup_phy(parent, &phy, 0));
+ ut_assertok(generic_setup_phy(parent, &phy, 0, PHY_MODE_USB_HOST, 0));
+ ut_assertok(generic_shutdown_phy(&phy));
+
+ /* set_mode as USB Host passes, anything else is not supported */
+ ut_assertok(generic_setup_phy(parent, &phy, 0, PHY_MODE_USB_HOST, 0));
+ ut_assertok(generic_phy_set_mode(&phy, PHY_MODE_USB_HOST, 0));
+ ut_asserteq(-EOPNOTSUPP, generic_phy_set_mode(&phy, PHY_MODE_USB_HOST, 1));
+ ut_asserteq(-EINVAL, generic_phy_set_mode(&phy, PHY_MODE_USB_DEVICE, 0));
ut_assertok(generic_shutdown_phy(&phy));
/* power_off fail with -EIO */
- ut_assertok(generic_setup_phy(parent, &phy, 1));
+ ut_assertok(generic_setup_phy(parent, &phy, 1, PHY_MODE_USB_HOST, 0));
ut_asserteq(-EIO, generic_shutdown_phy(&phy));
/* power_on fail with -EIO */
- ut_asserteq(-EIO, generic_setup_phy(parent, &phy, 2));
+ ut_asserteq(-EIO, generic_setup_phy(parent, &phy, 2, PHY_MODE_USB_HOST, 0));
ut_assertok(generic_shutdown_phy(&phy));
/* generic_phy_get_by_index fail with -ENOENT */
ut_asserteq(-ENOENT, generic_phy_get_by_index(parent, 3, &phy));
- ut_assertok(generic_setup_phy(parent, &phy, 3));
+ ut_assertok(generic_setup_phy(parent, &phy, 3, PHY_MODE_USB_HOST, 0));
ut_assertok(generic_shutdown_phy(&phy));
return 0;