the second element is expected to be a handle to the USB3/SS PHY
- phys: from the *Generic PHY* bindings
- phy-names: from the *Generic PHY* bindings
+ - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
- snps,usb3_lpm_capable: determines if platform is USB3 LPM capable
- snps,disable_scramble_quirk: true when SW should disable data scrambling.
Only really useful for FPGA builds.
register for post-silicon frame length adjustment when the
fladj_30mhz_sdbnd signal is invalid or incorrect.
- - <DEPRECATED> tx-fifo-resize: determines if the FIFO *has* to be reallocated.
-
This is usually a subnode to DWC3 glue to which it is connected.
dwc3@4a030000 {
reg = <0x4a030000 0xcfff>;
interrupts = <0 92 4>
usb-phy = <&usb2_phy>, <&usb3,phy>;
+ tx-fifo-resize;
};
interrupts = <0 205 0x4>;
phys = <&hs_phy>, <&ss_phy>;
phy-names = "usb2-phy", "usb3-phy";
+ tx-fifo-resize;
dr_mode = "host";
};
};
dwc->usb3_lpm_capable = device_property_read_bool(dev,
"snps,usb3_lpm_capable");
+ dwc->needs_fifo_resize = device_property_read_bool(dev,
+ "tx-fifo-resize");
+
dwc->disable_scramble_quirk = device_property_read_bool(dev,
"snps,disable_scramble_quirk");
dwc->u2exit_lfps_quirk = device_property_read_bool(dev,
if (pdata->hird_threshold)
hird_threshold = pdata->hird_threshold;
+ dwc->needs_fifo_resize = pdata->tx_fifo_resize;
dwc->usb3_lpm_capable = pdata->usb3_lpm_capable;
dwc->dr_mode = pdata->dr_mode;
* 0 - utmi_sleep_n
* 1 - utmi_l1_suspend_n
* @is_fpga: true when we are using the FPGA board
+ * @needs_fifo_resize: not all users might want fifo resizing, flag it
* @enabled: true when gadget driver is ready
* @pullups_connected: true when Run/Stop bit is set
+ * @resize_fifos: tells us it's ok to reconfigure our TxFIFO sizes.
* @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
* @start_config_issued: true when StartConfig command has been issued
* @three_stage_setup: set if we perform a three phase setup
unsigned has_lpm_erratum:1;
unsigned is_utmi_l1_suspend:1;
unsigned is_fpga:1;
+ unsigned needs_fifo_resize:1;
unsigned enabled:1;
unsigned pullups_connected:1;
+ unsigned resize_fifos:1;
unsigned setup_packet_pending:1;
unsigned three_stage_setup:1;
unsigned usb3_lpm_capable:1;
/* prototypes */
void dwc3_set_mode(struct dwc3 *dwc, u32 mode);
+int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc);
int dwc3_soft_reset(struct dwc3 *dwc);
int dwc3_event_buffers_setup(struct dwc3 *dwc);
void dwc3_event_buffers_cleanup(struct dwc3 *dwc);
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA);
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
+ dwc->resize_fifos = true;
+ dwc3_trace(trace_dwc3_ep0, "resize FIFOs flag SET");
}
break;
static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep)
{
+ if (dwc->resize_fifos) {
+ dwc3_trace(trace_dwc3_ep0, "Resizing FIFOs");
+ dwc3_gadget_resize_tx_fifos(dwc);
+ dwc->resize_fifos = 0;
+ }
+
WARN_ON(dwc3_ep0_start_control_status(dep));
}
return -ETIMEDOUT;
}
+/**
+ * dwc3_gadget_resize_tx_fifos - reallocate fifo spaces for current use-case
+ * @dwc: pointer to our context structure
+ *
+ * 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.
+ *
+ * Keep in mind that this operation will be highly dependent
+ * on the configured size for RAM1 - which contains TxFifo -,
+ * the amount of endpoints enabled on coreConsultant tool, and
+ * the width of the Master Bus.
+ *
+ * In the ideal world, we would always be able to satisfy the
+ * following equation:
+ *
+ * ((512 + 2 * MDWIDTH-Bytes) + (Number of IN Endpoints - 1) * \
+ * (3 * (1024 + MDWIDTH-Bytes) + MDWIDTH-Bytes)) / MDWIDTH-Bytes
+ *
+ * Unfortunately, due to many variables that's not always the case.
+ */
+int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc)
+{
+ int last_fifo_depth = 0;
+ int ram1_depth;
+ int fifo_size;
+ int mdwidth;
+ int num;
+
+ if (!dwc->needs_fifo_resize)
+ return 0;
+
+ ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
+ mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0);
+
+ /* MDWIDTH is represented in bits, we need it in bytes */
+ mdwidth >>= 3;
+
+ /*
+ * FIXME For now we will only allocate 1 wMaxPacketSize space
+ * for each enabled endpoint, later patches will come to
+ * improve this algorithm so that we better use the internal
+ * FIFO space
+ */
+ for (num = 0; num < dwc->num_in_eps; num++) {
+ /* bit0 indicates direction; 1 means IN ep */
+ struct dwc3_ep *dep = dwc->eps[(num << 1) | 1];
+ int mult = 1;
+ int tmp;
+
+ if (!(dep->flags & DWC3_EP_ENABLED))
+ continue;
+
+ if (usb_endpoint_xfer_bulk(dep->endpoint.desc)
+ || usb_endpoint_xfer_isoc(dep->endpoint.desc))
+ mult = 3;
+
+ /*
+ * REVISIT: the following assumes we will always have enough
+ * space available on the FIFO RAM for all possible use cases.
+ * Make sure that's true somehow and change FIFO allocation
+ * accordingly.
+ *
+ * If we have Bulk or Isochronous endpoints, we want
+ * them to be able to be very, very fast. So we're giving
+ * those endpoints a fifo_size which is enough for 3 full
+ * packets
+ */
+ tmp = mult * (dep->endpoint.maxpacket + mdwidth);
+ tmp += mdwidth;
+
+ fifo_size = DIV_ROUND_UP(tmp, mdwidth);
+
+ fifo_size |= (last_fifo_depth << 16);
+
+ dwc3_trace(trace_dwc3_gadget, "%s: Fifo Addr %04x Size %d",
+ dep->name, last_fifo_depth, fifo_size & 0xffff);
+
+ dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(num), fifo_size);
+
+ last_fifo_depth += (fifo_size & 0xffff);
+ }
+
+ return 0;
+}
+
void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
int status)
{
struct dwc3_platform_data {
enum usb_device_speed maximum_speed;
enum usb_dr_mode dr_mode;
+ bool tx_fifo_resize;
bool usb3_lpm_capable;
bool phyif_utmi_16_bits;