diff options
Diffstat (limited to 'drivers/usb/otg/fsl_otg.c')
-rw-r--r-- | drivers/usb/otg/fsl_otg.c | 39 |
1 files changed, 17 insertions, 22 deletions
diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c index eccd173b33e4..e32d7cab828e 100644 --- a/drivers/usb/otg/fsl_otg.c +++ b/drivers/usb/otg/fsl_otg.c @@ -445,8 +445,16 @@ static void fsl_otg_loading_monitor(unsigned long data) */ static void b_session_irq_enable(bool enable) { - int osc = le32_to_cpu(usb_dr_regs->otgsc); - pr_debug("%s:enable=%d", __func__, enable); + u32 osc; + fsl_otg_clk_gate(true); + if (le32_to_cpu(usb_dr_regs->portsc) & PORTSC_PHY_LOW_POWER_SPD) { + pr_debug("%s: the usb is in low power mode, vbus should not changed \n", __func__); + fsl_otg_clk_gate(false); + return; + } + + osc = le32_to_cpu(usb_dr_regs->otgsc); + pr_debug("%s:otgsc=0x%x", __func__, osc); /* The other interrupts' status should not be cleared */ osc &= ~(OTGSC_INTSTS_USB_ID | OTGSC_INTSTS_A_VBUS_VALID | OTGSC_INTSTS_A_SESSION_VALID | OTGSC_INTSTS_B_SESSION_VALID); @@ -456,6 +464,7 @@ static void b_session_irq_enable(bool enable) else osc &= ~OTGSC_INTR_B_SESSION_VALID_EN; usb_dr_regs->otgsc = cpu_to_le32(osc); + fsl_otg_clk_gate(false); } /* Reset controller, not reset the bus */ @@ -489,8 +498,11 @@ int fsl_otg_start_host(struct otg_fsm *fsm, int on) /* Update a_vbus_vld state as a_vbus_vld int is disabled * in device mode */ + fsl_otg_clk_gate(true); fsm->a_vbus_vld = (le32_to_cpu(usb_dr_regs->otgsc) & OTGSC_STS_A_VBUS_VALID) ? 1 : 0; + fsl_otg_clk_gate(false); + if (on) { /* start fsl usb host controller */ if (otg_dev->host_working) @@ -666,14 +678,6 @@ static int fsl_otg_set_peripheral(struct otg_transceiver *otg_p, if (otg_dev->fsm.id == 1) { fsl_otg_start_host(&otg_dev->fsm, 0); otg_drv_vbus(&otg_dev->fsm, 0); - /* Clear OTGSC_INTSTS_B_SESSION_VALID - * When the host driver loads, the vbus may change to 5v for some - * SoC's. But when there is no usb device at host port, the vbus - * will be off, in that case, vbus changes status will be set. - */ - fsl_otg_clk_gate(true); - b_session_irq_enable(false); - fsl_otg_clk_gate(false); fsl_otg_start_gadget(&otg_dev->fsm, 1); } @@ -707,6 +711,7 @@ static void fsl_otg_event(struct work_struct *work) struct otg_transceiver *otg = &og->otg; mutex_lock(&pm_mutex); + b_session_irq_enable(false); otg->default_a = (fsm->id == 0); /* clear conn information */ if (fsm->id) @@ -722,10 +727,12 @@ static void fsl_otg_event(struct work_struct *work) if (fsm->id) { /* switch to gadget */ fsl_otg_start_host(fsm, 0); otg_drv_vbus(fsm, 0); + b_session_irq_enable(false); fsl_otg_start_gadget(fsm, 1); } else { /* switch to host */ fsl_otg_start_gadget(fsm, 0); otg_drv_vbus(fsm, 1); + b_session_irq_enable(false); fsl_otg_start_host(fsm, 1); } mutex_unlock(&pm_mutex); @@ -791,12 +798,6 @@ irqreturn_t fsl_otg_isr_gpio(int irq, void *dev_id) cancel_delayed_work(&f_otg->otg_event); schedule_otg_work(&f_otg->otg_event, msecs_to_jiffies(10)); - /* if host mode, we should clear B_SESSION_VLD event and disable - * B_SESSION_VLD irq - */ - if (!f_otg->fsm.id) { - b_session_irq_enable(false); - } return IRQ_HANDLED; } @@ -841,12 +842,6 @@ irqreturn_t fsl_otg_isr(int irq, void *dev_id) cancel_delayed_work(&fotg->otg_event); schedule_otg_work(&fotg->otg_event, msecs_to_jiffies(10)); - /* if host mode, we should clear B_SESSION_VLD event and disable - * B_SESSION_VLD irq - */ - if (!fotg->fsm.id) { - b_session_irq_enable(false); - } ret = IRQ_HANDLED; } } |