diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 623afe6ba90f..7589bcdc9a27 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -748,6 +748,101 @@ void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc) dwc->num_ep_resized = 0; } +/** + * __dwc3_gadget_resize_tx_fifos - reallocate fifo spaces for Rockchip platform + * + * @dep: pointer to dwc3_ep structure + * + * According to the different USB transfer type and Speed, + * this function will a best effort FIFO allocation in order + * to improve FIFO usage and throughput, while still allowing + * us to enable as many endpoints as possible. + */ +static int __dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep) +{ + struct dwc3 *dwc = dep->dwc; + u32 fifo_0_start, last_fifo_depth, ram1_depth; + u32 fifo_size, maxpacket, mdwidth, mult; + u32 tmp; + + if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { + /* + * Set enough tx fifos for Isochronous endpoints to get better + * performance and more compliance with bus latency. + */ + maxpacket = dep->endpoint.maxpacket; + if (gadget_is_superspeed(dwc->gadget)) + mult = dep->endpoint.mult * dep->endpoint.maxburst; + else + mult = dep->endpoint.mult; + + mult = mult > 0 ? mult * 2 : 3; + if (mult > 6) + mult = 6; + } else if (usb_endpoint_xfer_bulk(dep->endpoint.desc)) { + /* + * Set enough tx fifos for Bulk endpoints to get + * better transmission performance. + */ + mult = 3; + if (gadget_is_superspeed(dwc->gadget)) { + if (dep->endpoint.maxburst > mult) { + mult = dep->endpoint.maxburst; + if (mult > 6) + mult = 6; + } + maxpacket = 1024; + } else { + maxpacket = 512; + } + } else if (usb_endpoint_xfer_int(dep->endpoint.desc)) { + /* + * REVIST: we assume that the maxpacket of interrupt + * endpoint is 64 Bytes for MTP and the other functions. + */ + mult = 1; + maxpacket = 64; + } else { + goto out; + } + + mdwidth = dwc3_mdwidth(dwc); + mdwidth >>= 3; /* bits convert to bytes */ + ram1_depth = dwc3_gadget_get_tx_fifos_size(dwc); + last_fifo_depth = dwc->last_fifo_depth; + + /* Calculate the fifo size for this EP */ + tmp = mult * (maxpacket + mdwidth); + tmp += mdwidth; + fifo_size = DIV_ROUND_UP(tmp, mdwidth); + + /* Check if TXFIFOs start at non-zero addr */ + tmp = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0)); + fifo_0_start = DWC3_GTXFIFOSIZ_TXFSTADDR(tmp); + fifo_size |= (fifo_0_start + (last_fifo_depth << 16)); + + if (DWC3_IP_IS(DWC3)) + last_fifo_depth += DWC3_GTXFIFOSIZ_TXFDEP(fifo_size); + else + last_fifo_depth += DWC31_GTXFIFOSIZ_TXFDEP(fifo_size); + + /* Check fifo size allocation doesn't exceed available RAM size. */ + if (last_fifo_depth >= ram1_depth) { + dev_err(dwc->dev, "Fifosize(0x%x) > RAM size(0x%x) %s depth(0x%x)\n", + last_fifo_depth, ram1_depth, + dep->endpoint.name, fifo_size & 0xfff); + return -ENOMEM; + } + + dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(dep->number >> 1), fifo_size); + dep->flags |= DWC3_EP_TXFIFO_RESIZED; + dwc->last_fifo_depth = last_fifo_depth; + dwc->num_ep_resized++; + +out: + return 0; +} + /* * dwc3_gadget_resize_tx_fifos - reallocate fifo spaces for current use-case * @dwc: pointer to our context structure @@ -793,6 +888,9 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep) if (dep->flags & DWC3_EP_TXFIFO_RESIZED) return 0; + if (IS_REACHABLE(CONFIG_ARCH_ROCKCHIP)) + return __dwc3_gadget_resize_tx_fifos(dep); + ram1_depth = dwc3_gadget_get_tx_fifos_size(dwc); if ((dep->endpoint.maxburst > 1 &&