usb: dwc3-msm: Add support for proprietary charger detection

Proprietary chargers pull D+/- to specific voltages between 2.0-3.3V
(VLGC) for identification.  The DM voltage may not exceed VLGC due
to pull-down resistor.  Hence a proprietary charger is detected as
a Standard downstream port (SDP).  Read line state to distinguish
between SDP and proprietary charger.  The DP voltage would exceed
VLGC for proprietary chargers.

CRs-fixed: 383075
Change-Id: Ic9afbdd0996a4c1c7a2af76cd99182d8ae5f3b68
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
This commit is contained in:
Manu Gautam
2013-02-14 10:49:21 -08:00
committed by Jay Chokshi
parent f71d9cbad3
commit a1e331dcbf
3 changed files with 32 additions and 7 deletions
+26 -6
View File
@@ -1326,6 +1326,17 @@ static void dwc3_chg_enable_secondary_det(struct dwc3_msm *mdwc)
dwc3_msm_write_readback(mdwc->base, CHARGING_DET_CTRL_REG, 0x3F, 0x34);
}
static bool dwc3_chg_det_check_linestate(struct dwc3_msm *mdwc)
{
u32 chg_det;
bool ret = false;
chg_det = dwc3_msm_read_reg(mdwc->base, CHARGING_DET_OUTPUT_REG);
ret = chg_det & (3 << 8);
return ret;
}
static bool dwc3_chg_det_check_output(struct dwc3_msm *mdwc)
{
u32 chg_det;
@@ -1391,9 +1402,10 @@ static void dwc3_chg_block_reset(struct dwc3_msm *mdwc)
static const char *chg_to_string(enum dwc3_chg_type chg_type)
{
switch (chg_type) {
case USB_SDP_CHARGER: return "USB_SDP_CHARGER";
case USB_DCP_CHARGER: return "USB_DCP_CHARGER";
case USB_CDP_CHARGER: return "USB_CDP_CHARGER";
case DWC3_SDP_CHARGER: return "USB_SDP_CHARGER";
case DWC3_DCP_CHARGER: return "USB_DCP_CHARGER";
case DWC3_CDP_CHARGER: return "USB_CDP_CHARGER";
case DWC3_PROPRIETARY_CHARGER: return "USB_PROPRIETARY_CHARGER";
default: return "INVALID_CHARGER";
}
}
@@ -1423,6 +1435,14 @@ static void dwc3_chg_detect_work(struct work_struct *w)
tmout = ++mdwc->dcd_retries == DWC3_CHG_DCD_MAX_RETRIES;
if (is_dcd || tmout) {
dwc3_chg_disable_dcd(mdwc);
if (dwc3_chg_det_check_linestate(mdwc)) {
dev_dbg(mdwc->dev, "proprietary charger\n");
mdwc->charger.chg_type =
DWC3_PROPRIETARY_CHARGER;
mdwc->chg_state = USB_CHG_STATE_DETECTED;
delay = 0;
break;
}
dwc3_chg_enable_primary_det(mdwc);
delay = DWC3_CHG_PRIMARY_DET_TIME;
mdwc->chg_state = USB_CHG_STATE_DCD_DONE;
@@ -1437,7 +1457,7 @@ static void dwc3_chg_detect_work(struct work_struct *w)
delay = DWC3_CHG_SECONDARY_DET_TIME;
mdwc->chg_state = USB_CHG_STATE_PRIMARY_DONE;
} else {
mdwc->charger.chg_type = USB_SDP_CHARGER;
mdwc->charger.chg_type = DWC3_SDP_CHARGER;
mdwc->chg_state = USB_CHG_STATE_DETECTED;
delay = 0;
}
@@ -1445,9 +1465,9 @@ static void dwc3_chg_detect_work(struct work_struct *w)
case USB_CHG_STATE_PRIMARY_DONE:
vout = dwc3_chg_det_check_output(mdwc);
if (vout)
mdwc->charger.chg_type = USB_DCP_CHARGER;
mdwc->charger.chg_type = DWC3_DCP_CHARGER;
else
mdwc->charger.chg_type = USB_CDP_CHARGER;
mdwc->charger.chg_type = DWC3_CDP_CHARGER;
mdwc->chg_state = USB_CHG_STATE_SECONDARY_DONE;
/* fall through */
case USB_CHG_STATE_SECONDARY_DONE:
+3 -1
View File
@@ -482,7 +482,8 @@ static int dwc3_otg_set_power(struct usb_phy *phy, unsigned mA)
power_supply_type = POWER_SUPPLY_TYPE_USB;
else if (dotg->charger->chg_type == DWC3_CDP_CHARGER)
power_supply_type = POWER_SUPPLY_TYPE_USB_CDP;
else if (dotg->charger->chg_type == DWC3_DCP_CHARGER)
else if (dotg->charger->chg_type == DWC3_DCP_CHARGER ||
dotg->charger->chg_type == DWC3_PROPRIETARY_CHARGER)
power_supply_type = POWER_SUPPLY_TYPE_USB_DCP;
else
power_supply_type = POWER_SUPPLY_TYPE_BATTERY;
@@ -685,6 +686,7 @@ static void dwc3_otg_sm_work(struct work_struct *w)
/* Has charger been detected? If no detect it */
switch (charger->chg_type) {
case DWC3_DCP_CHARGER:
case DWC3_PROPRIETARY_CHARGER:
dev_dbg(phy->dev, "lpm, DCP charger\n");
dwc3_otg_set_power(phy,
DWC3_IDEV_CHG_MAX);
+3
View File
@@ -61,12 +61,15 @@ struct dwc3_otg {
* DWC3_DCP_CHARGER Dedicated charger port (AC charger/ Wall charger).
* DWC3_CDP_CHARGER Charging downstream port. Enumeration can happen and
* IDEV_CHG_MAX can be drawn irrespective of USB state.
* DWC3_PROPRIETARY_CHARGER A proprietary charger pull DP and DM to specific
* voltages between 2.0-3.3v for identification.
*/
enum dwc3_chg_type {
DWC3_INVALID_CHARGER = 0,
DWC3_SDP_CHARGER,
DWC3_DCP_CHARGER,
DWC3_CDP_CHARGER,
DWC3_PROPRIETARY_CHARGER,
};
struct dwc3_charger {