diff options
author | Sevak Arakelyan <sevaka@synopsys.com> | 2017-01-23 15:01:23 -0800 |
---|---|---|
committer | Felipe Balbi <felipe.balbi@linux.intel.com> | 2017-01-24 16:19:11 +0200 |
commit | c138ecfa6108edee17fabfa56285b00f66641659 (patch) | |
tree | c7e467bba6576b96808dfddfeee77e8f66bd80d4 /drivers/usb/dwc2 | |
parent | e1f411d1b3db49a2089f47087410dcfec6564e28 (diff) | |
download | linux-c138ecfa6108edee17fabfa56285b00f66641659.tar.bz2 |
usb: dwc2: gadget: Set TX FIFO depths to calculated defaults
Remove legacy DWC2_G_P_LEGACY_TX_FIFO_SIZE array for TX FIFOs.
Update dwc2_set_param_tx_fifo_sizes function to calculate
and assign default average FIFO depth to each member of
g_tx_fifo_size array. Total FIFO size, EP Info block's size,
FIFO operation mode and device operation mode are taken into
consideration during the calculation.
Cc: Stefan Wahren <stefan.wahren@i2se.com>
Signed-off-by: Sevak Arakelyan <sevaka@synopsys.com>
Signed-off-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Diffstat (limited to 'drivers/usb/dwc2')
-rw-r--r-- | drivers/usb/dwc2/core.h | 16 | ||||
-rw-r--r-- | drivers/usb/dwc2/gadget.c | 93 | ||||
-rw-r--r-- | drivers/usb/dwc2/params.c | 12 |
3 files changed, 110 insertions, 11 deletions
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 5370e6429f28..f10eca91d2be 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -274,13 +274,6 @@ enum dwc2_lx_state { DWC2_L3, /* Off state */ }; -/* - * Gadget periodic tx fifo sizes as used by legacy driver - * EP0 is not included - */ -#define DWC2_G_P_LEGACY_TX_FIFO_SIZE {256, 256, 256, 256, 768, 768, 768, \ - 768, 0, 0, 0, 0, 0, 0, 0} - /* Gadget ep0 states */ enum dwc2_ep0_state { DWC2_EP0_SETUP, @@ -1180,6 +1173,9 @@ int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode); #define dwc2_is_device_connected(hsotg) (hsotg->connected) int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg); int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg); +int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg); +int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg); +int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg); #else static inline int dwc2_hsotg_remove(struct dwc2_hsotg *dwc2) { return 0; } @@ -1201,6 +1197,12 @@ static inline int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) { return 0; } static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg) { return 0; } +static inline int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg) +{ return 0; } +static inline int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg) +{ return 0; } +static inline int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg) +{ return 0; } #endif #if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 30ff51eab35c..eb579b6f68f0 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -192,6 +192,99 @@ static void dwc2_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg, } /** + * dwc2_hsotg_tx_fifo_count - return count of TX FIFOs in device mode + */ +int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg) +{ + if (hsotg->hw_params.en_multiple_tx_fifo) + /* In dedicated FIFO mode we need count of IN EPs */ + return (dwc2_readl(hsotg->regs + GHWCFG4) & + GHWCFG4_NUM_IN_EPS_MASK) >> GHWCFG4_NUM_IN_EPS_SHIFT; + else + /* In shared FIFO mode we need count of Periodic IN EPs */ + return hsotg->hw_params.num_dev_perio_in_ep; +} + +/** + * dwc2_hsotg_ep_info_size - return Endpoint Info Control block size in DWORDs + */ +static int dwc2_hsotg_ep_info_size(struct dwc2_hsotg *hsotg) +{ + int val = 0; + int i; + u32 ep_dirs; + + /* + * Don't need additional space for ep info control registers in + * slave mode. + */ + if (!using_dma(hsotg)) { + dev_dbg(hsotg->dev, "Buffer DMA ep info size 0\n"); + return 0; + } + + /* + * Buffer DMA mode - 1 location per endpoit + * Descriptor DMA mode - 4 locations per endpoint + */ + ep_dirs = hsotg->hw_params.dev_ep_dirs; + + for (i = 0; i <= hsotg->hw_params.num_dev_ep; i++) { + val += ep_dirs & 3 ? 1 : 2; + ep_dirs >>= 2; + } + + if (using_desc_dma(hsotg)) + val = val * 4; + + return val; +} + +/** + * dwc2_hsotg_tx_fifo_total_depth - return total FIFO depth available for + * device mode TX FIFOs + */ +int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg) +{ + int ep_info_size; + int addr; + int tx_addr_max; + u32 np_tx_fifo_size; + + np_tx_fifo_size = min_t(u32, hsotg->hw_params.dev_nperio_tx_fifo_size, + hsotg->params.g_np_tx_fifo_size); + + /* Get Endpoint Info Control block size in DWORDs. */ + ep_info_size = dwc2_hsotg_ep_info_size(hsotg); + tx_addr_max = hsotg->hw_params.total_fifo_size - ep_info_size; + + addr = hsotg->params.g_rx_fifo_size + np_tx_fifo_size; + if (tx_addr_max <= addr) + return 0; + + return tx_addr_max - addr; +} + +/** + * dwc2_hsotg_tx_fifo_average_depth - returns average depth of device mode + * TX FIFOs + */ +int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg) +{ + int tx_fifo_count; + int tx_fifo_depth; + + tx_fifo_depth = dwc2_hsotg_tx_fifo_total_depth(hsotg); + + tx_fifo_count = dwc2_hsotg_tx_fifo_count(hsotg); + + if (!tx_fifo_count) + return tx_fifo_depth; + else + return tx_fifo_depth / tx_fifo_count; +} + +/** * dwc2_hsotg_init_fifo - initialise non-periodic FIFOs * @hsotg: The device instance. */ diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 8e5039e2d3fc..016fff0cb887 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -207,12 +207,16 @@ static void dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg) static void dwc2_set_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg) { struct dwc2_core_params *p = &hsotg->params; - u32 p_tx_fifo[] = DWC2_G_P_LEGACY_TX_FIFO_SIZE; + int depth_average; + int fifo_count; + int i; + + fifo_count = dwc2_hsotg_tx_fifo_count(hsotg); memset(p->g_tx_fifo_size, 0, sizeof(p->g_tx_fifo_size)); - memcpy(&p->g_tx_fifo_size[1], - p_tx_fifo, - sizeof(p_tx_fifo)); + depth_average = dwc2_hsotg_tx_fifo_average_depth(hsotg); + for (i = 1; i <= fifo_count; i++) + p->g_tx_fifo_size[i] = depth_average; } /** |