aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc2
diff options
context:
space:
mode:
authorRobert Baldyga <r.baldyga@samsung.com>2014-09-09 04:44:56 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-09-19 19:16:39 -0400
commitb203d0a2e32dd28e87780078f0789322862e4da8 (patch)
tree3ad3cf19201105da8bb0bb13dbaaddcaca8fcc08 /drivers/usb/dwc2
parentcff9eb756e18a7763d7ab9c574c0ab191e712341 (diff)
usb: dwc2/gadget: assign TX FIFO dynamically
Because we have not enough memory to have each TX FIFO of size at least 3072 bytes (the maximum single packet size with 3 transactions per microframe), we create four FIFOs of lenght 1024, and four of length 3072 bytes, and assing them to endpoints dynamically according to maxpacket size value of given endpoint. Up to now there were initialized 16 TX FIFOs, but we use only 8 IN endpoints, so we can split available memory for 8 FIFOs to have more memory for each one. It needed to do some small modifications in few places in code, because there was assumption that TX FIFO numbers assigned to endpoints are the same as the endpoint numbers, which is not true since we have dynamic FIFO assigning. Signed-off-by: Robert Baldyga <r.baldyga@samsung.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/dwc2')
-rw-r--r--drivers/usb/dwc2/core.h2
-rw-r--r--drivers/usb/dwc2/gadget.c80
2 files changed, 52 insertions, 30 deletions
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index ba505f141606..bf015ab3b44c 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -139,6 +139,7 @@ struct s3c_hsotg_ep {
139 unsigned int last_load; 139 unsigned int last_load;
140 unsigned int fifo_load; 140 unsigned int fifo_load;
141 unsigned short fifo_size; 141 unsigned short fifo_size;
142 unsigned short fifo_index;
142 143
143 unsigned char dir_in; 144 unsigned char dir_in;
144 unsigned char index; 145 unsigned char index;
@@ -197,6 +198,7 @@ struct s3c_hsotg {
197 int fifo_mem; 198 int fifo_mem;
198 unsigned int dedicated_fifos:1; 199 unsigned int dedicated_fifos:1;
199 unsigned char num_of_eps; 200 unsigned char num_of_eps;
201 u32 fifo_map;
200 202
201 struct dentry *debug_root; 203 struct dentry *debug_root;
202 struct dentry *debug_file; 204 struct dentry *debug_file;
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 4c5f516479ac..09f4cbd4fcb9 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -182,14 +182,29 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)
182 182
183 /* start at the end of the GNPTXFSIZ, rounded up */ 183 /* start at the end of the GNPTXFSIZ, rounded up */
184 addr = 2048 + 1024; 184 addr = 2048 + 1024;
185 size = 768;
186 185
187 /* 186 /*
188 * currently we allocate TX FIFOs for all possible endpoints, 187 * Because we have not enough memory to have each TX FIFO of size at
189 * and assume that they are all the same size. 188 * least 3072 bytes (the maximum single packet size), we create four
189 * FIFOs of lenght 1024, and four of length 3072 bytes, and assing
190 * them to endpoints dynamically according to maxpacket size value of
191 * given endpoint.
190 */ 192 */
191 193
192 for (ep = 1; ep <= 15; ep++) { 194 /* 256*4=1024 bytes FIFO length */
195 size = 256;
196 for (ep = 1; ep <= 4; ep++) {
197 val = addr;
198 val |= size << FIFOSIZE_DEPTH_SHIFT;
199 WARN_ONCE(addr + size > hsotg->fifo_mem,
200 "insufficient fifo memory");
201 addr += size;
202
203 writel(val, hsotg->regs + DPTXFSIZN(ep));
204 }
205 /* 768*4=3072 bytes FIFO length */
206 size = 768;
207 for (ep = 5; ep <= 8; ep++) {
193 val = addr; 208 val = addr;
194 val |= size << FIFOSIZE_DEPTH_SHIFT; 209 val |= size << FIFOSIZE_DEPTH_SHIFT;
195 WARN_ONCE(addr + size > hsotg->fifo_mem, 210 WARN_ONCE(addr + size > hsotg->fifo_mem,
@@ -1834,7 +1849,7 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
1834 if (dir_in) { 1849 if (dir_in) {
1835 int epctl = readl(hsotg->regs + epctl_reg); 1850 int epctl = readl(hsotg->regs + epctl_reg);
1836 1851
1837 s3c_hsotg_txfifo_flush(hsotg, idx); 1852 s3c_hsotg_txfifo_flush(hsotg, hs_ep->fifo_index);
1838 1853
1839 if ((epctl & DXEPCTL_STALL) && 1854 if ((epctl & DXEPCTL_STALL) &&
1840 (epctl & DXEPCTL_EPTYPE_BULK)) { 1855 (epctl & DXEPCTL_EPTYPE_BULK)) {
@@ -1983,6 +1998,7 @@ static void kill_all_requests(struct s3c_hsotg *hsotg,
1983 int result, bool force) 1998 int result, bool force)
1984{ 1999{
1985 struct s3c_hsotg_req *req, *treq; 2000 struct s3c_hsotg_req *req, *treq;
2001 unsigned size;
1986 2002
1987 list_for_each_entry_safe(req, treq, &ep->queue, queue) { 2003 list_for_each_entry_safe(req, treq, &ep->queue, queue) {
1988 /* 2004 /*
@@ -1996,9 +2012,11 @@ static void kill_all_requests(struct s3c_hsotg *hsotg,
1996 s3c_hsotg_complete_request(hsotg, ep, req, 2012 s3c_hsotg_complete_request(hsotg, ep, req,
1997 result); 2013 result);
1998 } 2014 }
1999 if (hsotg->dedicated_fifos) 2015 if (!hsotg->dedicated_fifos)
2000 if ((readl(hsotg->regs + DTXFSTS(ep->index)) & 0xffff) * 4 < 3072) 2016 return;
2001 s3c_hsotg_txfifo_flush(hsotg, ep->index); 2017 size = (readl(hsotg->regs + DTXFSTS(ep->index)) & 0xffff) * 4;
2018 if (size < ep->fifo_size)
2019 s3c_hsotg_txfifo_flush(hsotg, ep->fifo_index);
2002} 2020}
2003 2021
2004/** 2022/**
@@ -2439,6 +2457,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
2439 u32 epctrl; 2457 u32 epctrl;
2440 u32 mps; 2458 u32 mps;
2441 int dir_in; 2459 int dir_in;
2460 int i, val, size;
2442 int ret = 0; 2461 int ret = 0;
2443 2462
2444 dev_dbg(hsotg->dev, 2463 dev_dbg(hsotg->dev,
@@ -2511,17 +2530,8 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
2511 break; 2530 break;
2512 2531
2513 case USB_ENDPOINT_XFER_INT: 2532 case USB_ENDPOINT_XFER_INT:
2514 if (dir_in) { 2533 if (dir_in)
2515 /*
2516 * Allocate our TxFNum by simply using the index
2517 * of the endpoint for the moment. We could do
2518 * something better if the host indicates how
2519 * many FIFOs we are expecting to use.
2520 */
2521
2522 hs_ep->periodic = 1; 2534 hs_ep->periodic = 1;
2523 epctrl |= DXEPCTL_TXFNUM(index);
2524 }
2525 2535
2526 epctrl |= DXEPCTL_EPTYPE_INTERRUPT; 2536 epctrl |= DXEPCTL_EPTYPE_INTERRUPT;
2527 break; 2537 break;
@@ -2535,8 +2545,25 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
2535 * if the hardware has dedicated fifos, we must give each IN EP 2545 * if the hardware has dedicated fifos, we must give each IN EP
2536 * a unique tx-fifo even if it is non-periodic. 2546 * a unique tx-fifo even if it is non-periodic.
2537 */ 2547 */
2538 if (dir_in && hsotg->dedicated_fifos) 2548 if (dir_in && hsotg->dedicated_fifos) {
2539 epctrl |= DXEPCTL_TXFNUM(index); 2549 size = hs_ep->ep.maxpacket*hs_ep->mc;
2550 for (i = 1; i <= 8; ++i) {
2551 if (hsotg->fifo_map & (1<<i))
2552 continue;
2553 val = readl(hsotg->regs + DPTXFSIZN(i));
2554 val = (val >> FIFOSIZE_DEPTH_SHIFT)*4;
2555 if (val < size)
2556 continue;
2557 hsotg->fifo_map |= 1<<i;
2558
2559 epctrl |= DXEPCTL_TXFNUM(i);
2560 hs_ep->fifo_index = i;
2561 hs_ep->fifo_size = val;
2562 break;
2563 }
2564 if (i == 8)
2565 return -ENOMEM;
2566 }
2540 2567
2541 /* for non control endpoints, set PID to D0 */ 2568 /* for non control endpoints, set PID to D0 */
2542 if (index) 2569 if (index)
@@ -2583,6 +2610,9 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
2583 /* terminate all requests with shutdown */ 2610 /* terminate all requests with shutdown */
2584 kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false); 2611 kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false);
2585 2612
2613 hsotg->fifo_map &= ~(1<<hs_ep->fifo_index);
2614 hs_ep->fifo_index = 0;
2615 hs_ep->fifo_size = 0;
2586 2616
2587 ctrl = readl(hsotg->regs + epctrl_reg); 2617 ctrl = readl(hsotg->regs + epctrl_reg);
2588 ctrl &= ~DXEPCTL_EPENA; 2618 ctrl &= ~DXEPCTL_EPENA;
@@ -2974,7 +3004,6 @@ static void s3c_hsotg_initep(struct s3c_hsotg *hsotg,
2974 struct s3c_hsotg_ep *hs_ep, 3004 struct s3c_hsotg_ep *hs_ep,
2975 int epnum) 3005 int epnum)
2976{ 3006{
2977 u32 ptxfifo;
2978 char *dir; 3007 char *dir;
2979 3008
2980 if (epnum == 0) 3009 if (epnum == 0)
@@ -3003,15 +3032,6 @@ static void s3c_hsotg_initep(struct s3c_hsotg *hsotg,
3003 hs_ep->ep.ops = &s3c_hsotg_ep_ops; 3032 hs_ep->ep.ops = &s3c_hsotg_ep_ops;
3004 3033
3005 /* 3034 /*
3006 * Read the FIFO size for the Periodic TX FIFO, even if we're
3007 * an OUT endpoint, we may as well do this if in future the
3008 * code is changed to make each endpoint's direction changeable.
3009 */
3010
3011 ptxfifo = readl(hsotg->regs + DPTXFSIZN(epnum));
3012 hs_ep->fifo_size = FIFOSIZE_DEPTH_GET(ptxfifo) * 4;
3013
3014 /*
3015 * if we're using dma, we need to set the next-endpoint pointer 3035 * if we're using dma, we need to set the next-endpoint pointer
3016 * to be something valid. 3036 * to be something valid.
3017 */ 3037 */