aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/renesas_usbhs
diff options
context:
space:
mode:
authorShimoda, Yoshihiro <yoshihiro.shimoda.uh@renesas.com>2012-08-20 05:39:23 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-09-05 19:52:08 -0400
commit697d5c004e390102efbf9320a5416873679bea81 (patch)
treedc707dc867027cb53a8014ab41b02fcca85d8a7b /drivers/usb/renesas_usbhs
parent47c56a1479373d46f90d2e301869b9952f632451 (diff)
usb: renesas_usbhs: modify the irq handler for sharing irq
When IORESOURCE_IRQ_SHAREABLE is set, the irq handler may be called even if the interupt of the USB module doesn't happen. So, it may clear the interrupt flags by mistake. This patch fixes it. Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/renesas_usbhs')
-rw-r--r--drivers/usb/renesas_usbhs/mod.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c
index 82a628f96c03..35c5208f3249 100644
--- a/drivers/usb/renesas_usbhs/mod.c
+++ b/drivers/usb/renesas_usbhs/mod.c
@@ -209,14 +209,18 @@ int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state)
209 return (int)irq_state->intsts0 & CTSQ_MASK; 209 return (int)irq_state->intsts0 & CTSQ_MASK;
210} 210}
211 211
212static void usbhs_status_get_each_irq(struct usbhs_priv *priv, 212static int usbhs_status_get_each_irq(struct usbhs_priv *priv,
213 struct usbhs_irq_state *state) 213 struct usbhs_irq_state *state)
214{ 214{
215 struct usbhs_mod *mod = usbhs_mod_get_current(priv); 215 struct usbhs_mod *mod = usbhs_mod_get_current(priv);
216 u16 intenb0, intenb1;
216 217
217 state->intsts0 = usbhs_read(priv, INTSTS0); 218 state->intsts0 = usbhs_read(priv, INTSTS0);
218 state->intsts1 = usbhs_read(priv, INTSTS1); 219 state->intsts1 = usbhs_read(priv, INTSTS1);
219 220
221 intenb0 = usbhs_read(priv, INTENB0);
222 intenb1 = usbhs_read(priv, INTENB1);
223
220 /* mask */ 224 /* mask */
221 if (mod) { 225 if (mod) {
222 state->brdysts = usbhs_read(priv, BRDYSTS); 226 state->brdysts = usbhs_read(priv, BRDYSTS);
@@ -226,6 +230,20 @@ static void usbhs_status_get_each_irq(struct usbhs_priv *priv,
226 state->bempsts &= mod->irq_bempsts; 230 state->bempsts &= mod->irq_bempsts;
227 state->brdysts &= mod->irq_brdysts; 231 state->brdysts &= mod->irq_brdysts;
228 } 232 }
233
234 /*
235 * Check whether the irq enable registers and the irq status are set
236 * when IRQF_SHARED is set.
237 */
238 if (priv->irqflags & IRQF_SHARED) {
239 if (!(intenb0 & state->intsts0) &&
240 !(intenb1 & state->intsts1) &&
241 !(state->bempsts) &&
242 !(state->brdysts))
243 return -EIO;
244 }
245
246 return 0;
229} 247}
230 248
231/* 249/*
@@ -238,7 +256,8 @@ static irqreturn_t usbhs_interrupt(int irq, void *data)
238 struct usbhs_priv *priv = data; 256 struct usbhs_priv *priv = data;
239 struct usbhs_irq_state irq_state; 257 struct usbhs_irq_state irq_state;
240 258
241 usbhs_status_get_each_irq(priv, &irq_state); 259 if (usbhs_status_get_each_irq(priv, &irq_state) < 0)
260 return IRQ_NONE;
242 261
243 /* 262 /*
244 * clear interrupt 263 * clear interrupt