summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBo Shen <voice.shen@atmel.com>2013-04-26 00:27:06 +0000
committerBo Shen <voice.shen@atmel.com>2013-05-13 17:37:20 +0800
commitb9d7ce5d0c46d6a65dfdb9af58f4b8d9de8c7650 (patch)
tree0b52d503ad8f3df1f8713ae056285c6238463759
parent157cf9d6ba73668122b4cce668af6e3d8e50da7d (diff)
mmc: atmel_mci: using IP version for different setting
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>
-rw-r--r--drivers/mmc/gen_atmel_mci.c42
-rw-r--r--include/atmel_mci.h2
2 files changed, 40 insertions, 4 deletions
diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
index 67b2dbe8d4c..3926f85512c 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;
@@ -352,7 +380,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 c711881276b..31c4569c8fb 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__ */