1
0
Fork 0

usbotg-bsp: improve vbus glitch detection/primary charger detection

Due to the USB-C connector introducing a slight delay between the detection of
a stable VBUS and the data lines making contact, the delay after setting the
USB PHY into charger detection mode before reading the detection status had to
be increased from 1 ms to 500 ms, enabling the user to use 500 ms to insert the
USB-C connector fully into the device and still get a positive CDP/DCP port
detection, enabling higher charge current where this is offered.
pull/10/head
Steinar Bakkemo 2020-06-10 08:23:06 +02:00
parent 6c59ac3a8d
commit 64a4289cf6
2 changed files with 42 additions and 7 deletions

View File

@ -139,21 +139,48 @@ enum ci_role ci_otg_role(struct ci_hdrc *ci)
* If the vbus can't be kept above B session valid for timeout value,
* we think it is a vbus glitch, otherwise it's a valid vbus.
*/
#define CI_VBUS_CONNECT_TIMEOUT_MS 300
#define CI_VBUS_CONNECT_GLITCH_TIMEOUT_MS 300
#define CI_VBUS_CONNECT_TOTAL_TIMEOUT_MS 1000
#define CI_VBUS_GLITCH_COUNTER_RESET_VAL (CI_VBUS_CONNECT_GLITCH_TIMEOUT_MS/20)
static int ci_is_vbus_glitch(struct ci_hdrc *ci)
{
int i;
int glitch_counter = CI_VBUS_GLITCH_COUNTER_RESET_VAL;
int total_counter = CI_VBUS_CONNECT_TOTAL_TIMEOUT_MS/20;
dev_dbg(ci->dev,
"Running for max %d ms while checking for VBUS glitc\n",
CI_VBUS_CONNECT_TOTAL_TIMEOUT_MS);
dev_dbg(ci->dev,
"(expecting min %d ms with stable VBUS)\n",
CI_VBUS_CONNECT_GLITCH_TIMEOUT_MS);
do {
for (i = 0; i < CI_VBUS_CONNECT_TIMEOUT_MS/20; i++) {
if (hw_read_otgsc(ci, OTGSC_AVV)) {
dev_dbg(ci->dev, "VBUS is valid, returning\n");
return 0;
} else if (!hw_read_otgsc(ci, OTGSC_BSV)) {
dev_dbg(ci->dev,
"B session glitch, resetting glitch counter\n");
glitch_counter = CI_VBUS_GLITCH_COUNTER_RESET_VAL;
dev_warn(ci->dev, "there is a vbus glitch\n");
return 1;
} else {
glitch_counter--;
}
msleep(20);
total_counter--;
} while ((total_counter > 0) && (glitch_counter > 0));
if (glitch_counter > 0) {
dev_dbg(ci->dev,
"Unable to measure stable VBUS for %d ms\n",
CI_VBUS_CONNECT_GLITCH_TIMEOUT_MS);
return 1;
}
dev_dbg(ci->dev,
"%d ms with stable VBUS !\n",
CI_VBUS_CONNECT_GLITCH_TIMEOUT_MS);
return 0;
}

View File

@ -735,7 +735,7 @@ static int imx7d_charger_secondary_detection(struct imx_usbmisc_data *data)
val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
if (val & MX7D_USB_OTG_PHY_STATUS_LINE_STATE1) {
dev_dbg(data->dev, "It is a dedicate charging port\n");
dev_dbg(data->dev, "It is a dedicated charging port\n");
usb_phy->chg_type = DCP_TYPE;
} else {
dev_dbg(data->dev, "It is a charging downstream port\n");
@ -851,20 +851,28 @@ static int imx7d_charger_primary_detection(struct imx_usbmisc_data *data)
* - Do not Check whether the USB plug has been in contact with
* each other
*/
dev_dbg(data->dev, "Setting up USB PHY to check whether a charger is "
"connected to the USB port\n");
dev_dbg(data->dev, "(NOT checking whether the USB plug has been in "
"contact with each other)\n");
val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 |
MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0,
usbmisc->base + MX7D_USB_OTG_PHY_CFG2);
spin_unlock_irqrestore(&usbmisc->lock, flags);
usleep_range(1000, 2000);
dev_dbg(data->dev, "Waiting 500 ms before reading status\n");
usleep_range(500000, 501000);
/* Check if it is a charger */
val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS);
if (!(val & MX7D_USB_OTG_PHY_STATUS_CHRGDET)) {
dev_dbg(data->dev, "It is a stardard downstream port\n");
dev_dbg(data->dev, "It is a standard downstream port\n");
usb_phy->chg_type = SDP_TYPE;
}
else {
dev_dbg(data->dev, "It is NOT a standard downstream port\n");
}
imx7_disable_charger_detector(data);