Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c138ecfa authored by Sevak Arakelyan's avatar Sevak Arakelyan Committed by Felipe Balbi
Browse files

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: default avatarSevak Arakelyan <sevaka@synopsys.com>
Signed-off-by: default avatarJohn Youn <johnyoun@synopsys.com>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
parent e1f411d1
Loading
Loading
Loading
Loading
+9 −7
Original line number Diff line number Diff line
@@ -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)
+93 −0
Original line number Diff line number Diff line
@@ -191,6 +191,99 @@ static void dwc2_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg,
	local_irq_restore(flags);
}

/**
 * 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.
+8 −4
Original line number Diff line number Diff line
@@ -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;
}

/**