From 4bdb576667a976996f870d36c5bb841b9d0c1258 Mon Sep 17 00:00:00 2001
From: Jonathan Bell <jonathan@raspberrypi.com>
Date: Tue, 26 Mar 2024 13:25:01 +0000
Subject: [PATCH 0994/1085] drivers: mmc: export SD extension register
 read/write functions

Certain status bits in these registers may need polling outside of
SD-specific code. Export in sd_ops.h

Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
---
 drivers/mmc/core/sd.c     | 97 ++++-----------------------------------
 drivers/mmc/core/sd_ops.c | 83 +++++++++++++++++++++++++++++++--
 drivers/mmc/core/sd_ops.h |  4 ++
 3 files changed, 93 insertions(+), 91 deletions(-)

--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1015,83 +1015,6 @@ static bool mmc_sd_card_using_v18(struct
 	       (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | SD_MODE_UHS_DDR50);
 }
 
-int sd_write_ext_reg(struct mmc_card *card, u8 fno, u8 page, u16 offset,
-		     u8 reg_data)
-{
-	struct mmc_host *host = card->host;
-	struct mmc_request mrq = {};
-	struct mmc_command cmd = {};
-	struct mmc_data data = {};
-	struct scatterlist sg;
-	u8 *reg_buf;
-
-	reg_buf = card->ext_reg_buf;
-	memset(reg_buf, 0, 512);
-
-	mrq.cmd = &cmd;
-	mrq.data = &data;
-
-	/*
-	 * Arguments of CMD49:
-	 * [31:31] MIO (0 = memory).
-	 * [30:27] FNO (function number).
-	 * [26:26] MW - mask write mode (0 = disable).
-	 * [25:18] page number.
-	 * [17:9] offset address.
-	 * [8:0] length (0 = 1 byte).
-	 */
-	cmd.arg = fno << 27 | page << 18 | offset << 9;
-
-	/* The first byte in the buffer is the data to be written. */
-	reg_buf[0] = reg_data;
-
-	data.flags = MMC_DATA_WRITE;
-	data.blksz = 512;
-	data.blocks = 1;
-	data.sg = &sg;
-	data.sg_len = 1;
-	sg_init_one(&sg, reg_buf, 512);
-
-	cmd.opcode = SD_WRITE_EXTR_SINGLE;
-	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-	mmc_set_data_timeout(&data, card);
-	mmc_wait_for_req(host, &mrq);
-
-	/*
-	 * Note that, the SD card is allowed to signal busy on DAT0 up to 1s
-	 * after the CMD49. Although, let's leave this to be managed by the
-	 * caller.
-	 */
-
-	if (cmd.error)
-		return cmd.error;
-	if (data.error)
-		return data.error;
-
-	return 0;
-}
-
-static int sd_read_ext_reg(struct mmc_card *card, u8 fno, u8 page,
-			   u16 offset, u16 len, u8 *reg_buf)
-{
-	u32 cmd_args;
-
-	/*
-	 * Command arguments of CMD48:
-	 * [31:31] MIO (0 = memory).
-	 * [30:27] FNO (function number).
-	 * [26:26] reserved (0).
-	 * [25:18] page number.
-	 * [17:9] offset address.
-	 * [8:0] length (0 = 1 byte, 1ff = 512 bytes).
-	 */
-	cmd_args = fno << 27 | page << 18 | offset << 9 | (len -1);
-
-	return mmc_send_adtc_data(card, card->host, SD_READ_EXTR_SINGLE,
-				  cmd_args, reg_buf, 512);
-}
-
 static int sd_parse_ext_reg_power(struct mmc_card *card, u8 fno, u8 page,
 				  u16 offset)
 {
@@ -1101,7 +1024,7 @@ static int sd_parse_ext_reg_power(struct
 	reg_buf = card->ext_reg_buf;
 
 	/* Read the extension register for power management function. */
-	err = sd_read_ext_reg(card, fno, page, offset, 512, reg_buf);
+	err = mmc_sd_read_ext_reg(card, fno, page, offset, 512, reg_buf);
 	if (err) {
 		pr_warn("%s: error %d reading PM func of ext reg\n",
 			mmc_hostname(card->host), err);
@@ -1139,7 +1062,7 @@ static int sd_parse_ext_reg_perf(struct
 
 	reg_buf = card->ext_reg_buf;
 
-	err = sd_read_ext_reg(card, fno, page, offset, 512, reg_buf);
+	err = mmc_sd_read_ext_reg(card, fno, page, offset, 512, reg_buf);
 	if (err) {
 		pr_warn("%s: error %d reading PERF func of ext reg\n",
 			mmc_hostname(card->host), err);
@@ -1234,7 +1157,7 @@ static int sd_parse_ext_reg(struct mmc_c
 	return 0;
 }
 
-static int sd_read_ext_regs(struct mmc_card *card)
+static int mmc_sd_read_ext_regs(struct mmc_card *card)
 {
 	int err, i;
 	u8 num_ext, *gen_info_buf;
@@ -1260,7 +1183,7 @@ static int sd_read_ext_regs(struct mmc_c
 	 * Read 512 bytes of general info, which is found at function number 0,
 	 * at page 0 and with no offset.
 	 */
-	err = sd_read_ext_reg(card, 0, 0, 0, 512, gen_info_buf);
+	err = mmc_sd_read_ext_reg(card, 0, 0, 0, 512, gen_info_buf);
 	if (err) {
 		pr_err("%s: error %d reading general info of SD ext reg\n",
 			mmc_hostname(card->host), err);
@@ -1332,7 +1255,7 @@ static int sd_flush_cache(struct mmc_hos
 	page = card->ext_perf.page;
 	offset = card->ext_perf.offset + 261;
 
-	err = sd_write_ext_reg(card, fno, page, offset, BIT(0));
+	err = mmc_sd_write_ext_reg(card, fno, page, offset, BIT(0));
 	if (err) {
 		pr_warn("%s: error %d writing Cache Flush bit\n",
 			mmc_hostname(host), err);
@@ -1348,7 +1271,7 @@ static int sd_flush_cache(struct mmc_hos
 	 * Read the Flush Cache bit. The card shall reset it, to confirm that
 	 * it's has completed the flushing of the cache.
 	 */
-	err = sd_read_ext_reg(card, fno, page, offset, 1, reg_buf);
+	err = mmc_sd_read_ext_reg(card, fno, page, offset, 1, reg_buf);
 	if (err) {
 		pr_warn("%s: error %d reading Cache Flush bit\n",
 			mmc_hostname(host), err);
@@ -1371,7 +1294,7 @@ static int sd_enable_cache(struct mmc_ca
 	 * Set Cache Enable at bit 0 in the performance enhancement register at
 	 * 260 bytes offset.
 	 */
-	err = sd_write_ext_reg(card, card->ext_perf.fno, card->ext_perf.page,
+	err = mmc_sd_write_ext_reg(card, card->ext_perf.fno, card->ext_perf.page,
 			       card->ext_perf.offset + 260, BIT(0));
 	if (err) {
 		pr_warn("%s: error %d writing Cache Enable bit\n",
@@ -1541,7 +1464,7 @@ retry:
 cont:
 	if (!oldcard) {
 		/* Read/parse the extension registers. */
-		err = sd_read_ext_regs(card);
+		err = mmc_sd_read_ext_regs(card);
 		if (err)
 			goto free_card;
 	}
@@ -1668,7 +1591,7 @@ static int sd_busy_poweroff_notify_cb(vo
 	 * one byte offset and is one byte long. The Power Off Notification
 	 * Ready is bit 0.
 	 */
-	err = sd_read_ext_reg(card, card->ext_power.fno, card->ext_power.page,
+	err = mmc_sd_read_ext_reg(card, card->ext_power.fno, card->ext_power.page,
 			      card->ext_power.offset + 1, 1, data->reg_buf);
 	if (err) {
 		pr_warn("%s: error %d reading status reg of PM func\n",
@@ -1694,7 +1617,7 @@ static int sd_poweroff_notify(struct mmc
 	 * Set the Power Off Notification bit in the power management settings
 	 * register at 2 bytes offset.
 	 */
-	err = sd_write_ext_reg(card, card->ext_power.fno, card->ext_power.page,
+	err = mmc_sd_write_ext_reg(card, card->ext_power.fno, card->ext_power.page,
 			       card->ext_power.offset + 2, BIT(0));
 	if (err) {
 		pr_warn("%s: error %d writing Power Off Notify bit\n",
--- a/drivers/mmc/core/sd_ops.c
+++ b/drivers/mmc/core/sd_ops.c
@@ -366,8 +366,83 @@ int mmc_app_sd_status(struct mmc_card *c
 	return 0;
 }
 
-int sd_write_ext_reg(struct mmc_card *card, u8 fno, u8 page, u16 offset,
-		     u8 reg_data);
+
+int mmc_sd_write_ext_reg(struct mmc_card *card, u8 fno, u8 page, u16 offset,
+		     u8 reg_data)
+{
+	struct mmc_host *host = card->host;
+	struct mmc_request mrq = {};
+	struct mmc_command cmd = {};
+	struct mmc_data data = {};
+	struct scatterlist sg;
+	u8 *reg_buf;
+
+	reg_buf = card->ext_reg_buf;
+	memset(reg_buf, 0, 512);
+
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+
+	/*
+	 * Arguments of CMD49:
+	 * [31:31] MIO (0 = memory).
+	 * [30:27] FNO (function number).
+	 * [26:26] MW - mask write mode (0 = disable).
+	 * [25:18] page number.
+	 * [17:9] offset address.
+	 * [8:0] length (0 = 1 byte).
+	 */
+	cmd.arg = fno << 27 | page << 18 | offset << 9;
+
+	/* The first byte in the buffer is the data to be written. */
+	reg_buf[0] = reg_data;
+
+	data.flags = MMC_DATA_WRITE;
+	data.blksz = 512;
+	data.blocks = 1;
+	data.sg = &sg;
+	data.sg_len = 1;
+	sg_init_one(&sg, reg_buf, 512);
+
+	cmd.opcode = SD_WRITE_EXTR_SINGLE;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+	mmc_set_data_timeout(&data, card);
+	mmc_wait_for_req(host, &mrq);
+
+	/*
+	 * Note that, the SD card is allowed to signal busy on DAT0 up to 1s
+	 * after the CMD49. Although, let's leave this to be managed by the
+	 * caller.
+	 */
+
+	if (cmd.error)
+		return cmd.error;
+	if (data.error)
+		return data.error;
+
+	return 0;
+}
+
+int mmc_sd_read_ext_reg(struct mmc_card *card, u8 fno, u8 page,
+			u16 offset, u16 len, u8 *reg_buf)
+{
+	u32 cmd_args;
+
+	/*
+	 * Command arguments of CMD48:
+	 * [31:31] MIO (0 = memory).
+	 * [30:27] FNO (function number).
+	 * [26:26] reserved (0).
+	 * [25:18] page number.
+	 * [17:9] offset address.
+	 * [8:0] length (0 = 1 byte, 1ff = 512 bytes).
+	 */
+	cmd_args = fno << 27 | page << 18 | offset << 9 | (len - 1);
+
+	return mmc_send_adtc_data(card, card->host, SD_READ_EXTR_SINGLE,
+				  cmd_args, reg_buf, 512);
+}
 
 static int mmc_sd_cmdq_switch(struct mmc_card *card, bool enable)
 {
@@ -383,8 +458,8 @@ static int mmc_sd_cmdq_switch(struct mmc
 		reg = BIT(0);
 
 	/* Performance enhancement register byte 262 controls command queueing */
-	err = sd_write_ext_reg(card, card->ext_perf.fno, card->ext_perf.page,
-			       card->ext_perf.offset + 262, reg);
+	err = mmc_sd_write_ext_reg(card, card->ext_perf.fno, card->ext_perf.page,
+				   card->ext_perf.offset + 262, reg);
 	if (!err)
 		card->ext_csd.cmdq_en = enable;
 
--- a/drivers/mmc/core/sd_ops.h
+++ b/drivers/mmc/core/sd_ops.h
@@ -23,6 +23,10 @@ int mmc_app_sd_status(struct mmc_card *c
 int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card);
 int mmc_sd_cmdq_enable(struct mmc_card *card);
 int mmc_sd_cmdq_disable(struct mmc_card *card);
+int mmc_sd_write_ext_reg(struct mmc_card *card, u8 fno, u8 page, u16 offset,
+			 u8 reg_data);
+int mmc_sd_read_ext_reg(struct mmc_card *card, u8 fno, u8 page,
+			u16 offset, u16 len, u8 *reg_buf);
 
 #endif
 
