Because we have not enough memory to have each TX FIFO of size at least 3072 bytes (the maximum single packet size), 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. Signed-off-by: Robert Baldyga <r.baldyga@xxxxxxxxxxx> --- drivers/usb/dwc2/core.h | 1 + drivers/usb/dwc2/gadget.c | 48 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 067390e..23f7e86 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -197,6 +197,7 @@ struct s3c_hsotg { int fifo_mem; unsigned int dedicated_fifos:1; unsigned char num_of_eps; + u32 fifo_map; struct dentry *debug_root; struct dentry *debug_file; diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 3435711..2a7c014 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -184,14 +184,26 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg) /* start at the end of the GNPTXFSIZ, rounded up */ addr = 2048 + 1024; - size = 768; /* * currently we allocate TX FIFOs for all possible endpoints, * and assume that they are all the same size. */ - for (ep = 1; ep <= 15; ep++) { + /* 256*4=1024 bytes FIFO length */ + size = 256; + for (ep = 1; ep <= 4; ep++) { + val = addr; + val |= size << FIFOSIZE_DEPTH_SHIFT; + WARN_ONCE(addr + size > hsotg->fifo_mem, + "insufficient fifo memory"); + addr += size; + + writel(val, hsotg->regs + DPTXFSIZN(ep)); + } + /* 768*4=3072 bytes FIFO length */ + size = 768; + for (ep = 5; ep <= 8; ep++) { val = addr; val |= size << FIFOSIZE_DEPTH_SHIFT; WARN_ONCE(addr + size > hsotg->fifo_mem, @@ -2440,6 +2452,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, u32 epctrl; u32 mps; int dir_in; + int i, val, size; int ret = 0; dev_dbg(hsotg->dev, @@ -2512,17 +2525,8 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, break; case USB_ENDPOINT_XFER_INT: - if (dir_in) { - /* - * Allocate our TxFNum by simply using the index - * of the endpoint for the moment. We could do - * something better if the host indicates how - * many FIFOs we are expecting to use. - */ - + if (dir_in) hs_ep->periodic = 1; - epctrl |= DXEPCTL_TXFNUM(index); - } epctrl |= DXEPCTL_EPTYPE_INTERRUPT; break; @@ -2536,8 +2540,24 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, * if the hardware has dedicated fifos, we must give each IN EP * a unique tx-fifo even if it is non-periodic. */ - if (dir_in && hsotg->dedicated_fifos) - epctrl |= DXEPCTL_TXFNUM(index); + if (dir_in && hsotg->dedicated_fifos) { + size = hs_ep->ep.maxpacket*hs_ep->mc; + for (i = 1; i < 8; ++i) { + if (hsotg->fifo_map & (1<<i)) + continue; + val = readl(hsotg->regs + DPTXFSIZN(i)); + val = (val >> FIFOSIZE_DEPTH_SHIFT)*4; + if (val < size) + continue; + hsotg->fifo_map |= 1<<i; + break; + } + + if (i == 8) + return -ENOMEM; + + epctrl |= DXEPCTL_TXFNUM(i); + } /* for non control endpoints, set PID to D0 */ if (index) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html