Linux MultiMedia Card development
 help / color / mirror / Atom feed
* [PATCH 0/2] mmc: litex_mmc: Respect the bus width request from the core.
@ 2026-06-29  7:25 Inochi Amaoto
  2026-06-29  7:25 ` [PATCH 1/2] mmc: litex_mmc: Set width from linux request Inochi Amaoto
  2026-06-29  7:25 ` [PATCH 2/2] mmc: litex_mmc: Remove unused logic for the fixed bus width Inochi Amaoto
  0 siblings, 2 replies; 3+ messages in thread
From: Inochi Amaoto @ 2026-06-29  7:25 UTC (permalink / raw)
  To: Ulf Hansson, Karol Gugala, Mateusz Holenko, Gabriel Somlo,
	Joel Stanley
  Cc: Inochi Amaoto, linux-mmc, linux-kernel, Yixun Lan, Longbin Li

The litex_mmc only forces to use a 4-bits bus width for data transfer,
however, it does support setting bus width. Use this interface to simplify
the litex_mmc driver.

Inochi Amaoto (2):
  mmc: litex_mmc: Set width from linux request
  mmc: litex_mmc: Remove unused logic for the fixed bus width

 drivers/mmc/host/litex_mmc.c | 131 +++++++++--------------------------
 1 file changed, 32 insertions(+), 99 deletions(-)

--
2.54.0


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

* [PATCH 1/2] mmc: litex_mmc: Set width from linux request
  2026-06-29  7:25 [PATCH 0/2] mmc: litex_mmc: Respect the bus width request from the core Inochi Amaoto
@ 2026-06-29  7:25 ` Inochi Amaoto
  2026-06-29  7:25 ` [PATCH 2/2] mmc: litex_mmc: Remove unused logic for the fixed bus width Inochi Amaoto
  1 sibling, 0 replies; 3+ messages in thread
From: Inochi Amaoto @ 2026-06-29  7:25 UTC (permalink / raw)
  To: Ulf Hansson, Karol Gugala, Mateusz Holenko, Gabriel Somlo,
	Joel Stanley
  Cc: Inochi Amaoto, linux-mmc, linux-kernel, Yixun Lan, Longbin Li

Previously, the litex_mmc driver force the 4 bits bus width.
This means that the gateware with 1 bit bus width is not fit.
However, litesdcard does support setting bus width, which
make the 1 bit bus width gateware possible to be used.

Add logic for setting bus width in the set_ios() function.

Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
 drivers/mmc/host/litex_mmc.c | 36 +++++++++++++++++++++++++++++-------
 1 file changed, 29 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c
index 3655542ca998..affdff8621bf 100644
--- a/drivers/mmc/host/litex_mmc.c
+++ b/drivers/mmc/host/litex_mmc.c
@@ -29,6 +29,7 @@
 #define LITEX_PHY_CLOCKERDIV  0x04
 #define LITEX_PHY_INITIALIZE  0x08
 #define LITEX_PHY_WRITESTATUS 0x0C
+#define LITEX_PHY_SETTINGS    0x18
 #define LITEX_CORE_CMDARG     0x00
 #define LITEX_CORE_CMDCMD     0x04
 #define LITEX_CORE_CMDSND     0x08
@@ -72,6 +73,10 @@
 #define SD_INIT_DELAY_US  1000
 #define SD_INIT_CLK_HZ    400000
 
+#define SD_PHY_SPEED_1X 0
+#define SD_PHY_SPEED_4X 1
+#define SD_PHY_SPEED_8X 2
+
 #define SDIRQ_CARD_DETECT    1
 #define SDIRQ_SD_TO_MEM_DONE 2
 #define SDIRQ_MEM_TO_SD_DONE 4
@@ -96,6 +101,8 @@ struct litex_mmc_host {
 	unsigned int ref_clk;
 	unsigned int sd_clk;
 
+	u8 width;
+
 	u32 resp[4];
 	u16 rca;
 
@@ -451,6 +458,24 @@ static void litex_mmc_setclk(struct litex_mmc_host *host, unsigned int freq)
 static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct litex_mmc_host *host = mmc_priv(mmc);
+	unsigned int bus_width = SD_PHY_SPEED_1X;
+
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_1:
+		bus_width = SD_PHY_SPEED_1X;
+		break;
+	case MMC_BUS_WIDTH_4:
+		bus_width = SD_PHY_SPEED_4X;
+		break;
+	case MMC_BUS_WIDTH_8:
+		bus_width = SD_PHY_SPEED_8X;
+		break;
+	}
+
+	if (host->width != ios->bus_width) {
+		litex_write8(host->sdphy + LITEX_PHY_SETTINGS, bus_width);
+		host->width = ios->bus_width;
+	}
 
 	/*
 	 * The SD specification requires at least 74 idle clocks before CMD0.
@@ -463,13 +488,6 @@ static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		return;
 	}
 
-	/*
-	 * NOTE: Ignore any ios->bus_width updates; they occur right after
-	 * the mmc core sends its own acmd6 bus-width change notification,
-	 * which is redundant since we snoop on the command flow and inject
-	 * an early acmd6 before the first data transfer command is sent!
-	 */
-
 	/* Update sd_clk */
 	if (ios->clock != host->sd_clk)
 		litex_mmc_setclk(host, ios->clock);
@@ -555,6 +573,7 @@ static int litex_mmc_probe(struct platform_device *pdev)
 	 */
 	host->is_bus_width_set = false;
 	host->app_cmd = false;
+	host->width = MMC_BUS_WIDTH_1;
 
 	/* LiteSDCard can support 64-bit DMA addressing */
 	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
@@ -587,6 +606,9 @@ static int litex_mmc_probe(struct platform_device *pdev)
 	litex_write8(host->sdreader + LITEX_BLK2MEM_ENA, 0);
 	litex_write8(host->sdwriter + LITEX_MEM2BLK_ENA, 0);
 
+	/* Ensure the litex is at bus width x1 */
+	litex_write8(host->sdphy + LITEX_PHY_SETTINGS, SD_PHY_SPEED_1X);
+
 	init_completion(&host->cmd_done);
 	ret = litex_mmc_irq_init(pdev, host);
 	if (ret)
-- 
2.54.0


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

* [PATCH 2/2] mmc: litex_mmc: Remove unused logic for the fixed bus width
  2026-06-29  7:25 [PATCH 0/2] mmc: litex_mmc: Respect the bus width request from the core Inochi Amaoto
  2026-06-29  7:25 ` [PATCH 1/2] mmc: litex_mmc: Set width from linux request Inochi Amaoto
@ 2026-06-29  7:25 ` Inochi Amaoto
  1 sibling, 0 replies; 3+ messages in thread
From: Inochi Amaoto @ 2026-06-29  7:25 UTC (permalink / raw)
  To: Ulf Hansson, Karol Gugala, Mateusz Holenko, Gabriel Somlo,
	Joel Stanley
  Cc: Inochi Amaoto, linux-mmc, linux-kernel, Yixun Lan, Longbin Li

As the set_ios() function in litex_mmc driver does support
setting bus width, it is not necessary to leave the logic
for fixed bus width. Clean up these unneeded code.

Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
 drivers/mmc/host/litex_mmc.c | 95 ++----------------------------------
 1 file changed, 3 insertions(+), 92 deletions(-)

diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c
index affdff8621bf..1b5ac4b38f4c 100644
--- a/drivers/mmc/host/litex_mmc.c
+++ b/drivers/mmc/host/litex_mmc.c
@@ -104,10 +104,6 @@ struct litex_mmc_host {
 	u8 width;
 
 	u32 resp[4];
-	u16 rca;
-
-	bool is_bus_width_set;
-	bool app_cmd;
 };
 
 static int litex_mmc_sdcard_wait_done(void __iomem *reg, struct device *dev)
@@ -172,11 +168,6 @@ static int litex_mmc_send_cmd(struct litex_mmc_host *host,
 			      host->sdcore + LITEX_CORE_CMDRSP, 0x10);
 	}
 
-	if (!host->app_cmd && cmd == SD_SEND_RELATIVE_ADDR)
-		host->rca = (host->resp[3] >> 16);
-
-	host->app_cmd = (cmd == MMC_APP_CMD);
-
 	if (transfer == SD_CTL_DATA_XFER_NONE)
 		return ret; /* OK from prior litex_mmc_sdcard_wait_done() */
 
@@ -198,51 +189,6 @@ static int litex_mmc_send_cmd(struct litex_mmc_host *host,
 	return ret;
 }
 
-static int litex_mmc_send_app_cmd(struct litex_mmc_host *host)
-{
-	return litex_mmc_send_cmd(host, MMC_APP_CMD, host->rca << 16,
-				  SD_CTL_RESP_SHORT, SD_CTL_DATA_XFER_NONE);
-}
-
-static int litex_mmc_send_set_bus_w_cmd(struct litex_mmc_host *host, u32 width)
-{
-	return litex_mmc_send_cmd(host, SD_APP_SET_BUS_WIDTH, width,
-				  SD_CTL_RESP_SHORT, SD_CTL_DATA_XFER_NONE);
-}
-
-static int litex_mmc_set_bus_width(struct litex_mmc_host *host)
-{
-	bool app_cmd_sent;
-	int ret;
-
-	if (host->is_bus_width_set)
-		return 0;
-
-	/* Ensure 'app_cmd' precedes 'app_set_bus_width_cmd' */
-	app_cmd_sent = host->app_cmd; /* was preceding command app_cmd? */
-	if (!app_cmd_sent) {
-		ret = litex_mmc_send_app_cmd(host);
-		if (ret)
-			return ret;
-	}
-
-	/* LiteSDCard only supports 4-bit bus width */
-	ret = litex_mmc_send_set_bus_w_cmd(host, MMC_BUS_WIDTH_4);
-	if (ret)
-		return ret;
-
-	/* Re-send 'app_cmd' if necessary */
-	if (app_cmd_sent) {
-		ret = litex_mmc_send_app_cmd(host);
-		if (ret)
-			return ret;
-	}
-
-	host->is_bus_width_set = true;
-
-	return 0;
-}
-
 static int litex_mmc_get_cd(struct mmc_host *mmc)
 {
 	struct litex_mmc_host *host = mmc_priv(mmc);
@@ -255,9 +201,6 @@ static int litex_mmc_get_cd(struct mmc_host *mmc)
 	if (ret)
 		return ret;
 
-	/* Ensure bus width will be set (again) upon card (re)insertion */
-	host->is_bus_width_set = false;
-
 	return 0;
 }
 
@@ -373,39 +316,19 @@ static void litex_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 						litex_mmc_response_len(sbc),
 						SD_CTL_DATA_XFER_NONE);
 		if (sbc->error) {
-			host->is_bus_width_set = false;
 			mmc_request_done(mmc, mrq);
 			return;
 		}
 	}
 
-	if (data) {
-		/*
-		 * LiteSDCard only supports 4-bit bus width; therefore, we MUST
-		 * inject a SET_BUS_WIDTH (acmd6) before the very first data
-		 * transfer, earlier than when the mmc subsystem would normally
-		 * get around to it!
-		 */
-		cmd->error = litex_mmc_set_bus_width(host);
-		if (cmd->error) {
-			dev_err(dev, "Can't set bus width!\n");
-			mmc_request_done(mmc, mrq);
-			return;
-		}
-
+	if (data)
 		litex_mmc_do_dma(host, data, &len, &direct, &transfer);
-	}
 
 	do {
 		cmd->error = litex_mmc_send_cmd(host, cmd->opcode, cmd->arg,
 						response_len, transfer);
 	} while (cmd->error && retries-- > 0);
 
-	if (cmd->error) {
-		/* Card may be gone; don't assume bus width is still set */
-		host->is_bus_width_set = false;
-	}
-
 	if (response_len == SD_CTL_RESP_SHORT) {
 		/* Pull short response fields from appropriate host registers */
 		cmd->resp[0] = host->resp[3];
@@ -418,13 +341,10 @@ static void litex_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 	}
 
 	/* Send stop-transmission command if required */
-	if (stop && (cmd->error || !sbc)) {
+	if (stop && (cmd->error || !sbc))
 		stop->error = litex_mmc_send_cmd(host, stop->opcode, stop->arg,
 						 litex_mmc_response_len(stop),
 						 SD_CTL_DATA_XFER_NONE);
-		if (stop->error)
-			host->is_bus_width_set = false;
-	}
 
 	if (data) {
 		dma_unmap_sg(dev, data->sg, data->sg_len,
@@ -565,14 +485,6 @@ static int litex_mmc_probe(struct platform_device *pdev)
 		return dev_err_probe(dev, PTR_ERR(clk), "can't get clock\n");
 	host->ref_clk = clk_get_rate(clk);
 	host->sd_clk = 0;
-
-	/*
-	 * LiteSDCard only supports 4-bit bus width; therefore, we MUST inject
-	 * a SET_BUS_WIDTH (acmd6) before the very first data transfer, earlier
-	 * than when the mmc subsystem would normally get around to it!
-	 */
-	host->is_bus_width_set = false;
-	host->app_cmd = false;
 	host->width = MMC_BUS_WIDTH_1;
 
 	/* LiteSDCard can support 64-bit DMA addressing */
@@ -633,9 +545,8 @@ static int litex_mmc_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	/* Force 4-bit bus_width (only width supported by hardware) */
+	/* Only drop 8-bit bus_width support */
 	mmc->caps &= ~MMC_CAP_8_BIT_DATA;
-	mmc->caps |= MMC_CAP_4_BIT_DATA;
 
 	/* Set default capabilities */
 	mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY |
-- 
2.54.0


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

end of thread, other threads:[~2026-06-29  7:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-29  7:25 [PATCH 0/2] mmc: litex_mmc: Respect the bus width request from the core Inochi Amaoto
2026-06-29  7:25 ` [PATCH 1/2] mmc: litex_mmc: Set width from linux request Inochi Amaoto
2026-06-29  7:25 ` [PATCH 2/2] mmc: litex_mmc: Remove unused logic for the fixed bus width Inochi Amaoto

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox