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

Commit a636518d authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: dwc3-msm: Support > 32-bit DMA addresses for GSI"

parents 46b9d552 706a1a8c
Loading
Loading
Loading
Loading
+77 −70
Original line number Diff line number Diff line
@@ -95,18 +95,23 @@
#define GSI_TRB_ADDR_BIT_53_MASK	(1 << 21)
#define GSI_TRB_ADDR_BIT_55_MASK	(1 << 23)

#define	GSI_GENERAL_CFG_REG(offset) (QSCRATCH_REG_OFFSET + offset)
#define	GSI_GENERAL_CFG_REG(reg)	(QSCRATCH_REG_OFFSET + \
						reg[GENERAL_CFG_REG])
#define	GSI_RESTART_DBL_PNTR_MASK	BIT(20)
#define	GSI_CLK_EN_MASK			BIT(12)
#define	BLOCK_GSI_WR_GO_MASK		BIT(1)
#define	GSI_EN_MASK			BIT(0)

#define GSI_DBL_ADDR_L(offset, n)	((QSCRATCH_REG_OFFSET + offset) + (n*4))
#define GSI_DBL_ADDR_H(offset, n)	((QSCRATCH_REG_OFFSET + offset) + (n*4))
#define GSI_RING_BASE_ADDR_L(offset, n)	((QSCRATCH_REG_OFFSET + offset) + (n*4))
#define GSI_RING_BASE_ADDR_H(offset, n)	((QSCRATCH_REG_OFFSET + offset) + (n*4))
#define GSI_DBL_ADDR_L(reg, n)		(QSCRATCH_REG_OFFSET + \
						reg[DBL_ADDR_L] + (n*4))
#define GSI_DBL_ADDR_H(reg, n)		(QSCRATCH_REG_OFFSET + \
						reg[DBL_ADDR_H] + (n*4))
#define GSI_RING_BASE_ADDR_L(reg, n)	(QSCRATCH_REG_OFFSET + \
						reg[RING_BASE_ADDR_L] + (n*4))
#define GSI_RING_BASE_ADDR_H(reg, n)	(QSCRATCH_REG_OFFSET + \
						reg[RING_BASE_ADDR_H] + (n*4))

#define	GSI_IF_STS(offset)	(QSCRATCH_REG_OFFSET + offset)
#define	GSI_IF_STS(reg)			(QSCRATCH_REG_OFFSET + reg[IF_STS])
#define	GSI_WR_CTRL_STATE_MASK	BIT(15)

#define DWC3_GEVNTCOUNT_EVNTINTRPTMASK		(1 << 31)
@@ -698,7 +703,7 @@ static int __dwc3_msm_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
	memset(trb_link, 0, sizeof(*trb_link));

	trb_link->bpl = lower_32_bits(req->trb_dma);
	trb_link->bph = DBM_TRB_BIT |
	trb_link->bph = upper_32_bits(req->trb_dma) | DBM_TRB_BIT |
			DBM_TRB_DMA | DBM_TRB_EP_NUM(dep->number);
	trb_link->size = 0;
	trb_link->ctrl = DWC3_TRBCTL_LINK_TRB | DWC3_TRB_CTRL_HWO;
@@ -707,7 +712,7 @@ static int __dwc3_msm_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
	 * Now start the transfer
	 */
	memset(&params, 0, sizeof(params));
	params.param0 = 0; /* TDAddr High */
	params.param0 = upper_32_bits(req->trb_dma); /* TDAddr High */
	params.param1 = lower_32_bits(req->trb_dma); /* DAddr Low */

	/* DBM requires IOC to be set */
@@ -956,6 +961,8 @@ static int gsi_startxfer_for_ep(struct usb_ep *ep)

	memset(&params, 0, sizeof(params));
	params.param0 = GSI_TRB_ADDR_BIT_53_MASK | GSI_TRB_ADDR_BIT_55_MASK;
	params.param0 |= upper_32_bits(dwc3_trb_dma_offset(dep,
						&dep->trb_pool[0]) & 0xffff);
	params.param0 |= (ep->ep_intr_num << 16);
	params.param1 = lower_32_bits(dwc3_trb_dma_offset(dep,
						&dep->trb_pool[0]));
@@ -985,9 +992,14 @@ static void gsi_store_ringbase_dbl_info(struct usb_ep *ep,
	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
	int n = ep->ep_intr_num - 1;

	dwc3_msm_write_reg(mdwc->base,
		GSI_RING_BASE_ADDR_L(mdwc->gsi_reg[RING_BASE_ADDR_L], (n)),
		dwc3_trb_dma_offset(dep, &dep->trb_pool[0]));
	dwc3_msm_write_reg(mdwc->base, GSI_RING_BASE_ADDR_L(mdwc->gsi_reg, n),
		lower_32_bits(dwc3_trb_dma_offset(dep, &dep->trb_pool[0])));
	dwc3_msm_write_reg(mdwc->base, GSI_RING_BASE_ADDR_H(mdwc->gsi_reg, n),
		upper_32_bits(dwc3_trb_dma_offset(dep, &dep->trb_pool[0])));

	dev_dbg(mdwc->dev, "Ring Base Addr %d: %x (LSB) %x (MSB)\n", n,
		lower_32_bits(dwc3_trb_dma_offset(dep, &dep->trb_pool[0])),
		upper_32_bits(dwc3_trb_dma_offset(dep, &dep->trb_pool[0])));

	if (!request->mapped_db_reg_phs_addr_lsb) {
		request->mapped_db_reg_phs_addr_lsb =
@@ -1011,20 +1023,14 @@ static void gsi_store_ringbase_dbl_info(struct usb_ep *ep,
	 * 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_field(mdwc->base,
			GSI_DBL_ADDR_H(mdwc->gsi_reg[DBL_ADDR_H], (n)),
			~0x0, 0x0);
	dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_H(mdwc->gsi_reg, n),
		upper_32_bits(request->mapped_db_reg_phs_addr_lsb));

	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);
	dev_dbg(mdwc->dev, "Ring Base Addr %d: %x (LSB)\n", n,
		dwc3_msm_read_reg(mdwc->base,
			GSI_RING_BASE_ADDR_L(mdwc->gsi_reg[RING_BASE_ADDR_L],
								(n))));
	dev_dbg(mdwc->dev, "GSI DB Addr %d: %x (LSB)\n", n,
		dwc3_msm_read_reg(mdwc->base,
			GSI_DBL_ADDR_L(mdwc->gsi_reg[DBL_ADDR_L], (n))));
	dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_L(mdwc->gsi_reg, n),
		lower_32_bits(request->mapped_db_reg_phs_addr_lsb));

	dev_dbg(mdwc->dev, "GSI DB Addr %d: %pa\n", n,
		&request->mapped_db_reg_phs_addr_lsb);
}

/**
@@ -1038,39 +1044,42 @@ static void gsi_ring_db(struct usb_ep *ep, struct usb_gsi_request *request)
{
	void __iomem *gsi_dbl_address_lsb;
	void __iomem *gsi_dbl_address_msb;
	dma_addr_t offset;
	dma_addr_t trb_dma;
	struct dwc3_ep *dep = to_dwc3_ep(ep);
	struct dwc3	*dwc = dep->dwc;
	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
	int num_trbs = (dep->direction) ? (2 * (request->num_bufs) + 2)
					: (request->num_bufs + 2);

	gsi_dbl_address_lsb = devm_ioremap_nocache(mdwc->dev,
				request->db_reg_phs_addr_lsb, sizeof(u32));
	gsi_dbl_address_lsb = ioremap_nocache(request->db_reg_phs_addr_lsb,
				sizeof(u32));
	if (!gsi_dbl_address_lsb) {
		dev_err(mdwc->dev, "Failed to get GSI DBL address LSB\n");
		dev_err(mdwc->dev, "Failed to map GSI DBL address LSB 0x%x\n",
				request->db_reg_phs_addr_lsb);
		return;
	}

	gsi_dbl_address_msb = devm_ioremap_nocache(mdwc->dev,
			request->db_reg_phs_addr_msb, sizeof(u32));
	gsi_dbl_address_msb = ioremap_nocache(request->db_reg_phs_addr_msb,
				sizeof(u32));
	if (!gsi_dbl_address_msb) {
		dev_err(mdwc->dev, "Failed to get GSI DBL address MSB\n");
		dev_err(mdwc->dev, "Failed to map GSI DBL address MSB 0x%x\n",
				request->db_reg_phs_addr_msb);
		iounmap(gsi_dbl_address_lsb);
		return;
	}

	offset = dwc3_trb_dma_offset(dep, &dep->trb_pool[num_trbs-1]);
	trb_dma = dwc3_trb_dma_offset(dep, &dep->trb_pool[num_trbs-1]);
	dev_dbg(mdwc->dev, "Writing link TRB addr: %pa to %pK (%x) for ep:%s\n",
		&offset, gsi_dbl_address_lsb, request->db_reg_phs_addr_lsb,
		&trb_dma, gsi_dbl_address_lsb, request->db_reg_phs_addr_lsb,
		ep->name);

	dbg_log_string("ep:%s link TRB addr:%pa db:%x\n",
		ep->name, &offset, request->db_reg_phs_addr_lsb);

	writel_relaxed(offset, gsi_dbl_address_lsb);
	writel_relaxed(lower_32_bits(trb_dma), gsi_dbl_address_lsb);
	readl_relaxed(gsi_dbl_address_lsb);
	writel_relaxed(0, gsi_dbl_address_msb);
	writel_relaxed(upper_32_bits(trb_dma), gsi_dbl_address_msb);
	readl_relaxed(gsi_dbl_address_msb);

	iounmap(gsi_dbl_address_lsb);
	iounmap(gsi_dbl_address_msb);
}

/**
@@ -1134,6 +1143,7 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
	size_t len;
	unsigned long dma_attr;
	dma_addr_t buffer_addr;
	dma_addr_t trb0_dma;
	struct dwc3_ep *dep = to_dwc3_ep(ep);
	struct dwc3		*dwc = dep->dwc;
	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
@@ -1176,6 +1186,8 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
		goto free_trb_buffer;
	}

	trb0_dma = dwc3_trb_dma_offset(dep, &dep->trb_pool[0]);

	dep->num_trbs = num_trbs;
	dma_get_sgtable(dwc->sysdev, &req->sgt_trb_xfer_ring, dep->trb_pool,
		dep->trb_pool_dma, num_trbs * sizeof(struct dwc3_trb));
@@ -1207,7 +1219,7 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req)

			/* Setup n TRBs pointing to valid buffers */
			trb->bpl = lower_32_bits(buffer_addr);
			trb->bph = 0;
			trb->bph = upper_32_bits(buffer_addr);
			trb->size = 0;
			trb->ctrl = DWC3_TRBCTL_NORMAL
					| DWC3_TRB_CTRL_IOC;
@@ -1215,9 +1227,9 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req)

			/* Set up the Link TRB at the end */
			if (i == (num_trbs - 1)) {
				trb->bpl = dwc3_trb_dma_offset(dep,
							&dep->trb_pool[0]);
				trb->bph = (1 << 23) | (1 << 21)
				trb->bpl = lower_32_bits(trb0_dma);
				trb->bph = upper_32_bits(trb0_dma & 0xffff);
				trb->bph |= (1 << 23) | (1 << 21)
						| (ep->ep_intr_num << 16);
				trb->size = 0;
				trb->ctrl = DWC3_TRBCTL_LINK_TRB
@@ -1232,19 +1244,22 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
			memset(trb, 0, sizeof(*trb));
			/* Setup LINK TRB to start with TRB ring */
			if (i == 0) {
				trb->bpl = dwc3_trb_dma_offset(dep,
							&dep->trb_pool[1]);
				trb->bpl =
					lower_32_bits(trb0_dma + sizeof(*trb));
				trb->bph =
					upper_32_bits(trb0_dma + sizeof(*trb));
				trb->ctrl = DWC3_TRBCTL_LINK_TRB;
			} else if (i == (num_trbs - 1)) {
				/* Set up the Link TRB at the end */
				trb->bpl = dwc3_trb_dma_offset(dep,
						&dep->trb_pool[0]);
				trb->bph = (1 << 23) | (1 << 21)
				trb->bpl = lower_32_bits(trb0_dma);
				trb->bph = upper_32_bits(trb0_dma & 0xffff);
				trb->bph |= (1 << 23) | (1 << 21)
						| (ep->ep_intr_num << 16);
				trb->ctrl = DWC3_TRBCTL_LINK_TRB
						| DWC3_TRB_CTRL_HWO;
			} else {
				trb->bpl = lower_32_bits(buffer_addr);
				trb->bph = upper_32_bits(buffer_addr);
				trb->size = req->buf_len;
				buffer_addr += req->buf_len;
				trb->ctrl = DWC3_TRBCTL_NORMAL
@@ -1335,16 +1350,12 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request)
	int ret;

	/* setup dummy doorbell as IPA connection isn't setup yet */
	dwc3_msm_write_reg_field(mdwc->base,
			GSI_DBL_ADDR_H(mdwc->gsi_reg[DBL_ADDR_H], (n)),
			~0x0, (u32)((u64)mdwc->dummy_gsi_db_dma >> 32));

	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);
	dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_H(mdwc->gsi_reg, n),
			upper_32_bits(mdwc->dummy_gsi_db_dma));
	dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_L(mdwc->gsi_reg, n),
			lower_32_bits(mdwc->dummy_gsi_db_dma));
	dev_dbg(mdwc->dev, "Dummy DB Addr %pK: %llx\n",
		&mdwc->dummy_gsi_db, mdwc->dummy_gsi_db_dma);

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

@@ -1423,18 +1434,14 @@ static void gsi_enable(struct usb_ep *ep)
	struct dwc3 *dwc = dep->dwc;
	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);

	dwc3_msm_write_reg_field(mdwc->base,
		GSI_GENERAL_CFG_REG(mdwc->gsi_reg[GENERAL_CFG_REG]),
	dwc3_msm_write_reg_field(mdwc->base, GSI_GENERAL_CFG_REG(mdwc->gsi_reg),
		GSI_CLK_EN_MASK, 1);
	dwc3_msm_write_reg_field(mdwc->base,
		GSI_GENERAL_CFG_REG(mdwc->gsi_reg[GENERAL_CFG_REG]),
	dwc3_msm_write_reg_field(mdwc->base, GSI_GENERAL_CFG_REG(mdwc->gsi_reg),
		GSI_RESTART_DBL_PNTR_MASK, 1);
	dwc3_msm_write_reg_field(mdwc->base,
		GSI_GENERAL_CFG_REG(mdwc->gsi_reg[GENERAL_CFG_REG]),
	dwc3_msm_write_reg_field(mdwc->base, GSI_GENERAL_CFG_REG(mdwc->gsi_reg),
		GSI_RESTART_DBL_PNTR_MASK, 0);
	dev_dbg(mdwc->dev, "%s: Enable GSI\n", __func__);
	dwc3_msm_write_reg_field(mdwc->base,
		GSI_GENERAL_CFG_REG(mdwc->gsi_reg[GENERAL_CFG_REG]),
	dwc3_msm_write_reg_field(mdwc->base, GSI_GENERAL_CFG_REG(mdwc->gsi_reg),
		GSI_EN_MASK, 1);
}

@@ -1454,8 +1461,7 @@ static void gsi_set_clear_dbell(struct usb_ep *ep,
	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);

	dbg_log_string("block_db(%d)", block_db);
	dwc3_msm_write_reg_field(mdwc->base,
		GSI_GENERAL_CFG_REG(mdwc->gsi_reg[GENERAL_CFG_REG]),
	dwc3_msm_write_reg_field(mdwc->base, GSI_GENERAL_CFG_REG(mdwc->gsi_reg),
		BLOCK_GSI_WR_GO_MASK, block_db);
}

@@ -1469,7 +1475,7 @@ static bool gsi_check_ready_to_suspend(struct dwc3_msm *mdwc)
	u32	timeout = 1500;

	while (dwc3_msm_read_reg_field(mdwc->base,
		GSI_IF_STS(mdwc->gsi_reg[IF_STS]), GSI_WR_CTRL_STATE_MASK)) {
		GSI_IF_STS(mdwc->gsi_reg), GSI_WR_CTRL_STATE_MASK)) {
		if (!timeout--) {
			dev_err(mdwc->dev,
			"Unable to suspend GSI ch. WR_CTRL_STATE != 0\n");
@@ -2092,6 +2098,7 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
			dwc3_writel(dwc->regs, DWC3_GEVNTADRLO((i+1)),
				lower_32_bits(evt->dma));
			dwc3_writel(dwc->regs, DWC3_GEVNTADRHI((i+1)),
				(upper_32_bits(evt->dma) & 0xffff) |
				DWC3_GEVNTADRHI_EVNTADRHI_GSI_EN(
				DWC3_GEVENT_TYPE_GSI) |
				DWC3_GEVNTADRHI_EVNTADRHI_GSI_IDX((i+1)));
@@ -2156,7 +2163,7 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
	case DWC3_CONTROLLER_NOTIFY_CLEAR_DB:
		dev_dbg(mdwc->dev, "DWC3_CONTROLLER_NOTIFY_CLEAR_DB\n");
		dwc3_msm_write_reg_field(mdwc->base,
			GSI_GENERAL_CFG_REG(mdwc->gsi_reg[GENERAL_CFG_REG]),
			GSI_GENERAL_CFG_REG(mdwc->gsi_reg),
			BLOCK_GSI_WR_GO_MASK, true);
		break;
	default: