/* Disable charger detection logic */
val = readl(base + UTMIP_BAT_CHRG_CFG0);
val &= ~(UTMIP_OP_SRC_EN | UTMIP_ON_SINK_EN);
+ val &= ~(UTMIP_ON_SRC_EN | UTMIP_OP_SINK_EN);
writel(val, base + UTMIP_BAT_CHRG_CFG0);
/* Delay of 40 ms before we pull the D+ as per battery charger spec */
status = false;
disable_charger_detection(base);
}
+ DBG("%s(%d) inst:[%d], UTMIP_BAT_CHRG_CFG0 = %08X\n",
+ __func__, __LINE__,
+ phy->inst, readl(base + UTMIP_BAT_CHRG_CFG0));
+ DBG("%s(%d) inst:[%d], UTMIP_MISC_CFG0 = %08X\n",
+ __func__, __LINE__,
+ phy->inst, readl(base + UTMIP_MISC_CFG0));
+
DBG("%s(%d) inst:[%d] DONE Status = %d\n",
__func__, __LINE__, phy->inst, status);
+
+ return status;
+}
+
+static bool cdp_charger_detection(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ int status;
+ void __iomem *base = phy->regs;
+
+ /* SRC D- to D+ */
+ val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val &= ~(UTMIP_OP_SRC_EN | UTMIP_ON_SINK_EN);
+ val |= UTMIP_ON_SRC_EN | UTMIP_OP_SINK_EN;
+ writel(val, base + UTMIP_BAT_CHRG_CFG0);
+
+ DBG("%s(%d) UTMIP_BAT_CHRG_CFG0 = %08x\n",
+ __func__, __LINE__,
+ readl(base + UTMIP_BAT_CHRG_CFG0));
+
+ msleep(10);
+
+ val = readl(base + USB_PHY_VBUS_WAKEUP_ID);
+ if (val & VDAT_DET_STS) {
+ status = false;
+ DBG("%s: DCP detected\n", __func__);
+ } else {
+ status = true;
+ disable_charger_detection(base);
+ DBG("%s: No voltage from D- to D+ found\n", __func__);
+ }
+
return status;
}
int status;
int qc2_timeout_ms;
int vbus_stat = 0;
+ unsigned long org_flags;
#ifdef QC_MEASURE_VOLTAGES
int timeout;
#endif
__func__, __LINE__, phy->inst, max_voltage);
status = false;
-
/* no need to detect qc2 if operating at 5V */
switch (max_voltage) {
+ case TEGRA_USB_QC2_5V:
case TEGRA_USB_QC2_9V:
case TEGRA_USB_QC2_12V:
case TEGRA_USB_QC2_20V:
break;
-
- case TEGRA_USB_QC2_5V:
default:
disable_charger_detection(base);
return status;
}
+ /* Ensure we start from an initial state */
+ writel(0, base + UTMIP_BAT_CHRG_CFG0);
+ utmi_phy_set_dp_dm_pull_up_down(phy, 0);
+
+ /* Force wall charger detection logic to reset */
+ org_flags = utmi_phy_set_dp_dm_pull_up_down(phy,
+ FORCE_PULLDN_DP | FORCE_PULLDN_DM);
+ ssleep(1);
+ msleep(500);
+ utmi_phy_set_dp_dm_pull_up_down(phy, org_flags);
+
+ /* Enable charger detection logic */
+ val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val |= UTMIP_OP_SRC_EN | UTMIP_ON_SINK_EN;
+ writel(val, base + UTMIP_BAT_CHRG_CFG0);
+
+ /* Source should be on for 100 ms as per USB charging spec */
+ msleep(TDP_SRC_ON_MS);
+
/* if vbus drops we are connected to quick charge 2 */
qc2_timeout_ms = 0;
- while (qc2_timeout_ms < 2000) {
+ while (qc2_timeout_ms < 1500) {
usleep_range(1000, 1200);
qc2_timeout_ms += 1;
val = readl(base + USB_PHY_VBUS_WAKEUP_ID);
}
}
- if (vbus_stat) {
- unsigned long org_flags;
-
+ if (vbus_stat && qc2_timeout_ms > 100) {
status = true;
DBG("%s(%d) inst:[%d], QC2 DETECTED !!!",
__func__, __LINE__, phy->inst);
+ /* Wall charger needs time before setting D+/D- */
+ mdelay(25);
+
switch (max_voltage) {
case TEGRA_USB_QC2_9V:
/* Set the input voltage to 9V */
#endif
}
+ /*
+ * If QC2 charger detected do not disable the charger
+ * detection voltage on D- and D+. Doing this will
+ * cause it to move to 5V
+ */
+ if (!status)
+ disable_charger_detection(base);
- DBG("%s(%d) inst:[%d], UTMIP_BAT_CHRG_CFG0 = %08X\n",
- __func__, __LINE__,
- phy->inst, readl(base + UTMIP_BAT_CHRG_CFG0));
- DBG("%s(%d) inst:[%d], UTMIP_MISC_CFG0 = %08X\n",
- __func__, __LINE__,
- phy->inst, readl(base + UTMIP_MISC_CFG0));
-
- disable_charger_detection(base);
DBG("%s(%d) inst:[%d] DONE Status = %d\n",
__func__, __LINE__, phy->inst, status);
return status;
.post_resume = utmi_phy_post_resume,
.charger_detect = utmi_phy_charger_detect,
.qc2_charger_detect = utmi_phy_qc2_charger_detect,
+ .cdp_charger_detect = cdp_charger_detection,
.nv_charger_detect = utmi_phy_nv_charger_detect,
.apple_charger_1000ma_detect = utmi_phy_apple_charger_1000ma_detect,
.apple_charger_2000ma_detect = utmi_phy_apple_charger_2000ma_detect,