diff options
author | Lukasz Majewski <l.majewski@samsung.com> | 2012-05-04 08:17:03 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2012-05-04 08:53:12 -0400 |
commit | 71225beeeba2bde80aac02fadb5c197389fa12e4 (patch) | |
tree | d019445bd250e0bbcaea834c0f1b680dc9eef526 /drivers/usb/gadget/s3c-hsotg.c | |
parent | fc9a731ed0ef7138432f0f14981710aea8e83320 (diff) |
usb:hsotg:samsung: NAK management for EP0 (Setup stage of control transfers)
For SETUP stage of USB control transmission, the NAK shall NOT be
CLEAR.
The SNAK/CNAK control is crucial for this type of driver,
since data arrives to earlier defined requests.
Tested with:
- DFU gadget (various size of the sent data - also packet = MPS)
- Ethernet gadget (CDC and RNDIS)
- Multi Function Gadget (g_multi)
HW:
- Samsung's C210 Universal rev.0
Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/s3c-hsotg.c')
-rw-r--r-- | drivers/usb/gadget/s3c-hsotg.c | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index e1a54d21ecaf..7b46af3e014f 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c | |||
@@ -147,6 +147,7 @@ struct s3c_hsotg_ep { | |||
147 | * @ep0_buff: Buffer for EP0 reply data, if needed. | 147 | * @ep0_buff: Buffer for EP0 reply data, if needed. |
148 | * @ctrl_buff: Buffer for EP0 control requests. | 148 | * @ctrl_buff: Buffer for EP0 control requests. |
149 | * @ctrl_req: Request for EP0 control packets. | 149 | * @ctrl_req: Request for EP0 control packets. |
150 | * @setup: NAK management for EP0 SETUP | ||
150 | * @eps: The endpoints being supplied to the gadget framework | 151 | * @eps: The endpoints being supplied to the gadget framework |
151 | */ | 152 | */ |
152 | struct s3c_hsotg { | 153 | struct s3c_hsotg { |
@@ -173,6 +174,7 @@ struct s3c_hsotg { | |||
173 | u8 ctrl_buff[8]; | 174 | u8 ctrl_buff[8]; |
174 | 175 | ||
175 | struct usb_gadget gadget; | 176 | struct usb_gadget gadget; |
177 | unsigned int setup; | ||
176 | struct s3c_hsotg_ep eps[]; | 178 | struct s3c_hsotg_ep eps[]; |
177 | }; | 179 | }; |
178 | 180 | ||
@@ -696,7 +698,8 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, | |||
696 | } | 698 | } |
697 | 699 | ||
698 | length = ureq->length - ureq->actual; | 700 | length = ureq->length - ureq->actual; |
699 | 701 | dev_dbg(hsotg->dev, "ureq->length:%d ureq->actual:%d\n", | |
702 | ureq->length, ureq->actual); | ||
700 | if (0) | 703 | if (0) |
701 | dev_dbg(hsotg->dev, | 704 | dev_dbg(hsotg->dev, |
702 | "REQ buf %p len %d dma 0x%08x noi=%d zp=%d snok=%d\n", | 705 | "REQ buf %p len %d dma 0x%08x noi=%d zp=%d snok=%d\n", |
@@ -762,7 +765,15 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, | |||
762 | 765 | ||
763 | ctrl |= S3C_DxEPCTL_EPEna; /* ensure ep enabled */ | 766 | ctrl |= S3C_DxEPCTL_EPEna; /* ensure ep enabled */ |
764 | ctrl |= S3C_DxEPCTL_USBActEp; | 767 | ctrl |= S3C_DxEPCTL_USBActEp; |
765 | ctrl |= S3C_DxEPCTL_CNAK; /* clear NAK set by core */ | 768 | |
769 | dev_dbg(hsotg->dev, "setup req:%d\n", hsotg->setup); | ||
770 | |||
771 | /* For Setup request do not clear NAK */ | ||
772 | if (hsotg->setup && index == 0) | ||
773 | hsotg->setup = 0; | ||
774 | else | ||
775 | ctrl |= S3C_DxEPCTL_CNAK; /* clear NAK set by core */ | ||
776 | |||
766 | 777 | ||
767 | dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl); | 778 | dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl); |
768 | writel(ctrl, hsotg->regs + epctrl_reg); | 779 | writel(ctrl, hsotg->regs + epctrl_reg); |
@@ -1527,6 +1538,12 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, | |||
1527 | if (req->actual < req->length && size_left == 0) { | 1538 | if (req->actual < req->length && size_left == 0) { |
1528 | s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true); | 1539 | s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true); |
1529 | return; | 1540 | return; |
1541 | } else if (epnum == 0) { | ||
1542 | /* | ||
1543 | * After was_setup = 1 => | ||
1544 | * set CNAK for non Setup requests | ||
1545 | */ | ||
1546 | hsotg->setup = was_setup ? 0 : 1; | ||
1530 | } | 1547 | } |
1531 | 1548 | ||
1532 | if (req->actual < req->length && req->short_not_ok) { | 1549 | if (req->actual < req->length && req->short_not_ok) { |