diff options
author | Peter Chen <peter.chen@freescale.com> | 2013-08-14 12:44:11 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-08-14 12:37:20 -0700 |
commit | a107f8c505cd8606ae192d24c70b380e980fbe67 (patch) | |
tree | c1451c9051588fe93537c83c034d62def233ed8f /drivers/usb/chipidea/core.c | |
parent | cbec6bd55a45fa88218ec5ea5ae91f9b96d158d0 (diff) | |
download | talos-obmc-linux-a107f8c505cd8606ae192d24c70b380e980fbe67.tar.gz talos-obmc-linux-a107f8c505cd8606ae192d24c70b380e980fbe67.zip |
usb: chipidea: add vbus interrupt handler
We add vbus interrupt handler at ci_otg_work, it uses OTGSC_BSV(at otgsc)
to know it is connect or disconnet event.
Meanwhile, we introduce two flags id_event and b_sess_valid_event to
indicate it is an id interrupt or a vbus interrupt.
Tested-by: Marek Vasut <marex@denx.de>
Signed-off-by: Peter Chen <peter.chen@freescale.com>
Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/chipidea/core.c')
-rw-r--r-- | drivers/usb/chipidea/core.c | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index ec6c984d2a6e..c95e098fe9db 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -303,16 +303,34 @@ static irqreturn_t ci_irq(int irq, void *data) if (ci->is_otg) otgsc = hw_read(ci, OP_OTGSC, ~0); - if (ci->role != CI_ROLE_END) - ret = ci_role(ci)->irq(ci); + /* + * Handle id change interrupt, it indicates device/host function + * switch. + */ + if (ci->is_otg && (otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS)) { + ci->id_event = true; + ci_clear_otg_interrupt(ci, OTGSC_IDIS); + disable_irq_nosync(ci->irq); + queue_work(ci->wq, &ci->work); + return IRQ_HANDLED; + } - if (ci->is_otg && (otgsc & OTGSC_IDIS)) { - hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS); + /* + * Handle vbus change interrupt, it indicates device connection + * and disconnection events. + */ + if (ci->is_otg && (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS)) { + ci->b_sess_valid_event = true; + ci_clear_otg_interrupt(ci, OTGSC_BSVIS); disable_irq_nosync(ci->irq); queue_work(ci->wq, &ci->work); - ret = IRQ_HANDLED; + return IRQ_HANDLED; } + /* Handle device/host interrupt */ + if (ci->role != CI_ROLE_END) + ret = ci_role(ci)->irq(ci); + return ret; } |