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

Commit eb380dff authored by Manu Gautam's avatar Manu Gautam Committed by Hemant Kumar
Browse files

usb: dwc3-msm: Use dummy buffer as doorbell until GSI is ready



USB GSI wrapper can try to access IPA GSI Doorbell as soon as
endpoint is enabled and transfers are started. However there
is always going to be some delay when transfers are started
and GSI doorbell address is updated. This may result in USB
GSI wrapper accessing address-0. Prevent this by using some
dummy buffer as doorbell until IPA GSI connections are setup.
At that stage driver will override doorbell address with valid
one.

Change-Id: I477602d33737a994992c5394c6c08d63744e525f
Signed-off-by: default avatarManu Gautam <mgautam@codeaurora.org>
parent df3d8915
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -326,6 +326,8 @@ struct dwc3_msm {
	struct notifier_block	dpdm_nb;
	struct regulator	*dpdm_reg;

	u64			dummy_gsi_db;
	dma_addr_t		dummy_gsi_db_dma;
};

#define USB_HSPHY_3P3_VOL_MIN		3050000 /* uV */
@@ -1003,6 +1005,10 @@ static void gsi_store_ringbase_dbl_info(struct usb_ep *ep,
		ep->name, request->db_reg_phs_addr_lsb,
		(unsigned long long)request->mapped_db_reg_phs_addr_lsb);

	/*
	 * Replace dummy doorbell address with real one as IPA connection
	 * is setup now and GSI must be ready to handle doorbell updates.
	 */
	dwc3_msm_write_reg(mdwc->base,
		GSI_DBL_ADDR_L(mdwc->gsi_reg[DBL_ADDR_L], (n)),
		(u32)request->mapped_db_reg_phs_addr_lsb);
@@ -1279,9 +1285,18 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request)
	struct dwc3_gadget_ep_cmd_params params;
	const struct usb_endpoint_descriptor *desc = ep->desc;
	const struct usb_ss_ep_comp_descriptor *comp_desc = ep->comp_desc;
	int n = ep->ep_intr_num - 1;
	u32 reg;
	int ret;

	/* setup dummy doorbell as IPA connection isn't setup yet */
	dwc3_msm_write_reg_field(mdwc->base,
			GSI_DBL_ADDR_L(mdwc->gsi_reg[DBL_ADDR_L], (n)),
			~0x0, (u32)mdwc->dummy_gsi_db_dma);
	dev_dbg(mdwc->dev, "Dummy DB Addr %pK: %llx %llx (LSB)\n",
		&mdwc->dummy_gsi_db, mdwc->dummy_gsi_db_dma,
		(u32)mdwc->dummy_gsi_db_dma);

	memset(&params, 0x00, sizeof(params));

	/* Configure GSI EP */
@@ -1972,6 +1987,19 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
			}
			mdwc->gsi_ev_buff[i] = evt;
		}
		/*
		 * Set-up dummy buffer to use as doorbell while IPA GSI
		 * connection is in progress.
		 */
		mdwc->dummy_gsi_db_dma = dma_map_single(dwc->sysdev,
						&mdwc->dummy_gsi_db,
						sizeof(mdwc->dummy_gsi_db),
						DMA_FROM_DEVICE);

		if (dma_mapping_error(dwc->sysdev, mdwc->dummy_gsi_db_dma)) {
			dev_err(dwc->dev, "failed to map dummy doorbell buffer\n");
			mdwc->dummy_gsi_db_dma = (dma_addr_t)NULL;
		}
		break;
	case DWC3_GSI_EVT_BUF_SETUP:
		dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_SETUP\n");
@@ -2045,6 +2073,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_gsi_db_dma) {
			dma_unmap_single(dwc->sysdev, mdwc->dummy_gsi_db_dma,
					 sizeof(mdwc->dummy_gsi_db),
					 DMA_FROM_DEVICE);
			mdwc->dummy_gsi_db_dma = (dma_addr_t)NULL;
		}
		break;
	case DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER:
		dwc3_msm_dbm_disable_updxfer(dwc, value);