From aac4b69b2c916736911976562bfc0cb4bfd26b2f Mon Sep 17 00:00:00 2001 From: Bo Shen Date: Fri, 26 Apr 2013 00:27:06 +0000 Subject: mmc: atmel_mci: using IP version for different setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using IP version for different setting - Higher version supports 8bit mode - Higher version bus width setting is different Signed-off-by: Bo Shen Signed-off-by: Andreas Bießmann 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__ */ -- cgit v0.10.2