aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/s3c-hsotg.c
diff options
context:
space:
mode:
authorAnton Tikhomirov <av.tikhomirov@samsung.com>2011-04-21 04:06:39 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-05-02 20:00:25 -0400
commita3395f0dd016f18273eac8e689e1e81e075e025e (patch)
treecb0f2af4ce3b0e312e61b98133bc3d1c006f5be8 /drivers/usb/gadget/s3c-hsotg.c
parentd00f500400a6e309f9bc43d385572f395eba2871 (diff)
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/s3c-hsotg.c')
-rw-r--r--drivers/usb/gadget/s3c-hsotg.c58
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,
1775 u32 epctl_reg = dir_in ? S3C_DIEPCTL(idx) : S3C_DOEPCTL(idx); 1775 u32 epctl_reg = dir_in ? S3C_DIEPCTL(idx) : S3C_DOEPCTL(idx);
1776 u32 epsiz_reg = dir_in ? S3C_DIEPTSIZ(idx) : S3C_DOEPTSIZ(idx); 1776 u32 epsiz_reg = dir_in ? S3C_DIEPTSIZ(idx) : S3C_DOEPTSIZ(idx);
1777 u32 ints; 1777 u32 ints;
1778 u32 clear = 0;
1779 1778
1780 ints = readl(hsotg->regs + epint_reg); 1779 ints = readl(hsotg->regs + epint_reg);
1781 1780
1781 /* Clear endpoint interrupts */
1782 writel(ints, hsotg->regs + epint_reg);
1783
1782 dev_dbg(hsotg->dev, "%s: ep%d(%s) DxEPINT=0x%08x\n", 1784 dev_dbg(hsotg->dev, "%s: ep%d(%s) DxEPINT=0x%08x\n",
1783 __func__, idx, dir_in ? "in" : "out", ints); 1785 __func__, idx, dir_in ? "in" : "out", ints);
1784 1786
@@ -1801,19 +1803,13 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
1801 1803
1802 s3c_hsotg_handle_outdone(hsotg, idx, false); 1804 s3c_hsotg_handle_outdone(hsotg, idx, false);
1803 } 1805 }
1804
1805 clear |= S3C_DxEPINT_XferCompl;
1806 } 1806 }
1807 1807
1808 if (ints & S3C_DxEPINT_EPDisbld) { 1808 if (ints & S3C_DxEPINT_EPDisbld)
1809 dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__); 1809 dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__);
1810 clear |= S3C_DxEPINT_EPDisbld;
1811 }
1812 1810
1813 if (ints & S3C_DxEPINT_AHBErr) { 1811 if (ints & S3C_DxEPINT_AHBErr)
1814 dev_dbg(hsotg->dev, "%s: AHBErr\n", __func__); 1812 dev_dbg(hsotg->dev, "%s: AHBErr\n", __func__);
1815 clear |= S3C_DxEPINT_AHBErr;
1816 }
1817 1813
1818 if (ints & S3C_DxEPINT_Setup) { /* Setup or Timeout */ 1814 if (ints & S3C_DxEPINT_Setup) { /* Setup or Timeout */
1819 dev_dbg(hsotg->dev, "%s: Setup/Timeout\n", __func__); 1815 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,
1829 else 1825 else
1830 s3c_hsotg_handle_outdone(hsotg, 0, true); 1826 s3c_hsotg_handle_outdone(hsotg, 0, true);
1831 } 1827 }
1832
1833 clear |= S3C_DxEPINT_Setup;
1834 } 1828 }
1835 1829
1836 if (ints & S3C_DxEPINT_Back2BackSetup) { 1830 if (ints & S3C_DxEPINT_Back2BackSetup)
1837 dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__); 1831 dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__);
1838 clear |= S3C_DxEPINT_Back2BackSetup;
1839 }
1840 1832
1841 if (dir_in) { 1833 if (dir_in) {
1842 /* not sure if this is important, but we'll clear it anyway 1834 /* 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,
1844 if (ints & S3C_DIEPMSK_INTknTXFEmpMsk) { 1836 if (ints & S3C_DIEPMSK_INTknTXFEmpMsk) {
1845 dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n", 1837 dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n",
1846 __func__, idx); 1838 __func__, idx);
1847 clear |= S3C_DIEPMSK_INTknTXFEmpMsk;
1848 } 1839 }
1849 1840
1850 /* this probably means something bad is happening */ 1841 /* this probably means something bad is happening */
1851 if (ints & S3C_DIEPMSK_INTknEPMisMsk) { 1842 if (ints & S3C_DIEPMSK_INTknEPMisMsk) {
1852 dev_warn(hsotg->dev, "%s: ep%d: INTknEP\n", 1843 dev_warn(hsotg->dev, "%s: ep%d: INTknEP\n",
1853 __func__, idx); 1844 __func__, idx);
1854 clear |= S3C_DIEPMSK_INTknEPMisMsk;
1855 } 1845 }
1856 1846
1857 /* FIFO has space or is empty (see GAHBCFG) */ 1847 /* FIFO has space or is empty (see GAHBCFG) */
@@ -1860,11 +1850,8 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
1860 dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n", 1850 dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n",
1861 __func__, idx); 1851 __func__, idx);
1862 s3c_hsotg_trytx(hsotg, hs_ep); 1852 s3c_hsotg_trytx(hsotg, hs_ep);
1863 clear |= S3C_DIEPMSK_TxFIFOEmpty;
1864 } 1853 }
1865 } 1854 }
1866
1867 writel(clear, hsotg->regs + epint_reg);
1868} 1855}
1869 1856
1870/** 1857/**
@@ -2056,7 +2043,6 @@ irq_retry:
2056 dev_info(hsotg->dev, "OTGInt: %08x\n", otgint); 2043 dev_info(hsotg->dev, "OTGInt: %08x\n", otgint);
2057 2044
2058 writel(otgint, hsotg->regs + S3C_GOTGINT); 2045 writel(otgint, hsotg->regs + S3C_GOTGINT);
2059 writel(S3C_GINTSTS_OTGInt, hsotg->regs + S3C_GINTSTS);
2060 } 2046 }
2061 2047
2062 if (gintsts & S3C_GINTSTS_DisconnInt) { 2048 if (gintsts & S3C_GINTSTS_DisconnInt) {
@@ -2072,8 +2058,9 @@ irq_retry:
2072 } 2058 }
2073 2059
2074 if (gintsts & S3C_GINTSTS_EnumDone) { 2060 if (gintsts & S3C_GINTSTS_EnumDone) {
2075 s3c_hsotg_irq_enumdone(hsotg);
2076 writel(S3C_GINTSTS_EnumDone, hsotg->regs + S3C_GINTSTS); 2061 writel(S3C_GINTSTS_EnumDone, hsotg->regs + S3C_GINTSTS);
2062
2063 s3c_hsotg_irq_enumdone(hsotg);
2077 } 2064 }
2078 2065
2079 if (gintsts & S3C_GINTSTS_ConIDStsChng) { 2066 if (gintsts & S3C_GINTSTS_ConIDStsChng) {
@@ -2101,10 +2088,6 @@ irq_retry:
2101 if (daint_in & 1) 2088 if (daint_in & 1)
2102 s3c_hsotg_epint(hsotg, ep, 1); 2089 s3c_hsotg_epint(hsotg, ep, 1);
2103 } 2090 }
2104
2105 writel(daint, hsotg->regs + S3C_DAINT);
2106 writel(gintsts & (S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt),
2107 hsotg->regs + S3C_GINTSTS);
2108 } 2091 }
2109 2092
2110 if (gintsts & S3C_GINTSTS_USBRst) { 2093 if (gintsts & S3C_GINTSTS_USBRst) {
@@ -2112,6 +2095,8 @@ irq_retry:
2112 dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n", 2095 dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
2113 readl(hsotg->regs + S3C_GNPTXSTS)); 2096 readl(hsotg->regs + S3C_GNPTXSTS));
2114 2097
2098 writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS);
2099
2115 kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true); 2100 kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true);
2116 2101
2117 /* it seems after a reset we can end up with a situation 2102 /* it seems after a reset we can end up with a situation
@@ -2123,8 +2108,6 @@ irq_retry:
2123 s3c_hsotg_init_fifo(hsotg); 2108 s3c_hsotg_init_fifo(hsotg);
2124 2109
2125 s3c_hsotg_enqueue_setup(hsotg); 2110 s3c_hsotg_enqueue_setup(hsotg);
2126
2127 writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS);
2128 } 2111 }
2129 2112
2130 /* check both FIFOs */ 2113 /* check both FIFOs */
@@ -2138,8 +2121,6 @@ irq_retry:
2138 2121
2139 s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_NPTxFEmp); 2122 s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_NPTxFEmp);
2140 s3c_hsotg_irq_fifoempty(hsotg, false); 2123 s3c_hsotg_irq_fifoempty(hsotg, false);
2141
2142 writel(S3C_GINTSTS_NPTxFEmp, hsotg->regs + S3C_GINTSTS);
2143 } 2124 }
2144 2125
2145 if (gintsts & S3C_GINTSTS_PTxFEmp) { 2126 if (gintsts & S3C_GINTSTS_PTxFEmp) {
@@ -2149,8 +2130,6 @@ irq_retry:
2149 2130
2150 s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_PTxFEmp); 2131 s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_PTxFEmp);
2151 s3c_hsotg_irq_fifoempty(hsotg, true); 2132 s3c_hsotg_irq_fifoempty(hsotg, true);
2152
2153 writel(S3C_GINTSTS_PTxFEmp, hsotg->regs + S3C_GINTSTS);
2154 } 2133 }
2155 2134
2156 if (gintsts & S3C_GINTSTS_RxFLvl) { 2135 if (gintsts & S3C_GINTSTS_RxFLvl) {
@@ -2159,7 +2138,6 @@ irq_retry:
2159 * set. */ 2138 * set. */
2160 2139
2161 s3c_hsotg_handle_rx(hsotg); 2140 s3c_hsotg_handle_rx(hsotg);
2162 writel(S3C_GINTSTS_RxFLvl, hsotg->regs + S3C_GINTSTS);
2163 } 2141 }
2164 2142
2165 if (gintsts & S3C_GINTSTS_ModeMis) { 2143 if (gintsts & S3C_GINTSTS_ModeMis) {
@@ -2193,19 +2171,17 @@ irq_retry:
2193 if (gintsts & S3C_GINTSTS_GOUTNakEff) { 2171 if (gintsts & S3C_GINTSTS_GOUTNakEff) {
2194 dev_info(hsotg->dev, "GOUTNakEff triggered\n"); 2172 dev_info(hsotg->dev, "GOUTNakEff triggered\n");
2195 2173
2196 s3c_hsotg_dump(hsotg);
2197
2198 writel(S3C_DCTL_CGOUTNak, hsotg->regs + S3C_DCTL); 2174 writel(S3C_DCTL_CGOUTNak, hsotg->regs + S3C_DCTL);
2199 writel(S3C_GINTSTS_GOUTNakEff, hsotg->regs + S3C_GINTSTS); 2175
2176 s3c_hsotg_dump(hsotg);
2200 } 2177 }
2201 2178
2202 if (gintsts & S3C_GINTSTS_GINNakEff) { 2179 if (gintsts & S3C_GINTSTS_GINNakEff) {
2203 dev_info(hsotg->dev, "GINNakEff triggered\n"); 2180 dev_info(hsotg->dev, "GINNakEff triggered\n");
2204 2181
2205 s3c_hsotg_dump(hsotg);
2206
2207 writel(S3C_DCTL_CGNPInNAK, hsotg->regs + S3C_DCTL); 2182 writel(S3C_DCTL_CGNPInNAK, hsotg->regs + S3C_DCTL);
2208 writel(S3C_GINTSTS_GINNakEff, hsotg->regs + S3C_GINTSTS); 2183
2184 s3c_hsotg_dump(hsotg);
2209 } 2185 }
2210 2186
2211 /* if we've had fifo events, we should try and go around the 2187 /* 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,
2585 2561
2586 writel(1 << 18 | S3C_DCFG_DevSpd_HS, hsotg->regs + S3C_DCFG); 2562 writel(1 << 18 | S3C_DCFG_DevSpd_HS, hsotg->regs + S3C_DCFG);
2587 2563
2564 /* Clear any pending OTG interrupts */
2565 writel(0xffffffff, hsotg->regs + S3C_GOTGINT);
2566
2567 /* Clear any pending interrupts */
2568 writel(0xffffffff, hsotg->regs + S3C_GINTSTS);
2569
2588 writel(S3C_GINTSTS_DisconnInt | S3C_GINTSTS_SessReqInt | 2570 writel(S3C_GINTSTS_DisconnInt | S3C_GINTSTS_SessReqInt |
2589 S3C_GINTSTS_ConIDStsChng | S3C_GINTSTS_USBRst | 2571 S3C_GINTSTS_ConIDStsChng | S3C_GINTSTS_USBRst |
2590 S3C_GINTSTS_EnumDone | S3C_GINTSTS_OTGInt | 2572 S3C_GINTSTS_EnumDone | S3C_GINTSTS_OTGInt |