aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/s3c-hsotg.c
diff options
context:
space:
mode:
authorLukasz Majewski <l.majewski@samsung.com>2012-05-04 08:17:03 -0400
committerFelipe Balbi <balbi@ti.com>2012-05-04 08:53:12 -0400
commit71225beeeba2bde80aac02fadb5c197389fa12e4 (patch)
treed019445bd250e0bbcaea834c0f1b680dc9eef526 /drivers/usb/gadget/s3c-hsotg.c
parentfc9a731ed0ef7138432f0f14981710aea8e83320 (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.c21
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 */
152struct s3c_hsotg { 153struct 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) {