linux-mmc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] misc: rtsx: usb card reader: add OCP support
@ 2025-08-05  3:22 Ricky Wu
  2025-08-06 10:24 ` kernel test robot
  0 siblings, 1 reply; 2+ messages in thread
From: Ricky Wu @ 2025-08-05  3:22 UTC (permalink / raw)
  To: linux-kernel, linux-mmc, arnd, gregkh, chenhuacai, ricky_wu,
	ulf.hansson, maximlevitsky

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.

Signed-off-by: Ricky Wu <ricky_wu@realtek.com>
---
 drivers/memstick/host/rtsx_usb_ms.c |  5 ++++-
 drivers/misc/cardreader/rtsx_usb.c  |  7 +++++++
 drivers/mmc/host/rtsx_usb_sdmmc.c   | 32 +++++++++++++++++++++++++----
 include/linux/rtsx_usb.h            | 11 ++++++++++
 4 files changed, 50 insertions(+), 5 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..0632d294b12f 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);
@@ -977,9 +989,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);
 
@@ -1029,7 +1051,8 @@ static void sd_set_power_mode(struct rtsx_usb_sdmmc *host,
 
 	case MMC_POWER_UP:
 		pm_runtime_get_noresume(sdmmc_dev(host));
-		err = sd_power_on(host);
+		if (!(host->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)))
+			err = sd_power_on(host);
 		if (err)
 			dev_dbg(sdmmc_dev(host), "power-on (err = %d)\n", err);
 		/* issue the clock signals to card at least 74 clocks */
@@ -1332,6 +1355,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] 2+ messages in thread

* Re: [PATCH] misc: rtsx: usb card reader: add OCP support
  2025-08-05  3:22 [PATCH] misc: rtsx: usb card reader: add OCP support Ricky Wu
@ 2025-08-06 10:24 ` kernel test robot
  0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2025-08-06 10:24 UTC (permalink / raw)
  To: Ricky Wu, linux-kernel, linux-mmc, arnd, gregkh, chenhuacai,
	ulf.hansson, maximlevitsky
  Cc: llvm, oe-kbuild-all

Hi Ricky,

kernel test robot noticed the following build warnings:

[auto build test WARNING on char-misc/char-misc-testing]
[also build test WARNING on char-misc/char-misc-next char-misc/char-misc-linus linus/master next-20250806]
[cannot apply to soc/for-next ulf-hansson-mmc-mirror/next v6.16]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ricky-Wu/misc-rtsx-usb-card-reader-add-OCP-support/20250806-101802
base:   char-misc/char-misc-testing
patch link:    https://lore.kernel.org/r/20250805032220.2355160-1-ricky_wu%40realtek.com
patch subject: [PATCH] misc: rtsx: usb card reader: add OCP support
config: i386-buildonly-randconfig-001-20250806 (https://download.01.org/0day-ci/archive/20250806/202508061704.hwI8epAJ-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250806/202508061704.hwI8epAJ-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202508061704.hwI8epAJ-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/mmc/host/rtsx_usb_sdmmc.c:1054:7: warning: variable 'err' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
    1054 |                 if (!(host->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)))
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/mmc/host/rtsx_usb_sdmmc.c:1056:7: note: uninitialized use occurs here
    1056 |                 if (err)
         |                     ^~~
   drivers/mmc/host/rtsx_usb_sdmmc.c:1054:3: note: remove the 'if' if its condition is always true
    1054 |                 if (!(host->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)))
         |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1055 |                         err = sd_power_on(host);
   drivers/mmc/host/rtsx_usb_sdmmc.c:1038:9: note: initialize the variable 'err' to silence this warning
    1038 |         int err;
         |                ^
         |                 = 0
   1 warning generated.


vim +1054 drivers/mmc/host/rtsx_usb_sdmmc.c

  1034	
  1035	static void sd_set_power_mode(struct rtsx_usb_sdmmc *host,
  1036			unsigned char power_mode)
  1037	{
  1038		int err;
  1039		struct rtsx_ucr *ucr = host->ucr;
  1040	
  1041		if (power_mode == host->power_mode)
  1042			return;
  1043	
  1044		switch (power_mode) {
  1045		case MMC_POWER_OFF:
  1046			err = sd_power_off(host);
  1047			if (err)
  1048				dev_dbg(sdmmc_dev(host), "power-off (err = %d)\n", err);
  1049			pm_runtime_put_noidle(sdmmc_dev(host));
  1050			break;
  1051	
  1052		case MMC_POWER_UP:
  1053			pm_runtime_get_noresume(sdmmc_dev(host));
> 1054			if (!(host->ocp_stat & (MS_OCP_NOW | MS_OCP_EVER)))
  1055				err = sd_power_on(host);
  1056			if (err)
  1057				dev_dbg(sdmmc_dev(host), "power-on (err = %d)\n", err);
  1058			/* issue the clock signals to card at least 74 clocks */
  1059			rtsx_usb_write_register(ucr, SD_BUS_STAT, SD_CLK_TOGGLE_EN, SD_CLK_TOGGLE_EN);
  1060			break;
  1061	
  1062		case MMC_POWER_ON:
  1063			/* stop to send the clock signals */
  1064			rtsx_usb_write_register(ucr, SD_BUS_STAT, SD_CLK_TOGGLE_EN, 0x00);
  1065			break;
  1066	
  1067		case MMC_POWER_UNDEFINED:
  1068			break;
  1069	
  1070		default:
  1071			break;
  1072		}
  1073	
  1074		host->power_mode = power_mode;
  1075	}
  1076	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

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

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-05  3:22 [PATCH] misc: rtsx: usb card reader: add OCP support Ricky Wu
2025-08-06 10:24 ` kernel test robot

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