aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndriy Gapon <avg@FreeBSD.org>2020-09-21 10:02:11 +0000
committerAndriy Gapon <avg@FreeBSD.org>2020-09-21 10:02:11 +0000
commitaea49d9fed9e24a5d7f5604262aa79fccc3f427e (patch)
tree549dd8d941a1356a789322348e6518b0bba6d263
parent2bd2b113353d79cc7bdd315c3c76e0fc13218219 (diff)
downloadsrc-aea49d9fed9.tar.gz
src-aea49d9fed9.zip
aw_usbphy: add support for device mode operation
OTG mode is not supported still. It's easy to do it as a one-off detection, but the proper support requires continuous monitoring and communicating the current state to the USB layer. Also, fix phy0_route setting for H3. Remove duplicate register definitions. Tested on Orange Pi PC Plus with dr_mode="peripheral" using hw.usb.template=3 umodem_load="YES" Reviewed by: manu MFC after: 5 weeks Differential Revision: https://reviews.freebsd.org/D26348
Notes
Notes: svn path=/head/; revision=365943
-rw-r--r--sys/arm/allwinner/aw_usbphy.c78
1 files changed, 39 insertions, 39 deletions
diff --git a/sys/arm/allwinner/aw_usbphy.c b/sys/arm/allwinner/aw_usbphy.c
index dbb1471fbfb7..b0fd24a81eee 100644
--- a/sys/arm/allwinner/aw_usbphy.c
+++ b/sys/arm/allwinner/aw_usbphy.c
@@ -102,7 +102,7 @@ static const struct aw_usbphy_conf h3_usbphy_conf = {
.num_phys = 4,
.phy_type = AWUSBPHY_TYPE_H3,
.pmu_unk1 = true,
- .phy0_route = false,
+ .phy0_route = true,
};
static const struct aw_usbphy_conf a64_usbphy_conf = {
@@ -175,8 +175,10 @@ DEFINE_CLASS_1(awusbphy_phynode, awusbphy_phynode_class, awusbphy_phynode_method
#define FORCE_ID (0x3 << 14)
#define FORCE_ID_SHIFT 14
#define FORCE_ID_LOW 2
+#define FORCE_ID_HIGH 3
#define FORCE_VBUS_VALID (0x3 << 12)
#define FORCE_VBUS_VALID_SHIFT 12
+#define FORCE_VBUS_VALID_LOW 2
#define FORCE_VBUS_VALID_HIGH 3
#define VBUS_CHANGE_DET (1 << 6)
#define ID_CHANGE_DET (1 << 5)
@@ -190,18 +192,6 @@ DEFINE_CLASS_1(awusbphy_phynode, awusbphy_phynode_class, awusbphy_phynode_method
#define PMU_ULPI_BYPASS (1 << 0)
#define PMU_UNK_H3 0x10
#define PMU_UNK_H3_CLR 0x2
-#define PHY_CSR 0x00
-#define ID_PULLUP_EN (1 << 17)
-#define DPDM_PULLUP_EN (1 << 16)
-#define FORCE_ID (0x3 << 14)
-#define FORCE_ID_SHIFT 14
-#define FORCE_ID_LOW 2
-#define FORCE_VBUS_VALID (0x3 << 12)
-#define FORCE_VBUS_VALID_SHIFT 12
-#define FORCE_VBUS_VALID_HIGH 3
-#define VBUS_CHANGE_DET (1 << 6)
-#define ID_CHANGE_DET (1 << 5)
-#define DPDM_CHANGE_DET (1 << 4)
static void
awusbphy_configure(device_t dev, int phyno)
@@ -335,7 +325,12 @@ awusbphy_vbus_detect(device_t dev, int *val)
return (0);
}
- *val = 0;
+ /* TODO check vbus_power-supply. */
+
+ /*
+ * If there is no way to detect, assume present.
+ */
+ *val = 1;
return (0);
}
@@ -369,10 +364,11 @@ awusbphy_phy_enable(struct phynode *phynode, bool enable)
if (error)
goto out;
- if (vbus_det == 1) {
+ /* TODO check vbus_power-supply as well. */
+ if (sc->vbus_det_valid && vbus_det == 1) {
if (bootverbose)
- device_printf(dev, "External VBUS detected, not enabling the regulator\n");
-
+ device_printf(dev, "External VBUS detected, "
+ "not enabling the regulator\n");
return (0);
}
}
@@ -426,36 +422,40 @@ awusbphy_set_mode(struct phynode *phynode, int mode)
return (0);
}
+ if (sc->mode == mode)
+ return (0);
+ if (mode == PHY_USB_MODE_OTG) /* TODO */
+ return (EOPNOTSUPP);
+
+ error = awusbphy_vbus_detect(dev, &vbus_det);
+ if (error != 0)
+ return (error);
+
+ val = bus_read_4(sc->phy_ctrl, PHY_CSR);
+ val &= ~(VBUS_CHANGE_DET | ID_CHANGE_DET | DPDM_CHANGE_DET);
+ val |= (ID_PULLUP_EN | DPDM_PULLUP_EN);
+ val &= ~FORCE_VBUS_VALID;
+ val |= (vbus_det ? FORCE_VBUS_VALID_HIGH : FORCE_VBUS_VALID_LOW) <<
+ FORCE_VBUS_VALID_SHIFT;
+ val &= ~FORCE_ID;
+
switch (mode) {
case PHY_USB_MODE_HOST:
- val = bus_read_4(sc->phy_ctrl, PHY_CSR);
- val &= ~(VBUS_CHANGE_DET | ID_CHANGE_DET | DPDM_CHANGE_DET);
- val |= (ID_PULLUP_EN | DPDM_PULLUP_EN);
- val &= ~FORCE_ID;
val |= (FORCE_ID_LOW << FORCE_ID_SHIFT);
- val &= ~FORCE_VBUS_VALID;
- val |= (FORCE_VBUS_VALID_HIGH << FORCE_VBUS_VALID_SHIFT);
- bus_write_4(sc->phy_ctrl, PHY_CSR, val);
- if (sc->phy_conf->phy0_route == true) {
- error = awusbphy_vbus_detect(dev, &vbus_det);
- if (error)
- goto out;
- if (vbus_det == 0)
- CLR4(sc->phy_ctrl, OTG_PHY_CFG,
- OTG_PHY_ROUTE_OTG);
- else
- SET4(sc->phy_ctrl, OTG_PHY_CFG,
- OTG_PHY_ROUTE_OTG);
- }
+ if (sc->phy_conf->phy0_route)
+ CLR4(sc->phy_ctrl, OTG_PHY_CFG, OTG_PHY_ROUTE_OTG);
break;
- case PHY_USB_MODE_OTG:
- /* TODO */
+ case PHY_USB_MODE_DEVICE:
+ val |= (FORCE_ID_HIGH << FORCE_ID_SHIFT);
+ if (sc->phy_conf->phy0_route)
+ SET4(sc->phy_ctrl, OTG_PHY_CFG, OTG_PHY_ROUTE_OTG);
break;
+ default:
+ return (EINVAL);
}
+ bus_write_4(sc->phy_ctrl, PHY_CSR, val);
sc->mode = mode;
-
-out:
return (0);
}