aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc3
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2012-01-18 11:04:09 -0500
committerFelipe Balbi <balbi@ti.com>2012-02-06 04:48:34 -0500
commit457e84b6624b4d97e6ffae437887ea51a22d54a0 (patch)
treee1ca1503cdda97570fa692589e44a1ca43e72d8b /drivers/usb/dwc3
parentbb5cfd6811c63c47403e98028bde7e98bd7a1751 (diff)
usb: dwc3: gadget: dynamically re-size TxFifos
We need to dynamically re-size TxFifos for the cases where default values will not do. While at that, we create a simple function which, for now, will just allocate one full packet fifo space for each of the enabled endpoints. This can be improved later in order to allow for better throughput by allocating more space for endpoints which could make good use of that like isochronous and bulk. Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r--drivers/usb/dwc3/core.c5
-rw-r--r--drivers/usb/dwc3/core.h16
-rw-r--r--drivers/usb/dwc3/ep0.c11
-rw-r--r--drivers/usb/dwc3/gadget.c74
4 files changed, 104 insertions, 2 deletions
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 7c9df630dbe4..d119a1fbf946 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -48,6 +48,7 @@
48#include <linux/list.h> 48#include <linux/list.h>
49#include <linux/delay.h> 49#include <linux/delay.h>
50#include <linux/dma-mapping.h> 50#include <linux/dma-mapping.h>
51#include <linux/of.h>
51 52
52#include <linux/usb/ch9.h> 53#include <linux/usb/ch9.h>
53#include <linux/usb/gadget.h> 54#include <linux/usb/gadget.h>
@@ -404,6 +405,7 @@ static void dwc3_core_exit(struct dwc3 *dwc)
404 405
405static int __devinit dwc3_probe(struct platform_device *pdev) 406static int __devinit dwc3_probe(struct platform_device *pdev)
406{ 407{
408 struct device_node *node = pdev->dev.of_node;
407 struct resource *res; 409 struct resource *res;
408 struct dwc3 *dwc; 410 struct dwc3 *dwc;
409 411
@@ -469,6 +471,9 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
469 else 471 else
470 dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; 472 dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
471 473
474 if (of_get_property(node, "tx-fifo-resize", NULL))
475 dwc->needs_fifo_resize = true;
476
472 pm_runtime_enable(&pdev->dev); 477 pm_runtime_enable(&pdev->dev);
473 pm_runtime_get_sync(&pdev->dev); 478 pm_runtime_get_sync(&pdev->dev);
474 pm_runtime_forbid(&pdev->dev); 479 pm_runtime_forbid(&pdev->dev);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index f4878c4dec0f..123c3aa47128 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -172,6 +172,10 @@
172#define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31) 172#define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 << 31)
173#define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17) 173#define DWC3_GUSB3PIPECTL_SUSPHY (1 << 17)
174 174
175/* Global TX Fifo Size Register */
176#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff)
177#define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000)
178
175/* Global HWPARAMS1 Register */ 179/* Global HWPARAMS1 Register */
176#define DWC3_GHWPARAMS1_EN_PWROPT(n) ((n & (3 << 24)) >> 24) 180#define DWC3_GHWPARAMS1_EN_PWROPT(n) ((n & (3 << 24)) >> 24)
177#define DWC3_GHWPARAMS1_EN_PWROPT_NO 0 181#define DWC3_GHWPARAMS1_EN_PWROPT_NO 0
@@ -546,8 +550,13 @@ struct dwc3_hwparams {
546#define DWC3_MODE_DRD 2 550#define DWC3_MODE_DRD 2
547#define DWC3_MODE_HUB 3 551#define DWC3_MODE_HUB 3
548 552
553#define DWC3_MDWIDTH(n) (((n) & 0xff00) >> 8)
554
549/* HWPARAMS1 */ 555/* HWPARAMS1 */
550#define DWC3_NUM_INT(n) (((n) & (0x3f << 15)) >> 15) 556#define DWC3_NUM_INT(n) (((n) & (0x3f << 15)) >> 15)
557
558/* HWPARAMS7 */
559#define DWC3_RAM1_DEPTH(n) ((n) & 0xffff)
551 560
552struct dwc3_request { 561struct dwc3_request {
553 struct usb_request request; 562 struct usb_request request;
@@ -594,6 +603,8 @@ struct dwc3_request {
594 * @ep0_expect_in: true when we expect a DATA IN transfer 603 * @ep0_expect_in: true when we expect a DATA IN transfer
595 * @start_config_issued: true when StartConfig command has been issued 604 * @start_config_issued: true when StartConfig command has been issued
596 * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround 605 * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
606 * @needs_fifo_resize: not all users might want fifo resizing, flag it
607 * @resize_fifos: tells us it's ok to reconfigure our TxFIFO sizes.
597 * @ep0_next_event: hold the next expected event 608 * @ep0_next_event: hold the next expected event
598 * @ep0state: state of endpoint zero 609 * @ep0state: state of endpoint zero
599 * @link_state: link state 610 * @link_state: link state
@@ -651,6 +662,8 @@ struct dwc3 {
651 unsigned start_config_issued:1; 662 unsigned start_config_issued:1;
652 unsigned setup_packet_pending:1; 663 unsigned setup_packet_pending:1;
653 unsigned delayed_status:1; 664 unsigned delayed_status:1;
665 unsigned needs_fifo_resize:1;
666 unsigned resize_fifos:1;
654 667
655 enum dwc3_ep0_next ep0_next_event; 668 enum dwc3_ep0_next ep0_next_event;
656 enum dwc3_ep0_state ep0state; 669 enum dwc3_ep0_state ep0state;
@@ -812,6 +825,7 @@ union dwc3_event {
812 825
813/* prototypes */ 826/* prototypes */
814void dwc3_set_mode(struct dwc3 *dwc, u32 mode); 827void dwc3_set_mode(struct dwc3 *dwc, u32 mode);
828int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc);
815 829
816int dwc3_host_init(struct dwc3 *dwc); 830int dwc3_host_init(struct dwc3 *dwc);
817void dwc3_host_exit(struct dwc3 *dwc); 831void dwc3_host_exit(struct dwc3 *dwc);
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index e90ebb9dd3e8..5104dbf46680 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -457,8 +457,11 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
457 case DWC3_ADDRESS_STATE: 457 case DWC3_ADDRESS_STATE:
458 ret = dwc3_ep0_delegate_req(dwc, ctrl); 458 ret = dwc3_ep0_delegate_req(dwc, ctrl);
459 /* if the cfg matches and the cfg is non zero */ 459 /* if the cfg matches and the cfg is non zero */
460 if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) 460 if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
461 dwc->dev_state = DWC3_CONFIGURED_STATE; 461 dwc->dev_state = DWC3_CONFIGURED_STATE;
462 dwc->resize_fifos = true;
463 dev_dbg(dwc->dev, "resize fifos flag SET\n");
464 }
462 break; 465 break;
463 466
464 case DWC3_CONFIGURED_STATE: 467 case DWC3_CONFIGURED_STATE:
@@ -707,6 +710,12 @@ static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum)
707{ 710{
708 struct dwc3_ep *dep = dwc->eps[epnum]; 711 struct dwc3_ep *dep = dwc->eps[epnum];
709 712
713 if (dwc->resize_fifos) {
714 dev_dbg(dwc->dev, "starting to resize fifos\n");
715 dwc3_gadget_resize_tx_fifos(dwc);
716 dwc->resize_fifos = 0;
717 }
718
710 WARN_ON(dwc3_ep0_start_control_status(dep)); 719 WARN_ON(dwc3_ep0_start_control_status(dep));
711} 720}
712 721
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index d406a75456a0..7913d1b50e38 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -125,6 +125,80 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state)
125 return -ETIMEDOUT; 125 return -ETIMEDOUT;
126} 126}
127 127
128/**
129 * dwc3_gadget_resize_tx_fifos - reallocate fifo spaces for current use-case
130 * @dwc: pointer to our context structure
131 *
132 * This function will a best effort FIFO allocation in order
133 * to improve FIFO usage and throughput, while still allowing
134 * us to enable as many endpoints as possible.
135 *
136 * Keep in mind that this operation will be highly dependent
137 * on the configured size for RAM1 - which contains TxFifo -,
138 * the amount of endpoints enabled on coreConsultant tool, and
139 * the width of the Master Bus.
140 *
141 * In the ideal world, we would always be able to satisfy the
142 * following equation:
143 *
144 * ((512 + 2 * MDWIDTH-Bytes) + (Number of IN Endpoints - 1) * \
145 * (3 * (1024 + MDWIDTH-Bytes) + MDWIDTH-Bytes)) / MDWIDTH-Bytes
146 *
147 * Unfortunately, due to many variables that's not always the case.
148 */
149int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc)
150{
151 int last_fifo_depth = 0;
152 int ram1_depth;
153 int fifo_size;
154 int mdwidth;
155 int num;
156
157 if (!dwc->needs_fifo_resize)
158 return 0;
159
160 ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
161 mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0);
162
163 /* MDWIDTH is represented in bits, we need it in bytes */
164 mdwidth >>= 3;
165
166 /*
167 * FIXME For now we will only allocate 1 wMaxPacketSize space
168 * for each enabled endpoint, later patches will come to
169 * improve this algorithm so that we better use the internal
170 * FIFO space
171 */
172 for (num = 0; num < DWC3_ENDPOINTS_NUM; num++) {
173 struct dwc3_ep *dep = dwc->eps[num];
174 int fifo_number = dep->number >> 1;
175 int tmp;
176
177 if (!(dep->number & 1))
178 continue;
179
180 if (!(dep->flags & DWC3_EP_ENABLED))
181 continue;
182
183 tmp = dep->endpoint.maxpacket;
184 tmp += mdwidth;
185 tmp += mdwidth;
186
187 fifo_size = DIV_ROUND_UP(tmp, mdwidth);
188 fifo_size |= (last_fifo_depth << 16);
189
190 dev_vdbg(dwc->dev, "%s: Fifo Addr %04x Size %d\n",
191 dep->name, last_fifo_depth, fifo_size & 0xffff);
192
193 dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(fifo_number),
194 fifo_size);
195
196 last_fifo_depth += (fifo_size & 0xffff);
197 }
198
199 return 0;
200}
201
128void dwc3_map_buffer_to_dma(struct dwc3_request *req) 202void dwc3_map_buffer_to_dma(struct dwc3_request *req)
129{ 203{
130 struct dwc3 *dwc = req->dep->dwc; 204 struct dwc3 *dwc = req->dep->dwc;