From 9fe552286b3ba6c98bfcbd68bbda190f071fe8b5 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Fri, 28 Feb 2020 17:06:18 +0530 Subject: [PATCH 1/2] usb: dwc3-msm: Support > 32-bit DMA addresses for GSI Fix a few places where only the lower 32-bits of DMA addresses are being passed to GSI. This includes the ring base address, GSI doorbell address, and TRBs. Also do the same for DBM endpoints' link TRB. Change-Id: I33f7c05f60070ff45d3bedb66f9976491d584186 Signed-off-by: Jack Pham --- drivers/usb/dwc3/dwc3-msm.c | 86 +++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 36 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 60e12d6c18b7..3059155b57d3 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -969,7 +969,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; @@ -978,7 +978,7 @@ static int __dwc3_msm_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) * Now start the transfer */ memset(¶ms, 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 */ @@ -1219,6 +1219,8 @@ static int gsi_startxfer_for_ep(struct usb_ep *ep, struct usb_gsi_request *req) memset(¶ms, 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 |= (req->ep_intr_num << 16); params.param1 = lower_32_bits(dwc3_trb_dma_offset(dep, &dep->trb_pool[0])); @@ -1248,7 +1250,13 @@ static void gsi_store_ringbase_dbl_info(struct usb_ep *ep, int n = request->ep_intr_num - 1; dwc3_msm_write_reg(mdwc->base, GSI_RING_BASE_ADDR_L(mdwc->gsi_reg, n), - dwc3_trb_dma_offset(dep, &dep->trb_pool[0])); + 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 = @@ -1272,17 +1280,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, 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, 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, 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, n))); + lower_32_bits(request->mapped_db_reg_phs_addr_lsb)); + + dev_dbg(mdwc->dev, "GSI DB Addr %d: %pad\n", n, + &request->mapped_db_reg_phs_addr_lsb); } /** @@ -1296,7 +1301,7 @@ 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); @@ -1320,13 +1325,17 @@ static void gsi_ring_db(struct usb_ep *ep, struct usb_gsi_request *request) return; } - offset = 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, - ep->name); + trb_dma = dwc3_trb_dma_offset(dep, &dep->trb_pool[num_trbs-1]); + dev_dbg(mdwc->dev, "Writing link TRB addr: %pad to %pK (lsb:%x msb:%x) for ep:%s\n", + &trb_dma, gsi_dbl_address_lsb, request->db_reg_phs_addr_lsb, + request->db_reg_phs_addr_msb, ep->name); - writel_relaxed(offset, gsi_dbl_address_lsb); - writel_relaxed(0, gsi_dbl_address_msb); + dbg_log_string("ep:%s link TRB addr:%pad db_lsb:%pad db_msb:%pad\n", + ep->name, &trb_dma, &request->db_reg_phs_addr_lsb, + &request->db_reg_phs_addr_msb); + + writel_relaxed(lower_32_bits(trb_dma), gsi_dbl_address_lsb); + writel_relaxed(upper_32_bits(trb_dma), gsi_dbl_address_msb); iounmap(gsi_dbl_address_lsb); iounmap(gsi_dbl_address_msb); @@ -1379,6 +1388,7 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req) int i = 0; size_t len; 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_trb *trb; @@ -1415,6 +1425,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)); @@ -1446,7 +1458,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; @@ -1454,9 +1466,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) | (req->ep_intr_num << 16); trb->size = 0; trb->ctrl = DWC3_TRBCTL_LINK_TRB @@ -1471,19 +1483,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) | (req->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 @@ -1567,14 +1582,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, n), - ~0x0, (u32)((u64)mdwc->dummy_gsi_db_dma >> 32)); - - dwc3_msm_write_reg_field(mdwc->base, GSI_DBL_ADDR_L(mdwc->gsi_reg, 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(¶ms, 0x00, sizeof(params)); @@ -2404,6 +2417,7 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, dwc3_msm_write_reg(mdwc->base, DWC3_GEVNTADRLO((i+1)), lower_32_bits(evt->dma)); dwc3_msm_write_reg(mdwc->base, 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))); From 278e2428948ed3d9de7e4f7b9dc5771262646de3 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Thu, 16 Apr 2020 22:57:53 -0700 Subject: [PATCH 2/2] usb: dwc3-msm: Clean up gsi_prepare_trbs() This is mostly a cosmetic change to clean up gsi_prepare_trbs() for better readability: - Perform a memset() once for the entire pool instead of zeroing out each TRB within the loop. - Separate out the initialization for link TRBs and keep the for loops for just the normal buffer initialization Finally, remove the final loop at the end whose only purpose is to print the entire TRB pool contents to the kernel log. It's just as useful to simply inspect using debugfs as every endpoint already offers a trb_ring file. Change-Id: Ifcd841efbd51cc3229a3d4e552a3df1ef244ce96 Signed-off-by: Jack Pham --- drivers/usb/dwc3/dwc3-msm.c | 104 ++++++++++++------------------------ 1 file changed, 35 insertions(+), 69 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 3059155b57d3..08b6172f1317 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -1413,8 +1413,7 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req) buffer_addr = req->dma; - /* Allocate and configgure TRBs */ - + /* Allocate and configure TRBs */ dep->trb_pool = dma_alloc_coherent(dwc->sysdev, num_trbs * sizeof(struct dwc3_trb), &dep->trb_pool_dma, GFP_KERNEL); @@ -1425,6 +1424,8 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req) goto free_trb_buffer; } + memset(dep->trb_pool, 0, num_trbs * sizeof(struct dwc3_trb)); + trb0_dma = dwc3_trb_dma_offset(dep, &dep->trb_pool[0]); dep->num_trbs = num_trbs; @@ -1443,85 +1444,50 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req) /* IN direction */ if (dep->direction) { - for (i = 0; i < num_trbs ; i++) { - trb = &dep->trb_pool[i]; - memset(trb, 0, sizeof(*trb)); - /* Set up first n+1 TRBs for ZLPs */ - if (i < (req->num_bufs + 1)) { - trb->bpl = 0; - trb->bph = 0; - trb->size = 0; - trb->ctrl = DWC3_TRBCTL_NORMAL - | DWC3_TRB_CTRL_IOC; - continue; - } + trb = &dep->trb_pool[0]; + /* Set up first n+1 TRBs for ZLPs */ + for (i = 0; i < req->num_bufs + 1; i++, trb++) + trb->ctrl = DWC3_TRBCTL_NORMAL | DWC3_TRB_CTRL_IOC; - /* Setup n TRBs pointing to valid buffers */ + /* Setup next n TRBs pointing to valid buffers */ + for (; i < num_trbs - 1; i++, trb++) { trb->bpl = lower_32_bits(buffer_addr); trb->bph = upper_32_bits(buffer_addr); - trb->size = 0; - trb->ctrl = DWC3_TRBCTL_NORMAL - | DWC3_TRB_CTRL_IOC; + trb->ctrl = DWC3_TRBCTL_NORMAL | DWC3_TRB_CTRL_IOC; buffer_addr += req->buf_len; - - /* Set up the Link TRB at the end */ - if (i == (num_trbs - 1)) { - trb->bpl = lower_32_bits(trb0_dma); - trb->bph = upper_32_bits(trb0_dma & 0xffff); - trb->bph |= (1 << 23) | (1 << 21) - | (req->ep_intr_num << 16); - trb->size = 0; - trb->ctrl = DWC3_TRBCTL_LINK_TRB - | DWC3_TRB_CTRL_HWO; - } } + + /* Set up the Link TRB at the end */ + trb->bpl = lower_32_bits(trb0_dma); + trb->bph = upper_32_bits(trb0_dma & 0xffff); + trb->bph |= (1 << 23) | (1 << 21) | (req->ep_intr_num << 16); + trb->ctrl = DWC3_TRBCTL_LINK_TRB | DWC3_TRB_CTRL_HWO; } else { /* OUT direction */ + /* Start ring with LINK TRB pointing to second entry */ + trb = &dep->trb_pool[0]; + trb->bpl = lower_32_bits(trb0_dma + sizeof(*trb)); + trb->bph = upper_32_bits(trb0_dma + sizeof(*trb)); + trb->ctrl = DWC3_TRBCTL_LINK_TRB; - for (i = 0; i < num_trbs ; i++) { - - trb = &dep->trb_pool[i]; - memset(trb, 0, sizeof(*trb)); - /* Setup LINK TRB to start with TRB ring */ - if (i == 0) { - 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 = lower_32_bits(trb0_dma); - trb->bph = upper_32_bits(trb0_dma & 0xffff); - trb->bph |= (1 << 23) | (1 << 21) - | (req->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 - | DWC3_TRB_CTRL_IOC - | DWC3_TRB_CTRL_CSP - | DWC3_TRB_CTRL_ISP_IMI; - } + /* Setup next n-1 TRBs pointing to valid buffers */ + for (i = 1, trb++; i < num_trbs - 1; i++, trb++) { + 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 | DWC3_TRB_CTRL_IOC + | DWC3_TRB_CTRL_CSP | DWC3_TRB_CTRL_ISP_IMI; } + + /* Set up the Link TRB at the end */ + trb->bpl = lower_32_bits(trb0_dma); + trb->bph = upper_32_bits(trb0_dma & 0xffff); + trb->bph |= (1 << 23) | (1 << 21) | (req->ep_intr_num << 16); + trb->ctrl = DWC3_TRBCTL_LINK_TRB | DWC3_TRB_CTRL_HWO; } dev_dbg(dwc->dev, "%s: Initialized TRB Ring for %s\n", __func__, dep->name); - trb = &dep->trb_pool[0]; - if (trb) { - for (i = 0; i < num_trbs; i++) { - dev_dbg(dwc->dev, - "TRB %d: ADDR:%lx bpl:%x bph:%x sz:%x ctl:%x\n", - i, (unsigned long)dwc3_trb_dma_offset(dep, - &dep->trb_pool[i]), trb->bpl, trb->bph, - trb->size, trb->ctrl); - trb++; - } - } return 0;