From aea49d9fed9e24a5d7f5604262aa79fccc3f427e Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Mon, 21 Sep 2020 10:02:11 +0000 Subject: 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 --- sys/arm/allwinner/aw_usbphy.c | 78 +++++++++++++++++++++---------------------- 1 file 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); } -- cgit v1.2.3