diff options
Diffstat (limited to 'drivers/usb/gadget/s3c-hsotg.c')
-rw-r--r-- | drivers/usb/gadget/s3c-hsotg.c | 235 |
1 files changed, 146 insertions, 89 deletions
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 0912679de99a..acb9cc418df9 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c | |||
@@ -1,5 +1,8 @@ | |||
1 | /* linux/drivers/usb/gadget/s3c-hsotg.c | 1 | /* linux/drivers/usb/gadget/s3c-hsotg.c |
2 | * | 2 | * |
3 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | 6 | * Copyright 2008 Openmoko, Inc. |
4 | * Copyright 2008 Simtec Electronics | 7 | * Copyright 2008 Simtec Electronics |
5 | * Ben Dooks <ben@simtec.co.uk> | 8 | * Ben Dooks <ben@simtec.co.uk> |
@@ -613,11 +616,10 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep) | |||
613 | maxpkt = S3C_DxEPTSIZ_PktCnt_LIMIT + 1; | 616 | maxpkt = S3C_DxEPTSIZ_PktCnt_LIMIT + 1; |
614 | } else { | 617 | } else { |
615 | maxsize = 64+64; | 618 | maxsize = 64+64; |
616 | if (hs_ep->dir_in) { | 619 | if (hs_ep->dir_in) |
617 | maxpkt = S3C_DIEPTSIZ0_PktCnt_LIMIT + 1; | 620 | maxpkt = S3C_DIEPTSIZ0_PktCnt_LIMIT + 1; |
618 | } else { | 621 | else |
619 | maxpkt = 2; | 622 | maxpkt = 2; |
620 | } | ||
621 | } | 623 | } |
622 | 624 | ||
623 | /* we made the constant loading easier above by using +1 */ | 625 | /* we made the constant loading easier above by using +1 */ |
@@ -679,6 +681,14 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, | |||
679 | __func__, readl(hsotg->regs + epctrl_reg), index, | 681 | __func__, readl(hsotg->regs + epctrl_reg), index, |
680 | hs_ep->dir_in ? "in" : "out"); | 682 | hs_ep->dir_in ? "in" : "out"); |
681 | 683 | ||
684 | /* If endpoint is stalled, we will restart request later */ | ||
685 | ctrl = readl(hsotg->regs + epctrl_reg); | ||
686 | |||
687 | if (ctrl & S3C_DxEPCTL_Stall) { | ||
688 | dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index); | ||
689 | return; | ||
690 | } | ||
691 | |||
682 | length = ureq->length - ureq->actual; | 692 | length = ureq->length - ureq->actual; |
683 | 693 | ||
684 | if (0) | 694 | if (0) |
@@ -731,18 +741,6 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, | |||
731 | /* write size / packets */ | 741 | /* write size / packets */ |
732 | writel(epsize, hsotg->regs + epsize_reg); | 742 | writel(epsize, hsotg->regs + epsize_reg); |
733 | 743 | ||
734 | ctrl = readl(hsotg->regs + epctrl_reg); | ||
735 | |||
736 | if (ctrl & S3C_DxEPCTL_Stall) { | ||
737 | dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index); | ||
738 | |||
739 | /* not sure what we can do here, if it is EP0 then we should | ||
740 | * get this cleared once the endpoint has transmitted the | ||
741 | * STALL packet, otherwise it needs to be cleared by the | ||
742 | * host. | ||
743 | */ | ||
744 | } | ||
745 | |||
746 | if (using_dma(hsotg)) { | 744 | if (using_dma(hsotg)) { |
747 | unsigned int dma_reg; | 745 | unsigned int dma_reg; |
748 | 746 | ||
@@ -1048,6 +1046,20 @@ static int s3c_hsotg_process_req_status(struct s3c_hsotg *hsotg, | |||
1048 | static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value); | 1046 | static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value); |
1049 | 1047 | ||
1050 | /** | 1048 | /** |
1049 | * get_ep_head - return the first request on the endpoint | ||
1050 | * @hs_ep: The controller endpoint to get | ||
1051 | * | ||
1052 | * Get the first request on the endpoint. | ||
1053 | */ | ||
1054 | static struct s3c_hsotg_req *get_ep_head(struct s3c_hsotg_ep *hs_ep) | ||
1055 | { | ||
1056 | if (list_empty(&hs_ep->queue)) | ||
1057 | return NULL; | ||
1058 | |||
1059 | return list_first_entry(&hs_ep->queue, struct s3c_hsotg_req, queue); | ||
1060 | } | ||
1061 | |||
1062 | /** | ||
1051 | * s3c_hsotg_process_req_featire - process request {SET,CLEAR}_FEATURE | 1063 | * s3c_hsotg_process_req_featire - process request {SET,CLEAR}_FEATURE |
1052 | * @hsotg: The device state | 1064 | * @hsotg: The device state |
1053 | * @ctrl: USB control request | 1065 | * @ctrl: USB control request |
@@ -1055,8 +1067,12 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value); | |||
1055 | static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg, | 1067 | static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg, |
1056 | struct usb_ctrlrequest *ctrl) | 1068 | struct usb_ctrlrequest *ctrl) |
1057 | { | 1069 | { |
1070 | struct s3c_hsotg_ep *ep0 = &hsotg->eps[0]; | ||
1071 | struct s3c_hsotg_req *hs_req; | ||
1072 | bool restart; | ||
1058 | bool set = (ctrl->bRequest == USB_REQ_SET_FEATURE); | 1073 | bool set = (ctrl->bRequest == USB_REQ_SET_FEATURE); |
1059 | struct s3c_hsotg_ep *ep; | 1074 | struct s3c_hsotg_ep *ep; |
1075 | int ret; | ||
1060 | 1076 | ||
1061 | dev_dbg(hsotg->dev, "%s: %s_FEATURE\n", | 1077 | dev_dbg(hsotg->dev, "%s: %s_FEATURE\n", |
1062 | __func__, set ? "SET" : "CLEAR"); | 1078 | __func__, set ? "SET" : "CLEAR"); |
@@ -1072,6 +1088,36 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg, | |||
1072 | switch (le16_to_cpu(ctrl->wValue)) { | 1088 | switch (le16_to_cpu(ctrl->wValue)) { |
1073 | case USB_ENDPOINT_HALT: | 1089 | case USB_ENDPOINT_HALT: |
1074 | s3c_hsotg_ep_sethalt(&ep->ep, set); | 1090 | s3c_hsotg_ep_sethalt(&ep->ep, set); |
1091 | |||
1092 | ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0); | ||
1093 | if (ret) { | ||
1094 | dev_err(hsotg->dev, | ||
1095 | "%s: failed to send reply\n", __func__); | ||
1096 | return ret; | ||
1097 | } | ||
1098 | |||
1099 | if (!set) { | ||
1100 | /* | ||
1101 | * If we have request in progress, | ||
1102 | * then complete it | ||
1103 | */ | ||
1104 | if (ep->req) { | ||
1105 | hs_req = ep->req; | ||
1106 | ep->req = NULL; | ||
1107 | list_del_init(&hs_req->queue); | ||
1108 | hs_req->req.complete(&ep->ep, | ||
1109 | &hs_req->req); | ||
1110 | } | ||
1111 | |||
1112 | /* If we have pending request, then start it */ | ||
1113 | restart = !list_empty(&ep->queue); | ||
1114 | if (restart) { | ||
1115 | hs_req = get_ep_head(ep); | ||
1116 | s3c_hsotg_start_req(hsotg, ep, | ||
1117 | hs_req, false); | ||
1118 | } | ||
1119 | } | ||
1120 | |||
1075 | break; | 1121 | break; |
1076 | 1122 | ||
1077 | default: | 1123 | default: |
@@ -1148,14 +1194,6 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, | |||
1148 | dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret); | 1194 | dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret); |
1149 | } | 1195 | } |
1150 | 1196 | ||
1151 | if (ret > 0) { | ||
1152 | if (!ep0->dir_in) { | ||
1153 | /* need to generate zlp in reply or take data */ | ||
1154 | /* todo - deal with any data we might be sent? */ | ||
1155 | ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0); | ||
1156 | } | ||
1157 | } | ||
1158 | |||
1159 | /* the request is either unhandlable, or is not formatted correctly | 1197 | /* the request is either unhandlable, or is not formatted correctly |
1160 | * so respond with a STALL for the status stage to indicate failure. | 1198 | * so respond with a STALL for the status stage to indicate failure. |
1161 | */ | 1199 | */ |
@@ -1247,20 +1285,6 @@ static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg) | |||
1247 | } | 1285 | } |
1248 | 1286 | ||
1249 | /** | 1287 | /** |
1250 | * get_ep_head - return the first request on the endpoint | ||
1251 | * @hs_ep: The controller endpoint to get | ||
1252 | * | ||
1253 | * Get the first request on the endpoint. | ||
1254 | */ | ||
1255 | static struct s3c_hsotg_req *get_ep_head(struct s3c_hsotg_ep *hs_ep) | ||
1256 | { | ||
1257 | if (list_empty(&hs_ep->queue)) | ||
1258 | return NULL; | ||
1259 | |||
1260 | return list_first_entry(&hs_ep->queue, struct s3c_hsotg_req, queue); | ||
1261 | } | ||
1262 | |||
1263 | /** | ||
1264 | * s3c_hsotg_complete_request - complete a request given to us | 1288 | * s3c_hsotg_complete_request - complete a request given to us |
1265 | * @hsotg: The device state. | 1289 | * @hsotg: The device state. |
1266 | * @hs_ep: The endpoint the request was on. | 1290 | * @hs_ep: The endpoint the request was on. |
@@ -1683,6 +1707,37 @@ bad_mps: | |||
1683 | dev_err(hsotg->dev, "ep%d: bad mps of %d\n", ep, mps); | 1707 | dev_err(hsotg->dev, "ep%d: bad mps of %d\n", ep, mps); |
1684 | } | 1708 | } |
1685 | 1709 | ||
1710 | /** | ||
1711 | * s3c_hsotg_txfifo_flush - flush Tx FIFO | ||
1712 | * @hsotg: The driver state | ||
1713 | * @idx: The index for the endpoint (0..15) | ||
1714 | */ | ||
1715 | static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx) | ||
1716 | { | ||
1717 | int timeout; | ||
1718 | int val; | ||
1719 | |||
1720 | writel(S3C_GRSTCTL_TxFNum(idx) | S3C_GRSTCTL_TxFFlsh, | ||
1721 | hsotg->regs + S3C_GRSTCTL); | ||
1722 | |||
1723 | /* wait until the fifo is flushed */ | ||
1724 | timeout = 100; | ||
1725 | |||
1726 | while (1) { | ||
1727 | val = readl(hsotg->regs + S3C_GRSTCTL); | ||
1728 | |||
1729 | if ((val & (S3C_GRSTCTL_TxFFlsh)) == 0) | ||
1730 | break; | ||
1731 | |||
1732 | if (--timeout == 0) { | ||
1733 | dev_err(hsotg->dev, | ||
1734 | "%s: timeout flushing fifo (GRSTCTL=%08x)\n", | ||
1735 | __func__, val); | ||
1736 | } | ||
1737 | |||
1738 | udelay(1); | ||
1739 | } | ||
1740 | } | ||
1686 | 1741 | ||
1687 | /** | 1742 | /** |
1688 | * s3c_hsotg_trytx - check to see if anything needs transmitting | 1743 | * s3c_hsotg_trytx - check to see if anything needs transmitting |
@@ -1775,10 +1830,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); | 1830 | u32 epctl_reg = dir_in ? S3C_DIEPCTL(idx) : S3C_DOEPCTL(idx); |
1776 | u32 epsiz_reg = dir_in ? S3C_DIEPTSIZ(idx) : S3C_DOEPTSIZ(idx); | 1831 | u32 epsiz_reg = dir_in ? S3C_DIEPTSIZ(idx) : S3C_DOEPTSIZ(idx); |
1777 | u32 ints; | 1832 | u32 ints; |
1778 | u32 clear = 0; | ||
1779 | 1833 | ||
1780 | ints = readl(hsotg->regs + epint_reg); | 1834 | ints = readl(hsotg->regs + epint_reg); |
1781 | 1835 | ||
1836 | /* Clear endpoint interrupts */ | ||
1837 | writel(ints, hsotg->regs + epint_reg); | ||
1838 | |||
1782 | dev_dbg(hsotg->dev, "%s: ep%d(%s) DxEPINT=0x%08x\n", | 1839 | dev_dbg(hsotg->dev, "%s: ep%d(%s) DxEPINT=0x%08x\n", |
1783 | __func__, idx, dir_in ? "in" : "out", ints); | 1840 | __func__, idx, dir_in ? "in" : "out", ints); |
1784 | 1841 | ||
@@ -1801,19 +1858,28 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, | |||
1801 | 1858 | ||
1802 | s3c_hsotg_handle_outdone(hsotg, idx, false); | 1859 | s3c_hsotg_handle_outdone(hsotg, idx, false); |
1803 | } | 1860 | } |
1804 | |||
1805 | clear |= S3C_DxEPINT_XferCompl; | ||
1806 | } | 1861 | } |
1807 | 1862 | ||
1808 | if (ints & S3C_DxEPINT_EPDisbld) { | 1863 | if (ints & S3C_DxEPINT_EPDisbld) { |
1809 | dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__); | 1864 | dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__); |
1810 | clear |= S3C_DxEPINT_EPDisbld; | 1865 | |
1866 | if (dir_in) { | ||
1867 | int epctl = readl(hsotg->regs + epctl_reg); | ||
1868 | |||
1869 | s3c_hsotg_txfifo_flush(hsotg, idx); | ||
1870 | |||
1871 | if ((epctl & S3C_DxEPCTL_Stall) && | ||
1872 | (epctl & S3C_DxEPCTL_EPType_Bulk)) { | ||
1873 | int dctl = readl(hsotg->regs + S3C_DCTL); | ||
1874 | |||
1875 | dctl |= S3C_DCTL_CGNPInNAK; | ||
1876 | writel(dctl, hsotg->regs + S3C_DCTL); | ||
1877 | } | ||
1878 | } | ||
1811 | } | 1879 | } |
1812 | 1880 | ||
1813 | if (ints & S3C_DxEPINT_AHBErr) { | 1881 | if (ints & S3C_DxEPINT_AHBErr) |
1814 | dev_dbg(hsotg->dev, "%s: AHBErr\n", __func__); | 1882 | dev_dbg(hsotg->dev, "%s: AHBErr\n", __func__); |
1815 | clear |= S3C_DxEPINT_AHBErr; | ||
1816 | } | ||
1817 | 1883 | ||
1818 | if (ints & S3C_DxEPINT_Setup) { /* Setup or Timeout */ | 1884 | if (ints & S3C_DxEPINT_Setup) { /* Setup or Timeout */ |
1819 | dev_dbg(hsotg->dev, "%s: Setup/Timeout\n", __func__); | 1885 | dev_dbg(hsotg->dev, "%s: Setup/Timeout\n", __func__); |
@@ -1829,14 +1895,10 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, | |||
1829 | else | 1895 | else |
1830 | s3c_hsotg_handle_outdone(hsotg, 0, true); | 1896 | s3c_hsotg_handle_outdone(hsotg, 0, true); |
1831 | } | 1897 | } |
1832 | |||
1833 | clear |= S3C_DxEPINT_Setup; | ||
1834 | } | 1898 | } |
1835 | 1899 | ||
1836 | if (ints & S3C_DxEPINT_Back2BackSetup) { | 1900 | if (ints & S3C_DxEPINT_Back2BackSetup) |
1837 | dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__); | 1901 | dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__); |
1838 | clear |= S3C_DxEPINT_Back2BackSetup; | ||
1839 | } | ||
1840 | 1902 | ||
1841 | if (dir_in) { | 1903 | if (dir_in) { |
1842 | /* not sure if this is important, but we'll clear it anyway | 1904 | /* not sure if this is important, but we'll clear it anyway |
@@ -1844,14 +1906,12 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, | |||
1844 | if (ints & S3C_DIEPMSK_INTknTXFEmpMsk) { | 1906 | if (ints & S3C_DIEPMSK_INTknTXFEmpMsk) { |
1845 | dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n", | 1907 | dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n", |
1846 | __func__, idx); | 1908 | __func__, idx); |
1847 | clear |= S3C_DIEPMSK_INTknTXFEmpMsk; | ||
1848 | } | 1909 | } |
1849 | 1910 | ||
1850 | /* this probably means something bad is happening */ | 1911 | /* this probably means something bad is happening */ |
1851 | if (ints & S3C_DIEPMSK_INTknEPMisMsk) { | 1912 | if (ints & S3C_DIEPMSK_INTknEPMisMsk) { |
1852 | dev_warn(hsotg->dev, "%s: ep%d: INTknEP\n", | 1913 | dev_warn(hsotg->dev, "%s: ep%d: INTknEP\n", |
1853 | __func__, idx); | 1914 | __func__, idx); |
1854 | clear |= S3C_DIEPMSK_INTknEPMisMsk; | ||
1855 | } | 1915 | } |
1856 | 1916 | ||
1857 | /* FIFO has space or is empty (see GAHBCFG) */ | 1917 | /* FIFO has space or is empty (see GAHBCFG) */ |
@@ -1860,11 +1920,8 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, | |||
1860 | dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n", | 1920 | dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n", |
1861 | __func__, idx); | 1921 | __func__, idx); |
1862 | s3c_hsotg_trytx(hsotg, hs_ep); | 1922 | s3c_hsotg_trytx(hsotg, hs_ep); |
1863 | clear |= S3C_DIEPMSK_TxFIFOEmpty; | ||
1864 | } | 1923 | } |
1865 | } | 1924 | } |
1866 | |||
1867 | writel(clear, hsotg->regs + epint_reg); | ||
1868 | } | 1925 | } |
1869 | 1926 | ||
1870 | /** | 1927 | /** |
@@ -2056,7 +2113,6 @@ irq_retry: | |||
2056 | dev_info(hsotg->dev, "OTGInt: %08x\n", otgint); | 2113 | dev_info(hsotg->dev, "OTGInt: %08x\n", otgint); |
2057 | 2114 | ||
2058 | writel(otgint, hsotg->regs + S3C_GOTGINT); | 2115 | writel(otgint, hsotg->regs + S3C_GOTGINT); |
2059 | writel(S3C_GINTSTS_OTGInt, hsotg->regs + S3C_GINTSTS); | ||
2060 | } | 2116 | } |
2061 | 2117 | ||
2062 | if (gintsts & S3C_GINTSTS_DisconnInt) { | 2118 | if (gintsts & S3C_GINTSTS_DisconnInt) { |
@@ -2072,8 +2128,9 @@ irq_retry: | |||
2072 | } | 2128 | } |
2073 | 2129 | ||
2074 | if (gintsts & S3C_GINTSTS_EnumDone) { | 2130 | if (gintsts & S3C_GINTSTS_EnumDone) { |
2075 | s3c_hsotg_irq_enumdone(hsotg); | ||
2076 | writel(S3C_GINTSTS_EnumDone, hsotg->regs + S3C_GINTSTS); | 2131 | writel(S3C_GINTSTS_EnumDone, hsotg->regs + S3C_GINTSTS); |
2132 | |||
2133 | s3c_hsotg_irq_enumdone(hsotg); | ||
2077 | } | 2134 | } |
2078 | 2135 | ||
2079 | if (gintsts & S3C_GINTSTS_ConIDStsChng) { | 2136 | if (gintsts & S3C_GINTSTS_ConIDStsChng) { |
@@ -2101,10 +2158,6 @@ irq_retry: | |||
2101 | if (daint_in & 1) | 2158 | if (daint_in & 1) |
2102 | s3c_hsotg_epint(hsotg, ep, 1); | 2159 | s3c_hsotg_epint(hsotg, ep, 1); |
2103 | } | 2160 | } |
2104 | |||
2105 | writel(daint, hsotg->regs + S3C_DAINT); | ||
2106 | writel(gintsts & (S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt), | ||
2107 | hsotg->regs + S3C_GINTSTS); | ||
2108 | } | 2161 | } |
2109 | 2162 | ||
2110 | if (gintsts & S3C_GINTSTS_USBRst) { | 2163 | if (gintsts & S3C_GINTSTS_USBRst) { |
@@ -2112,6 +2165,8 @@ irq_retry: | |||
2112 | dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n", | 2165 | dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n", |
2113 | readl(hsotg->regs + S3C_GNPTXSTS)); | 2166 | readl(hsotg->regs + S3C_GNPTXSTS)); |
2114 | 2167 | ||
2168 | writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS); | ||
2169 | |||
2115 | kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true); | 2170 | kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true); |
2116 | 2171 | ||
2117 | /* it seems after a reset we can end up with a situation | 2172 | /* it seems after a reset we can end up with a situation |
@@ -2123,8 +2178,6 @@ irq_retry: | |||
2123 | s3c_hsotg_init_fifo(hsotg); | 2178 | s3c_hsotg_init_fifo(hsotg); |
2124 | 2179 | ||
2125 | s3c_hsotg_enqueue_setup(hsotg); | 2180 | s3c_hsotg_enqueue_setup(hsotg); |
2126 | |||
2127 | writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS); | ||
2128 | } | 2181 | } |
2129 | 2182 | ||
2130 | /* check both FIFOs */ | 2183 | /* check both FIFOs */ |
@@ -2138,8 +2191,6 @@ irq_retry: | |||
2138 | 2191 | ||
2139 | s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_NPTxFEmp); | 2192 | s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_NPTxFEmp); |
2140 | s3c_hsotg_irq_fifoempty(hsotg, false); | 2193 | s3c_hsotg_irq_fifoempty(hsotg, false); |
2141 | |||
2142 | writel(S3C_GINTSTS_NPTxFEmp, hsotg->regs + S3C_GINTSTS); | ||
2143 | } | 2194 | } |
2144 | 2195 | ||
2145 | if (gintsts & S3C_GINTSTS_PTxFEmp) { | 2196 | if (gintsts & S3C_GINTSTS_PTxFEmp) { |
@@ -2149,8 +2200,6 @@ irq_retry: | |||
2149 | 2200 | ||
2150 | s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_PTxFEmp); | 2201 | s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_PTxFEmp); |
2151 | s3c_hsotg_irq_fifoempty(hsotg, true); | 2202 | s3c_hsotg_irq_fifoempty(hsotg, true); |
2152 | |||
2153 | writel(S3C_GINTSTS_PTxFEmp, hsotg->regs + S3C_GINTSTS); | ||
2154 | } | 2203 | } |
2155 | 2204 | ||
2156 | if (gintsts & S3C_GINTSTS_RxFLvl) { | 2205 | if (gintsts & S3C_GINTSTS_RxFLvl) { |
@@ -2159,7 +2208,6 @@ irq_retry: | |||
2159 | * set. */ | 2208 | * set. */ |
2160 | 2209 | ||
2161 | s3c_hsotg_handle_rx(hsotg); | 2210 | s3c_hsotg_handle_rx(hsotg); |
2162 | writel(S3C_GINTSTS_RxFLvl, hsotg->regs + S3C_GINTSTS); | ||
2163 | } | 2211 | } |
2164 | 2212 | ||
2165 | if (gintsts & S3C_GINTSTS_ModeMis) { | 2213 | if (gintsts & S3C_GINTSTS_ModeMis) { |
@@ -2193,19 +2241,17 @@ irq_retry: | |||
2193 | if (gintsts & S3C_GINTSTS_GOUTNakEff) { | 2241 | if (gintsts & S3C_GINTSTS_GOUTNakEff) { |
2194 | dev_info(hsotg->dev, "GOUTNakEff triggered\n"); | 2242 | dev_info(hsotg->dev, "GOUTNakEff triggered\n"); |
2195 | 2243 | ||
2196 | s3c_hsotg_dump(hsotg); | ||
2197 | |||
2198 | writel(S3C_DCTL_CGOUTNak, hsotg->regs + S3C_DCTL); | 2244 | writel(S3C_DCTL_CGOUTNak, hsotg->regs + S3C_DCTL); |
2199 | writel(S3C_GINTSTS_GOUTNakEff, hsotg->regs + S3C_GINTSTS); | 2245 | |
2246 | s3c_hsotg_dump(hsotg); | ||
2200 | } | 2247 | } |
2201 | 2248 | ||
2202 | if (gintsts & S3C_GINTSTS_GINNakEff) { | 2249 | if (gintsts & S3C_GINTSTS_GINNakEff) { |
2203 | dev_info(hsotg->dev, "GINNakEff triggered\n"); | 2250 | dev_info(hsotg->dev, "GINNakEff triggered\n"); |
2204 | 2251 | ||
2205 | s3c_hsotg_dump(hsotg); | ||
2206 | |||
2207 | writel(S3C_DCTL_CGNPInNAK, hsotg->regs + S3C_DCTL); | 2252 | writel(S3C_DCTL_CGNPInNAK, hsotg->regs + S3C_DCTL); |
2208 | writel(S3C_GINTSTS_GINNakEff, hsotg->regs + S3C_GINTSTS); | 2253 | |
2254 | s3c_hsotg_dump(hsotg); | ||
2209 | } | 2255 | } |
2210 | 2256 | ||
2211 | /* if we've had fifo events, we should try and go around the | 2257 | /* if we've had fifo events, we should try and go around the |
@@ -2403,11 +2449,6 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) | |||
2403 | 2449 | ||
2404 | dev_info(hs->dev, "ep_dequeue(%p,%p)\n", ep, req); | 2450 | dev_info(hs->dev, "ep_dequeue(%p,%p)\n", ep, req); |
2405 | 2451 | ||
2406 | if (hs_req == hs_ep->req) { | ||
2407 | dev_dbg(hs->dev, "%s: already in progress\n", __func__); | ||
2408 | return -EINPROGRESS; | ||
2409 | } | ||
2410 | |||
2411 | spin_lock_irqsave(&hs_ep->lock, flags); | 2452 | spin_lock_irqsave(&hs_ep->lock, flags); |
2412 | 2453 | ||
2413 | if (!on_list(hs_ep, hs_req)) { | 2454 | if (!on_list(hs_ep, hs_req)) { |
@@ -2429,6 +2470,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) | |||
2429 | unsigned long irqflags; | 2470 | unsigned long irqflags; |
2430 | u32 epreg; | 2471 | u32 epreg; |
2431 | u32 epctl; | 2472 | u32 epctl; |
2473 | u32 xfertype; | ||
2432 | 2474 | ||
2433 | dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value); | 2475 | dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value); |
2434 | 2476 | ||
@@ -2439,10 +2481,17 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) | |||
2439 | epreg = S3C_DIEPCTL(index); | 2481 | epreg = S3C_DIEPCTL(index); |
2440 | epctl = readl(hs->regs + epreg); | 2482 | epctl = readl(hs->regs + epreg); |
2441 | 2483 | ||
2442 | if (value) | 2484 | if (value) { |
2443 | epctl |= S3C_DxEPCTL_Stall; | 2485 | epctl |= S3C_DxEPCTL_Stall + S3C_DxEPCTL_SNAK; |
2444 | else | 2486 | if (epctl & S3C_DxEPCTL_EPEna) |
2487 | epctl |= S3C_DxEPCTL_EPDis; | ||
2488 | } else { | ||
2445 | epctl &= ~S3C_DxEPCTL_Stall; | 2489 | epctl &= ~S3C_DxEPCTL_Stall; |
2490 | xfertype = epctl & S3C_DxEPCTL_EPType_MASK; | ||
2491 | if (xfertype == S3C_DxEPCTL_EPType_Bulk || | ||
2492 | xfertype == S3C_DxEPCTL_EPType_Intterupt) | ||
2493 | epctl |= S3C_DxEPCTL_SetD0PID; | ||
2494 | } | ||
2446 | 2495 | ||
2447 | writel(epctl, hs->regs + epreg); | 2496 | writel(epctl, hs->regs + epreg); |
2448 | 2497 | ||
@@ -2451,8 +2500,13 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) | |||
2451 | 2500 | ||
2452 | if (value) | 2501 | if (value) |
2453 | epctl |= S3C_DxEPCTL_Stall; | 2502 | epctl |= S3C_DxEPCTL_Stall; |
2454 | else | 2503 | else { |
2455 | epctl &= ~S3C_DxEPCTL_Stall; | 2504 | epctl &= ~S3C_DxEPCTL_Stall; |
2505 | xfertype = epctl & S3C_DxEPCTL_EPType_MASK; | ||
2506 | if (xfertype == S3C_DxEPCTL_EPType_Bulk || | ||
2507 | xfertype == S3C_DxEPCTL_EPType_Intterupt) | ||
2508 | epctl |= S3C_DxEPCTL_SetD0PID; | ||
2509 | } | ||
2456 | 2510 | ||
2457 | writel(epctl, hs->regs + epreg); | 2511 | writel(epctl, hs->regs + epreg); |
2458 | 2512 | ||
@@ -2491,9 +2545,9 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg) | |||
2491 | timeout = 1000; | 2545 | timeout = 1000; |
2492 | do { | 2546 | do { |
2493 | grstctl = readl(hsotg->regs + S3C_GRSTCTL); | 2547 | grstctl = readl(hsotg->regs + S3C_GRSTCTL); |
2494 | } while (!(grstctl & S3C_GRSTCTL_CSftRst) && timeout-- > 0); | 2548 | } while ((grstctl & S3C_GRSTCTL_CSftRst) && timeout-- > 0); |
2495 | 2549 | ||
2496 | if (!(grstctl & S3C_GRSTCTL_CSftRst)) { | 2550 | if (grstctl & S3C_GRSTCTL_CSftRst) { |
2497 | dev_err(hsotg->dev, "Failed to get CSftRst asserted\n"); | 2551 | dev_err(hsotg->dev, "Failed to get CSftRst asserted\n"); |
2498 | return -EINVAL; | 2552 | return -EINVAL; |
2499 | } | 2553 | } |
@@ -2510,13 +2564,10 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg) | |||
2510 | return -ETIMEDOUT; | 2564 | return -ETIMEDOUT; |
2511 | } | 2565 | } |
2512 | 2566 | ||
2513 | if (grstctl & S3C_GRSTCTL_CSftRst) | ||
2514 | continue; | ||
2515 | |||
2516 | if (!(grstctl & S3C_GRSTCTL_AHBIdle)) | 2567 | if (!(grstctl & S3C_GRSTCTL_AHBIdle)) |
2517 | continue; | 2568 | continue; |
2518 | 2569 | ||
2519 | break; /* reset done */ | 2570 | break; /* reset done */ |
2520 | } | 2571 | } |
2521 | 2572 | ||
2522 | dev_dbg(hsotg->dev, "reset successful\n"); | 2573 | dev_dbg(hsotg->dev, "reset successful\n"); |
@@ -2588,6 +2639,12 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, | |||
2588 | 2639 | ||
2589 | writel(1 << 18 | S3C_DCFG_DevSpd_HS, hsotg->regs + S3C_DCFG); | 2640 | writel(1 << 18 | S3C_DCFG_DevSpd_HS, hsotg->regs + S3C_DCFG); |
2590 | 2641 | ||
2642 | /* Clear any pending OTG interrupts */ | ||
2643 | writel(0xffffffff, hsotg->regs + S3C_GOTGINT); | ||
2644 | |||
2645 | /* Clear any pending interrupts */ | ||
2646 | writel(0xffffffff, hsotg->regs + S3C_GINTSTS); | ||
2647 | |||
2591 | writel(S3C_GINTSTS_DisconnInt | S3C_GINTSTS_SessReqInt | | 2648 | writel(S3C_GINTSTS_DisconnInt | S3C_GINTSTS_SessReqInt | |
2592 | S3C_GINTSTS_ConIDStsChng | S3C_GINTSTS_USBRst | | 2649 | S3C_GINTSTS_ConIDStsChng | S3C_GINTSTS_USBRst | |
2593 | S3C_GINTSTS_EnumDone | S3C_GINTSTS_OTGInt | | 2650 | S3C_GINTSTS_EnumDone | S3C_GINTSTS_OTGInt | |
@@ -3261,7 +3318,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) | |||
3261 | hsotg->clk = clk_get(&pdev->dev, "otg"); | 3318 | hsotg->clk = clk_get(&pdev->dev, "otg"); |
3262 | if (IS_ERR(hsotg->clk)) { | 3319 | if (IS_ERR(hsotg->clk)) { |
3263 | dev_err(dev, "cannot get otg clock\n"); | 3320 | dev_err(dev, "cannot get otg clock\n"); |
3264 | ret = -EINVAL; | 3321 | ret = PTR_ERR(hsotg->clk); |
3265 | goto err_mem; | 3322 | goto err_mem; |
3266 | } | 3323 | } |
3267 | 3324 | ||