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
This commit is contained in:
parent
2bd2b11335
commit
aea49d9fed
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user