phy: cpcap-usb: Improve host vs docked mode detection
When docked to a Motorola lapdock or media dock, we're in USB A-host mode with VBUS provided by the dock. When in regular USB A-host mode, we're providing the VBUS. And in regular USB A-host mode we must also keep kicking the VBUS to keep it active. Let's wait a bit before configuring the USB PHY to allow some time between the ID and VBUS changes. And let's add vbus_provider flag so we can detect docked mode and regularo USB A-host mode better. With better USB A-host mode detection, we can now also just kick the VBUS to keep it enabled and leave out the unnecessary line muxing. We only need to set and clear vbus_provider in the delayed work so no locking is needed for it currently. Cc: Merlijn Wajer <merlijn@wizzup.org> Cc: Pavel Machek <pavel@ucw.cz> Cc: Sebastian Reichel <sre@kernel.org> Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
This commit is contained in:
parent
63078b6ba0
commit
9492535ecd
|
@ -134,6 +134,8 @@ struct cpcap_phy_ddata {
|
|||
struct iio_channel *id;
|
||||
struct regulator *vusb;
|
||||
atomic_t active;
|
||||
unsigned int vbus_provider:1;
|
||||
unsigned int docked:1;
|
||||
};
|
||||
|
||||
static bool cpcap_usb_vbus_valid(struct cpcap_phy_ddata *ddata)
|
||||
|
@ -233,8 +235,60 @@ static void cpcap_usb_detect(struct work_struct *work)
|
|||
if (error)
|
||||
return;
|
||||
|
||||
if (s.id_ground) {
|
||||
vbus = cpcap_usb_vbus_valid(ddata);
|
||||
|
||||
/* We need to kick the VBUS as USB A-host */
|
||||
if (s.id_ground && ddata->vbus_provider) {
|
||||
dev_dbg(ddata->dev, "still in USB A-host mode, kicking VBUS\n");
|
||||
|
||||
cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
|
||||
|
||||
error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
|
||||
CPCAP_BIT_VBUSSTBY_EN |
|
||||
CPCAP_BIT_VBUSEN_SPI,
|
||||
CPCAP_BIT_VBUSEN_SPI);
|
||||
if (error)
|
||||
goto out_err;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (vbus && s.id_ground && ddata->docked) {
|
||||
dev_dbg(ddata->dev, "still docked as A-host, signal ID down\n");
|
||||
|
||||
cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* No VBUS needed with docks */
|
||||
if (vbus && s.id_ground && !ddata->vbus_provider) {
|
||||
dev_dbg(ddata->dev, "connected to a dock\n");
|
||||
|
||||
ddata->docked = true;
|
||||
|
||||
error = cpcap_usb_set_usb_mode(ddata);
|
||||
if (error)
|
||||
goto out_err;
|
||||
|
||||
cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
|
||||
|
||||
/*
|
||||
* Force check state again after musb has reoriented,
|
||||
* otherwise devices won't enumerate after loading PHY
|
||||
* driver.
|
||||
*/
|
||||
schedule_delayed_work(&ddata->detect_work,
|
||||
msecs_to_jiffies(1000));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (s.id_ground && !ddata->docked) {
|
||||
dev_dbg(ddata->dev, "id ground, USB host mode\n");
|
||||
|
||||
ddata->vbus_provider = true;
|
||||
|
||||
error = cpcap_usb_set_usb_mode(ddata);
|
||||
if (error)
|
||||
goto out_err;
|
||||
|
@ -259,21 +313,8 @@ static void cpcap_usb_detect(struct work_struct *work)
|
|||
|
||||
vbus = cpcap_usb_vbus_valid(ddata);
|
||||
|
||||
/* Otherwise assume we're connected to a USB host */
|
||||
if (vbus) {
|
||||
/* Are we connected to a docking station with vbus? */
|
||||
if (s.id_ground) {
|
||||
dev_dbg(ddata->dev, "connected to a dock\n");
|
||||
|
||||
/* No VBUS needed with docks */
|
||||
error = cpcap_usb_set_usb_mode(ddata);
|
||||
if (error)
|
||||
goto out_err;
|
||||
cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise assume we're connected to a USB host */
|
||||
dev_dbg(ddata->dev, "connected to USB host\n");
|
||||
error = cpcap_usb_set_usb_mode(ddata);
|
||||
if (error)
|
||||
|
@ -283,6 +324,8 @@ static void cpcap_usb_detect(struct work_struct *work)
|
|||
return;
|
||||
}
|
||||
|
||||
ddata->vbus_provider = false;
|
||||
ddata->docked = false;
|
||||
cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_OFF);
|
||||
|
||||
/* Default to debug UART mode */
|
||||
|
|
Loading…
Reference in New Issue