diff options
author | Anton Tikhomirov <av.tikhomirov@samsung.com> | 2011-04-21 17:06:39 +0900 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-05-02 17:00:25 -0700 |
commit | a3395f0dd016f18273eac8e689e1e81e075e025e (patch) | |
tree | cb0f2af4ce3b0e312e61b98133bc3d1c006f5be8 /drivers/usb/gadget | |
parent | d00f500400a6e309f9bc43d385572f395eba2871 (diff) | |
download | linux-a3395f0dd016f18273eac8e689e1e81e075e025e.tar.gz linux-a3395f0dd016f18273eac8e689e1e81e075e025e.tar.bz2 linux-a3395f0dd016f18273eac8e689e1e81e075e025e.zip |
USB: s3c-hsotg: Fix interrupt cleaning code
This commit does the following:
1) clears all pending interrupts before unmasking;
2) clears interrupts as soon as possible to avoid missing
next coming that may occur during handling;
3) removes ineffective interrupt cleaning code.
Signed-off-by: Anton Tikhomirov <av.tikhomirov@samsung.com>
Reviewed-by: Kyoungil Kim<ki0351.kim@samsung.com>
Cc: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/s3c-hsotg.c | 58 |
1 files changed, 20 insertions, 38 deletions
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 7cd597ca162f..d7a279bb51dc 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -1775,10 +1775,12 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, u32 epctl_reg = dir_in ? S3C_DIEPCTL(idx) : S3C_DOEPCTL(idx); u32 epsiz_reg = dir_in ? S3C_DIEPTSIZ(idx) : S3C_DOEPTSIZ(idx); u32 ints; - u32 clear = 0; ints = readl(hsotg->regs + epint_reg); + /* Clear endpoint interrupts */ + writel(ints, hsotg->regs + epint_reg); + dev_dbg(hsotg->dev, "%s: ep%d(%s) DxEPINT=0x%08x\n", __func__, idx, dir_in ? "in" : "out", ints); @@ -1801,19 +1803,13 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, s3c_hsotg_handle_outdone(hsotg, idx, false); } - - clear |= S3C_DxEPINT_XferCompl; } - if (ints & S3C_DxEPINT_EPDisbld) { + if (ints & S3C_DxEPINT_EPDisbld) dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__); - clear |= S3C_DxEPINT_EPDisbld; - } - if (ints & S3C_DxEPINT_AHBErr) { + if (ints & S3C_DxEPINT_AHBErr) dev_dbg(hsotg->dev, "%s: AHBErr\n", __func__); - clear |= S3C_DxEPINT_AHBErr; - } if (ints & S3C_DxEPINT_Setup) { /* Setup or Timeout */ dev_dbg(hsotg->dev, "%s: Setup/Timeout\n", __func__); @@ -1829,14 +1825,10 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, else s3c_hsotg_handle_outdone(hsotg, 0, true); } - - clear |= S3C_DxEPINT_Setup; } - if (ints & S3C_DxEPINT_Back2BackSetup) { + if (ints & S3C_DxEPINT_Back2BackSetup) dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__); - clear |= S3C_DxEPINT_Back2BackSetup; - } if (dir_in) { /* not sure if this is important, but we'll clear it anyway @@ -1844,14 +1836,12 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, if (ints & S3C_DIEPMSK_INTknTXFEmpMsk) { dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n", __func__, idx); - clear |= S3C_DIEPMSK_INTknTXFEmpMsk; } /* this probably means something bad is happening */ if (ints & S3C_DIEPMSK_INTknEPMisMsk) { dev_warn(hsotg->dev, "%s: ep%d: INTknEP\n", __func__, idx); - clear |= S3C_DIEPMSK_INTknEPMisMsk; } /* FIFO has space or is empty (see GAHBCFG) */ @@ -1860,11 +1850,8 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n", __func__, idx); s3c_hsotg_trytx(hsotg, hs_ep); - clear |= S3C_DIEPMSK_TxFIFOEmpty; } } - - writel(clear, hsotg->regs + epint_reg); } /** @@ -2056,7 +2043,6 @@ irq_retry: dev_info(hsotg->dev, "OTGInt: %08x\n", otgint); writel(otgint, hsotg->regs + S3C_GOTGINT); - writel(S3C_GINTSTS_OTGInt, hsotg->regs + S3C_GINTSTS); } if (gintsts & S3C_GINTSTS_DisconnInt) { @@ -2072,8 +2058,9 @@ irq_retry: } if (gintsts & S3C_GINTSTS_EnumDone) { - s3c_hsotg_irq_enumdone(hsotg); writel(S3C_GINTSTS_EnumDone, hsotg->regs + S3C_GINTSTS); + + s3c_hsotg_irq_enumdone(hsotg); } if (gintsts & S3C_GINTSTS_ConIDStsChng) { @@ -2101,10 +2088,6 @@ irq_retry: if (daint_in & 1) s3c_hsotg_epint(hsotg, ep, 1); } - - writel(daint, hsotg->regs + S3C_DAINT); - writel(gintsts & (S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt), - hsotg->regs + S3C_GINTSTS); } if (gintsts & S3C_GINTSTS_USBRst) { @@ -2112,6 +2095,8 @@ irq_retry: dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n", readl(hsotg->regs + S3C_GNPTXSTS)); + writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS); + kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true); /* it seems after a reset we can end up with a situation @@ -2123,8 +2108,6 @@ irq_retry: s3c_hsotg_init_fifo(hsotg); s3c_hsotg_enqueue_setup(hsotg); - - writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS); } /* check both FIFOs */ @@ -2138,8 +2121,6 @@ irq_retry: s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_NPTxFEmp); s3c_hsotg_irq_fifoempty(hsotg, false); - - writel(S3C_GINTSTS_NPTxFEmp, hsotg->regs + S3C_GINTSTS); } if (gintsts & S3C_GINTSTS_PTxFEmp) { @@ -2149,8 +2130,6 @@ irq_retry: s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_PTxFEmp); s3c_hsotg_irq_fifoempty(hsotg, true); - - writel(S3C_GINTSTS_PTxFEmp, hsotg->regs + S3C_GINTSTS); } if (gintsts & S3C_GINTSTS_RxFLvl) { @@ -2159,7 +2138,6 @@ irq_retry: * set. */ s3c_hsotg_handle_rx(hsotg); - writel(S3C_GINTSTS_RxFLvl, hsotg->regs + S3C_GINTSTS); } if (gintsts & S3C_GINTSTS_ModeMis) { @@ -2193,19 +2171,17 @@ irq_retry: if (gintsts & S3C_GINTSTS_GOUTNakEff) { dev_info(hsotg->dev, "GOUTNakEff triggered\n"); - s3c_hsotg_dump(hsotg); - writel(S3C_DCTL_CGOUTNak, hsotg->regs + S3C_DCTL); - writel(S3C_GINTSTS_GOUTNakEff, hsotg->regs + S3C_GINTSTS); + + s3c_hsotg_dump(hsotg); } if (gintsts & S3C_GINTSTS_GINNakEff) { dev_info(hsotg->dev, "GINNakEff triggered\n"); - s3c_hsotg_dump(hsotg); - writel(S3C_DCTL_CGNPInNAK, hsotg->regs + S3C_DCTL); - writel(S3C_GINTSTS_GINNakEff, hsotg->regs + S3C_GINTSTS); + + s3c_hsotg_dump(hsotg); } /* if we've had fifo events, we should try and go around the @@ -2585,6 +2561,12 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, writel(1 << 18 | S3C_DCFG_DevSpd_HS, hsotg->regs + S3C_DCFG); + /* Clear any pending OTG interrupts */ + writel(0xffffffff, hsotg->regs + S3C_GOTGINT); + + /* Clear any pending interrupts */ + writel(0xffffffff, hsotg->regs + S3C_GINTSTS); + writel(S3C_GINTSTS_DisconnInt | S3C_GINTSTS_SessReqInt | S3C_GINTSTS_ConIDStsChng | S3C_GINTSTS_USBRst | S3C_GINTSTS_EnumDone | S3C_GINTSTS_OTGInt | |