diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 1598645e4f56..af64f2ec7c7e 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -972,7 +972,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; @@ -981,7 +981,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 */ @@ -1222,6 +1222,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])); @@ -1251,7 +1253,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 = @@ -1275,17 +1283,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); } /** @@ -1299,7 +1304,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); @@ -1323,13 +1328,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); @@ -1382,6 +1391,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; @@ -1406,8 +1416,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); @@ -1418,6 +1427,10 @@ 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; dma_get_sgtable(dwc->sysdev, &req->sgt_trb_xfer_ring, dep->trb_pool, dep->trb_pool_dma, num_trbs * sizeof(struct dwc3_trb)); @@ -1434,82 +1447,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 = 0; - trb->size = 0; - trb->ctrl = DWC3_TRBCTL_NORMAL - | DWC3_TRB_CTRL_IOC; + trb->bph = upper_32_bits(buffer_addr); + 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 = dwc3_trb_dma_offset(dep, - &dep->trb_pool[0]); - 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 = dwc3_trb_dma_offset(dep, - &dep->trb_pool[1]); - 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) - | (req->ep_intr_num << 16); - trb->ctrl = DWC3_TRBCTL_LINK_TRB - | DWC3_TRB_CTRL_HWO; - } else { - trb->bpl = lower_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; @@ -1570,14 +1551,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)); @@ -2402,6 +2381,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)));