diff mbox series

drivers: usb: host: Fix the write to W1C fields in HPRT register

Message ID 20230202011458.20850-1-teik.heng.chong@intel.com
State Superseded
Delegated to: Marek Vasut
Headers show
Series drivers: usb: host: Fix the write to W1C fields in HPRT register | expand

Commit Message

Chong, Teik Heng Feb. 2, 2023, 1:14 a.m. UTC
From: Teik Heng Chong <teik.heng.chong@intel.com>

Fix the write to the HPRT register which treat W1C fields
as if they were mere RW. This leads to unintended clearing of such fields

Signed-off-by: Teik Heng Chong <teik.heng.chong@intel.com>
---
 drivers/usb/host/dwc2.c | 34 ++++++++--------------------------
 drivers/usb/host/dwc2.h |  4 ++++
 2 files changed, 12 insertions(+), 26 deletions(-)

Comments

Marek Vasut Feb. 2, 2023, 3:15 p.m. UTC | #1
On 2/2/23 02:14, teik.heng.chong@intel.com wrote:

The subject tags are 'usb: dwc2:' .

> diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
> index 23060fc369..9818f9be94 100644
> --- a/drivers/usb/host/dwc2.c
> +++ b/drivers/usb/host/dwc2.c
> @@ -315,9 +315,7 @@ static void dwc_otg_core_host_init(struct udevice *dev,
>   
>   	/* Turn on the vbus power. */
>   	if (readl(&regs->gintsts) & DWC2_GINTSTS_CURMODE_HOST) {
> -		hprt0 = readl(&regs->hprt0);
> -		hprt0 &= ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET);
> -		hprt0 &= ~(DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG);
> +		hprt0 = readl(&regs->hprt0) & ~DWC2_HPRT0_W1C_MASK;
>   		if (!(hprt0 & DWC2_HPRT0_PRTPWR)) {
>   			hprt0 |= DWC2_HPRT0_PRTPWR;
>   			writel(hprt0, &regs->hprt0);
> @@ -748,7 +746,7 @@ static int dwc_otg_submit_rh_msg_out(struct dwc2_priv *priv,
>   	case (USB_REQ_CLEAR_FEATURE << 8) | USB_RECIP_OTHER | USB_TYPE_CLASS:
>   		switch (wValue) {
>   		case USB_PORT_FEAT_C_CONNECTION:
> -			setbits_le32(&regs->hprt0, DWC2_HPRT0_PRTCONNDET);
> +			clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_W1C_MASK, DWC2_HPRT0_PRTCONNDET);
>   			break;
>   		}
>   		break;
> @@ -759,21 +757,13 @@ static int dwc_otg_submit_rh_msg_out(struct dwc2_priv *priv,
>   			break;
>   
>   		case USB_PORT_FEAT_RESET:
> -			clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA |
> -					DWC2_HPRT0_PRTCONNDET |
> -					DWC2_HPRT0_PRTENCHNG |
> -					DWC2_HPRT0_PRTOVRCURRCHNG,
> -					DWC2_HPRT0_PRTRST);
> +			clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_W1C_MASK, DWC2_HPRT0_PRTRST);

The code above used to be clearing the W1C (write 1 to clear) bits , 
while the changed code is no longer clearing those bits. Is that correct ?

[...]
Chong, Teik Heng Feb. 7, 2023, 4:28 a.m. UTC | #2
-----Original Message-----
From: Marek Vasut <marex@denx.de> 
Sent: Thursday, 2 February, 2023 11:16 PM
To: Chong, Teik Heng <teik.heng.chong@intel.com>; u-boot@lists.denx.de
Cc: Simon <simon.k.r.goldschmidt@gmail.com>; Chee, Tien Fong <tien.fong.chee@intel.com>; Hea, Kok Kiang <kok.kiang.hea@intel.com>; Lim, Elly Siew Chin <elly.siew.chin.lim@intel.com>; Kho, Sin Hui <sin.hui.kho@intel.com>; Lokanathan, Raaj <raaj.lokanathan@intel.com>; Maniyam, Dinesh <dinesh.maniyam@intel.com>; Ng, Boon Khai <boon.khai.ng@intel.com>; Yuslaimi, Alif Zakuan <alif.zakuan.yuslaimi@intel.com>; Zamri, Muhammad Hazim Izzat <muhammad.hazim.izzat.zamri@intel.com>; Lim, Jit Loon <jit.loon.lim@intel.com>; Tang, Sieu Mun <sieu.mun.tang@intel.com>
Subject: Re: [PATCH] drivers: usb: host: Fix the write to W1C fields in HPRT register

On 2/2/23 02:14, teik.heng.chong@intel.com wrote:

The subject tags are 'usb: dwc2:' .

> diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index 
> 23060fc369..9818f9be94 100644
> --- a/drivers/usb/host/dwc2.c
> +++ b/drivers/usb/host/dwc2.c
> @@ -315,9 +315,7 @@ static void dwc_otg_core_host_init(struct udevice 
> *dev,
>   
>   	/* Turn on the vbus power. */
>   	if (readl(&regs->gintsts) & DWC2_GINTSTS_CURMODE_HOST) {
> -		hprt0 = readl(&regs->hprt0);
> -		hprt0 &= ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET);
> -		hprt0 &= ~(DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG);
> +		hprt0 = readl(&regs->hprt0) & ~DWC2_HPRT0_W1C_MASK;
>   		if (!(hprt0 & DWC2_HPRT0_PRTPWR)) {
>   			hprt0 |= DWC2_HPRT0_PRTPWR;
>   			writel(hprt0, &regs->hprt0);
> @@ -748,7 +746,7 @@ static int dwc_otg_submit_rh_msg_out(struct dwc2_priv *priv,
>   	case (USB_REQ_CLEAR_FEATURE << 8) | USB_RECIP_OTHER | USB_TYPE_CLASS:
>   		switch (wValue) {
>   		case USB_PORT_FEAT_C_CONNECTION:
> -			setbits_le32(&regs->hprt0, DWC2_HPRT0_PRTCONNDET);
> +			clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_W1C_MASK, 
> +DWC2_HPRT0_PRTCONNDET);
>   			break;
>   		}
>   		break;
> @@ -759,21 +757,13 @@ static int dwc_otg_submit_rh_msg_out(struct dwc2_priv *priv,
>   			break;
>   
>   		case USB_PORT_FEAT_RESET:
> -			clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA |
> -					DWC2_HPRT0_PRTCONNDET |
> -					DWC2_HPRT0_PRTENCHNG |
> -					DWC2_HPRT0_PRTOVRCURRCHNG,
> -					DWC2_HPRT0_PRTRST);
> +			clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_W1C_MASK, 
> +DWC2_HPRT0_PRTRST);

The code above used to be clearing the W1C (write 1 to clear) bits , while the changed code is no longer clearing those bits. Is that correct ?

yes

[...]
diff mbox series

Patch

diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index 23060fc369..9818f9be94 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -315,9 +315,7 @@  static void dwc_otg_core_host_init(struct udevice *dev,
 
 	/* Turn on the vbus power. */
 	if (readl(&regs->gintsts) & DWC2_GINTSTS_CURMODE_HOST) {
-		hprt0 = readl(&regs->hprt0);
-		hprt0 &= ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET);
-		hprt0 &= ~(DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG);
+		hprt0 = readl(&regs->hprt0) & ~DWC2_HPRT0_W1C_MASK;
 		if (!(hprt0 & DWC2_HPRT0_PRTPWR)) {
 			hprt0 |= DWC2_HPRT0_PRTPWR;
 			writel(hprt0, &regs->hprt0);
@@ -748,7 +746,7 @@  static int dwc_otg_submit_rh_msg_out(struct dwc2_priv *priv,
 	case (USB_REQ_CLEAR_FEATURE << 8) | USB_RECIP_OTHER | USB_TYPE_CLASS:
 		switch (wValue) {
 		case USB_PORT_FEAT_C_CONNECTION:
-			setbits_le32(&regs->hprt0, DWC2_HPRT0_PRTCONNDET);
+			clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_W1C_MASK, DWC2_HPRT0_PRTCONNDET);
 			break;
 		}
 		break;
@@ -759,21 +757,13 @@  static int dwc_otg_submit_rh_msg_out(struct dwc2_priv *priv,
 			break;
 
 		case USB_PORT_FEAT_RESET:
-			clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA |
-					DWC2_HPRT0_PRTCONNDET |
-					DWC2_HPRT0_PRTENCHNG |
-					DWC2_HPRT0_PRTOVRCURRCHNG,
-					DWC2_HPRT0_PRTRST);
+			clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_W1C_MASK, DWC2_HPRT0_PRTRST);
 			mdelay(50);
-			clrbits_le32(&regs->hprt0, DWC2_HPRT0_PRTRST);
+			clrbits_le32(&regs->hprt0, DWC2_HPRT0_W1C_MASK | DWC2_HPRT0_PRTRST);
 			break;
 
 		case USB_PORT_FEAT_POWER:
-			clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA |
-					DWC2_HPRT0_PRTCONNDET |
-					DWC2_HPRT0_PRTENCHNG |
-					DWC2_HPRT0_PRTOVRCURRCHNG,
-					DWC2_HPRT0_PRTRST);
+			clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_W1C_MASK, DWC2_HPRT0_PRTRST);
 			break;
 
 		case USB_PORT_FEAT_ENABLE:
@@ -1213,14 +1203,9 @@  static int dwc2_init_common(struct udevice *dev, struct dwc2_priv *priv)
 		dwc_otg_core_host_init(dev, regs);
 	}
 
-	clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA |
-			DWC2_HPRT0_PRTCONNDET | DWC2_HPRT0_PRTENCHNG |
-			DWC2_HPRT0_PRTOVRCURRCHNG,
-			DWC2_HPRT0_PRTRST);
+	clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_W1C_MASK, DWC2_HPRT0_PRTRST);
 	mdelay(50);
-	clrbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET |
-		     DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG |
-		     DWC2_HPRT0_PRTRST);
+	clrbits_le32(&regs->hprt0, DWC2_HPRT0_W1C_MASK | DWC2_HPRT0_PRTRST);
 
 	for (i = 0; i < MAX_DEVICE; i++) {
 		for (j = 0; j < MAX_ENDPOINT; j++) {
@@ -1246,10 +1231,7 @@  static int dwc2_init_common(struct udevice *dev, struct dwc2_priv *priv)
 static void dwc2_uninit_common(struct dwc2_core_regs *regs)
 {
 	/* Put everything in reset. */
-	clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_PRTENA |
-			DWC2_HPRT0_PRTCONNDET | DWC2_HPRT0_PRTENCHNG |
-			DWC2_HPRT0_PRTOVRCURRCHNG,
-			DWC2_HPRT0_PRTRST);
+	clrsetbits_le32(&regs->hprt0, DWC2_HPRT0_W1C_MASK, DWC2_HPRT0_PRTRST);
 }
 
 #if !CONFIG_IS_ENABLED(DM_USB)
diff --git a/drivers/usb/host/dwc2.h b/drivers/usb/host/dwc2.h
index a6f562fe60..6f022e33a1 100644
--- a/drivers/usb/host/dwc2.h
+++ b/drivers/usb/host/dwc2.h
@@ -543,6 +543,10 @@  struct dwc2_core_regs {
 #define DWC2_HPRT0_PRTSPD_LOW				(2 << 17)
 #define DWC2_HPRT0_PRTSPD_MASK				(0x3 << 17)
 #define DWC2_HPRT0_PRTSPD_OFFSET			17
+#define DWC2_HPRT0_W1C_MASK				(DWC2_HPRT0_PRTCONNDET | \
+							DWC2_HPRT0_PRTENA | \
+							DWC2_HPRT0_PRTENCHNG | \
+							DWC2_HPRT0_PRTOVRCURRCHNG)
 #define DWC2_HAINT_CH0					(1 << 0)
 #define DWC2_HAINT_CH0_OFFSET				0
 #define DWC2_HAINT_CH1					(1 << 1)