public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] usb: cdnsp: add support for eUSB2v2 port
@ 2026-04-17  8:37 Pawel Laszczak via B4 Relay
  2026-04-18  1:38 ` Peter Chen (CIX)
  0 siblings, 1 reply; 2+ messages in thread
From: Pawel Laszczak via B4 Relay @ 2026-04-17  8:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: linux-usb, linux-kernel, peter.chen, Pawel Laszczak

From: Pawel Laszczak <pawell@cadence.com>

The Cadence CDNSP controller optionally supports eUSB2 (embedded USB2)
port. While this port type operates logically like high-speed USB 2.0,
it utilizes a different physical layer signaling.

This patch:
- Extends the port detection logic to recognize the eUSB2 protocol.
- Tracks the eUSB2 port offset in the cdnsp_device structure.
- Ensures that eUSB2 ports are correctly handled during Link State
  transitions, specifically forcing L0 when LPM is capable, similar
  to standard USB 2.0 ports.

Signed-off-by: Pawel Laszczak <pawell@cadence.com>
---
 drivers/usb/cdns3/cdnsp-gadget.c | 49 ++++++++++++++++++---------
 drivers/usb/cdns3/cdnsp-gadget.h |  1 +
 drivers/usb/cdns3/cdnsp-mem.c    | 73 +++++++++++++++++++++++++++-------------
 drivers/usb/cdns3/cdnsp-ring.c   |  9 +++--
 4 files changed, 90 insertions(+), 42 deletions(-)

diff --git a/drivers/usb/cdns3/cdnsp-gadget.c b/drivers/usb/cdns3/cdnsp-gadget.c
index 6b3815f8a6e5..2c71c77e6ec3 100644
--- a/drivers/usb/cdns3/cdnsp-gadget.c
+++ b/drivers/usb/cdns3/cdnsp-gadget.c
@@ -124,20 +124,28 @@ void cdnsp_set_link_state(struct cdnsp_device *pdev,
 }
 
 static void cdnsp_disable_port(struct cdnsp_device *pdev,
-			       __le32 __iomem *port_regs)
+			       struct cdnsp_port *port)
 {
-	u32 temp = cdnsp_port_state_to_neutral(readl(port_regs));
+	u32 temp;
+
+	if (!port->exist)
+		return;
 
-	writel(temp | PORT_PED, port_regs);
+	temp = cdnsp_port_state_to_neutral(readl(&port->regs->portsc));
+	writel(temp | PORT_PED, &port->regs->portsc);
 }
 
 static void cdnsp_clear_port_change_bit(struct cdnsp_device *pdev,
-					__le32 __iomem *port_regs)
+					struct cdnsp_port *port)
 {
-	u32 portsc = readl(port_regs);
+	u32 portsc;
+
+	if (!port->exist)
+		return;
 
+	portsc = readl(&port->regs->portsc);
 	writel(cdnsp_port_state_to_neutral(portsc) |
-	       (portsc & PORT_CHANGE_BITS), port_regs);
+	       (portsc & PORT_CHANGE_BITS), &port->regs->portsc);
 }
 
 static void cdnsp_set_apb_timeout_value(struct cdnsp_device *pdev)
@@ -944,7 +952,7 @@ void cdnsp_set_usb2_hardware_lpm(struct cdnsp_device *pdev,
 				 struct usb_request *req,
 				 int enable)
 {
-	if (pdev->active_port != &pdev->usb2_port || !pdev->gadget.lpm_capable)
+	if (pdev->active_port == &pdev->usb3_port || !pdev->gadget.lpm_capable)
 		return;
 
 	trace_cdnsp_lpm(enable);
@@ -1310,20 +1318,26 @@ static int cdnsp_run(struct cdnsp_device *pdev,
 		break;
 	}
 
-	if (speed >= USB_SPEED_SUPER) {
+	if (pdev->usb3_port.exist && speed >= USB_SPEED_SUPER) {
 		writel(temp, &pdev->port3x_regs->mode_addr);
 		cdnsp_set_link_state(pdev, &pdev->usb3_port.regs->portsc,
 				     XDEV_RXDETECT);
 	} else {
-		cdnsp_disable_port(pdev, &pdev->usb3_port.regs->portsc);
+		cdnsp_disable_port(pdev, &pdev->usb3_port);
 	}
 
-	cdnsp_set_link_state(pdev, &pdev->usb2_port.regs->portsc,
-			     XDEV_RXDETECT);
+	if (pdev->usb2_port.exist) {
+		cdnsp_set_link_state(pdev, &pdev->usb2_port.regs->portsc,
+				     XDEV_RXDETECT);
+		writel(PORT_REG6_L1_L0_HW_EN | fs_speed, &pdev->port20_regs->port_reg6);
+	}
+
+	if (pdev->eusb_port.exist)
+		cdnsp_set_link_state(pdev, &pdev->eusb_port.regs->portsc,
+				     XDEV_RXDETECT);
 
 	cdnsp_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
 
-	writel(PORT_REG6_L1_L0_HW_EN | fs_speed, &pdev->port20_regs->port_reg6);
 
 	ret = cdnsp_start(pdev);
 	if (ret) {
@@ -1469,8 +1483,10 @@ static void cdnsp_stop(struct cdnsp_device *pdev)
 			cdnsp_ep_dequeue(&pdev->eps[0], req);
 	}
 
-	cdnsp_disable_port(pdev, &pdev->usb2_port.regs->portsc);
-	cdnsp_disable_port(pdev, &pdev->usb3_port.regs->portsc);
+	cdnsp_disable_port(pdev, &pdev->usb2_port);
+	cdnsp_disable_port(pdev, &pdev->usb3_port);
+	cdnsp_disable_port(pdev, &pdev->eusb_port);
+
 	cdnsp_disable_slot(pdev);
 	cdnsp_halt(pdev);
 
@@ -1479,8 +1495,9 @@ static void cdnsp_stop(struct cdnsp_device *pdev)
 	temp = readl(&pdev->ir_set->irq_pending);
 	writel(IMAN_IE_CLEAR(temp), &pdev->ir_set->irq_pending);
 
-	cdnsp_clear_port_change_bit(pdev, &pdev->usb2_port.regs->portsc);
-	cdnsp_clear_port_change_bit(pdev, &pdev->usb3_port.regs->portsc);
+	cdnsp_clear_port_change_bit(pdev, &pdev->usb2_port);
+	cdnsp_clear_port_change_bit(pdev, &pdev->eusb_port);
+	cdnsp_clear_port_change_bit(pdev, &pdev->usb3_port);
 
 	/* Clear interrupt line */
 	temp = readl(&pdev->ir_set->irq_pending);
diff --git a/drivers/usb/cdns3/cdnsp-gadget.h b/drivers/usb/cdns3/cdnsp-gadget.h
index a91cca509db0..c44bca348a41 100644
--- a/drivers/usb/cdns3/cdnsp-gadget.h
+++ b/drivers/usb/cdns3/cdnsp-gadget.h
@@ -1474,6 +1474,7 @@ struct cdnsp_device {
 	unsigned int link_state;
 
 	struct cdnsp_port usb2_port;
+	struct cdnsp_port eusb_port;
 	struct cdnsp_port usb3_port;
 	struct cdnsp_port *active_port;
 	u16 test_mode;
diff --git a/drivers/usb/cdns3/cdnsp-mem.c b/drivers/usb/cdns3/cdnsp-mem.c
index a2a1b21f2ef8..932071818d1e 100644
--- a/drivers/usb/cdns3/cdnsp-mem.c
+++ b/drivers/usb/cdns3/cdnsp-mem.c
@@ -1088,11 +1088,9 @@ void cdnsp_mem_cleanup(struct cdnsp_device *pdev)
 			  pdev->dcbaa, pdev->dcbaa->dma);
 
 	pdev->dcbaa = NULL;
-
-	pdev->usb2_port.exist = 0;
-	pdev->usb3_port.exist = 0;
-	pdev->usb2_port.port_num = 0;
-	pdev->usb3_port.port_num = 0;
+	memset(&pdev->usb2_port, 0, sizeof(struct cdnsp_port));
+	memset(&pdev->eusb_port, 0, sizeof(struct cdnsp_port));
+	memset(&pdev->usb3_port, 0, sizeof(struct cdnsp_port));
 	pdev->active_port = NULL;
 }
 
@@ -1133,6 +1131,18 @@ static void cdnsp_add_in_port(struct cdnsp_device *pdev,
 	port_offset = CDNSP_EXT_PORT_OFF(temp);
 	port_count = CDNSP_EXT_PORT_COUNT(temp);
 
+	if (port == &pdev->eusb_port) {
+		/*
+		 * If controller has usb2 + eusb port then eusb is as
+		 * second port
+		 */
+		if (port_count == 2)
+			port_offset++;
+
+		if (port_count == 1 && pdev->usb2_port.exist)
+			return;
+	}
+
 	trace_cdnsp_port_info(addr, port_offset, port_count, port->maj_rev);
 
 	port->port_num = port_offset;
@@ -1152,13 +1162,10 @@ static int cdnsp_setup_port_arrays(struct cdnsp_device *pdev)
 	base = &pdev->cap_regs->hc_capbase;
 	offset = cdnsp_find_next_ext_cap(base, 0,
 					 EXT_CAP_CFG_DEV_20PORT_CAP_ID);
-	pdev->port20_regs = base + offset;
-
-	offset = cdnsp_find_next_ext_cap(base, 0, D_XEC_CFG_3XPORT_CAP);
-	pdev->port3x_regs =  base + offset;
+	if (offset)
+		pdev->port20_regs = base + offset;
 
 	offset = 0;
-	base = &pdev->cap_regs->hc_capbase;
 
 	/* Driver expects max 2 extended protocol capability. */
 	for (i = 0; i < 2; i++) {
@@ -1173,26 +1180,46 @@ static int cdnsp_setup_port_arrays(struct cdnsp_device *pdev)
 			cdnsp_add_in_port(pdev, &pdev->usb3_port,
 					  base + offset);
 
-		if (CDNSP_EXT_PORT_MAJOR(temp) == 0x02 &&
-		    !pdev->usb2_port.port_num)
-			cdnsp_add_in_port(pdev, &pdev->usb2_port,
-					  base + offset);
+		if (CDNSP_EXT_PORT_MAJOR(temp) == 0x02) {
+			if (!pdev->usb2_port.port_num && pdev->port20_regs)
+				cdnsp_add_in_port(pdev, &pdev->usb2_port,
+						  base + offset);
+
+			if (!pdev->eusb_port.port_num)
+				cdnsp_add_in_port(pdev, &pdev->eusb_port,
+						  base + offset);
+		}
 	}
 
-	if (!pdev->usb2_port.exist || !pdev->usb3_port.exist) {
-		dev_err(pdev->dev, "Error: Only one port detected\n");
+	if (!pdev->usb2_port.exist && !pdev->eusb_port.exist &&
+	    !pdev->usb3_port.exist) {
+		dev_err(pdev->dev, "Error: No port detected\n");
 		return -ENODEV;
 	}
 
-	trace_cdnsp_init("Found USB 2.0 ports and  USB 3.0 ports.");
+	if (pdev->usb2_port.exist) {
+		pdev->usb2_port.regs = (struct cdnsp_port_regs __iomem *)
+				       (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
+					(pdev->usb2_port.port_num - 1));
+		trace_cdnsp_init("Found USB 2.0 port.");
+	}
 
-	pdev->usb2_port.regs = (struct cdnsp_port_regs __iomem *)
-			       (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
-				(pdev->usb2_port.port_num - 1));
+	if (pdev->eusb_port.exist) {
+		pdev->eusb_port.regs = (struct cdnsp_port_regs __iomem *)
+				       (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
+					(pdev->eusb_port.port_num - 1));
+		trace_cdnsp_init("Found eUSB 2.0 port.");
+	}
+
+	if (pdev->usb3_port.exist) {
+		offset = cdnsp_find_next_ext_cap(base, 0, D_XEC_CFG_3XPORT_CAP);
+		pdev->port3x_regs =  base + offset;
 
-	pdev->usb3_port.regs = (struct cdnsp_port_regs __iomem *)
-			       (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
-				(pdev->usb3_port.port_num - 1));
+		pdev->usb3_port.regs = (struct cdnsp_port_regs __iomem *)
+				       (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
+					(pdev->usb3_port.port_num - 1));
+		trace_cdnsp_init("Found  USB 3.x port.");
+	}
 
 	return 0;
 }
diff --git a/drivers/usb/cdns3/cdnsp-ring.c b/drivers/usb/cdns3/cdnsp-ring.c
index 0758f171f73e..715658c981ff 100644
--- a/drivers/usb/cdns3/cdnsp-ring.c
+++ b/drivers/usb/cdns3/cdnsp-ring.c
@@ -259,7 +259,7 @@ static bool cdnsp_room_on_ring(struct cdnsp_device *pdev,
  */
 static void cdnsp_force_l0_go(struct cdnsp_device *pdev)
 {
-	if (pdev->active_port == &pdev->usb2_port && pdev->gadget.lpm_capable)
+	if (pdev->active_port != &pdev->usb3_port && pdev->gadget.lpm_capable)
 		cdnsp_set_link_state(pdev, &pdev->active_port->regs->portsc, XDEV_U0);
 }
 
@@ -763,6 +763,8 @@ static int cdnsp_update_port_id(struct cdnsp_device *pdev, u32 port_id)
 
 	if (port_id == pdev->usb2_port.port_num) {
 		port = &pdev->usb2_port;
+	} else if (port_id == pdev->eusb_port.port_num) {
+		port = &pdev->eusb_port;
 	} else if (port_id == pdev->usb3_port.port_num) {
 		port  = &pdev->usb3_port;
 	} else {
@@ -779,7 +781,8 @@ static int cdnsp_update_port_id(struct cdnsp_device *pdev, u32 port_id)
 		cdnsp_enable_slot(pdev);
 	}
 
-	if (port_id == pdev->usb2_port.port_num)
+	if ((pdev->usb2_port.exist && port_id == pdev->usb2_port.port_num) ||
+	    (pdev->eusb_port.exist && port_id == pdev->eusb_port.port_num))
 		cdnsp_set_usb2_hardware_lpm(pdev, NULL, 1);
 	else
 		writel(PORT_U1_TIMEOUT(1) | PORT_U2_TIMEOUT(1),
@@ -808,7 +811,7 @@ static void cdnsp_handle_port_status(struct cdnsp_device *pdev,
 
 	port_regs = pdev->active_port->regs;
 
-	if (port_id == pdev->usb2_port.port_num)
+	if (port_id == pdev->usb2_port.port_num || port_id == pdev->eusb_port.port_num)
 		port2 = true;
 
 new_event:

---
base-commit: 1c7cc4904160c6fc6377564140062d68a3dc93a0
change-id: 20260417-eusb2v2_upstream-80c5b29a7bba

Best regards,
--  
Pawel Laszczak <pawell@cadence.com>



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] usb: cdnsp: add support for eUSB2v2 port
  2026-04-17  8:37 [PATCH] usb: cdnsp: add support for eUSB2v2 port Pawel Laszczak via B4 Relay
@ 2026-04-18  1:38 ` Peter Chen (CIX)
  0 siblings, 0 replies; 2+ messages in thread
From: Peter Chen (CIX) @ 2026-04-18  1:38 UTC (permalink / raw)
  To: pawell; +Cc: Greg Kroah-Hartman, linux-usb, linux-kernel

On 26-04-17 10:37:31, Pawel Laszczak via B4 Relay wrote:
> From: Pawel Laszczak <pawell@cadence.com>
> 
> The Cadence CDNSP controller optionally supports eUSB2 (embedded USB2)
> port. While this port type operates logically like high-speed USB 2.0,
> it utilizes a different physical layer signaling.
> 
> This patch:
> - Extends the port detection logic to recognize the eUSB2 protocol.
> - Tracks the eUSB2 port offset in the cdnsp_device structure.
> - Ensures that eUSB2 ports are correctly handled during Link State
>   transitions, specifically forcing L0 when LPM is capable, similar
>   to standard USB 2.0 ports.
> 
> Signed-off-by: Pawel Laszczak <pawell@cadence.com>

Pawel, I would like double confirm if you have tested current USB2 and
USB3 device mode, basically, I think you did it.

> ---
>  drivers/usb/cdns3/cdnsp-gadget.c | 49 ++++++++++++++++++---------
>  drivers/usb/cdns3/cdnsp-gadget.h |  1 +
>  drivers/usb/cdns3/cdnsp-mem.c    | 73 +++++++++++++++++++++++++++-------------
>  drivers/usb/cdns3/cdnsp-ring.c   |  9 +++--
>  4 files changed, 90 insertions(+), 42 deletions(-)
> 
> diff --git a/drivers/usb/cdns3/cdnsp-gadget.c b/drivers/usb/cdns3/cdnsp-gadget.c
> index 6b3815f8a6e5..2c71c77e6ec3 100644
> --- a/drivers/usb/cdns3/cdnsp-gadget.c
> +++ b/drivers/usb/cdns3/cdnsp-gadget.c
> @@ -124,20 +124,28 @@ void cdnsp_set_link_state(struct cdnsp_device *pdev,
>  }
>  
>  static void cdnsp_disable_port(struct cdnsp_device *pdev,
> -			       __le32 __iomem *port_regs)
> +			       struct cdnsp_port *port)
>  {
> -	u32 temp = cdnsp_port_state_to_neutral(readl(port_regs));
> +	u32 temp;
> +
> +	if (!port->exist)
> +		return;
>  
> -	writel(temp | PORT_PED, port_regs);
> +	temp = cdnsp_port_state_to_neutral(readl(&port->regs->portsc));
> +	writel(temp | PORT_PED, &port->regs->portsc);
>  }

Why above changes are added, is it related to this change?

>  
>  static void cdnsp_clear_port_change_bit(struct cdnsp_device *pdev,
> -					__le32 __iomem *port_regs)
> +					struct cdnsp_port *port)
>  {
> -	u32 portsc = readl(port_regs);
> +	u32 portsc;
> +
> +	if (!port->exist)
> +		return;
>  
> +	portsc = readl(&port->regs->portsc);
>  	writel(cdnsp_port_state_to_neutral(portsc) |
> -	       (portsc & PORT_CHANGE_BITS), port_regs);
> +	       (portsc & PORT_CHANGE_BITS), &port->regs->portsc);
>  }

ditto

>  
>  static void cdnsp_set_apb_timeout_value(struct cdnsp_device *pdev)
> @@ -944,7 +952,7 @@ void cdnsp_set_usb2_hardware_lpm(struct cdnsp_device *pdev,
>  				 struct usb_request *req,
>  				 int enable)
>  {
> -	if (pdev->active_port != &pdev->usb2_port || !pdev->gadget.lpm_capable)
> +	if (pdev->active_port == &pdev->usb3_port || !pdev->gadget.lpm_capable)
>  		return;
>  
>  	trace_cdnsp_lpm(enable);
> @@ -1310,20 +1318,26 @@ static int cdnsp_run(struct cdnsp_device *pdev,
>  		break;
>  	}
>  
> -	if (speed >= USB_SPEED_SUPER) {
> +	if (pdev->usb3_port.exist && speed >= USB_SPEED_SUPER) {
>  		writel(temp, &pdev->port3x_regs->mode_addr);
>  		cdnsp_set_link_state(pdev, &pdev->usb3_port.regs->portsc,
>  				     XDEV_RXDETECT);
>  	} else {
> -		cdnsp_disable_port(pdev, &pdev->usb3_port.regs->portsc);
> +		cdnsp_disable_port(pdev, &pdev->usb3_port);
>  	}
>  
> -	cdnsp_set_link_state(pdev, &pdev->usb2_port.regs->portsc,
> -			     XDEV_RXDETECT);
> +	if (pdev->usb2_port.exist) {
> +		cdnsp_set_link_state(pdev, &pdev->usb2_port.regs->portsc,
> +				     XDEV_RXDETECT);
> +		writel(PORT_REG6_L1_L0_HW_EN | fs_speed, &pdev->port20_regs->port_reg6);
> +	}
> +
> +	if (pdev->eusb_port.exist)
> +		cdnsp_set_link_state(pdev, &pdev->eusb_port.regs->portsc,
> +				     XDEV_RXDETECT);
>  
>  	cdnsp_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
>  
> -	writel(PORT_REG6_L1_L0_HW_EN | fs_speed, &pdev->port20_regs->port_reg6);
>  
>  	ret = cdnsp_start(pdev);
>  	if (ret) {
> @@ -1469,8 +1483,10 @@ static void cdnsp_stop(struct cdnsp_device *pdev)
>  			cdnsp_ep_dequeue(&pdev->eps[0], req);
>  	}
>  
> -	cdnsp_disable_port(pdev, &pdev->usb2_port.regs->portsc);
> -	cdnsp_disable_port(pdev, &pdev->usb3_port.regs->portsc);
> +	cdnsp_disable_port(pdev, &pdev->usb2_port);
> +	cdnsp_disable_port(pdev, &pdev->usb3_port);
> +	cdnsp_disable_port(pdev, &pdev->eusb_port);
> +
>  	cdnsp_disable_slot(pdev);
>  	cdnsp_halt(pdev);
>  
> @@ -1479,8 +1495,9 @@ static void cdnsp_stop(struct cdnsp_device *pdev)
>  	temp = readl(&pdev->ir_set->irq_pending);
>  	writel(IMAN_IE_CLEAR(temp), &pdev->ir_set->irq_pending);
>  
> -	cdnsp_clear_port_change_bit(pdev, &pdev->usb2_port.regs->portsc);
> -	cdnsp_clear_port_change_bit(pdev, &pdev->usb3_port.regs->portsc);
> +	cdnsp_clear_port_change_bit(pdev, &pdev->usb2_port);
> +	cdnsp_clear_port_change_bit(pdev, &pdev->eusb_port);
> +	cdnsp_clear_port_change_bit(pdev, &pdev->usb3_port);
>  
>  	/* Clear interrupt line */
>  	temp = readl(&pdev->ir_set->irq_pending);
> diff --git a/drivers/usb/cdns3/cdnsp-gadget.h b/drivers/usb/cdns3/cdnsp-gadget.h
> index a91cca509db0..c44bca348a41 100644
> --- a/drivers/usb/cdns3/cdnsp-gadget.h
> +++ b/drivers/usb/cdns3/cdnsp-gadget.h
> @@ -1474,6 +1474,7 @@ struct cdnsp_device {
>  	unsigned int link_state;
>  
>  	struct cdnsp_port usb2_port;
> +	struct cdnsp_port eusb_port;
>  	struct cdnsp_port usb3_port;
>  	struct cdnsp_port *active_port;
>  	u16 test_mode;
> diff --git a/drivers/usb/cdns3/cdnsp-mem.c b/drivers/usb/cdns3/cdnsp-mem.c
> index a2a1b21f2ef8..932071818d1e 100644
> --- a/drivers/usb/cdns3/cdnsp-mem.c
> +++ b/drivers/usb/cdns3/cdnsp-mem.c
> @@ -1088,11 +1088,9 @@ void cdnsp_mem_cleanup(struct cdnsp_device *pdev)
>  			  pdev->dcbaa, pdev->dcbaa->dma);
>  
>  	pdev->dcbaa = NULL;
> -
> -	pdev->usb2_port.exist = 0;
> -	pdev->usb3_port.exist = 0;
> -	pdev->usb2_port.port_num = 0;
> -	pdev->usb3_port.port_num = 0;
> +	memset(&pdev->usb2_port, 0, sizeof(struct cdnsp_port));
> +	memset(&pdev->eusb_port, 0, sizeof(struct cdnsp_port));
> +	memset(&pdev->usb3_port, 0, sizeof(struct cdnsp_port));
>  	pdev->active_port = NULL;
>  }
>  
> @@ -1133,6 +1131,18 @@ static void cdnsp_add_in_port(struct cdnsp_device *pdev,
>  	port_offset = CDNSP_EXT_PORT_OFF(temp);
>  	port_count = CDNSP_EXT_PORT_COUNT(temp);
>  
> +	if (port == &pdev->eusb_port) {
> +		/*
> +		 * If controller has usb2 + eusb port then eusb is as
> +		 * second port
> +		 */

What kinds of topology like below usb2 + eusb?

> +		if (port_count == 2)
> +			port_offset++;
> +
> +		if (port_count == 1 && pdev->usb2_port.exist)
> +			return;
> +	}
> +
>  	trace_cdnsp_port_info(addr, port_offset, port_count, port->maj_rev);
>  
>  	port->port_num = port_offset;
> @@ -1152,13 +1162,10 @@ static int cdnsp_setup_port_arrays(struct cdnsp_device *pdev)
>  	base = &pdev->cap_regs->hc_capbase;
>  	offset = cdnsp_find_next_ext_cap(base, 0,
>  					 EXT_CAP_CFG_DEV_20PORT_CAP_ID);
> -	pdev->port20_regs = base + offset;
> -
> -	offset = cdnsp_find_next_ext_cap(base, 0, D_XEC_CFG_3XPORT_CAP);
> -	pdev->port3x_regs =  base + offset;
> +	if (offset)
> +		pdev->port20_regs = base + offset;
>  
>  	offset = 0;
> -	base = &pdev->cap_regs->hc_capbase;
>  
>  	/* Driver expects max 2 extended protocol capability. */
>  	for (i = 0; i < 2; i++) {
> @@ -1173,26 +1180,46 @@ static int cdnsp_setup_port_arrays(struct cdnsp_device *pdev)
>  			cdnsp_add_in_port(pdev, &pdev->usb3_port,
>  					  base + offset);
>  
> -		if (CDNSP_EXT_PORT_MAJOR(temp) == 0x02 &&
> -		    !pdev->usb2_port.port_num)
> -			cdnsp_add_in_port(pdev, &pdev->usb2_port,
> -					  base + offset);
> +		if (CDNSP_EXT_PORT_MAJOR(temp) == 0x02) {
> +			if (!pdev->usb2_port.port_num && pdev->port20_regs)

Why "&& pdev->port20_regs" is added?

> +				cdnsp_add_in_port(pdev, &pdev->usb2_port,
> +						  base + offset);
> +
> +			if (!pdev->eusb_port.port_num)
> +				cdnsp_add_in_port(pdev, &pdev->eusb_port,
> +						  base + offset);
> +		}
>  	}
>  
> -	if (!pdev->usb2_port.exist || !pdev->usb3_port.exist) {
> -		dev_err(pdev->dev, "Error: Only one port detected\n");
> +	if (!pdev->usb2_port.exist && !pdev->eusb_port.exist &&
> +	    !pdev->usb3_port.exist) {
> +		dev_err(pdev->dev, "Error: No port detected\n");
>  		return -ENODEV;
>  	}
>  
> -	trace_cdnsp_init("Found USB 2.0 ports and  USB 3.0 ports.");
> +	if (pdev->usb2_port.exist) {
> +		pdev->usb2_port.regs = (struct cdnsp_port_regs __iomem *)
> +				       (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
> +					(pdev->usb2_port.port_num - 1));
> +		trace_cdnsp_init("Found USB 2.0 port.");
> +	}
>  
> -	pdev->usb2_port.regs = (struct cdnsp_port_regs __iomem *)
> -			       (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
> -				(pdev->usb2_port.port_num - 1));
> +	if (pdev->eusb_port.exist) {
> +		pdev->eusb_port.regs = (struct cdnsp_port_regs __iomem *)
> +				       (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
> +					(pdev->eusb_port.port_num - 1));
> +		trace_cdnsp_init("Found eUSB 2.0 port.");
> +	}
> +
> +	if (pdev->usb3_port.exist) {
> +		offset = cdnsp_find_next_ext_cap(base, 0, D_XEC_CFG_3XPORT_CAP);
> +		pdev->port3x_regs =  base + offset;
>  
> -	pdev->usb3_port.regs = (struct cdnsp_port_regs __iomem *)
> -			       (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
> -				(pdev->usb3_port.port_num - 1));
> +		pdev->usb3_port.regs = (struct cdnsp_port_regs __iomem *)
> +				       (&pdev->op_regs->port_reg_base + NUM_PORT_REGS *
> +					(pdev->usb3_port.port_num - 1));
> +		trace_cdnsp_init("Found  USB 3.x port.");

One More blank space after "Found"

Peter
> +	}
>  
>  	return 0;
>  }
> diff --git a/drivers/usb/cdns3/cdnsp-ring.c b/drivers/usb/cdns3/cdnsp-ring.c
> index 0758f171f73e..715658c981ff 100644
> --- a/drivers/usb/cdns3/cdnsp-ring.c
> +++ b/drivers/usb/cdns3/cdnsp-ring.c
> @@ -259,7 +259,7 @@ static bool cdnsp_room_on_ring(struct cdnsp_device *pdev,
>   */
>  static void cdnsp_force_l0_go(struct cdnsp_device *pdev)
>  {
> -	if (pdev->active_port == &pdev->usb2_port && pdev->gadget.lpm_capable)
> +	if (pdev->active_port != &pdev->usb3_port && pdev->gadget.lpm_capable)
>  		cdnsp_set_link_state(pdev, &pdev->active_port->regs->portsc, XDEV_U0);
>  }
>  
> @@ -763,6 +763,8 @@ static int cdnsp_update_port_id(struct cdnsp_device *pdev, u32 port_id)
>  
>  	if (port_id == pdev->usb2_port.port_num) {
>  		port = &pdev->usb2_port;
> +	} else if (port_id == pdev->eusb_port.port_num) {
> +		port = &pdev->eusb_port;
>  	} else if (port_id == pdev->usb3_port.port_num) {
>  		port  = &pdev->usb3_port;
>  	} else {
> @@ -779,7 +781,8 @@ static int cdnsp_update_port_id(struct cdnsp_device *pdev, u32 port_id)
>  		cdnsp_enable_slot(pdev);
>  	}
>  
> -	if (port_id == pdev->usb2_port.port_num)
> +	if ((pdev->usb2_port.exist && port_id == pdev->usb2_port.port_num) ||
> +	    (pdev->eusb_port.exist && port_id == pdev->eusb_port.port_num))
>  		cdnsp_set_usb2_hardware_lpm(pdev, NULL, 1);
>  	else
>  		writel(PORT_U1_TIMEOUT(1) | PORT_U2_TIMEOUT(1),
> @@ -808,7 +811,7 @@ static void cdnsp_handle_port_status(struct cdnsp_device *pdev,
>  
>  	port_regs = pdev->active_port->regs;
>  
> -	if (port_id == pdev->usb2_port.port_num)
> +	if (port_id == pdev->usb2_port.port_num || port_id == pdev->eusb_port.port_num)
>  		port2 = true;
>  
>  new_event:
> 
> ---
> base-commit: 1c7cc4904160c6fc6377564140062d68a3dc93a0
> change-id: 20260417-eusb2v2_upstream-80c5b29a7bba
> 
> Best regards,
> --  
> Pawel Laszczak <pawell@cadence.com>
> 
> 

-- 

Best regards,
Peter

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-04-18  1:38 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-17  8:37 [PATCH] usb: cdnsp: add support for eUSB2v2 port Pawel Laszczak via B4 Relay
2026-04-18  1:38 ` Peter Chen (CIX)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox