diff options
author | Bo Shen <voice.shen@atmel.com> | 2013-04-26 00:27:06 +0000 |
---|---|---|
committer | Bo Shen <voice.shen@atmel.com> | 2013-05-13 17:37:20 +0800 |
commit | b9d7ce5d0c46d6a65dfdb9af58f4b8d9de8c7650 (patch) | |
tree | 0b52d503ad8f3df1f8713ae056285c6238463759 | |
parent | 157cf9d6ba73668122b4cce668af6e3d8e50da7d (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.c | 42 | ||||
-rw-r--r-- | include/atmel_mci.h | 2 |
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__ */ |