diff mbox

[U-Boot,1/3] MMC: atmel_mci: refactor setting the mode register

Message ID 1406788772-23377-2-git-send-email-voice.shen@atmel.com
State Accepted
Delegated to: Pantelis Antoniou
Headers show

Commit Message

Bo Shen July 31, 2014, 6:39 a.m. UTC
The mode register is different between MCI IP version.
So, according to MCI IP version to set the mode register.

Signed-off-by: Bo Shen <voice.shen@atmel.com>
---
 drivers/mmc/gen_atmel_mci.c | 56 +++++++++++++++++++++++++++++++++------------
 include/atmel_mci.h         |  4 ++++
 2 files changed, 46 insertions(+), 14 deletions(-)

Comments

Pantelis Antoniou Aug. 1, 2014, 4:59 p.m. UTC | #1
Hi Bo,

On Jul 31, 2014, at 9:39 AM, Bo Shen wrote:

> The mode register is different between MCI IP version.
> So, according to MCI IP version to set the mode register.
> 
> Signed-off-by: Bo Shen <voice.shen@atmel.com>
> ---
> drivers/mmc/gen_atmel_mci.c | 56 +++++++++++++++++++++++++++++++++------------
> include/atmel_mci.h         |  4 ++++
> 2 files changed, 46 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
> index a57a9b1..8778a4d 100644
> --- a/drivers/mmc/gen_atmel_mci.c
> +++ b/drivers/mmc/gen_atmel_mci.c
> @@ -58,30 +58,58 @@ static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
> 	atmel_mci_t *mci = mmc->priv;
> 	u32 bus_hz = get_mci_clk_rate();
> 	u32 clkdiv = 255;
> +	unsigned int version = atmel_mci_get_version(mci);
> +	u32 clkodd = 0;
> +	u32 mr;
> 
> 	debug("mci: bus_hz is %u, setting clock %u Hz, block size %u\n",
> 		bus_hz, hz, blklen);
> 	if (hz > 0) {
> -		/* find lowest clkdiv yielding a rate <= than requested */
> -		for (clkdiv=0; clkdiv<255; clkdiv++) {
> -			if ((bus_hz / (clkdiv+1) / 2) <= hz)
> -				break;
> +		if (version >= 0x500) {
> +			clkdiv = DIV_ROUND_UP(bus_hz, hz) - 2;
> +			if (clkdiv > 511)
> +				clkdiv = 511;
> +
> +			clkodd = clkdiv & 1;
> +			clkdiv >>= 1;
> +
> +			printf("mci: setting clock %u Hz, block size %u\n",
> +			       bus_hz / (clkdiv * 2 + clkodd + 2), blklen);
> +		} else {
> +			/* find clkdiv yielding a rate <= than requested */
> +			for (clkdiv = 0; clkdiv < 255; clkdiv++) {
> +				if ((bus_hz / (clkdiv + 1) / 2) <= hz)
> +					break;
> +			}
> +			printf("mci: setting clock %u Hz, block size %u\n",
> +			       (bus_hz / (clkdiv + 1)) / 2, blklen);
> +
> 		}
> 	}
> -	printf("mci: setting clock %u Hz, block size %u\n",
> -		(bus_hz / (clkdiv+1)) / 2, blklen);
> 
> 	blklen &= 0xfffc;
> -	/* On some platforms RDPROOF and WRPROOF are ignored */
> -	writel((MMCI_BF(CLKDIV, clkdiv)
> -		 | MMCI_BF(BLKLEN, blklen)
> -		 | MMCI_BIT(RDPROOF)
> -		 | MMCI_BIT(WRPROOF)), &mci->mr);
> +
> +	mr = MMCI_BF(CLKDIV, clkdiv);
> +
> +	/* MCI IP version >= 0x200 has R/WPROOF */
> +	if (version >= 0x200)
> +		mr |= MMCI_BIT(RDPROOF) | MMCI_BIT(WRPROOF);
> +
> 	/*
> -	 * On some new platforms BLKLEN in mci->mr is ignored.
> -	 * Should use the BLKLEN in the block register.
> +	 * MCI IP version >= 0x500 use bit 16 as clkodd.
> +	 * MCI IP version < 0x500 use upper 16 bits for blklen.
> 	 */
> -	writel(MMCI_BF(BLKLEN, blklen), &mci->blkr);
> +	if (version >= 0x500)
> +		mr |= MMCI_BF(CLKODD, clkodd);
> +	else
> +		mr |= MMCI_BF(BLKLEN, blklen);
> +
> +	writel(mr, &mci->mr);
> +
> +	/* MCI IP version >= 0x200 has blkr */
> +	if (version >= 0x200)
> +		writel(MMCI_BF(BLKLEN, blklen), &mci->blkr);
> +
> 	initialized = 1;
> }
> 
> diff --git a/include/atmel_mci.h b/include/atmel_mci.h
> index 090574d..3d2870f 100644
> --- a/include/atmel_mci.h
> +++ b/include/atmel_mci.h
> @@ -67,6 +67,10 @@ typedef struct atmel_mci {
> #define MMCI_PDCPADV_SIZE			1
> #define MMCI_PDCMODE_OFFSET			15
> #define MMCI_PDCMODE_SIZE			1
> +/* MCI IP version >= 0x500, MR bit 16 used for CLKODD */
> +#define MMCI_CLKODD_OFFSET			16
> +#define MMCI_CLKODD_SIZE			1
> +/* MCI IP version < 0x200, MR higher 16bits for BLKLEN */
> #define MMCI_BLKLEN_OFFSET			16
> #define MMCI_BLKLEN_SIZE			16
> 
> -- 
> 1.8.5.2
> 

Looks good.

Applied, thanks.
diff mbox

Patch

diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
index a57a9b1..8778a4d 100644
--- a/drivers/mmc/gen_atmel_mci.c
+++ b/drivers/mmc/gen_atmel_mci.c
@@ -58,30 +58,58 @@  static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
 	atmel_mci_t *mci = mmc->priv;
 	u32 bus_hz = get_mci_clk_rate();
 	u32 clkdiv = 255;
+	unsigned int version = atmel_mci_get_version(mci);
+	u32 clkodd = 0;
+	u32 mr;
 
 	debug("mci: bus_hz is %u, setting clock %u Hz, block size %u\n",
 		bus_hz, hz, blklen);
 	if (hz > 0) {
-		/* find lowest clkdiv yielding a rate <= than requested */
-		for (clkdiv=0; clkdiv<255; clkdiv++) {
-			if ((bus_hz / (clkdiv+1) / 2) <= hz)
-				break;
+		if (version >= 0x500) {
+			clkdiv = DIV_ROUND_UP(bus_hz, hz) - 2;
+			if (clkdiv > 511)
+				clkdiv = 511;
+
+			clkodd = clkdiv & 1;
+			clkdiv >>= 1;
+
+			printf("mci: setting clock %u Hz, block size %u\n",
+			       bus_hz / (clkdiv * 2 + clkodd + 2), blklen);
+		} else {
+			/* find clkdiv yielding a rate <= than requested */
+			for (clkdiv = 0; clkdiv < 255; clkdiv++) {
+				if ((bus_hz / (clkdiv + 1) / 2) <= hz)
+					break;
+			}
+			printf("mci: setting clock %u Hz, block size %u\n",
+			       (bus_hz / (clkdiv + 1)) / 2, blklen);
+
 		}
 	}
-	printf("mci: setting clock %u Hz, block size %u\n",
-		(bus_hz / (clkdiv+1)) / 2, blklen);
 
 	blklen &= 0xfffc;
-	/* On some platforms RDPROOF and WRPROOF are ignored */
-	writel((MMCI_BF(CLKDIV, clkdiv)
-		 | MMCI_BF(BLKLEN, blklen)
-		 | MMCI_BIT(RDPROOF)
-		 | MMCI_BIT(WRPROOF)), &mci->mr);
+
+	mr = MMCI_BF(CLKDIV, clkdiv);
+
+	/* MCI IP version >= 0x200 has R/WPROOF */
+	if (version >= 0x200)
+		mr |= MMCI_BIT(RDPROOF) | MMCI_BIT(WRPROOF);
+
 	/*
-	 * On some new platforms BLKLEN in mci->mr is ignored.
-	 * Should use the BLKLEN in the block register.
+	 * MCI IP version >= 0x500 use bit 16 as clkodd.
+	 * MCI IP version < 0x500 use upper 16 bits for blklen.
 	 */
-	writel(MMCI_BF(BLKLEN, blklen), &mci->blkr);
+	if (version >= 0x500)
+		mr |= MMCI_BF(CLKODD, clkodd);
+	else
+		mr |= MMCI_BF(BLKLEN, blklen);
+
+	writel(mr, &mci->mr);
+
+	/* MCI IP version >= 0x200 has blkr */
+	if (version >= 0x200)
+		writel(MMCI_BF(BLKLEN, blklen), &mci->blkr);
+
 	initialized = 1;
 }
 
diff --git a/include/atmel_mci.h b/include/atmel_mci.h
index 090574d..3d2870f 100644
--- a/include/atmel_mci.h
+++ b/include/atmel_mci.h
@@ -67,6 +67,10 @@  typedef struct atmel_mci {
 #define MMCI_PDCPADV_SIZE			1
 #define MMCI_PDCMODE_OFFSET			15
 #define MMCI_PDCMODE_SIZE			1
+/* MCI IP version >= 0x500, MR bit 16 used for CLKODD */
+#define MMCI_CLKODD_OFFSET			16
+#define MMCI_CLKODD_SIZE			1
+/* MCI IP version < 0x200, MR higher 16bits for BLKLEN */
 #define MMCI_BLKLEN_OFFSET			16
 #define MMCI_BLKLEN_SIZE			16