mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
USB: msm_otg: Check ID state before entering into LPM
Fix a possible bug where id interrupt is not monitored during ID detection circuit switch between ACA and PMIC. This can happen during quick Micro-A cable reconnection. (cherry picked from commit becab5ba0d6a342612ff31ff9514e324f2f02517) CRs-Fixed: 404516 Change-Id: I7e7edda54d1a9f5c4334cab1c48413c7461df2f1 Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org> Signed-off-by: Neha Pandey <nehap@codeaurora.org>
This commit is contained in:
parent
e4d7ef596b
commit
d4bc4c74ff
1 changed files with 35 additions and 12 deletions
|
@ -1457,6 +1457,26 @@ static int msm_otg_set_peripheral(struct usb_otg *otg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool msm_otg_read_pmic_id_state(struct msm_otg *motg)
|
||||
{
|
||||
unsigned long flags;
|
||||
int id;
|
||||
|
||||
if (!motg->pdata->pmic_id_irq)
|
||||
return -ENODEV;
|
||||
|
||||
local_irq_save(flags);
|
||||
id = irq_read_line(motg->pdata->pmic_id_irq);
|
||||
local_irq_restore(flags);
|
||||
|
||||
/*
|
||||
* If we can not read ID line state for some reason, treat
|
||||
* it as float. This would prevent MHL discovery and kicking
|
||||
* host mode unnecessarily.
|
||||
*/
|
||||
return !!id;
|
||||
}
|
||||
|
||||
static int msm_otg_mhl_register_callback(struct msm_otg *motg,
|
||||
void (*callback)(int on))
|
||||
{
|
||||
|
@ -1534,14 +1554,11 @@ static bool msm_otg_is_mhl(struct msm_otg *motg)
|
|||
static bool msm_chg_mhl_detect(struct msm_otg *motg)
|
||||
{
|
||||
bool ret, id;
|
||||
unsigned long flags;
|
||||
|
||||
if (!motg->mhl_enabled)
|
||||
return false;
|
||||
|
||||
local_irq_save(flags);
|
||||
id = irq_read_line(motg->pdata->pmic_id_irq);
|
||||
local_irq_restore(flags);
|
||||
id = msm_otg_read_pmic_id_state(motg);
|
||||
|
||||
if (id)
|
||||
return false;
|
||||
|
@ -2186,13 +2203,10 @@ static void msm_otg_init_sm(struct msm_otg *motg)
|
|||
clear_bit(B_SESS_VLD, &motg->inputs);
|
||||
} else if (pdata->otg_control == OTG_PMIC_CONTROL) {
|
||||
if (pdata->pmic_id_irq) {
|
||||
unsigned long flags;
|
||||
local_irq_save(flags);
|
||||
if (irq_read_line(pdata->pmic_id_irq))
|
||||
if (msm_otg_read_pmic_id_state(motg))
|
||||
set_bit(ID, &motg->inputs);
|
||||
else
|
||||
clear_bit(ID, &motg->inputs);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
/*
|
||||
* VBUS initial state is reported after PMIC
|
||||
|
@ -2343,6 +2357,18 @@ static void msm_otg_sm_work(struct work_struct *w)
|
|||
motg->chg_type = USB_INVALID_CHARGER;
|
||||
msm_otg_notify_charger(motg, 0);
|
||||
msm_otg_reset(otg->phy);
|
||||
/*
|
||||
* There is a small window where ID interrupt
|
||||
* is not monitored during ID detection circuit
|
||||
* switch from ACA to PMIC. Check ID state
|
||||
* before entering into low power mode.
|
||||
*/
|
||||
if (!msm_otg_read_pmic_id_state(motg)) {
|
||||
pr_debug("process missed ID intr\n");
|
||||
clear_bit(ID, &motg->inputs);
|
||||
work = 1;
|
||||
break;
|
||||
}
|
||||
pm_runtime_put_noidle(otg->phy->dev);
|
||||
pm_runtime_suspend(otg->phy->dev);
|
||||
}
|
||||
|
@ -2994,10 +3020,8 @@ static void msm_pmic_id_status_w(struct work_struct *w)
|
|||
struct msm_otg *motg = container_of(w, struct msm_otg,
|
||||
pmic_id_status_work.work);
|
||||
int work = 0;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
if (irq_read_line(motg->pdata->pmic_id_irq)) {
|
||||
if (msm_otg_read_pmic_id_state(motg)) {
|
||||
if (!test_and_set_bit(ID, &motg->inputs)) {
|
||||
pr_debug("PMIC: ID set\n");
|
||||
work = 1;
|
||||
|
@ -3016,7 +3040,6 @@ static void msm_pmic_id_status_w(struct work_struct *w)
|
|||
else
|
||||
queue_work(system_nrt_wq, &motg->sm_work);
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue