diff options
author | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2014-10-11 01:20:30 +0200 |
---|---|---|
committer | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2014-10-11 01:20:30 +0200 |
commit | 790af815436bc6a93e4c581840be2419897f23b1 (patch) | |
tree | 1ba0aaacad86092aea67d3612ae066b33b117619 /drivers/mmc | |
parent | d0b3723034aa865b8618428739efe1d98b1a2e2b (diff) | |
parent | db67801bf92f7fae6131dbc0d387131698fb9490 (diff) | |
download | u-boot-imx-790af815436bc6a93e4c581840be2419897f23b1.zip u-boot-imx-790af815436bc6a93e4c581840be2419897f23b1.tar.gz u-boot-imx-790af815436bc6a93e4c581840be2419897f23b1.tar.bz2 |
Merge branch 'u-boot/master' into 'u-boot-arm/master'
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/bfin_sdh.c | 7 | ||||
-rw-r--r-- | drivers/mmc/dw_mmc.c | 34 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 18 | ||||
-rw-r--r-- | drivers/mmc/mvebu_mmc.c | 62 | ||||
-rw-r--r-- | drivers/mmc/socfpga_dw_mmc.c | 15 |
5 files changed, 111 insertions, 25 deletions
diff --git a/drivers/mmc/bfin_sdh.c b/drivers/mmc/bfin_sdh.c index bcd6a3e..9bdfbbc 100644 --- a/drivers/mmc/bfin_sdh.c +++ b/drivers/mmc/bfin_sdh.c @@ -138,9 +138,9 @@ static int sdh_setup_data(struct mmc *mmc, struct mmc_data *data) if (data->flags & MMC_DATA_WRITE) return UNUSABLE_ERR; #ifndef RSI_BLKSZ - data_ctl |= ((ffs(data_size) - 1) << 4); + data_ctl |= ((ffs(data->blocksize) - 1) << 4); #else - bfin_write_SDH_BLK_SIZE(data_size); + bfin_write_SDH_BLK_SIZE(data->blocksize); #endif data_ctl |= DTX_DIR; bfin_write_SDH_DATA_CTL(data_ctl); @@ -189,7 +189,8 @@ static int bfin_sdh_request(struct mmc *mmc, struct mmc_cmd *cmd, do { udelay(1); status = bfin_read_SDH_STATUS(); - } while (!(status & (DAT_BLK_END | DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN))); + } while (!(status & (DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | + RX_OVERRUN))); if (status & DAT_TIME_OUT) { bfin_write_SDH_STATUS_CLR(DAT_TIMEOUT_STAT); diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 0df30bc..785eed5 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -119,7 +119,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) { if (get_timer(start) > timeout) { - printf("Timeout on data busy\n"); + printf("%s: Timeout on data busy\n", __func__); return TIMEOUT; } } @@ -177,14 +177,24 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, } } - if (i == retry) + if (i == retry) { + printf("%s: Timeout.\n", __func__); return TIMEOUT; + } if (mask & DWMCI_INTMSK_RTO) { - debug("Response Timeout..\n"); + /* + * Timeout here is not necessarily fatal. (e)MMC cards + * will splat here when they receive CMD55 as they do + * not support this command and that is exactly the way + * to tell them apart from SD cards. Thus, this output + * below shall be debug(). eMMC cards also do not favor + * CMD8, please keep that in mind. + */ + debug("%s: Response Timeout.\n", __func__); return TIMEOUT; } else if (mask & DWMCI_INTMSK_RE) { - debug("Response Error..\n"); + printf("%s: Response Error.\n", __func__); return -1; } @@ -204,7 +214,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, do { mask = dwmci_readl(host, DWMCI_RINTSTS); if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) { - debug("DATA ERROR!\n"); + printf("%s: DATA ERROR!\n", __func__); return -1; } } while (!(mask & DWMCI_INTMSK_DTO)); @@ -232,16 +242,16 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) if ((freq == host->clock) || (freq == 0)) return 0; /* - * If host->get_mmc_clk didn't define, + * If host->get_mmc_clk isn't defined, * then assume that host->bus_hz is source clock value. - * host->bus_hz should be set from user. + * host->bus_hz should be set by user. */ if (host->get_mmc_clk) sclk = host->get_mmc_clk(host); else if (host->bus_hz) sclk = host->bus_hz; else { - printf("Didn't get source clock value..\n"); + printf("%s: Didn't get source clock value.\n", __func__); return -EINVAL; } @@ -260,7 +270,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) do { status = dwmci_readl(host, DWMCI_CMD); if (timeout-- < 0) { - printf("TIMEOUT error!!\n"); + printf("%s: Timeout!\n", __func__); return -ETIMEDOUT; } } while (status & DWMCI_CMD_START); @@ -275,7 +285,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) do { status = dwmci_readl(host, DWMCI_CMD); if (timeout-- < 0) { - printf("TIMEOUT error!!\n"); + printf("%s: Timeout!\n", __func__); return -ETIMEDOUT; } } while (status & DWMCI_CMD_START); @@ -290,7 +300,7 @@ static void dwmci_set_ios(struct mmc *mmc) struct dwmci_host *host = (struct dwmci_host *)mmc->priv; u32 ctype, regs; - debug("Buswidth = %d, clock: %d\n",mmc->bus_width, mmc->clock); + debug("Buswidth = %d, clock: %d\n", mmc->bus_width, mmc->clock); dwmci_setup_bus(host, mmc->clock); switch (mmc->bus_width) { @@ -329,7 +339,7 @@ static int dwmci_init(struct mmc *mmc) dwmci_writel(host, DWMCI_PWREN, 1); if (!dwmci_wait_reset(host, DWMCI_RESET_ALL)) { - debug("%s[%d] Fail-reset!!\n",__func__,__LINE__); + printf("%s[%d] Fail-reset!!\n", __func__, __LINE__); return -1; } diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index a26f3ce..44a4feb 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -594,10 +594,15 @@ int mmc_switch_part(int dev_num, unsigned int part_num) ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF, (mmc->part_config & ~PART_ACCESS_MASK) | (part_num & PART_ACCESS_MASK)); - if (ret) - return ret; - return mmc_set_capacity(mmc, part_num); + /* + * Set the capacity if the switch succeeded or was intended + * to return to representing the raw device. + */ + if ((ret == 0) || ((ret == -ENODEV) && (part_num == 0))) + ret = mmc_set_capacity(mmc, part_num); + + return ret; } int mmc_getcd(struct mmc *mmc) @@ -1010,6 +1015,8 @@ static int mmc_startup(struct mmc *mmc) if (err) return err; + else + ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1; /* Read out group size from ext_csd */ mmc->erase_grp_size = @@ -1127,10 +1134,11 @@ static int mmc_startup(struct mmc *mmc) mmc_set_bus_width(mmc, widths[idx]); err = mmc_send_ext_csd(mmc, test_csd); + /* Only compare read only fields */ if (!err && ext_csd[EXT_CSD_PARTITIONING_SUPPORT] \ == test_csd[EXT_CSD_PARTITIONING_SUPPORT] - && ext_csd[EXT_CSD_ERASE_GROUP_DEF] \ - == test_csd[EXT_CSD_ERASE_GROUP_DEF] \ + && ext_csd[EXT_CSD_HC_WP_GRP_SIZE] \ + == test_csd[EXT_CSD_HC_WP_GRP_SIZE] \ && ext_csd[EXT_CSD_REV] \ == test_csd[EXT_CSD_REV] && ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] \ diff --git a/drivers/mmc/mvebu_mmc.c b/drivers/mmc/mvebu_mmc.c index 9759198..d34e743 100644 --- a/drivers/mmc/mvebu_mmc.c +++ b/drivers/mmc/mvebu_mmc.c @@ -17,8 +17,12 @@ #include <asm/arch/kirkwood.h> #include <mvebu_mmc.h> +DECLARE_GLOBAL_DATA_PTR; + #define DRIVER_NAME "MVEBU_MMC" +#define MVEBU_TARGET_DRAM 0 + static void mvebu_mmc_write(u32 offs, u32 val) { writel(val, CONFIG_SYS_MMC_BASE + (offs)); @@ -164,6 +168,9 @@ static int mvebu_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, return TIMEOUT; } } + if (mvebu_mmc_read(SDIO_ERR_INTR_STATUS) & + (SDIO_ERR_CMD_TIMEOUT | SDIO_ERR_DATA_TIMEOUT)) + return TIMEOUT; /* Handling response */ if (cmd->resp_type & MMC_RSP_136) { @@ -271,6 +278,7 @@ static void mvebu_mmc_set_bus(unsigned int bus) /* default to maximum timeout */ ctrl_reg |= SDIO_HOST_CTRL_TMOUT(SDIO_HOST_CTRL_TMOUT_MAX); + ctrl_reg |= SDIO_HOST_CTRL_TMOUT_EN; ctrl_reg |= SDIO_HOST_CTRL_PUSH_PULL_EN; @@ -296,6 +304,55 @@ static void mvebu_mmc_set_ios(struct mmc *mmc) mvebu_mmc_set_clk(mmc->clock); } +/* + * Set window register. + */ +static void mvebu_window_setup(void) +{ + int i; + + for (i = 0; i < 4; i++) { + mvebu_mmc_write(WINDOW_CTRL(i), 0); + mvebu_mmc_write(WINDOW_BASE(i), 0); + } + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + u32 size, base, attrib; + + /* Enable DRAM bank */ + switch (i) { + case 0: + attrib = KWCPU_ATTR_DRAM_CS0; + break; + case 1: + attrib = KWCPU_ATTR_DRAM_CS1; + break; + case 2: + attrib = KWCPU_ATTR_DRAM_CS2; + break; + case 3: + attrib = KWCPU_ATTR_DRAM_CS3; + break; + default: + /* invalide bank, disable access */ + attrib = 0; + break; + } + + size = gd->bd->bi_dram[i].size; + base = gd->bd->bi_dram[i].start; + if (size && attrib) { + mvebu_mmc_write(WINDOW_CTRL(i), + MVCPU_WIN_CTRL_DATA(size, + MVEBU_TARGET_DRAM, + attrib, + MVCPU_WIN_ENABLE)); + } else { + mvebu_mmc_write(WINDOW_CTRL(i), MVCPU_WIN_DISABLE); + } + mvebu_mmc_write(WINDOW_BASE(i), base); + } +} + static int mvebu_mmc_initialize(struct mmc *mmc) { debug("%s: mvebu_mmc_initialize", DRIVER_NAME); @@ -322,6 +379,8 @@ static int mvebu_mmc_initialize(struct mmc *mmc) mvebu_mmc_write(SDIO_NOR_INTR_EN, 0); mvebu_mmc_write(SDIO_ERR_INTR_EN, 0); + mvebu_window_setup(); + /* SW reset */ mvebu_mmc_write(SDIO_SW_RESET, SDIO_SW_RESET_NOW); @@ -342,7 +401,8 @@ static struct mmc_config mvebu_mmc_cfg = { .f_min = MVEBU_MMC_BASE_FAST_CLOCK / MVEBU_MMC_BASE_DIV_MAX, .f_max = MVEBU_MMC_CLOCKRATE_MAX, .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, - .host_caps = MMC_MODE_4BIT | MMC_MODE_HS, + .host_caps = MMC_MODE_4BIT | MMC_MODE_HS | MMC_MODE_HC | + MMC_MODE_HS_52MHz, .part_type = PART_TYPE_DOS, .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT, }; diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c index 1f96382..eb69aed 100644 --- a/drivers/mmc/socfpga_dw_mmc.c +++ b/drivers/mmc/socfpga_dw_mmc.c @@ -7,6 +7,7 @@ #include <common.h> #include <malloc.h> #include <dwmmc.h> +#include <errno.h> #include <asm/arch/dwmmc.h> #include <asm/arch/clock_manager.h> #include <asm/arch/system_manager.h> @@ -44,12 +45,18 @@ static void socfpga_dwmci_clksel(struct dwmci_host *host) int socfpga_dwmmc_init(u32 regbase, int bus_width, int index) { struct dwmci_host *host; + unsigned long clk = cm_get_mmc_controller_clk_hz(); + + if (clk == 0) { + printf("%s: MMC clock is zero!", __func__); + return -EINVAL; + } /* calloc for zero init */ - host = calloc(sizeof(struct dwmci_host), 1); + host = calloc(1, sizeof(struct dwmci_host)); if (!host) { - printf("dwmci_host calloc fail!\n"); - return -1; + printf("%s: calloc() failed!\n", __func__); + return -ENOMEM; } host->name = "SOCFPGA DWMMC"; @@ -58,7 +65,7 @@ int socfpga_dwmmc_init(u32 regbase, int bus_width, int index) host->clksel = socfpga_dwmci_clksel; host->dev_index = index; /* fixed clock divide by 4 which due to the SDMMC wrapper */ - host->bus_hz = CONFIG_SOCFPGA_DWMMC_BUS_HZ; + host->bus_hz = clk; host->fifoth_val = MSIZE(0x2) | RX_WMARK(CONFIG_SOCFPGA_DWMMC_FIFO_DEPTH / 2 - 1) | TX_WMARK(CONFIG_SOCFPGA_DWMMC_FIFO_DEPTH / 2); |