diff options
author | Anton Tikhomirov <av.tikhomirov@samsung.com> | 2011-04-21 04:06:39 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-05-02 20:00:25 -0400 |
commit | a3395f0dd016f18273eac8e689e1e81e075e025e (patch) | |
tree | cb0f2af4ce3b0e312e61b98133bc3d1c006f5be8 /drivers/usb/gadget/s3c-hsotg.c | |
parent | d00f500400a6e309f9bc43d385572f395eba2871 (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.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, | |||
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 | |