host->get_mmc_clk = exynos_dwmci_get_clk;
/* Add the mmc channel to be registered with mmc core */
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 0;
flag = host->buswidth == 8 ? PINMUX_FLAG_8BIT_MODE : PINMUX_FLAG_NONE;
err = exynos_pinmux_config(host->dev_id, flag);
if (err) {
- debug("DWMMC not configure\n");
+ printf("DWMMC%d not configure\n", index);
return err;
}
/* Extract device id for each mmc channel */
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 */
host->buswidth = fdtdec_get_int(blob, node, "samsung,bus-width", 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;
}
- 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 */
base = fdtdec_get_addr(blob, node, "reg");
if (!base) {
- debug("DWMMC: Can't get base address\n");
+ printf("DWMMC%d: Can't get base address\n", host->dev_index);
return -EINVAL;
}
host->ioaddr = (void *)base;
/* Extract the timing info from the node */
err = fdtdec_get_int_array(blob, node, "samsung,timing", timing, 3);
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;
}
host = &dwmci_host[i];
err = exynos_dwmci_get_config(blob, node, host);
if (err) {
- debug("%s: failed to decode dev %d\n", __func__, i);
+ printf("%s: failed to decode dev %d\n", __func__, i);
return err;
}
{
struct mmc_cmd cmd;
- if (mmc->card_caps & MMC_MODE_DDR_52MHz)
+ if (mmc->ddr_mode)
return 0;
cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
char cardtype;
int err;
- mmc->card_caps = 0;
+ mmc->card_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
if (mmc_host_is_spi(mmc))
return 0;
/* High Speed is set, there are two types: 52MHz and 26MHz */
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_HS_52MHz | MMC_MODE_HS;
} else {
case 6:
mmc->version = MMC_VERSION_4_5;
break;
+ case 7:
+ mmc->version = MMC_VERSION_5_0;
+ break;
}
/*
mmc->erase_grp_size =
ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] *
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 {
/* Calculate the group size from the csd value. */
int erase_gsz, erase_gmul;
/* An array to map CSD bus widths to host cap bits */
static unsigned ext_to_hostcaps[] = {
- [EXT_CSD_DDR_BUS_WIDTH_4] = MMC_MODE_DDR_52MHz,
- [EXT_CSD_DDR_BUS_WIDTH_8] = MMC_MODE_DDR_52MHz,
+ [EXT_CSD_DDR_BUS_WIDTH_4] =
+ 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_8] = MMC_MODE_8BIT,
};
for (idx=0; idx < ARRAY_SIZE(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
- * this bus width, if it's more than 1
+ * Check to make sure the card and controller support
+ * these capabilities
*/
- if (extw != EXT_CSD_BUS_WIDTH_1 &&
- !(mmc->cfg->host_caps & ext_to_hostcaps[extw]))
+ if ((mmc->card_caps & caps) != caps)
continue;
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
if (err)
continue;
+ mmc->ddr_mode = (caps & MMC_MODE_DDR_52MHz) ? 1 : 0;
mmc_set_bus_width(mmc, widths[idx]);
err = mmc_send_ext_csd(mmc, test_csd);
+
+ if (err)
+ continue;
+
/* Only compare read only fields */
- if (!err && ext_csd[EXT_CSD_PARTITIONING_SUPPORT] \
- == test_csd[EXT_CSD_PARTITIONING_SUPPORT]
- && 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] \
- == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE]
- && memcmp(&ext_csd[EXT_CSD_SEC_CNT], \
- &test_csd[EXT_CSD_SEC_CNT], 4) == 0) {
-
- mmc->card_caps |= ext_to_hostcaps[extw];
+ if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT]
+ == test_csd[EXT_CSD_PARTITIONING_SUPPORT] &&
+ 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]
+ == test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] &&
+ memcmp(&ext_csd[EXT_CSD_SEC_CNT],
+ &test_csd[EXT_CSD_SEC_CNT], 4) == 0)
break;
- }
+ else
+ err = SWITCH_ERR;
}
+ if (err)
+ return err;
+
if (mmc->card_caps & MMC_MODE_HS) {
if (mmc->card_caps & MMC_MODE_HS_52MHz)
mmc->tran_speed = 52000000;
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 */
mmc->block_dev.lun = 0;
mmc->block_dev.type = 0;
if (err)
return err;
+ mmc->ddr_mode = 0;
mmc_set_bus_width(mmc, 1);
mmc_set_clock(mmc, 1);
printf("%s: %d", m->cfg->name, m->block_dev.dev);
- if (entry->next != &mmc_devices)
- printf("%c ", separator);
+ if (entry->next != &mmc_devices) {
+ printf("%c", separator);
+ if (separator != '\n')
+ puts (" ");
+ }
}
printf("\n");
#define MMC_VERSION_4_3 (MMC_VERSION_MMC | 0x403)
#define MMC_VERSION_4_41 (MMC_VERSION_MMC | 0x429)
#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_52MHz (1 << 1)
* EXT_CSD fields
*/
#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_PARTITIONING_SUPPORT 160 /* RO */
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */
#define EXT_CSD_BOOT_BUS_WIDTH_RESET(x) (x << 2)
#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_APP_CMD (1 << 5)
char init_in_progress; /* 1 if we have done mmc_start_init() */
char preinit; /* start init as early as possible */
uint op_cond_response; /* the response byte from the last op_cond */
+ int ddr_mode;
};
int mmc_register(struct mmc *mmc);