diff options
Diffstat (limited to 'drivers/usb/cdns3')
| -rw-r--r-- | drivers/usb/cdns3/cdns3-gadget.c | 8 | ||||
| -rw-r--r-- | drivers/usb/cdns3/core.c | 1 | ||||
| -rw-r--r-- | drivers/usb/cdns3/drd.c | 13 | ||||
| -rw-r--r-- | drivers/usb/cdns3/drd.h | 6 | ||||
| -rw-r--r-- | drivers/usb/cdns3/host.c | 16 | 
5 files changed, 34 insertions, 10 deletions
| diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c index aeca902ab6cc..fd1beb10bba7 100644 --- a/drivers/usb/cdns3/cdns3-gadget.c +++ b/drivers/usb/cdns3/cdns3-gadget.c @@ -828,7 +828,11 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep,  			return;  	} -	if (request->complete) { +	/* +	 * zlp request is appended by driver, needn't call usb_gadget_giveback_request() to notify +	 * gadget composite driver. +	 */ +	if (request->complete && request->buf != priv_dev->zlp_buf) {  		spin_unlock(&priv_dev->lock);  		usb_gadget_giveback_request(&priv_ep->endpoint,  					    request); @@ -2540,11 +2544,11 @@ static int cdns3_gadget_ep_disable(struct usb_ep *ep)  	while (!list_empty(&priv_ep->wa2_descmiss_req_list)) {  		priv_req = cdns3_next_priv_request(&priv_ep->wa2_descmiss_req_list); +		list_del_init(&priv_req->list);  		kfree(priv_req->request.buf);  		cdns3_gadget_ep_free_request(&priv_ep->endpoint,  					     &priv_req->request); -		list_del_init(&priv_req->list);  		--priv_ep->wa2_counter;  	} diff --git a/drivers/usb/cdns3/core.c b/drivers/usb/cdns3/core.c index 33548771a0d3..465e9267b49c 100644 --- a/drivers/usb/cdns3/core.c +++ b/drivers/usb/cdns3/core.c @@ -395,7 +395,6 @@ pm_put:  	return ret;  } -  /**   * cdns_wakeup_irq - interrupt handler for wakeup events   * @irq: irq number for cdns3/cdnsp core device diff --git a/drivers/usb/cdns3/drd.c b/drivers/usb/cdns3/drd.c index 04b6d12f2b9a..8b936a2e93a0 100644 --- a/drivers/usb/cdns3/drd.c +++ b/drivers/usb/cdns3/drd.c @@ -156,7 +156,8 @@ bool cdns_is_device(struct cdns *cdns)   */  static void cdns_otg_disable_irq(struct cdns *cdns)  { -	writel(0, &cdns->otg_irq_regs->ien); +	if (cdns->version) +		writel(0, &cdns->otg_irq_regs->ien);  }  /** @@ -422,15 +423,20 @@ int cdns_drd_init(struct cdns *cdns)  		cdns->otg_regs = (void __iomem *)&cdns->otg_v1_regs->cmd; -		if (readl(&cdns->otg_cdnsp_regs->did) == OTG_CDNSP_DID) { +		state = readl(&cdns->otg_cdnsp_regs->did); + +		if (OTG_CDNSP_CHECK_DID(state)) {  			cdns->otg_irq_regs = (struct cdns_otg_irq_regs __iomem *)  					      &cdns->otg_cdnsp_regs->ien;  			cdns->version  = CDNSP_CONTROLLER_V2; -		} else { +		} else if (OTG_CDNS3_CHECK_DID(state)) {  			cdns->otg_irq_regs = (struct cdns_otg_irq_regs __iomem *)  					      &cdns->otg_v1_regs->ien;  			writel(1, &cdns->otg_v1_regs->simulate);  			cdns->version  = CDNS3_CONTROLLER_V1; +		} else { +			dev_err(cdns->dev, "not supported DID=0x%08x\n", state); +			return -EINVAL;  		}  		dev_dbg(cdns->dev, "DRD version v1 (ID: %08x, rev: %08x)\n", @@ -483,7 +489,6 @@ int cdns_drd_exit(struct cdns *cdns)  	return 0;  } -  /* Indicate the cdns3 core was power lost before */  bool cdns_power_is_lost(struct cdns *cdns)  { diff --git a/drivers/usb/cdns3/drd.h b/drivers/usb/cdns3/drd.h index cbdf94f73ed9..d72370c321d3 100644 --- a/drivers/usb/cdns3/drd.h +++ b/drivers/usb/cdns3/drd.h @@ -79,7 +79,11 @@ struct cdnsp_otg_regs {  	__le32 susp_timing_ctrl;  }; -#define OTG_CDNSP_DID	0x0004034E +/* CDNSP driver supports 0x000403xx Cadence USB controller family. */ +#define OTG_CDNSP_CHECK_DID(did) (((did) & GENMASK(31, 8)) == 0x00040300) + +/* CDNS3 driver supports 0x000402xx Cadence USB controller family. */ +#define OTG_CDNS3_CHECK_DID(did) (((did) & GENMASK(31, 8)) == 0x00040200)  /*   * Common registers interface for both CDNS3 and CDNSP version of DRD. diff --git a/drivers/usb/cdns3/host.c b/drivers/usb/cdns3/host.c index 6164fc4c96a4..ceca4d839dfd 100644 --- a/drivers/usb/cdns3/host.c +++ b/drivers/usb/cdns3/host.c @@ -18,6 +18,11 @@  #include "../host/xhci.h"  #include "../host/xhci-plat.h" +/* + * The XECP_PORT_CAP_REG and XECP_AUX_CTRL_REG1 exist only + * in Cadence USB3 dual-role controller, so it can't be used + * with Cadence CDNSP dual-role controller. + */  #define XECP_PORT_CAP_REG	0x8000  #define XECP_AUX_CTRL_REG1	0x8120 @@ -57,6 +62,8 @@ static const struct xhci_plat_priv xhci_plat_cdns3_xhci = {  	.resume_quirk = xhci_cdns3_resume_quirk,  }; +static const struct xhci_plat_priv xhci_plat_cdnsp_xhci; +  static int __cdns_host_init(struct cdns *cdns)  {  	struct platform_device *xhci; @@ -81,8 +88,13 @@ static int __cdns_host_init(struct cdns *cdns)  		goto err1;  	} -	cdns->xhci_plat_data = kmemdup(&xhci_plat_cdns3_xhci, -			sizeof(struct xhci_plat_priv), GFP_KERNEL); +	if (cdns->version < CDNSP_CONTROLLER_V2) +		cdns->xhci_plat_data = kmemdup(&xhci_plat_cdns3_xhci, +				sizeof(struct xhci_plat_priv), GFP_KERNEL); +	else +		cdns->xhci_plat_data = kmemdup(&xhci_plat_cdnsp_xhci, +				sizeof(struct xhci_plat_priv), GFP_KERNEL); +  	if (!cdns->xhci_plat_data) {  		ret = -ENOMEM;  		goto err1; |