* [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).