Merge branch 'master' of git://git.denx.de/u-boot-mmc

master
Tom Rini 10 years ago
commit 6983951a61
  1. 3
      common/cmd_mmc.c
  2. 2
      drivers/mmc/dw_mmc.c
  3. 22
      drivers/mmc/exynos_dw_mmc.c
  4. 85
      drivers/mmc/mmc.c
  5. 5
      include/mmc.h

@ -90,7 +90,8 @@ static void print_mmcinfo(struct mmc *mmc)
puts("Capacity: "); puts("Capacity: ");
print_size(mmc->capacity, "\n"); print_size(mmc->capacity, "\n");
printf("Bus Width: %d-bit\n", mmc->bus_width); printf("Bus Width: %d-bit%s\n", mmc->bus_width,
mmc->ddr_mode ? " DDR" : "");
} }
static struct mmc *init_mmc_device(int dev, bool force_init) static struct mmc *init_mmc_device(int dev, bool force_init)
{ {

@ -318,7 +318,7 @@ static void dwmci_set_ios(struct mmc *mmc)
dwmci_writel(host, DWMCI_CTYPE, ctype); dwmci_writel(host, DWMCI_CTYPE, ctype);
regs = dwmci_readl(host, DWMCI_UHS_REG); regs = dwmci_readl(host, DWMCI_UHS_REG);
if (mmc->card_caps & MMC_MODE_DDR_52MHz) if (mmc->ddr_mode)
regs |= DWMCI_DDR_MODE; regs |= DWMCI_DDR_MODE;
else else
regs &= DWMCI_DDR_MODE; regs &= DWMCI_DDR_MODE;

@ -101,7 +101,7 @@ static int exynos_dwmci_core_init(struct dwmci_host *host, int index)
host->get_mmc_clk = exynos_dwmci_get_clk; host->get_mmc_clk = exynos_dwmci_get_clk;
/* Add the mmc channel to be registered with mmc core */ /* Add the mmc channel to be registered with mmc core */
if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) { if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) {
debug("dwmmc%d registration failed\n", index); printf("DWMMC%d registration failed\n", index);
return -1; return -1;
} }
return 0; return 0;
@ -146,7 +146,7 @@ static int do_dwmci_init(struct dwmci_host *host)
flag = host->buswidth == 8 ? PINMUX_FLAG_8BIT_MODE : PINMUX_FLAG_NONE; flag = host->buswidth == 8 ? PINMUX_FLAG_8BIT_MODE : PINMUX_FLAG_NONE;
err = exynos_pinmux_config(host->dev_id, flag); err = exynos_pinmux_config(host->dev_id, flag);
if (err) { if (err) {
debug("DWMMC not configure\n"); printf("DWMMC%d not configure\n", index);
return err; return err;
} }
@ -162,21 +162,22 @@ static int exynos_dwmci_get_config(const void *blob, int node,
/* Extract device id for each mmc channel */ /* Extract device id for each mmc channel */
host->dev_id = pinmux_decode_periph_id(blob, node); host->dev_id = pinmux_decode_periph_id(blob, node);
host->dev_index = fdtdec_get_int(blob, node, "index", host->dev_id);
if (host->dev_index == host->dev_id)
host->dev_index = host->dev_id - PERIPH_ID_SDMMC0;
/* Get the bus width from the device node */ /* Get the bus width from the device node */
host->buswidth = fdtdec_get_int(blob, node, "samsung,bus-width", 0); host->buswidth = fdtdec_get_int(blob, node, "samsung,bus-width", 0);
if (host->buswidth <= 0) { if (host->buswidth <= 0) {
debug("DWMMC: Can't get bus-width\n"); printf("DWMMC%d: Can't get bus-width\n", host->dev_index);
return -EINVAL; return -EINVAL;
} }
host->dev_index = fdtdec_get_int(blob, node, "index", host->dev_id);
if (host->dev_index == host->dev_id)
host->dev_index = host->dev_id - PERIPH_ID_SDMMC0;
/* Set the base address from the device node */ /* Set the base address from the device node */
base = fdtdec_get_addr(blob, node, "reg"); base = fdtdec_get_addr(blob, node, "reg");
if (!base) { if (!base) {
debug("DWMMC: Can't get base address\n"); printf("DWMMC%d: Can't get base address\n", host->dev_index);
return -EINVAL; return -EINVAL;
} }
host->ioaddr = (void *)base; host->ioaddr = (void *)base;
@ -184,7 +185,8 @@ static int exynos_dwmci_get_config(const void *blob, int node,
/* Extract the timing info from the node */ /* Extract the timing info from the node */
err = fdtdec_get_int_array(blob, node, "samsung,timing", timing, 3); err = fdtdec_get_int_array(blob, node, "samsung,timing", timing, 3);
if (err) { if (err) {
debug("Can't get sdr-timings for devider\n"); printf("DWMMC%d: Can't get sdr-timings for devider\n",
host->dev_index);
return -EINVAL; return -EINVAL;
} }
@ -214,7 +216,7 @@ static int exynos_dwmci_process_node(const void *blob,
host = &dwmci_host[i]; host = &dwmci_host[i];
err = exynos_dwmci_get_config(blob, node, host); err = exynos_dwmci_get_config(blob, node, host);
if (err) { if (err) {
debug("%s: failed to decode dev %d\n", __func__, i); printf("%s: failed to decode dev %d\n", __func__, i);
return err; return err;
} }

@ -159,7 +159,7 @@ int mmc_set_blocklen(struct mmc *mmc, int len)
{ {
struct mmc_cmd cmd; struct mmc_cmd cmd;
if (mmc->card_caps & MMC_MODE_DDR_52MHz) if (mmc->ddr_mode)
return 0; return 0;
cmd.cmdidx = MMC_CMD_SET_BLOCKLEN; cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
@ -486,7 +486,7 @@ static int mmc_change_freq(struct mmc *mmc)
char cardtype; char cardtype;
int err; int err;
mmc->card_caps = 0; mmc->card_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
if (mmc_host_is_spi(mmc)) if (mmc_host_is_spi(mmc))
return 0; return 0;
@ -519,7 +519,7 @@ static int mmc_change_freq(struct mmc *mmc)
/* High Speed is set, there are two types: 52MHz and 26MHz */ /* High Speed is set, there are two types: 52MHz and 26MHz */
if (cardtype & EXT_CSD_CARD_TYPE_52) { if (cardtype & EXT_CSD_CARD_TYPE_52) {
if (cardtype & EXT_CSD_CARD_TYPE_DDR_52) if (cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V)
mmc->card_caps |= MMC_MODE_DDR_52MHz; mmc->card_caps |= MMC_MODE_DDR_52MHz;
mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
} else { } else {
@ -1001,6 +1001,9 @@ static int mmc_startup(struct mmc *mmc)
case 6: case 6:
mmc->version = MMC_VERSION_4_5; mmc->version = MMC_VERSION_4_5;
break; break;
case 7:
mmc->version = MMC_VERSION_5_0;
break;
} }
/* /*
@ -1022,6 +1025,21 @@ static int mmc_startup(struct mmc *mmc)
mmc->erase_grp_size = mmc->erase_grp_size =
ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] *
MMC_MAX_BLOCK_LEN * 1024; MMC_MAX_BLOCK_LEN * 1024;
/*
* if high capacity and partition setting completed
* SEC_COUNT is valid even if it is smaller than 2 GiB
* JEDEC Standard JESD84-B45, 6.2.4
*/
if (mmc->high_capacity &&
(ext_csd[EXT_CSD_PARTITION_SETTING] &
EXT_CSD_PARTITION_SETTING_COMPLETED)) {
capacity = (ext_csd[EXT_CSD_SEC_CNT]) |
(ext_csd[EXT_CSD_SEC_CNT + 1] << 8) |
(ext_csd[EXT_CSD_SEC_CNT + 2] << 16) |
(ext_csd[EXT_CSD_SEC_CNT + 3] << 24);
capacity *= MMC_MAX_BLOCK_LEN;
mmc->capacity_user = capacity;
}
} else { } else {
/* Calculate the group size from the csd value. */ /* Calculate the group size from the csd value. */
int erase_gsz, erase_gmul; int erase_gsz, erase_gmul;
@ -1103,8 +1121,10 @@ static int mmc_startup(struct mmc *mmc)
/* An array to map CSD bus widths to host cap bits */ /* An array to map CSD bus widths to host cap bits */
static unsigned ext_to_hostcaps[] = { static unsigned ext_to_hostcaps[] = {
[EXT_CSD_DDR_BUS_WIDTH_4] = MMC_MODE_DDR_52MHz, [EXT_CSD_DDR_BUS_WIDTH_4] =
[EXT_CSD_DDR_BUS_WIDTH_8] = MMC_MODE_DDR_52MHz, MMC_MODE_DDR_52MHz | MMC_MODE_4BIT,
[EXT_CSD_DDR_BUS_WIDTH_8] =
MMC_MODE_DDR_52MHz | MMC_MODE_8BIT,
[EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT, [EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT,
[EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT, [EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT,
}; };
@ -1116,13 +1136,13 @@ static int mmc_startup(struct mmc *mmc)
for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) { for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
unsigned int extw = ext_csd_bits[idx]; unsigned int extw = ext_csd_bits[idx];
unsigned int caps = ext_to_hostcaps[extw];
/* /*
* Check to make sure the controller supports * Check to make sure the card and controller support
* this bus width, if it's more than 1 * these capabilities
*/ */
if (extw != EXT_CSD_BUS_WIDTH_1 && if ((mmc->card_caps & caps) != caps)
!(mmc->cfg->host_caps & ext_to_hostcaps[extw]))
continue; continue;
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
@ -1131,26 +1151,33 @@ static int mmc_startup(struct mmc *mmc)
if (err) if (err)
continue; continue;
mmc->ddr_mode = (caps & MMC_MODE_DDR_52MHz) ? 1 : 0;
mmc_set_bus_width(mmc, widths[idx]); mmc_set_bus_width(mmc, widths[idx]);
err = mmc_send_ext_csd(mmc, test_csd); err = mmc_send_ext_csd(mmc, test_csd);
if (err)
continue;
/* Only compare read only fields */ /* Only compare read only fields */
if (!err && ext_csd[EXT_CSD_PARTITIONING_SUPPORT] \ if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT]
== test_csd[EXT_CSD_PARTITIONING_SUPPORT] == test_csd[EXT_CSD_PARTITIONING_SUPPORT] &&
&& ext_csd[EXT_CSD_HC_WP_GRP_SIZE] \ ext_csd[EXT_CSD_HC_WP_GRP_SIZE]
== test_csd[EXT_CSD_HC_WP_GRP_SIZE] \ == test_csd[EXT_CSD_HC_WP_GRP_SIZE] &&
&& ext_csd[EXT_CSD_REV] \ ext_csd[EXT_CSD_REV]
== test_csd[EXT_CSD_REV] == test_csd[EXT_CSD_REV] &&
&& ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] \ ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
== test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] &&
&& memcmp(&ext_csd[EXT_CSD_SEC_CNT], \ memcmp(&ext_csd[EXT_CSD_SEC_CNT],
&test_csd[EXT_CSD_SEC_CNT], 4) == 0) { &test_csd[EXT_CSD_SEC_CNT], 4) == 0)
mmc->card_caps |= ext_to_hostcaps[extw];
break; break;
} else
err = SWITCH_ERR;
} }
if (err)
return err;
if (mmc->card_caps & MMC_MODE_HS) { if (mmc->card_caps & MMC_MODE_HS) {
if (mmc->card_caps & MMC_MODE_HS_52MHz) if (mmc->card_caps & MMC_MODE_HS_52MHz)
mmc->tran_speed = 52000000; mmc->tran_speed = 52000000;
@ -1161,6 +1188,12 @@ static int mmc_startup(struct mmc *mmc)
mmc_set_clock(mmc, mmc->tran_speed); mmc_set_clock(mmc, mmc->tran_speed);
/* Fix the block length for DDR mode */
if (mmc->ddr_mode) {
mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
}
/* fill in device description */ /* fill in device description */
mmc->block_dev.lun = 0; mmc->block_dev.lun = 0;
mmc->block_dev.type = 0; mmc->block_dev.type = 0;
@ -1306,6 +1339,7 @@ int mmc_start_init(struct mmc *mmc)
if (err) if (err)
return err; return err;
mmc->ddr_mode = 0;
mmc_set_bus_width(mmc, 1); mmc_set_bus_width(mmc, 1);
mmc_set_clock(mmc, 1); mmc_set_clock(mmc, 1);
@ -1408,8 +1442,11 @@ void print_mmc_devices(char separator)
printf("%s: %d", m->cfg->name, m->block_dev.dev); printf("%s: %d", m->cfg->name, m->block_dev.dev);
if (entry->next != &mmc_devices) if (entry->next != &mmc_devices) {
printf("%c ", separator); printf("%c", separator);
if (separator != '\n')
puts (" ");
}
} }
printf("\n"); printf("\n");

@ -31,6 +31,7 @@
#define MMC_VERSION_4_3 (MMC_VERSION_MMC | 0x403) #define MMC_VERSION_4_3 (MMC_VERSION_MMC | 0x403)
#define MMC_VERSION_4_41 (MMC_VERSION_MMC | 0x429) #define MMC_VERSION_4_41 (MMC_VERSION_MMC | 0x429)
#define MMC_VERSION_4_5 (MMC_VERSION_MMC | 0x405) #define MMC_VERSION_4_5 (MMC_VERSION_MMC | 0x405)
#define MMC_VERSION_5_0 (MMC_VERSION_MMC | 0x500)
#define MMC_MODE_HS (1 << 0) #define MMC_MODE_HS (1 << 0)
#define MMC_MODE_HS_52MHz (1 << 1) #define MMC_MODE_HS_52MHz (1 << 1)
@ -147,6 +148,7 @@
* EXT_CSD fields * EXT_CSD fields
*/ */
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ #define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
#define EXT_CSD_PARTITION_SETTING 155 /* R/W */
#define EXT_CSD_PARTITIONS_ATTRIBUTE 156 /* R/W */ #define EXT_CSD_PARTITIONS_ATTRIBUTE 156 /* R/W */
#define EXT_CSD_PARTITIONING_SUPPORT 160 /* RO */ #define EXT_CSD_PARTITIONING_SUPPORT 160 /* RO */
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ #define EXT_CSD_RST_N_FUNCTION 162 /* R/W */
@ -197,6 +199,8 @@
#define EXT_CSD_BOOT_BUS_WIDTH_RESET(x) (x << 2) #define EXT_CSD_BOOT_BUS_WIDTH_RESET(x) (x << 2)
#define EXT_CSD_BOOT_BUS_WIDTH_WIDTH(x) (x) #define EXT_CSD_BOOT_BUS_WIDTH_WIDTH(x) (x)
#define EXT_CSD_PARTITION_SETTING_COMPLETED (1 << 0)
#define R1_ILLEGAL_COMMAND (1 << 22) #define R1_ILLEGAL_COMMAND (1 << 22)
#define R1_APP_CMD (1 << 5) #define R1_APP_CMD (1 << 5)
@ -314,6 +318,7 @@ struct mmc {
char init_in_progress; /* 1 if we have done mmc_start_init() */ char init_in_progress; /* 1 if we have done mmc_start_init() */
char preinit; /* start init as early as possible */ char preinit; /* start init as early as possible */
uint op_cond_response; /* the response byte from the last op_cond */ uint op_cond_response; /* the response byte from the last op_cond */
int ddr_mode;
}; };
int mmc_register(struct mmc *mmc); int mmc_register(struct mmc *mmc);

Loading…
Cancel
Save