[PATCH v4] mmc: litex_mmc: Set mandatory idle clocks before CMD0

Inochi Amaoto posted 1 patch 1 week, 1 day ago
There is a newer version of this series
drivers/mmc/host/litex_mmc.c | 11 +++++++++++
1 file changed, 11 insertions(+)
[PATCH v4] mmc: litex_mmc: Set mandatory idle clocks before CMD0
Posted by Inochi Amaoto 1 week, 1 day ago
The litex_mmc driver assumes the card is already probed in the BIOS
and skip the phy initialization. This will cause the command fail
like the following when the old card is unplugged and then insert
a new card:

[   62.923593] litex-mmc f0004000.mmc: Command (cmd 8) error, status -110
[   62.949717] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
[   62.976606] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
[   63.002516] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
[   63.028442] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110

Add required clock settings and initialization for the CMD 0, so it can
probe the new card.

Fixes: 92e099104729 ("mmc: Add driver for LiteX's LiteSDCard interface")
Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
Changed from v3:
- https://lore.kernel.org/linux-mmc/20260426112016.1370929-1-inochiama@gmail.com/
1. Remove patch 1: mmc: litex_mmc: Move litex_mmc_setclk() to bottom for reuse
2. Use set_ios() callback to apply the clock change.

Changed from v2:
- https://lore.kernel.org/linux-mmc/20260424013615.470325-1-inochiama@gmail.com/
1. Remove the added function forward reference and add a new patch
   for moving litex_mmc_setclk() function

Change from v1:
- https://lore.kernel.org/linux-mmc/20260421025052.755471-1-inochiama@gmail.com/
1. use fsleep to replace udelay

Inochi Amaoto (2):
  mmc: litex_mmc: Move litex_mmc_setclk() to bottom for reuse
  mmc: litex_mmc: Set mandatory idle clocks before CMD0

 drivers/mmc/host/litex_mmc.c | 37 ++++++++++++++++++++++--------------
 1 file changed, 23 insertions(+), 14 deletions(-)
---
 drivers/mmc/host/litex_mmc.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c
index d2f19c2dc673..65d5c728f536 100644
--- a/drivers/mmc/host/litex_mmc.c
+++ b/drivers/mmc/host/litex_mmc.c
@@ -68,6 +68,9 @@
 #define SD_SLEEP_US       5
 #define SD_TIMEOUT_US 20000

+#define SD_INIT_DELAY_US  1000
+#define SD_INIT_CLK_HZ    400000
+
 #define SDIRQ_CARD_DETECT    1
 #define SDIRQ_SD_TO_MEM_DONE 2
 #define SDIRQ_MEM_TO_SD_DONE 4
@@ -449,6 +452,9 @@ static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct litex_mmc_host *host = mmc_priv(mmc);

+	if (ios->chip_select == MMC_CS_HIGH)
+		ios->clock = SD_INIT_CLK_HZ;
+
 	/*
 	 * NOTE: Ignore any ios->bus_width updates; they occur right after
 	 * the mmc core sends its own acmd6 bus-width change notification,
@@ -459,6 +465,11 @@ static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	/* Update sd_clk */
 	if (ios->clock != host->sd_clk)
 		litex_mmc_setclk(host, ios->clock);
+
+	if (ios->chip_select == MMC_CS_HIGH) {
+		litex_write8(host->sdphy + LITEX_PHY_INITIALIZE, 1);
+		fsleep(SD_INIT_DELAY_US);
+	}
 }

 static const struct mmc_host_ops litex_mmc_ops = {
--
2.54.0
Re: [PATCH v4] mmc: litex_mmc: Set mandatory idle clocks before CMD0
Posted by Gabriel L. Somlo 6 days, 8 hours ago
with this patch on top of today's latest (4d3a2a466b8d), I get
(on 64-bit rocketchip with Litex):

[    6.475114] mmc0: invalid bus width
[    6.477870] mmc0: error -22 whilst initialising SD card

Thanks,
--Gabriel

On Sun, May 17, 2026 at 09:53:23AM +0800, Inochi Amaoto wrote:
> The litex_mmc driver assumes the card is already probed in the BIOS
> and skip the phy initialization. This will cause the command fail
> like the following when the old card is unplugged and then insert
> a new card:
> 
> [   62.923593] litex-mmc f0004000.mmc: Command (cmd 8) error, status -110
> [   62.949717] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
> [   62.976606] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
> [   63.002516] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
> [   63.028442] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
> 
> Add required clock settings and initialization for the CMD 0, so it can
> probe the new card.
> 
> Fixes: 92e099104729 ("mmc: Add driver for LiteX's LiteSDCard interface")
> Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
> ---
> Changed from v3:
> - https://lore.kernel.org/linux-mmc/20260426112016.1370929-1-inochiama@gmail.com/
> 1. Remove patch 1: mmc: litex_mmc: Move litex_mmc_setclk() to bottom for reuse
> 2. Use set_ios() callback to apply the clock change.
> 
> Changed from v2:
> - https://lore.kernel.org/linux-mmc/20260424013615.470325-1-inochiama@gmail.com/
> 1. Remove the added function forward reference and add a new patch
>    for moving litex_mmc_setclk() function
> 
> Change from v1:
> - https://lore.kernel.org/linux-mmc/20260421025052.755471-1-inochiama@gmail.com/
> 1. use fsleep to replace udelay
> 
> Inochi Amaoto (2):
>   mmc: litex_mmc: Move litex_mmc_setclk() to bottom for reuse
>   mmc: litex_mmc: Set mandatory idle clocks before CMD0
> 
>  drivers/mmc/host/litex_mmc.c | 37 ++++++++++++++++++++++--------------
>  1 file changed, 23 insertions(+), 14 deletions(-)
> ---
>  drivers/mmc/host/litex_mmc.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c
> index d2f19c2dc673..65d5c728f536 100644
> --- a/drivers/mmc/host/litex_mmc.c
> +++ b/drivers/mmc/host/litex_mmc.c
> @@ -68,6 +68,9 @@
>  #define SD_SLEEP_US       5
>  #define SD_TIMEOUT_US 20000
> 
> +#define SD_INIT_DELAY_US  1000
> +#define SD_INIT_CLK_HZ    400000
> +
>  #define SDIRQ_CARD_DETECT    1
>  #define SDIRQ_SD_TO_MEM_DONE 2
>  #define SDIRQ_MEM_TO_SD_DONE 4
> @@ -449,6 +452,9 @@ static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  {
>  	struct litex_mmc_host *host = mmc_priv(mmc);
> 
> +	if (ios->chip_select == MMC_CS_HIGH)
> +		ios->clock = SD_INIT_CLK_HZ;
> +
>  	/*
>  	 * NOTE: Ignore any ios->bus_width updates; they occur right after
>  	 * the mmc core sends its own acmd6 bus-width change notification,
> @@ -459,6 +465,11 @@ static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  	/* Update sd_clk */
>  	if (ios->clock != host->sd_clk)
>  		litex_mmc_setclk(host, ios->clock);
> +
> +	if (ios->chip_select == MMC_CS_HIGH) {
> +		litex_write8(host->sdphy + LITEX_PHY_INITIALIZE, 1);
> +		fsleep(SD_INIT_DELAY_US);
> +	}
>  }
> 
>  static const struct mmc_host_ops litex_mmc_ops = {
> --
> 2.54.0
>
Re: [PATCH v4] mmc: litex_mmc: Set mandatory idle clocks before CMD0
Posted by Inochi Amaoto 6 days, 8 hours ago
On Mon, May 18, 2026 at 06:20:49PM -0400, Gabriel L. Somlo wrote:
> with this patch on top of today's latest (4d3a2a466b8d), I get
> (on 64-bit rocketchip with Litex):
> 
> [    6.475114] mmc0: invalid bus width
> [    6.477870] mmc0: error -22 whilst initialising SD card
> 
> Thanks,
> --Gabriel
> 

Hi, Gabriel,

Could you share the board link and build commands? I think I need to
take a look for why this occurs.

Regards,
Inochi

> On Sun, May 17, 2026 at 09:53:23AM +0800, Inochi Amaoto wrote:
> > The litex_mmc driver assumes the card is already probed in the BIOS
> > and skip the phy initialization. This will cause the command fail
> > like the following when the old card is unplugged and then insert
> > a new card:
> > 
> > [   62.923593] litex-mmc f0004000.mmc: Command (cmd 8) error, status -110
> > [   62.949717] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
> > [   62.976606] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
> > [   63.002516] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
> > [   63.028442] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
> > 
> > Add required clock settings and initialization for the CMD 0, so it can
> > probe the new card.
> > 
> > Fixes: 92e099104729 ("mmc: Add driver for LiteX's LiteSDCard interface")
> > Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
> > ---
> > Changed from v3:
> > - https://lore.kernel.org/linux-mmc/20260426112016.1370929-1-inochiama@gmail.com/
> > 1. Remove patch 1: mmc: litex_mmc: Move litex_mmc_setclk() to bottom for reuse
> > 2. Use set_ios() callback to apply the clock change.
> > 
> > Changed from v2:
> > - https://lore.kernel.org/linux-mmc/20260424013615.470325-1-inochiama@gmail.com/
> > 1. Remove the added function forward reference and add a new patch
> >    for moving litex_mmc_setclk() function
> > 
> > Change from v1:
> > - https://lore.kernel.org/linux-mmc/20260421025052.755471-1-inochiama@gmail.com/
> > 1. use fsleep to replace udelay
> > 
> > Inochi Amaoto (2):
> >   mmc: litex_mmc: Move litex_mmc_setclk() to bottom for reuse
> >   mmc: litex_mmc: Set mandatory idle clocks before CMD0
> > 
> >  drivers/mmc/host/litex_mmc.c | 37 ++++++++++++++++++++++--------------
> >  1 file changed, 23 insertions(+), 14 deletions(-)
> > ---
> >  drivers/mmc/host/litex_mmc.c | 11 +++++++++++
> >  1 file changed, 11 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c
> > index d2f19c2dc673..65d5c728f536 100644
> > --- a/drivers/mmc/host/litex_mmc.c
> > +++ b/drivers/mmc/host/litex_mmc.c
> > @@ -68,6 +68,9 @@
> >  #define SD_SLEEP_US       5
> >  #define SD_TIMEOUT_US 20000
> > 
> > +#define SD_INIT_DELAY_US  1000
> > +#define SD_INIT_CLK_HZ    400000
> > +
> >  #define SDIRQ_CARD_DETECT    1
> >  #define SDIRQ_SD_TO_MEM_DONE 2
> >  #define SDIRQ_MEM_TO_SD_DONE 4
> > @@ -449,6 +452,9 @@ static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> >  {
> >  	struct litex_mmc_host *host = mmc_priv(mmc);
> > 
> > +	if (ios->chip_select == MMC_CS_HIGH)
> > +		ios->clock = SD_INIT_CLK_HZ;
> > +
> >  	/*
> >  	 * NOTE: Ignore any ios->bus_width updates; they occur right after
> >  	 * the mmc core sends its own acmd6 bus-width change notification,
> > @@ -459,6 +465,11 @@ static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> >  	/* Update sd_clk */
> >  	if (ios->clock != host->sd_clk)
> >  		litex_mmc_setclk(host, ios->clock);
> > +
> > +	if (ios->chip_select == MMC_CS_HIGH) {
> > +		litex_write8(host->sdphy + LITEX_PHY_INITIALIZE, 1);
> > +		fsleep(SD_INIT_DELAY_US);
> > +	}
> >  }
> > 
> >  static const struct mmc_host_ops litex_mmc_ops = {
> > --
> > 2.54.0
> >
Re: [PATCH v4] mmc: litex_mmc: Set mandatory idle clocks before CMD0
Posted by Gabriel L. Somlo 6 days, 7 hours ago
On Tue, May 19, 2026 at 06:24:19AM +0800, Inochi Amaoto wrote:
> On Mon, May 18, 2026 at 06:20:49PM -0400, Gabriel L. Somlo wrote:
> > with this patch on top of today's latest (4d3a2a466b8d), I get
> > (on 64-bit rocketchip with Litex):
> > 
> > [    6.475114] mmc0: invalid bus width
> > [    6.477870] mmc0: error -22 whilst initialising SD card
> > 
> > Thanks,
> > --Gabriel
> > 
> 
> Hi, Gabriel,
> 
> Could you share the board link and build commands? I think I need to
> take a look for why this occurs.
> 
> Regards,
> Inochi

Hi Inochi,

it's the digilent nexys-video board; the command line to build the
bitstream is:

litex-boards/litex_boards/targets/digilent_nexys_video.py --build \
  --cpu-type rocket --cpu-variant linux --cpu-num-cores 4 --cpu-mem-width 2 \
  --sys-clk-freq 50e6 --with-ethernet --with-sdcard --with-sata --sata-gen 1

(for more details see https://github.com/litex-hub/linux-on-litex-rocket)

I've added your patch on top of the LiteX kernel tree at
https://github.com/litex-hub/linux/tree/litex-rebase

and compiled it with:

make clean
make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- litex_rocket_defconfig
make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu-

FWIW, your previous versions of the patch did work, and did fix the
issue you were trying to address (which I did notice being a problem
on my configuration :)

Thanks,
--Gabriel
 
> > On Sun, May 17, 2026 at 09:53:23AM +0800, Inochi Amaoto wrote:
> > > The litex_mmc driver assumes the card is already probed in the BIOS
> > > and skip the phy initialization. This will cause the command fail
> > > like the following when the old card is unplugged and then insert
> > > a new card:
> > > 
> > > [   62.923593] litex-mmc f0004000.mmc: Command (cmd 8) error, status -110
> > > [   62.949717] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
> > > [   62.976606] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
> > > [   63.002516] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
> > > [   63.028442] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
> > > 
> > > Add required clock settings and initialization for the CMD 0, so it can
> > > probe the new card.
> > > 
> > > Fixes: 92e099104729 ("mmc: Add driver for LiteX's LiteSDCard interface")
> > > Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
> > > ---
> > > Changed from v3:
> > > - https://lore.kernel.org/linux-mmc/20260426112016.1370929-1-inochiama@gmail.com/
> > > 1. Remove patch 1: mmc: litex_mmc: Move litex_mmc_setclk() to bottom for reuse
> > > 2. Use set_ios() callback to apply the clock change.
> > > 
> > > Changed from v2:
> > > - https://lore.kernel.org/linux-mmc/20260424013615.470325-1-inochiama@gmail.com/
> > > 1. Remove the added function forward reference and add a new patch
> > >    for moving litex_mmc_setclk() function
> > > 
> > > Change from v1:
> > > - https://lore.kernel.org/linux-mmc/20260421025052.755471-1-inochiama@gmail.com/
> > > 1. use fsleep to replace udelay
> > > 
> > > Inochi Amaoto (2):
> > >   mmc: litex_mmc: Move litex_mmc_setclk() to bottom for reuse
> > >   mmc: litex_mmc: Set mandatory idle clocks before CMD0
> > > 
> > >  drivers/mmc/host/litex_mmc.c | 37 ++++++++++++++++++++++--------------
> > >  1 file changed, 23 insertions(+), 14 deletions(-)
> > > ---
> > >  drivers/mmc/host/litex_mmc.c | 11 +++++++++++
> > >  1 file changed, 11 insertions(+)
> > > 
> > > diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c
> > > index d2f19c2dc673..65d5c728f536 100644
> > > --- a/drivers/mmc/host/litex_mmc.c
> > > +++ b/drivers/mmc/host/litex_mmc.c
> > > @@ -68,6 +68,9 @@
> > >  #define SD_SLEEP_US       5
> > >  #define SD_TIMEOUT_US 20000
> > > 
> > > +#define SD_INIT_DELAY_US  1000
> > > +#define SD_INIT_CLK_HZ    400000
> > > +
> > >  #define SDIRQ_CARD_DETECT    1
> > >  #define SDIRQ_SD_TO_MEM_DONE 2
> > >  #define SDIRQ_MEM_TO_SD_DONE 4
> > > @@ -449,6 +452,9 @@ static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> > >  {
> > >  	struct litex_mmc_host *host = mmc_priv(mmc);
> > > 
> > > +	if (ios->chip_select == MMC_CS_HIGH)
> > > +		ios->clock = SD_INIT_CLK_HZ;
> > > +
> > >  	/*
> > >  	 * NOTE: Ignore any ios->bus_width updates; they occur right after
> > >  	 * the mmc core sends its own acmd6 bus-width change notification,
> > > @@ -459,6 +465,11 @@ static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> > >  	/* Update sd_clk */
> > >  	if (ios->clock != host->sd_clk)
> > >  		litex_mmc_setclk(host, ios->clock);
> > > +
> > > +	if (ios->chip_select == MMC_CS_HIGH) {
> > > +		litex_write8(host->sdphy + LITEX_PHY_INITIALIZE, 1);
> > > +		fsleep(SD_INIT_DELAY_US);
> > > +	}
> > >  }
> > > 
> > >  static const struct mmc_host_ops litex_mmc_ops = {
> > > --
> > > 2.54.0
> > >
Re: [PATCH v4] mmc: litex_mmc: Set mandatory idle clocks before CMD0
Posted by Inochi Amaoto 6 days, 3 hours ago
On Mon, May 18, 2026 at 06:45:26PM -0400, Gabriel L. Somlo wrote:
> On Tue, May 19, 2026 at 06:24:19AM +0800, Inochi Amaoto wrote:
> > On Mon, May 18, 2026 at 06:20:49PM -0400, Gabriel L. Somlo wrote:
> > > with this patch on top of today's latest (4d3a2a466b8d), I get
> > > (on 64-bit rocketchip with Litex):
> > > 
> > > [    6.475114] mmc0: invalid bus width
> > > [    6.477870] mmc0: error -22 whilst initialising SD card
> > > 
> > > Thanks,
> > > --Gabriel
> > > 
> > 
> > Hi, Gabriel,
> > 
> > Could you share the board link and build commands? I think I need to
> > take a look for why this occurs.
> > 
> > Regards,
> > Inochi
> 
> Hi Inochi,
> 
> it's the digilent nexys-video board; the command line to build the
> bitstream is:
> 
> litex-boards/litex_boards/targets/digilent_nexys_video.py --build \
>   --cpu-type rocket --cpu-variant linux --cpu-num-cores 4 --cpu-mem-width 2 \
>   --sys-clk-freq 50e6 --with-ethernet --with-sdcard --with-sata --sata-gen 1
> 
> (for more details see https://github.com/litex-hub/linux-on-litex-rocket)
> 
> I've added your patch on top of the LiteX kernel tree at
> https://github.com/litex-hub/linux/tree/litex-rebase
> 
> and compiled it with:
> 
> make clean
> make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- litex_rocket_defconfig
> make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu-
> 
> FWIW, your previous versions of the patch did work, and did fix the
> issue you were trying to address (which I did notice being a problem
> on my configuration :)
> 
> Thanks,
> --Gabriel
>  

Hi Gabriel,

Although I fail to compile the rocket and can not reproduced this
error with VexiiRiscv, I have noticed some interesting things:

[  745.321341] mmc0: card aaaa removed
[  745.363624] litex-mmc f0004000.mmc: clock 25000000 -> 0
[  747.357770] litex-mmc f0004000.mmc: clock 0 -> 12500000
[  747.374898] litex-mmc f0004000.mmc: clock 12500000 -> 400000
[  747.706917] litex-mmc f0004000.mmc: clock 400000 -> 25000000
[  747.711954] mmc0: new SDHC card at address aaaa
[  747.722665] mmcblk0: mmc0:aaaa SL16G 14.8 GiB
[  747.751452]  mmcblk0: p1 p2

It seems like that the controller does not switch to the required init
frequency. Instead, it jump to a working frequency. It may lead to a
false reset.

Another thing is that I noticed the bios sets the PHY to x1 when
initing, but the current set_ios() does nothing with this, only
setting x4 every time that sends the command. I have added a simple
reset that changes the PHY to x1 when setting MMC_CS_HIGH.
(And I think it could be better to add bus width length handler
instead of leaving a force x4 mode).

I have prepared a new patch for these thing. Could you have a try?

Regards,
Inochi

diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c
index d2f19c2dc673..97e07222872e 100644
--- a/drivers/mmc/host/litex_mmc.c
+++ b/drivers/mmc/host/litex_mmc.c
@@ -28,6 +28,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
@@ -68,6 +69,12 @@
 #define SD_SLEEP_US       5
 #define SD_TIMEOUT_US 20000
 
+#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 SDIRQ_CARD_DETECT    1
 #define SDIRQ_SD_TO_MEM_DONE 2
 #define SDIRQ_MEM_TO_SD_DONE 4
@@ -220,6 +227,8 @@ static int litex_mmc_set_bus_width(struct litex_mmc_host *host)
 	if (ret)
 		return ret;
 
+	litex_write8(host->sdphy + LITEX_PHY_SETTINGS, SD_PHY_SPEED_4X);
+
 	/* Re-send 'app_cmd' if necessary */
 	if (app_cmd_sent) {
 		ret = litex_mmc_send_app_cmd(host);
@@ -449,6 +458,12 @@ static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct litex_mmc_host *host = mmc_priv(mmc);
 
+	if (ios->chip_select == MMC_CS_HIGH) {
+		litex_write8(host->sdphy + LITEX_PHY_SETTINGS, SD_PHY_SPEED_1X);
+		ios->clock = SD_INIT_CLK_HZ;
+		host->is_bus_width_set = false;
+	}
+
 	/*
 	 * NOTE: Ignore any ios->bus_width updates; they occur right after
 	 * the mmc core sends its own acmd6 bus-width change notification,
@@ -457,8 +472,14 @@ static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	 */
 
 	/* Update sd_clk */
-	if (ios->clock != host->sd_clk)
+	if (ios->clock != host->sd_clk) {
 		litex_mmc_setclk(host, ios->clock);
+	}
+
+	if (ios->chip_select == MMC_CS_HIGH) {
+		litex_write8(host->sdphy + LITEX_PHY_INITIALIZE, 1);
+		fsleep(SD_INIT_DELAY_US);
+	}
 }
 
 static const struct mmc_host_ops litex_mmc_ops = {
@@ -590,7 +611,7 @@ static int litex_mmc_probe(struct platform_device *pdev)
 	 * Set default sd_clk frequency range based on empirical observations
 	 * of LiteSDCard gateware behavior on typical SDCard media
 	 */
-	mmc->f_min = 12.5e6;
+	mmc->f_min = SD_INIT_CLK_HZ;
 	mmc->f_max = 50e6;
 
 	ret = mmc_of_parse(mmc);
---
Re: [PATCH v4] mmc: litex_mmc: Set mandatory idle clocks before CMD0
Posted by Andy Shevchenko 5 days, 22 hours ago
On Tue, May 19, 2026 at 5:51 AM Inochi Amaoto <inochiama@gmail.com> wrote:
> On Mon, May 18, 2026 at 06:45:26PM -0400, Gabriel L. Somlo wrote:

...

>         /* Update sd_clk */
> -       if (ios->clock != host->sd_clk)
> +       if (ios->clock != host->sd_clk) {
>                 litex_mmc_setclk(host, ios->clock);
> +       }

FWIW, it's a stray change.

-- 
With Best Regards,
Andy Shevchenko
Re: [PATCH v4] mmc: litex_mmc: Set mandatory idle clocks before CMD0
Posted by Gabriel L. Somlo 5 days, 6 hours ago
On Tue, May 19, 2026 at 10:52:10AM +0300, Andy Shevchenko wrote:
> On Tue, May 19, 2026 at 5:51 AM Inochi Amaoto <inochiama@gmail.com> wrote:
> > On Mon, May 18, 2026 at 06:45:26PM -0400, Gabriel L. Somlo wrote:
> 
> ...
> 
> >         /* Update sd_clk */
> > -       if (ios->clock != host->sd_clk)
> > +       if (ios->clock != host->sd_clk) {
> >                 litex_mmc_setclk(host, ios->clock);
> > +       }
> 
> FWIW, it's a stray change.

and I'm still getting:

[    6.508084] mmc0: invalid bus width
[    6.510652] mmc0: error -22 whilst initialising SD card

when booting with this change on 64-bit litex/rocket.

Thanks,
--Gabriel
Re: [PATCH v4] mmc: litex_mmc: Set mandatory idle clocks before CMD0
Posted by Inochi Amaoto 6 days, 5 hours ago
On Mon, May 18, 2026 at 06:45:26PM -0400, Gabriel L. Somlo wrote:
> On Tue, May 19, 2026 at 06:24:19AM +0800, Inochi Amaoto wrote:
> > On Mon, May 18, 2026 at 06:20:49PM -0400, Gabriel L. Somlo wrote:
> > > with this patch on top of today's latest (4d3a2a466b8d), I get
> > > (on 64-bit rocketchip with Litex):
> > > 
> > > [    6.475114] mmc0: invalid bus width
> > > [    6.477870] mmc0: error -22 whilst initialising SD card
> > > 
> > > Thanks,
> > > --Gabriel
> > > 
> > 
> > Hi, Gabriel,
> > 
> > Could you share the board link and build commands? I think I need to
> > take a look for why this occurs.
> > 
> > Regards,
> > Inochi
> 
> Hi Inochi,
> 
> it's the digilent nexys-video board; the command line to build the
> bitstream is:
> 
> litex-boards/litex_boards/targets/digilent_nexys_video.py --build \
>   --cpu-type rocket --cpu-variant linux --cpu-num-cores 4 --cpu-mem-width 2 \
>   --sys-clk-freq 50e6 --with-ethernet --with-sdcard --with-sata --sata-gen 1
> 
> (for more details see https://github.com/litex-hub/linux-on-litex-rocket)
> 
> I've added your patch on top of the LiteX kernel tree at
> https://github.com/litex-hub/linux/tree/litex-rebase
> 
> and compiled it with:
> 
> make clean
> make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- litex_rocket_defconfig
> make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu-
> 
> FWIW, your previous versions of the patch did work, and did fix the
> issue you were trying to address (which I did notice being a problem
> on my configuration :)
> 
> Thanks,
> --Gabriel
>  

Hi, Gabriel,

Could you do me a favor by testing this patch (and the new patch below)
on the VexiiRiscv. My own board does not have a "rst" pin. I guess that
gives some difference? The build command could be:
./litex-boards/litex_boards/targets/riguke_xcku5p.py \
  --build --update-repo=no --cpu-type vexiiriscv --cpu-variant debian \
  --cpu-count 4 \
  --with-coherent-dma --no-netlist-cache \
  --sys-clk-freq 150000000.0 --libc-mode full \
  --with-isa sstc \
  --with-sdcard --with-ethernet

--with-coherent-dma is a requirement for sdcard, and others you
can modify freely.

Anyway, there is a new slice that mitigates the side effect of
changing the ios->clock. Could you have a try? Hope this could
solve the problem.

Regards,
Inochi

diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c
index d2f19c2dc673..95fc07d9a613 100644
--- a/drivers/mmc/host/litex_mmc.c
+++ b/drivers/mmc/host/litex_mmc.c
@@ -68,6 +68,9 @@
 #define SD_SLEEP_US       5
 #define SD_TIMEOUT_US 20000
 
+#define SD_INIT_DELAY_US  1000
+#define SD_INIT_CLK_HZ    400000
+
 #define SDIRQ_CARD_DETECT    1
 #define SDIRQ_SD_TO_MEM_DONE 2
 #define SDIRQ_MEM_TO_SD_DONE 4
@@ -448,6 +451,10 @@ 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 ios_clock = ios->clock;
+
+	if (ios->chip_select == MMC_CS_HIGH)
+		ios_clock = SD_INIT_CLK_HZ;
 
 	/*
 	 * NOTE: Ignore any ios->bus_width updates; they occur right after
@@ -457,8 +464,13 @@ static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	 */
 
 	/* Update sd_clk */
-	if (ios->clock != host->sd_clk)
+	if (ios_clock != host->sd_clk)
 		litex_mmc_setclk(host, ios->clock);
+
+	if (ios->chip_select == MMC_CS_HIGH) {
+		litex_write8(host->sdphy + LITEX_PHY_INITIALIZE, 1);
+		fsleep(SD_INIT_DELAY_US);
+	}
 }
 
 static const struct mmc_host_ops litex_mmc_ops = {

> > > On Sun, May 17, 2026 at 09:53:23AM +0800, Inochi Amaoto wrote:
> > > > The litex_mmc driver assumes the card is already probed in the BIOS
> > > > and skip the phy initialization. This will cause the command fail
> > > > like the following when the old card is unplugged and then insert
> > > > a new card:
> > > > 
> > > > [   62.923593] litex-mmc f0004000.mmc: Command (cmd 8) error, status -110
> > > > [   62.949717] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
> > > > [   62.976606] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
> > > > [   63.002516] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
> > > > [   63.028442] litex-mmc f0004000.mmc: Command (cmd 55) error, status -110
> > > > 
> > > > Add required clock settings and initialization for the CMD 0, so it can
> > > > probe the new card.
> > > > 
> > > > Fixes: 92e099104729 ("mmc: Add driver for LiteX's LiteSDCard interface")
> > > > Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
> > > > ---
> > > > Changed from v3:
> > > > - https://lore.kernel.org/linux-mmc/20260426112016.1370929-1-inochiama@gmail.com/
> > > > 1. Remove patch 1: mmc: litex_mmc: Move litex_mmc_setclk() to bottom for reuse
> > > > 2. Use set_ios() callback to apply the clock change.
> > > > 
> > > > Changed from v2:
> > > > - https://lore.kernel.org/linux-mmc/20260424013615.470325-1-inochiama@gmail.com/
> > > > 1. Remove the added function forward reference and add a new patch
> > > >    for moving litex_mmc_setclk() function
> > > > 
> > > > Change from v1:
> > > > - https://lore.kernel.org/linux-mmc/20260421025052.755471-1-inochiama@gmail.com/
> > > > 1. use fsleep to replace udelay
> > > > 
> > > > Inochi Amaoto (2):
> > > >   mmc: litex_mmc: Move litex_mmc_setclk() to bottom for reuse
> > > >   mmc: litex_mmc: Set mandatory idle clocks before CMD0
> > > > 
> > > >  drivers/mmc/host/litex_mmc.c | 37 ++++++++++++++++++++++--------------
> > > >  1 file changed, 23 insertions(+), 14 deletions(-)
> > > > ---
> > > >  drivers/mmc/host/litex_mmc.c | 11 +++++++++++
> > > >  1 file changed, 11 insertions(+)
> > > > 
> > > > diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c
> > > > index d2f19c2dc673..65d5c728f536 100644
> > > > --- a/drivers/mmc/host/litex_mmc.c
> > > > +++ b/drivers/mmc/host/litex_mmc.c
> > > > @@ -68,6 +68,9 @@
> > > >  #define SD_SLEEP_US       5
> > > >  #define SD_TIMEOUT_US 20000
> > > > 
> > > > +#define SD_INIT_DELAY_US  1000
> > > > +#define SD_INIT_CLK_HZ    400000
> > > > +
> > > >  #define SDIRQ_CARD_DETECT    1
> > > >  #define SDIRQ_SD_TO_MEM_DONE 2
> > > >  #define SDIRQ_MEM_TO_SD_DONE 4
> > > > @@ -449,6 +452,9 @@ static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> > > >  {
> > > >  	struct litex_mmc_host *host = mmc_priv(mmc);
> > > > 
> > > > +	if (ios->chip_select == MMC_CS_HIGH)
> > > > +		ios->clock = SD_INIT_CLK_HZ;
> > > > +
> > > >  	/*
> > > >  	 * NOTE: Ignore any ios->bus_width updates; they occur right after
> > > >  	 * the mmc core sends its own acmd6 bus-width change notification,
> > > > @@ -459,6 +465,11 @@ static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> > > >  	/* Update sd_clk */
> > > >  	if (ios->clock != host->sd_clk)
> > > >  		litex_mmc_setclk(host, ios->clock);
> > > > +
> > > > +	if (ios->chip_select == MMC_CS_HIGH) {
> > > > +		litex_write8(host->sdphy + LITEX_PHY_INITIALIZE, 1);
> > > > +		fsleep(SD_INIT_DELAY_US);
> > > > +	}
> > > >  }
> > > > 
> > > >  static const struct mmc_host_ops litex_mmc_ops = {
> > > > --
> > > > 2.54.0
> > > >