linux-mmc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] misc: rtsx: usb card reader: add OCP support
@ 2025-08-12  3:08 Ricky Wu
  2025-08-12  6:33 ` Greg KH
  2025-08-18 10:55 ` Ulf Hansson
  0 siblings, 2 replies; 3+ messages in thread
From: Ricky Wu @ 2025-08-12  3:08 UTC (permalink / raw)
  To: linux-kernel, linux-mmc, arnd, gregkh, chenhuacai, ricky_wu,
	ulf.hansson, maximlevitsky
  Cc: kernel test robot

This patch adds support for Over Current Protection (OCP) to the Realtek
USB card reader driver.

The OCP mechanism protects the hardware by detecting and handling current
overload conditions.
This implementation includes:

- Register configurations to enable OCP monitoring.
- Handling of OCP interrupt events and associated error reporting.
- Card power management changes in response to OCP triggers.

This enhancement improves the robustness of the driver when operating in
environments where electrical anomalies may occur, particularly with SD
and MS card interfaces.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202508061704.hwI8epAJ-lkp@intel.com/
Signed-off-by: Ricky Wu <ricky_wu@realtek.com>
...

v2: move ocp check in power_on flow
---
 drivers/memstick/host/rtsx_usb_ms.c |  5 ++++-
 drivers/misc/cardreader/rtsx_usb.c  |  7 ++++++
 drivers/mmc/host/rtsx_usb_sdmmc.c   | 33 ++++++++++++++++++++++++++---
 include/linux/rtsx_usb.h            | 11 ++++++++++
 4 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/drivers/memstick/host/rtsx_usb_ms.c b/drivers/memstick/host/rtsx_usb_ms.c
index 3878136227e4..9389e9643c24 100644
--- a/drivers/memstick/host/rtsx_usb_ms.c
+++ b/drivers/memstick/host/rtsx_usb_ms.c
@@ -216,7 +216,10 @@ static int ms_power_off(struct rtsx_usb_ms *host)
 
 	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, 0);
 	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0);
-
+	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
+			POWER_MASK, POWER_OFF);
+	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
+			POWER_MASK | LDO3318_PWR_MASK, POWER_OFF | LDO_SUSPEND);
 	err = rtsx_usb_send_cmd(ucr, MODE_C, 100);
 	if (err < 0)
 		return err;
diff --git a/drivers/misc/cardreader/rtsx_usb.c b/drivers/misc/cardreader/rtsx_usb.c
index d007a4455ce5..1830e9ed2521 100644
--- a/drivers/misc/cardreader/rtsx_usb.c
+++ b/drivers/misc/cardreader/rtsx_usb.c
@@ -552,6 +552,10 @@ static int rtsx_usb_reset_chip(struct rtsx_ucr *ucr)
 	ret = rtsx_usb_send_cmd(ucr, MODE_C, 100);
 	if (ret)
 		return ret;
+	/* config OCP */
+	rtsx_usb_write_register(ucr, OCPCTL, MS_OCP_DETECT_EN, MS_OCP_DETECT_EN);
+	rtsx_usb_write_register(ucr, OCPPARA1, 0xF0, 0x50);
+	rtsx_usb_write_register(ucr, OCPPARA2, 0x7, 0x3);
 
 	/* config non-crystal mode */
 	rtsx_usb_read_register(ucr, CFG_MODE, &val);
@@ -722,6 +726,9 @@ static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message)
 			if (val & (SD_CD | MS_CD)) {
 				device_for_each_child(&intf->dev, NULL, rtsx_usb_resume_child);
 				return -EAGAIN;
+			} else {
+				/* if the card does not exists, clear OCP status */
+				rtsx_usb_write_register(ucr, OCPCTL, MS_OCP_CLEAR, MS_OCP_CLEAR);
 			}
 		} else {
 			/* There is an ongoing operation*/
diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c
index c5f6b9df066b..e1ed39c657c3 100644
--- a/drivers/mmc/host/rtsx_usb_sdmmc.c
+++ b/drivers/mmc/host/rtsx_usb_sdmmc.c
@@ -48,7 +48,7 @@ struct rtsx_usb_sdmmc {
 	bool			ddr_mode;
 
 	unsigned char		power_mode;
-
+	u16			ocp_stat;
 #ifdef RTSX_USB_USE_LEDS_CLASS
 	struct led_classdev	led;
 	char			led_name[32];
@@ -785,6 +785,9 @@ static int sdmmc_get_cd(struct mmc_host *mmc)
 
 	mutex_unlock(&ucr->dev_mutex);
 
+	/* get OCP status */
+	host->ocp_stat = (val >> 4) & 0x03;
+
 	/* Treat failed detection as non-exist */
 	if (err)
 		goto no_card;
@@ -795,6 +798,11 @@ static int sdmmc_get_cd(struct mmc_host *mmc)
 	}
 
 no_card:
+	/* clear OCP status */
+	if (host->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)) {
+		rtsx_usb_write_register(ucr, OCPCTL, MS_OCP_CLEAR, MS_OCP_CLEAR);
+		host->ocp_stat = 0;
+	}
 	host->card_exist = false;
 	return 0;
 }
@@ -818,7 +826,11 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 		cmd->error = -ENOMEDIUM;
 		goto finish_detect_card;
 	}
-
+	/* check OCP stat */
+	if (host->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)) {
+		cmd->error = -ENOMEDIUM;
+		goto finish_detect_card;
+	}
 	mutex_lock(&ucr->dev_mutex);
 
 	mutex_lock(&host->host_mutex);
@@ -952,6 +964,10 @@ static int sd_power_on(struct rtsx_usb_sdmmc *host)
 	struct rtsx_ucr *ucr = host->ucr;
 	int err;
 
+	if (host->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)) {
+		dev_dbg(sdmmc_dev(host), "over current\n");
+		return -EIO;
+	}
 	dev_dbg(sdmmc_dev(host), "%s\n", __func__);
 	rtsx_usb_init_cmd(ucr);
 	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL);
@@ -977,9 +993,19 @@ static int sd_power_on(struct rtsx_usb_sdmmc *host)
 
 	usleep_range(800, 1000);
 
+	rtsx_usb_init_cmd(ucr);
+	/* WA OCP issue: after OCP, there were problems with reopen card power */
+	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, POWER_MASK, POWER_ON);
+	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, FPDCTL, SSC_POWER_MASK, SSC_POWER_DOWN);
+	err = rtsx_usb_send_cmd(ucr, MODE_C, 100);
+	if (err)
+		return err;
+	msleep(20);
+	rtsx_usb_write_register(ucr, FPDCTL, SSC_POWER_MASK, SSC_POWER_ON);
+	usleep_range(180, 200);
 	rtsx_usb_init_cmd(ucr);
 	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
-			POWER_MASK|LDO3318_PWR_MASK, POWER_ON|LDO_ON);
+			LDO3318_PWR_MASK, LDO_ON);
 	rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE,
 			SD_OUTPUT_EN, SD_OUTPUT_EN);
 
@@ -1332,6 +1358,7 @@ static void rtsx_usb_init_host(struct rtsx_usb_sdmmc *host)
 	mmc->max_req_size = 524288;
 
 	host->power_mode = MMC_POWER_OFF;
+	host->ocp_stat = 0;
 }
 
 static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev)
diff --git a/include/linux/rtsx_usb.h b/include/linux/rtsx_usb.h
index f267a06c6b1e..276b509c03e3 100644
--- a/include/linux/rtsx_usb.h
+++ b/include/linux/rtsx_usb.h
@@ -99,6 +99,17 @@ extern int rtsx_usb_card_exclusive_check(struct rtsx_ucr *ucr, int card);
 #define CD_MASK		(SD_CD | MS_CD | XD_CD)
 #define SD_WP		0x08
 
+/* OCPCTL */
+#define MS_OCP_DETECT_EN		0x08
+#define	MS_OCP_INT_EN			0x04
+#define	MS_OCP_INT_CLR			0x02
+#define	MS_OCP_CLEAR			0x01
+
+/* OCPSTAT */
+#define MS_OCP_DETECT			0x80
+#define MS_OCP_NOW			0x02
+#define MS_OCP_EVER			0x01
+
 /* reader command field offset & parameters */
 #define READ_REG_CMD		0
 #define WRITE_REG_CMD		1
-- 
2.25.1


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

* Re: [PATCH v2] misc: rtsx: usb card reader: add OCP support
  2025-08-12  3:08 [PATCH v2] misc: rtsx: usb card reader: add OCP support Ricky Wu
@ 2025-08-12  6:33 ` Greg KH
  2025-08-18 10:55 ` Ulf Hansson
  1 sibling, 0 replies; 3+ messages in thread
From: Greg KH @ 2025-08-12  6:33 UTC (permalink / raw)
  To: Ricky Wu
  Cc: linux-kernel, linux-mmc, arnd, chenhuacai, ulf.hansson,
	maximlevitsky, kernel test robot

On Tue, Aug 12, 2025 at 11:08:11AM +0800, Ricky Wu wrote:
> This patch adds support for Over Current Protection (OCP) to the Realtek
> USB card reader driver.
> 
> The OCP mechanism protects the hardware by detecting and handling current
> overload conditions.
> This implementation includes:
> 
> - Register configurations to enable OCP monitoring.
> - Handling of OCP interrupt events and associated error reporting.
> - Card power management changes in response to OCP triggers.
> 
> This enhancement improves the robustness of the driver when operating in
> environments where electrical anomalies may occur, particularly with SD
> and MS card interfaces.
> 
> Reported-by: kernel test robot <lkp@intel.com>

the kernel test robot did NOT report that this driver was lacking this
new feature :(


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

* Re: [PATCH v2] misc: rtsx: usb card reader: add OCP support
  2025-08-12  3:08 [PATCH v2] misc: rtsx: usb card reader: add OCP support Ricky Wu
  2025-08-12  6:33 ` Greg KH
@ 2025-08-18 10:55 ` Ulf Hansson
  1 sibling, 0 replies; 3+ messages in thread
From: Ulf Hansson @ 2025-08-18 10:55 UTC (permalink / raw)
  To: Ricky Wu
  Cc: linux-kernel, linux-mmc, arnd, gregkh, chenhuacai, maximlevitsky,
	kernel test robot

On Tue, 12 Aug 2025 at 05:08, Ricky Wu <ricky_wu@realtek.com> wrote:
>
> This patch adds support for Over Current Protection (OCP) to the Realtek
> USB card reader driver.
>
> The OCP mechanism protects the hardware by detecting and handling current
> overload conditions.
> This implementation includes:
>
> - Register configurations to enable OCP monitoring.
> - Handling of OCP interrupt events and associated error reporting.
> - Card power management changes in response to OCP triggers.
>
> This enhancement improves the robustness of the driver when operating in
> environments where electrical anomalies may occur, particularly with SD
> and MS card interfaces.
>
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202508061704.hwI8epAJ-lkp@intel.com/
> Signed-off-by: Ricky Wu <ricky_wu@realtek.com>

Applied for next and by removing the Reported-by/Closes tags, thanks!

Kind regards
Uffe


> ...
>
> v2: move ocp check in power_on flow
> ---
>  drivers/memstick/host/rtsx_usb_ms.c |  5 ++++-
>  drivers/misc/cardreader/rtsx_usb.c  |  7 ++++++
>  drivers/mmc/host/rtsx_usb_sdmmc.c   | 33 ++++++++++++++++++++++++++---
>  include/linux/rtsx_usb.h            | 11 ++++++++++
>  4 files changed, 52 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/memstick/host/rtsx_usb_ms.c b/drivers/memstick/host/rtsx_usb_ms.c
> index 3878136227e4..9389e9643c24 100644
> --- a/drivers/memstick/host/rtsx_usb_ms.c
> +++ b/drivers/memstick/host/rtsx_usb_ms.c
> @@ -216,7 +216,10 @@ static int ms_power_off(struct rtsx_usb_ms *host)
>
>         rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, 0);
>         rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0);
> -
> +       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
> +                       POWER_MASK, POWER_OFF);
> +       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
> +                       POWER_MASK | LDO3318_PWR_MASK, POWER_OFF | LDO_SUSPEND);
>         err = rtsx_usb_send_cmd(ucr, MODE_C, 100);
>         if (err < 0)
>                 return err;
> diff --git a/drivers/misc/cardreader/rtsx_usb.c b/drivers/misc/cardreader/rtsx_usb.c
> index d007a4455ce5..1830e9ed2521 100644
> --- a/drivers/misc/cardreader/rtsx_usb.c
> +++ b/drivers/misc/cardreader/rtsx_usb.c
> @@ -552,6 +552,10 @@ static int rtsx_usb_reset_chip(struct rtsx_ucr *ucr)
>         ret = rtsx_usb_send_cmd(ucr, MODE_C, 100);
>         if (ret)
>                 return ret;
> +       /* config OCP */
> +       rtsx_usb_write_register(ucr, OCPCTL, MS_OCP_DETECT_EN, MS_OCP_DETECT_EN);
> +       rtsx_usb_write_register(ucr, OCPPARA1, 0xF0, 0x50);
> +       rtsx_usb_write_register(ucr, OCPPARA2, 0x7, 0x3);
>
>         /* config non-crystal mode */
>         rtsx_usb_read_register(ucr, CFG_MODE, &val);
> @@ -722,6 +726,9 @@ static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message)
>                         if (val & (SD_CD | MS_CD)) {
>                                 device_for_each_child(&intf->dev, NULL, rtsx_usb_resume_child);
>                                 return -EAGAIN;
> +                       } else {
> +                               /* if the card does not exists, clear OCP status */
> +                               rtsx_usb_write_register(ucr, OCPCTL, MS_OCP_CLEAR, MS_OCP_CLEAR);
>                         }
>                 } else {
>                         /* There is an ongoing operation*/
> diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c
> index c5f6b9df066b..e1ed39c657c3 100644
> --- a/drivers/mmc/host/rtsx_usb_sdmmc.c
> +++ b/drivers/mmc/host/rtsx_usb_sdmmc.c
> @@ -48,7 +48,7 @@ struct rtsx_usb_sdmmc {
>         bool                    ddr_mode;
>
>         unsigned char           power_mode;
> -
> +       u16                     ocp_stat;
>  #ifdef RTSX_USB_USE_LEDS_CLASS
>         struct led_classdev     led;
>         char                    led_name[32];
> @@ -785,6 +785,9 @@ static int sdmmc_get_cd(struct mmc_host *mmc)
>
>         mutex_unlock(&ucr->dev_mutex);
>
> +       /* get OCP status */
> +       host->ocp_stat = (val >> 4) & 0x03;
> +
>         /* Treat failed detection as non-exist */
>         if (err)
>                 goto no_card;
> @@ -795,6 +798,11 @@ static int sdmmc_get_cd(struct mmc_host *mmc)
>         }
>
>  no_card:
> +       /* clear OCP status */
> +       if (host->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)) {
> +               rtsx_usb_write_register(ucr, OCPCTL, MS_OCP_CLEAR, MS_OCP_CLEAR);
> +               host->ocp_stat = 0;
> +       }
>         host->card_exist = false;
>         return 0;
>  }
> @@ -818,7 +826,11 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
>                 cmd->error = -ENOMEDIUM;
>                 goto finish_detect_card;
>         }
> -
> +       /* check OCP stat */
> +       if (host->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)) {
> +               cmd->error = -ENOMEDIUM;
> +               goto finish_detect_card;
> +       }
>         mutex_lock(&ucr->dev_mutex);
>
>         mutex_lock(&host->host_mutex);
> @@ -952,6 +964,10 @@ static int sd_power_on(struct rtsx_usb_sdmmc *host)
>         struct rtsx_ucr *ucr = host->ucr;
>         int err;
>
> +       if (host->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)) {
> +               dev_dbg(sdmmc_dev(host), "over current\n");
> +               return -EIO;
> +       }
>         dev_dbg(sdmmc_dev(host), "%s\n", __func__);
>         rtsx_usb_init_cmd(ucr);
>         rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL);
> @@ -977,9 +993,19 @@ static int sd_power_on(struct rtsx_usb_sdmmc *host)
>
>         usleep_range(800, 1000);
>
> +       rtsx_usb_init_cmd(ucr);
> +       /* WA OCP issue: after OCP, there were problems with reopen card power */
> +       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL, POWER_MASK, POWER_ON);
> +       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, FPDCTL, SSC_POWER_MASK, SSC_POWER_DOWN);
> +       err = rtsx_usb_send_cmd(ucr, MODE_C, 100);
> +       if (err)
> +               return err;
> +       msleep(20);
> +       rtsx_usb_write_register(ucr, FPDCTL, SSC_POWER_MASK, SSC_POWER_ON);
> +       usleep_range(180, 200);
>         rtsx_usb_init_cmd(ucr);
>         rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
> -                       POWER_MASK|LDO3318_PWR_MASK, POWER_ON|LDO_ON);
> +                       LDO3318_PWR_MASK, LDO_ON);
>         rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE,
>                         SD_OUTPUT_EN, SD_OUTPUT_EN);
>
> @@ -1332,6 +1358,7 @@ static void rtsx_usb_init_host(struct rtsx_usb_sdmmc *host)
>         mmc->max_req_size = 524288;
>
>         host->power_mode = MMC_POWER_OFF;
> +       host->ocp_stat = 0;
>  }
>
>  static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev)
> diff --git a/include/linux/rtsx_usb.h b/include/linux/rtsx_usb.h
> index f267a06c6b1e..276b509c03e3 100644
> --- a/include/linux/rtsx_usb.h
> +++ b/include/linux/rtsx_usb.h
> @@ -99,6 +99,17 @@ extern int rtsx_usb_card_exclusive_check(struct rtsx_ucr *ucr, int card);
>  #define CD_MASK                (SD_CD | MS_CD | XD_CD)
>  #define SD_WP          0x08
>
> +/* OCPCTL */
> +#define MS_OCP_DETECT_EN               0x08
> +#define        MS_OCP_INT_EN                   0x04
> +#define        MS_OCP_INT_CLR                  0x02
> +#define        MS_OCP_CLEAR                    0x01
> +
> +/* OCPSTAT */
> +#define MS_OCP_DETECT                  0x80
> +#define MS_OCP_NOW                     0x02
> +#define MS_OCP_EVER                    0x01
> +
>  /* reader command field offset & parameters */
>  #define READ_REG_CMD           0
>  #define WRITE_REG_CMD          1
> --
> 2.25.1
>

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

end of thread, other threads:[~2025-08-18 10:55 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-12  3:08 [PATCH v2] misc: rtsx: usb card reader: add OCP support Ricky Wu
2025-08-12  6:33 ` Greg KH
2025-08-18 10:55 ` Ulf Hansson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).