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>
This commit is contained in:
Родитель
7e98f60003
Коммит
c9f721b2f3
|
@ -1185,6 +1185,41 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg,
|
|||
static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg);
|
||||
static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg);
|
||||
|
||||
/**
|
||||
* s3c_hsotg_stall_ep0 - stall ep0
|
||||
* @hsotg: The device state
|
||||
*
|
||||
* Set stall for ep0 as response for setup request.
|
||||
*/
|
||||
static void s3c_hsotg_stall_ep0(struct s3c_hsotg *hsotg) {
|
||||
struct s3c_hsotg_ep *ep0 = &hsotg->eps[0];
|
||||
u32 reg;
|
||||
u32 ctrl;
|
||||
|
||||
dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in);
|
||||
reg = (ep0->dir_in) ? DIEPCTL0 : DOEPCTL0;
|
||||
|
||||
/*
|
||||
* DxEPCTL_Stall will be cleared by EP once it has
|
||||
* taken effect, so no need to clear later.
|
||||
*/
|
||||
|
||||
ctrl = readl(hsotg->regs + reg);
|
||||
ctrl |= DxEPCTL_Stall;
|
||||
ctrl |= DxEPCTL_CNAK;
|
||||
writel(ctrl, hsotg->regs + reg);
|
||||
|
||||
dev_dbg(hsotg->dev,
|
||||
"written DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n",
|
||||
ctrl, reg, readl(hsotg->regs + reg));
|
||||
|
||||
/*
|
||||
* complete won't be called, so we enqueue
|
||||
* setup request here
|
||||
*/
|
||||
s3c_hsotg_enqueue_setup(hsotg);
|
||||
}
|
||||
|
||||
/**
|
||||
* s3c_hsotg_process_control - process a control request
|
||||
* @hsotg: The device state
|
||||
|
@ -1262,38 +1297,8 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
|
|||
* so respond with a STALL for the status stage to indicate failure.
|
||||
*/
|
||||
|
||||
if (ret < 0) {
|
||||
u32 reg;
|
||||
u32 ctrl;
|
||||
|
||||
dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in);
|
||||
reg = (ep0->dir_in) ? DIEPCTL0 : DOEPCTL0;
|
||||
|
||||
/*
|
||||
* DxEPCTL_Stall will be cleared by EP once it has
|
||||
* taken effect, so no need to clear later.
|
||||
*/
|
||||
|
||||
ctrl = readl(hsotg->regs + reg);
|
||||
ctrl |= DxEPCTL_Stall;
|
||||
ctrl |= DxEPCTL_CNAK;
|
||||
writel(ctrl, hsotg->regs + reg);
|
||||
|
||||
dev_dbg(hsotg->dev,
|
||||
"written DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n",
|
||||
ctrl, reg, readl(hsotg->regs + reg));
|
||||
|
||||
/*
|
||||
* don't believe we need to anything more to get the EP
|
||||
* to reply with a STALL packet
|
||||
*/
|
||||
|
||||
/*
|
||||
* complete won't be called, so we enqueue
|
||||
* setup request here
|
||||
*/
|
||||
s3c_hsotg_enqueue_setup(hsotg);
|
||||
}
|
||||
if (ret < 0)
|
||||
s3c_hsotg_stall_ep0(hsotg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2832,6 +2837,15 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
|
|||
|
||||
dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value);
|
||||
|
||||
if (index == 0) {
|
||||
if (value)
|
||||
s3c_hsotg_stall_ep0(hs);
|
||||
else
|
||||
dev_warn(hs->dev,
|
||||
"%s: can't clear halt on ep0\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* write both IN and OUT control registers */
|
||||
|
||||
epreg = DIEPCTL(index);
|
||||
|
|
Загрузка…
Ссылка в новой задаче