Skip to contentSkip to conversation

mmc: atmel: Properly fix clock configuration

PATCH Superseded Gregory CLEMENT 4 participants 8 messages Nov 5, 2015 – Jan 27, 2016

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 mmc: atmel: Properly fix clock configuration

Timing issue occurs on eMMC not only when modifying the frequency but also for all the switch command(CMD6). According to the MMC spec waiting 8 clocks after a switch command would be the thing to do.

This patch allows fixing CPU hang observed when trying to changing the bus width on a eMMC on SAMA5D4.

---
 drivers/mmc/gen_atmel_mci.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/mmc/gen_atmel_mci.c +12 -3
index da870c6..f090b27 100644
@@ -36,6 +36,7 @@ struct atmel_mci_priv {
 	struct mmc_config	cfg;
 	struct atmel_mci	*mci;
 	unsigned int		initialized:1;
+	unsigned int		curr_clk;
 };
 
 /* Read Atmel MCI IP version */
@@ -91,7 +92,10 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
 
 		}
 	}
-
+	if (version >= 0x500)
+		priv->curr_clk = bus_hz / (clkdiv * 2 + clkodd + 2);
+	else
+		priv->curr_clk = (bus_hz / (clkdiv + 1)) / 2;
 	blklen &= 0xfffc;
 
 	mr = MMCI_BF(CLKDIV, clkdiv);
@@ -118,8 +122,6 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
 	if (mmc->card_caps & mmc->cfg->host_caps & MMC_MODE_HS)
 		writel(MMCI_BIT(HSMODE), &mci->cfg);
 
-	udelay(50);
-
 	priv->initialized = 1;
 }
 
@@ -323,6 +325,13 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 		}
 	}
 
+	/*
+	 * After the switch command, wait for 8 clocks before the next
+	 * command
+	 */
+	if (cmd->cmdidx == MMC_CMD_SWITCH)
+		udelay(8*1000000/ priv->curr_clk); /* 8 clk in us */
+
 	return 0;
 }
 
Signature · 1 line
2.5.0
#1 lore raw

PATCH v2 1/1 mmc: atmel: Properly fix clock configuration

Quoted 48 lines · Gregory CLEMENT

Timing issue occurs on eMMC not only when modifying the frequency but also for all the switch command(CMD6). According to the MMC spec waiting 8 clocks after a switch command would be the thing to do.

This patch allows fixing CPU hang observed when trying to changing the bus width on a eMMC on SAMA5D4.

---
 drivers/mmc/gen_atmel_mci.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/mmc/gen_atmel_mci.c +5 -1
index da870c6..f090b27 100644
@@ -36,6 +36,7 @@ struct atmel_mci_priv {
 	struct mmc_config	cfg;
 	struct atmel_mci	*mci;
 	unsigned int		initialized:1;
+	unsigned int		curr_clk;
 };
 
 /* Read Atmel MCI IP version */
@@ -91,7 +92,10 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32
 blklen)
 
 		}
 	}
-
+	if (version >= 0x500)
+		priv->curr_clk = bus_hz / (clkdiv * 2 + clkodd + 2);
+	else
+		priv->curr_clk = (bus_hz / (clkdiv + 1)) / 2;
 	blklen &= 0xfffc;
 
drivers/mmc/gen_atmel_mci.c +0 -2
 	mr = MMCI_BF(CLKDIV, clkdiv);
@@ -118,8 +122,6 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32
 blklen) if (mmc->card_caps & mmc->cfg->host_caps & MMC_MODE_HS)
 		writel(MMCI_BIT(HSMODE), &mci->cfg);
 
-	udelay(50);
-
 	priv->initialized = 1;
 }
 

drivers/mmc/gen_atmel_mci.c mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, · line 333

Quoted 9 lines
drivers/mmc/gen_atmel_mci.c +6 -0
@@ -323,6 +325,13 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 struct mmc_data *data) }
 	}
 
+	/*
+	 * After the switch command, wait for 8 clocks before the next
+	 * command
+	 */
+	if (cmd->cmdidx == MMC_CMD_SWITCH)
+		udelay(8*1000000/ priv->curr_clk); /* 8 clk in us */

Is there a chance that curr_clk will be inited to zero and this would be called? I guess the easy fix is to init curr_clk to 1 in the probe() call. Sorry that I didn't mention this earlier.

Otherwise,

drivers/mmc/gen_atmel_mci.c mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) · line 336

Quoted 3 lines
drivers/mmc/gen_atmel_mci.c +1 -0
+
 	return 0;
 }

Best regards,
Marek Vasut

#2 lore raw

PATCH v2 1/1 mmc: atmel: Properly fix clock configuration

Hi Marek,

Quoted 52 lines · Marek Vasut
Quoted 51 lines · Gregory CLEMENT

Timing issue occurs on eMMC not only when modifying the frequency but also for all the switch command(CMD6). According to the MMC spec waiting 8 clocks after a switch command would be the thing to do.

This patch allows fixing CPU hang observed when trying to changing the bus width on a eMMC on SAMA5D4.

---
 drivers/mmc/gen_atmel_mci.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/mmc/gen_atmel_mci.c +5 -1
index da870c6..f090b27 100644
@@ -36,6 +36,7 @@ struct atmel_mci_priv {
 	struct mmc_config	cfg;
 	struct atmel_mci	*mci;
 	unsigned int		initialized:1;
+	unsigned int		curr_clk;
 };
 
 /* Read Atmel MCI IP version */
@@ -91,7 +92,10 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32
 blklen)
 
 		}
 	}
-
+	if (version >= 0x500)
+		priv->curr_clk = bus_hz / (clkdiv * 2 + clkodd + 2);
+	else
+		priv->curr_clk = (bus_hz / (clkdiv + 1)) / 2;
 	blklen &= 0xfffc;
 
drivers/mmc/gen_atmel_mci.c +0 -2
 	mr = MMCI_BF(CLKDIV, clkdiv);
@@ -118,8 +122,6 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32
 blklen) if (mmc->card_caps & mmc->cfg->host_caps & MMC_MODE_HS)
 		writel(MMCI_BIT(HSMODE), &mci->cfg);
 
-	udelay(50);
-
 	priv->initialized = 1;
 }
 
@@ -323,6 +325,13 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 struct mmc_data *data) }
 	}
 
Quoted 9 lines

drivers/mmc/gen_atmel_mci.c mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) · line 333

Quoted 6 lines
drivers/mmc/gen_atmel_mci.c +6 -0
+	/*
+	 * After the switch command, wait for 8 clocks before the next
+	 * command
+	 */
+	if (cmd->cmdidx == MMC_CMD_SWITCH)
+		udelay(8*1000000/ priv->curr_clk); /* 8 clk in us */

Is there a chance that curr_clk will be inited to zero and this would be called?

curr_clk is set in the mci_set_mode function which is called from mci_init which is called by the mmc core function mmc_start_init before any use of a command and especially of mci_send_cmd(). So we are safe.

Quoted 6 lines

I guess the easy fix is to init curr_clk to 1 in the probe() call. Sorry that I didn't mention this earlier.

Otherwise,

Thanks,

Gregory

Quoted 7 lines

drivers/mmc/gen_atmel_mci.c mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) · line 336

Quoted 4 lines
drivers/mmc/gen_atmel_mci.c +1 -0
+
 	return 0;
 }

Best regards,
Marek Vasut

Signature · 4 lines
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
#3 lore raw

PATCH v2 1/1 mmc: atmel: Properly fix clock configuration

Quoted 78 lines · Gregory CLEMENT

Hi Marek,

Quoted 65 lines · Marek Vasut
Quoted 64 lines · Gregory CLEMENT

Timing issue occurs on eMMC not only when modifying the frequency but also for all the switch command(CMD6). According to the MMC spec waiting 8 clocks after a switch command would be the thing to do.

This patch allows fixing CPU hang observed when trying to changing the bus width on a eMMC on SAMA5D4.

---

 drivers/mmc/gen_atmel_mci.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/mmc/gen_atmel_mci.c +1 -0
index da870c6..f090b27 100644
@@ -36,6 +36,7 @@ struct atmel_mci_priv {
 
 	struct mmc_config	cfg;
 	struct atmel_mci	*mci;
 	unsigned int		initialized:1;
 
+	unsigned int		curr_clk;
 

};

/* Read Atmel MCI IP version */

drivers/mmc/gen_atmel_mci.c +4 -1
@@ -91,7 +92,10 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32
 blklen)
 
 		}
 
 	}
 
-
+	if (version >= 0x500)
+		priv->curr_clk = bus_hz / (clkdiv * 2 + clkodd + 2);
+	else
+		priv->curr_clk = (bus_hz / (clkdiv + 1)) / 2;
drivers/mmc/gen_atmel_mci.c +0 -2
 	blklen &= 0xfffc;
 
 	mr = MMCI_BF(CLKDIV, clkdiv);
@@ -118,8 +122,6 @@ static void mci_set_mode(struct mmc *mmc, u32 hz,
 u32 blklen) if (mmc->card_caps & mmc->cfg->host_caps & MMC_MODE_HS)
 
 		writel(MMCI_BIT(HSMODE), &mci->cfg);
 
-	udelay(50);
-
 
 	priv->initialized = 1;

}

drivers/mmc/gen_atmel_mci.c +0 -0
@@ -323,6 +325,13 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 struct mmc_data *data) }
 
 	}
 
Quoted 9 lines

drivers/mmc/gen_atmel_mci.c mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) · line 333

Quoted 6 lines
drivers/mmc/gen_atmel_mci.c +6 -0
+	/*
+	 * After the switch command, wait for 8 clocks before the next
+	 * command
+	 */
+	if (cmd->cmdidx == MMC_CMD_SWITCH)
+		udelay(8*1000000/ priv->curr_clk); /* 8 clk in us */

Is there a chance that curr_clk will be inited to zero and this would be called?

Quoted 3 lines

curr_clk is set in the mci_set_mode function which is called from mci_init which is called by the mmc core function mmc_start_init before any use of a command and especially of mci_send_cmd(). So we are safe.

Excellent, thanks for checking this :-)

Quoted 10 lines
Quoted 6 lines

I guess the easy fix is to init curr_clk to 1 in the probe() call. Sorry that I didn't mention this earlier.

Otherwise,

Thanks,

Gregory

Thanks!

Best regards,
Marek Vasut

#4 lore raw

PATCH v2 1/1 mmc: atmel: Properly fix clock configuration

In reply to Gregory CLEMENT

Hi Gregory,

Quoted 9 lines · Gregory CLEMENT

Timing issue occurs on eMMC not only when modifying the frequency but also for all the switch command(CMD6). According to the MMC spec waiting 8 clocks after a switch command would be the thing to do.

This patch allows fixing CPU hang observed when trying to changing the bus width on a eMMC on SAMA5D4.

this patch seams to break avr32 ... I'm on it to investigate the root cause.

Andreas

Quoted 52 lines
---
 drivers/mmc/gen_atmel_mci.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/mmc/gen_atmel_mci.c +12 -3
index da870c6..f090b27 100644
@@ -36,6 +36,7 @@ struct atmel_mci_priv {
 	struct mmc_config	cfg;
 	struct atmel_mci	*mci;
 	unsigned int		initialized:1;
+	unsigned int		curr_clk;
 };
 
 /* Read Atmel MCI IP version */
@@ -91,7 +92,10 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
 
 		}
 	}
-
+	if (version >= 0x500)
+		priv->curr_clk = bus_hz / (clkdiv * 2 + clkodd + 2);
+	else
+		priv->curr_clk = (bus_hz / (clkdiv + 1)) / 2;
 	blklen &= 0xfffc;
 
 	mr = MMCI_BF(CLKDIV, clkdiv);
@@ -118,8 +122,6 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
 	if (mmc->card_caps & mmc->cfg->host_caps & MMC_MODE_HS)
 		writel(MMCI_BIT(HSMODE), &mci->cfg);
 
-	udelay(50);
-
 	priv->initialized = 1;
 }
 
@@ -323,6 +325,13 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 		}
 	}
 
+	/*
+	 * After the switch command, wait for 8 clocks before the next
+	 * command
+	 */
+	if (cmd->cmdidx == MMC_CMD_SWITCH)
+		udelay(8*1000000/ priv->curr_clk); /* 8 clk in us */
+
 	return 0;
 }
 
#5 lore raw

PATCH v2 1/1 mmc: atmel: Properly fix clock configuration

Quoted 7 lines · Andreas Bie?mann

Hi Gregory,

Quoted 4 lines · Gregory CLEMENT

Timing issue occurs on eMMC not only when modifying the frequency but also for all the switch command(CMD6). According to the MMC spec waiting 8 clocks after a switch command would be the thing to do.

Quoted 7 lines
Quoted 5 lines

This patch allows fixing CPU hang observed when trying to changing the bus width on a eMMC on SAMA5D4.

this patch seams to break avr32 ... I'm on it to investigate the root cause.

Sorry, was my fault.

#6 lore raw

PATCH v2 1/1 mmc: atmel: Properly fix clock configuration

In reply to Gregory CLEMENT

Hi Pantelis,

Quoted 9 lines · Gregory CLEMENT

Timing issue occurs on eMMC not only when modifying the frequency but also for all the switch command(CMD6). According to the MMC spec waiting 8 clocks after a switch command would be the thing to do.

This patch allows fixing CPU hang observed when trying to changing the bus width on a eMMC on SAMA5D4.

this patch [1] is delegated to you on patchwork ... will you take it?

Andreas

[1] http://patchwork.ozlabs.org/patch/540686/

Quoted 42 lines
---
 drivers/mmc/gen_atmel_mci.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/mmc/gen_atmel_mci.c +5 -3
index da870c6..f090b27 100644
@@ -36,6 +36,7 @@ struct atmel_mci_priv {
 	struct mmc_config	cfg;
 	struct atmel_mci	*mci;
 	unsigned int		initialized:1;
+	unsigned int		curr_clk;
 };
 
 /* Read Atmel MCI IP version */
@@ -91,7 +92,10 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
 
 		}
 	}
-
+	if (version >= 0x500)
+		priv->curr_clk = bus_hz / (clkdiv * 2 + clkodd + 2);
+	else
+		priv->curr_clk = (bus_hz / (clkdiv + 1)) / 2;
 	blklen &= 0xfffc;
 
 	mr = MMCI_BF(CLKDIV, clkdiv);
@@ -118,8 +122,6 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
 	if (mmc->card_caps & mmc->cfg->host_caps & MMC_MODE_HS)
 		writel(MMCI_BIT(HSMODE), &mci->cfg);
 
-	udelay(50);
-
 	priv->initialized = 1;
 }
 
@@ -323,6 +325,13 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 		}
 	}
 

drivers/mmc/gen_atmel_mci.c mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) · line 337

Quoted 10 lines
drivers/mmc/gen_atmel_mci.c +7 -0
+	/*
+	 * After the switch command, wait for 8 clocks before the next
+	 * command
+	 */
+	if (cmd->cmdidx == MMC_CMD_SWITCH)
+		udelay(8*1000000/ priv->curr_clk); /* 8 clk in us */
+
 	return 0;
 }
 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0xBC2469C7.asc
Type: application/pgp-keys
Size: 36384 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20151201/b60c930b/attachment.key>

#7 lore raw

PATCH v2 1/1 mmc: atmel: Properly fix clock configuration

In reply to Gregory CLEMENT

Dear Gregory CLEMENT,

Quoted 14 lines · Gregory CLEMENT

Timing issue occurs on eMMC not only when modifying the frequency but also for all the switch command(CMD6). According to the MMC spec waiting 8 clocks after a switch command would be the thing to do.

This patch allows fixing CPU hang observed when trying to changing the bus width on a eMMC on SAMA5D4.

Quoted 3 lines

---
drivers/mmc/gen_atmel_mci.c | 15 ++++++++++++---

1 file changed, 12 insertions(+), 3 deletions(-)

applied to u-boot-atmel/master, thanks!

Best regards,
Andreas Bie?mann