Patchwork [U-Boot,1/2] mmc: atmel_mci: using IP version for different setting

login
register
mail settings
Submitter Bo Shen
Date April 26, 2013, 10:27 a.m.
Message ID <1366972027-26840-1-git-send-email-voice.shen@atmel.com>
Download mbox | patch
Permalink /patch/239797/
State Accepted
Delegated to: Andreas BieƟmann
Headers show

Comments

Bo Shen - April 26, 2013, 10:27 a.m.
Using IP version for different setting
  - Higher version supports 8bit mode
  - Higher version bus width setting is different

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

Patch

diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
index 70a9f91..fc0a181 100644
--- a/drivers/mmc/gen_atmel_mci.c
+++ b/drivers/mmc/gen_atmel_mci.c
@@ -50,6 +50,12 @@ 
 
 static int initialized = 0;
 
+/* Read Atmel MCI IP version */
+static unsigned int atmel_mci_get_version(struct atmel_mci *mci)
+{
+	return readl(&mci->version) & 0x00000fff;
+}
+
 /*
  * Print command and status:
  *
@@ -297,7 +303,9 @@  mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 static void mci_set_ios(struct mmc *mmc)
 {
 	atmel_mci_t *mci = (atmel_mci_t *)mmc->priv;
-	int busw = (mmc->bus_width == 4) ? 1 : 0;
+	int bus_width = mmc->bus_width;
+	unsigned int version = atmel_mci_get_version(mci);
+	int busw;
 
 	/* Set the clock speed */
 	mci_set_mode(mmc, mmc->clock, MMC_DEFAULT_BLKLEN);
@@ -305,9 +313,26 @@  static void mci_set_ios(struct mmc *mmc)
 	/*
 	 * set the bus width and select slot for this interface
 	 * there is no capability for multiple slots on the same interface yet
-	 * Bitfield SCDBUS needs to be expanded to 2 bits for 8-bit buses
 	 */
-	writel(MMCI_BF(SCDBUS, busw) | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
+	if ((version & 0xf00) >= 0x300) {
+		switch (bus_width) {
+		case 8:
+			busw = 3;
+			break;
+		case 4:
+			busw = 2;
+			break;
+		default:
+			busw = 0;
+			break;
+		}
+
+		writel(busw << 6 | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
+	} else {
+		busw = (bus_width == 4) ? 1 : 0;
+
+		writel(busw << 7 | MMCI_BF(SCDSEL, MCI_BUS), &mci->sdcr);
+	}
 }
 
 /* Entered into mmc structure during driver init */
@@ -340,9 +365,12 @@  static int mci_init(struct mmc *mmc)
 int atmel_mci_init(void *regs)
 {
 	struct mmc *mmc = malloc(sizeof(struct mmc));
+	struct atmel_mci *mci;
+	unsigned int version;
 
 	if (!mmc)
 		return -1;
+
 	strcpy(mmc->name, "mci");
 	mmc->priv = regs;
 	mmc->send_cmd = mci_send_cmd;
@@ -353,7 +381,13 @@  int atmel_mci_init(void *regs)
 
 	/* need to be able to pass these in on a board by board basis */
 	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
-	mmc->host_caps = MMC_MODE_4BIT;
+	mci = (struct atmel_mci *)mmc->priv;
+	version = atmel_mci_get_version(mci);
+	if ((version & 0xf00) >= 0x300)
+		mmc->host_caps = MMC_MODE_8BIT;
+
+	mmc->host_caps |= MMC_MODE_4BIT;
+
 	/*
 	 * min and max frequencies determined by
 	 * max and min of clock divider
diff --git a/include/atmel_mci.h b/include/atmel_mci.h
index c711881..31c4569 100644
--- a/include/atmel_mci.h
+++ b/include/atmel_mci.h
@@ -52,6 +52,8 @@  typedef struct atmel_mci {
 	u32	ier;	/* 0x44 */
 	u32	idr;	/* 0x48 */
 	u32	imr;	/* 0x4c */
+	u32	reserved[43];
+	u32	version;
 } atmel_mci_t;
 
 #endif /* __ASSEMBLY__ */