diff options
author | Robert Baldyga <r.baldyga@samsung.com> | 2014-01-14 02:36:00 -0500 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2014-02-18 11:52:54 -0500 |
commit | c9f721b2f3168a0a3b1cc29e92ad1f6f3d62e376 (patch) | |
tree | 9956f1f5046a1bc14375d30901c1514a79aa23cf | |
parent | 7e98f60003df98026edd66916f282501eee075c4 (diff) |
usb: gadget: s3c-hsotg: stall ep0 in set_halt function
When s3c_hsotg_ep_sethalt() function is called for ep0 it should be stalled
in the same way that it is in s3c_hsotg_process_control() function, because
SET_HALT for ep0 is delayed response for setup request. Endpoint 0, if
halted, it doesn't need CLEAR_HALT because it clears "stalled" state
automatically when next setup request is received.
For this reason this patch moves code setting ep0 to "stalled" state to new
function named s3c_hsotg_stall_ep0() which is called in
s3c_hsotg_process_control() function as an immediate response for setup
request, and in s3c_hsotg_ep_sethalt() function as a delayed response for
setup request.
Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r-- | drivers/usb/gadget/s3c-hsotg.c | 78 |
1 files changed, 46 insertions, 32 deletions
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 930c490dd83b..99c8e3ca6a3c 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c | |||
@@ -1186,6 +1186,41 @@ static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg); | |||
1186 | static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg); | 1186 | static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg); |
1187 | 1187 | ||
1188 | /** | 1188 | /** |
1189 | * s3c_hsotg_stall_ep0 - stall ep0 | ||
1190 | * @hsotg: The device state | ||
1191 | * | ||
1192 | * Set stall for ep0 as response for setup request. | ||
1193 | */ | ||
1194 | static void s3c_hsotg_stall_ep0(struct s3c_hsotg *hsotg) { | ||
1195 | struct s3c_hsotg_ep *ep0 = &hsotg->eps[0]; | ||
1196 | u32 reg; | ||
1197 | u32 ctrl; | ||
1198 | |||
1199 | dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in); | ||
1200 | reg = (ep0->dir_in) ? DIEPCTL0 : DOEPCTL0; | ||
1201 | |||
1202 | /* | ||
1203 | * DxEPCTL_Stall will be cleared by EP once it has | ||
1204 | * taken effect, so no need to clear later. | ||
1205 | */ | ||
1206 | |||
1207 | ctrl = readl(hsotg->regs + reg); | ||
1208 | ctrl |= DxEPCTL_Stall; | ||
1209 | ctrl |= DxEPCTL_CNAK; | ||
1210 | writel(ctrl, hsotg->regs + reg); | ||
1211 | |||
1212 | dev_dbg(hsotg->dev, | ||
1213 | "written DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n", | ||
1214 | ctrl, reg, readl(hsotg->regs + reg)); | ||
1215 | |||
1216 | /* | ||
1217 | * complete won't be called, so we enqueue | ||
1218 | * setup request here | ||
1219 | */ | ||
1220 | s3c_hsotg_enqueue_setup(hsotg); | ||
1221 | } | ||
1222 | |||
1223 | /** | ||
1189 | * s3c_hsotg_process_control - process a control request | 1224 | * s3c_hsotg_process_control - process a control request |
1190 | * @hsotg: The device state | 1225 | * @hsotg: The device state |
1191 | * @ctrl: The control request received | 1226 | * @ctrl: The control request received |
@@ -1262,38 +1297,8 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, | |||
1262 | * so respond with a STALL for the status stage to indicate failure. | 1297 | * so respond with a STALL for the status stage to indicate failure. |
1263 | */ | 1298 | */ |
1264 | 1299 | ||
1265 | if (ret < 0) { | 1300 | if (ret < 0) |
1266 | u32 reg; | 1301 | s3c_hsotg_stall_ep0(hsotg); |
1267 | u32 ctrl; | ||
1268 | |||
1269 | dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in); | ||
1270 | reg = (ep0->dir_in) ? DIEPCTL0 : DOEPCTL0; | ||
1271 | |||
1272 | /* | ||
1273 | * DxEPCTL_Stall will be cleared by EP once it has | ||
1274 | * taken effect, so no need to clear later. | ||
1275 | */ | ||
1276 | |||
1277 | ctrl = readl(hsotg->regs + reg); | ||
1278 | ctrl |= DxEPCTL_Stall; | ||
1279 | ctrl |= DxEPCTL_CNAK; | ||
1280 | writel(ctrl, hsotg->regs + reg); | ||
1281 | |||
1282 | dev_dbg(hsotg->dev, | ||
1283 | "written DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n", | ||
1284 | ctrl, reg, readl(hsotg->regs + reg)); | ||
1285 | |||
1286 | /* | ||
1287 | * don't believe we need to anything more to get the EP | ||
1288 | * to reply with a STALL packet | ||
1289 | */ | ||
1290 | |||
1291 | /* | ||
1292 | * complete won't be called, so we enqueue | ||
1293 | * setup request here | ||
1294 | */ | ||
1295 | s3c_hsotg_enqueue_setup(hsotg); | ||
1296 | } | ||
1297 | } | 1302 | } |
1298 | 1303 | ||
1299 | /** | 1304 | /** |
@@ -2832,6 +2837,15 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) | |||
2832 | 2837 | ||
2833 | dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value); | 2838 | dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value); |
2834 | 2839 | ||
2840 | if (index == 0) { | ||
2841 | if (value) | ||
2842 | s3c_hsotg_stall_ep0(hs); | ||
2843 | else | ||
2844 | dev_warn(hs->dev, | ||
2845 | "%s: can't clear halt on ep0\n", __func__); | ||
2846 | return 0; | ||
2847 | } | ||
2848 | |||
2835 | /* write both IN and OUT control registers */ | 2849 | /* write both IN and OUT control registers */ |
2836 | 2850 | ||
2837 | epreg = DIEPCTL(index); | 2851 | epreg = DIEPCTL(index); |