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

Commit 0d3cc847 authored by Ajay Agarwal's avatar Ajay Agarwal Committed by Gerrit - the friendly Code Review server
Browse files

usb: gadget: Add support for RmNet CV2X instance



Add support for RmNet CV2X interface. Details of the patch:
 - Add support for 2 normal EPs to be used in GSI mode
 - Add new protocol ID and make necessary changes

For this new protocol USB_PROT_RMNET_V2X_IPA:
 - Use USB2_PROD and USB2_CONS as channel client type
 - Use normal EPs
 - Pass dummy GEVENTCOUNT register address to GSI.

Change-Id: I35e7f4f52562cd4fa8ffab4e2950c17827c2cc4f
Signed-off-by: default avatarAjay Agarwal <ajaya@codeaurora.org>
parent 22f3f5d7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ Optional properties:
	during bus suspend.
 - snps,usb3-u1u2-disable: If present, disable U1U2 low power modes in Superspeed mode
 - snps,usb2-l1-disable: If present, disable L1 low power modes in Highspeed mode
 - normal-eps-in-gsi-mode: If present, two normal EPS (1 In, 1 Out) can be used in GSI mode

This is usually a subnode to DWC3 glue to which it is connected.

+2 −0
Original line number Diff line number Diff line
@@ -1284,6 +1284,8 @@ static int dwc3_probe(struct platform_device *pdev)
					"snps,usb3-u1u2-disable");
	dwc->usb2_l1_disable = device_property_read_bool(dev,
					"snps,usb2-l1-disable");
	dwc->normal_eps_in_gsi_mode = device_property_read_bool(dev,
					"normal-eps-in-gsi-mode");
	if (dwc->enable_bus_suspend) {
		pm_runtime_set_autosuspend_delay(dev, 500);
		pm_runtime_use_autosuspend(dev);
+3 −0
Original line number Diff line number Diff line
@@ -991,6 +991,8 @@ struct dwc3_scratchpad_array {
 * @create_reg_debugfs: create debugfs entry to allow dwc3 register dump
 * @xhci_imod_value: imod value to use with xhci
 * @core_id: usb core id to differentiate different controller
 * @normal_eps_in_gsi_mode: if true, two normal EPS (1 In, 1 Out) can be used in
 *			    GSI mode
 */
struct dwc3 {
	struct usb_ctrlrequest	*ctrl_req;
@@ -1193,6 +1195,7 @@ struct dwc3 {
	u32			xhci_imod_value;
	int			core_id;
	int			retries_on_error;
	bool			normal_eps_in_gsi_mode;
};

/* -------------------------------------------------------------------------- */
+34 −7
Original line number Diff line number Diff line
@@ -312,6 +312,8 @@ struct dwc3_msm {

	u64			dummy_gsi_db;
	dma_addr_t		dummy_gsi_db_dma;
	u64			dummy_gevntcnt;
	dma_addr_t		dummy_gevntcnt_dma;
};

#define USB_HSPHY_3P3_VOL_MIN		3050000 /* uV */
@@ -864,6 +866,7 @@ static void gsi_get_channel_info(struct usb_ep *ep,
	int last_trb_index = 0;
	struct dwc3	*dwc = dep->dwc;
	struct usb_gsi_request *request = ch_info->ch_req;
	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);

	/* Provide physical USB addresses for DEPCMD and GEVENTCNT registers */
	ch_info->depcmd_low_addr = (u32)(dwc->reg_phys +
@@ -898,6 +901,8 @@ static void gsi_get_channel_info(struct usb_ep *ep,
	/* Store last 16 bits of LINK TRB address as per GSI hw requirement */
	ch_info->last_trb_addr = (dwc3_trb_dma_offset(dep,
			&dep->trb_pool[last_trb_index - 1]) & 0x0000FFFF);
	dev_dbg(dwc->dev, "depcmd_laddr=%x last_trb_addr=%x\n",
		ch_info->depcmd_low_addr, ch_info->last_trb_addr);

	/*
	 * Check if NORMAL EP is used with GSI. In that case USB driver
@@ -906,15 +911,18 @@ static void gsi_get_channel_info(struct usb_ep *ep,
	if (ep->ep_intr_num) {
		ch_info->gevntcount_low_addr = (u32)(dwc->reg_phys +
			DWC3_GEVNTCOUNT(ep->ep_intr_num));
	} else {
		dev_dbg(dwc->dev, "gevntcount returned as 0 for normal EP\n");
	}
		ch_info->gevntcount_hi_addr = 0;

	dev_dbg(dwc->dev,
	"depcmd_laddr=%x last_trb_addr=%x gevtcnt_laddr=%x gevtcnt_haddr=%x",
		ch_info->depcmd_low_addr, ch_info->last_trb_addr,
		dev_dbg(dwc->dev, "gevtcnt_laddr=%x gevtcnt_haddr=%x\n",
		     ch_info->gevntcount_low_addr, ch_info->gevntcount_hi_addr);
	} else {
		ch_info->gevntcount_low_addr = (u32)mdwc->dummy_gevntcnt_dma;
		ch_info->gevntcount_hi_addr =
				(u32)((u64)mdwc->dummy_gevntcnt_dma >> 32);
		dev_dbg(dwc->dev, "Dummy GEVNTCNT Addr %pK: %llx %x (LSB)\n",
			&mdwc->dummy_gevntcnt,
			(unsigned long long)mdwc->dummy_gevntcnt_dma,
			(u32)mdwc->dummy_gevntcnt_dma);
	}
}

/*
@@ -2129,6 +2137,19 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
			dev_err(dwc->dev, "failed to map dummy doorbell buffer\n");
			mdwc->dummy_gsi_db_dma = (dma_addr_t)NULL;
		}

		/*
		 * Set-up dummy GEVNTCOUNT address to be passed on to GSI for
		 * normal (non HW-accelerated) EPs.
		 */
		mdwc->dummy_gevntcnt_dma = dma_map_single(dwc->sysdev,
						&mdwc->dummy_gevntcnt,
						sizeof(mdwc->dummy_gevntcnt),
						DMA_FROM_DEVICE);
		if (dma_mapping_error(dwc->sysdev, mdwc->dummy_gevntcnt_dma)) {
			dev_err(dwc->dev, "failed to map dummy geventcount\n");
			mdwc->dummy_gevntcnt_dma = (dma_addr_t)NULL;
		}
		break;
	case DWC3_GSI_EVT_BUF_SETUP:
		dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_SETUP\n");
@@ -2202,6 +2223,12 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
				dma_free_coherent(dwc->sysdev, evt->length,
							evt->buf, evt->dma);
		}
		if (mdwc->dummy_gevntcnt_dma) {
			dma_unmap_single(dwc->sysdev, mdwc->dummy_gevntcnt_dma,
					 sizeof(mdwc->dummy_gevntcnt),
					 DMA_FROM_DEVICE);
			mdwc->dummy_gevntcnt_dma = (dma_addr_t)NULL;
		}
		if (mdwc->dummy_gsi_db_dma) {
			dma_unmap_single(dwc->sysdev, mdwc->dummy_gsi_db_dma,
					 sizeof(mdwc->dummy_gsi_db),
+5 −5
Original line number Diff line number Diff line
@@ -2390,8 +2390,8 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {

/* -------------------------------------------------------------------------- */

#define NUM_GSI_OUT_EPS	1
#define NUM_GSI_IN_EPS	2
#define NUM_GSI_OUT_EPS(dwc)	(dwc->normal_eps_in_gsi_mode ? 2 : 1)
#define NUM_GSI_IN_EPS(dwc)	(dwc->normal_eps_in_gsi_mode ? 3 : 2)

static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
		u8 num, u32 direction)
@@ -2399,13 +2399,13 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
	struct dwc3_ep			*dep;
	u8				i, gsi_ep_count, gsi_ep_index = 0;

	gsi_ep_count = NUM_GSI_OUT_EPS + NUM_GSI_IN_EPS;
	gsi_ep_count = NUM_GSI_OUT_EPS(dwc) + NUM_GSI_IN_EPS(dwc);
	/* OUT GSI EPs based on direction field */
	if (gsi_ep_count && !direction)
		gsi_ep_count = NUM_GSI_OUT_EPS;
		gsi_ep_count = NUM_GSI_OUT_EPS(dwc);
	/* IN GSI EPs */
	else if (gsi_ep_count && direction)
		gsi_ep_count = NUM_GSI_IN_EPS;
		gsi_ep_count = NUM_GSI_IN_EPS(dwc);

	for (i = 0; i < num; i++) {
		u8 epnum = (i << 1) | (direction ? 1 : 0);
Loading