mmc: split mmc_startup()

No functionnal change here. The function is really big and can be split.
The part related to bus configuration are put in 2 separate functions: one
for MMC and one for SD.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
master
Jean-Jacques Hiblot 7 years ago committed by Jaehoon Chung
parent 06ec045fee
commit 8ac8a26304
  1. 274
      drivers/mmc/mmc.c

@ -1103,6 +1103,152 @@ static void mmc_set_bus_width(struct mmc *mmc, uint width)
mmc_set_ios(mmc);
}
static int sd_select_bus_freq_width(struct mmc *mmc)
{
int err;
struct mmc_cmd cmd;
err = sd_change_freq(mmc);
if (err)
return err;
/* Restrict card's capabilities by what the host can do */
mmc->card_caps &= mmc->cfg->host_caps;
if (mmc->card_caps & MMC_MODE_4BIT) {
cmd.cmdidx = MMC_CMD_APP_CMD;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = mmc->rca << 16;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
return err;
cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = 2;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
return err;
mmc_set_bus_width(mmc, 4);
}
err = sd_read_ssr(mmc);
if (err)
return err;
if (mmc->card_caps & MMC_MODE_HS)
mmc->tran_speed = 50000000;
else
mmc->tran_speed = 25000000;
return 0;
}
static int mmc_select_bus_freq_width(struct mmc *mmc, const u8 *ext_csd)
{
ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
/* An array of possible bus widths in order of preference */
static const unsigned int ext_csd_bits[] = {
EXT_CSD_DDR_BUS_WIDTH_8,
EXT_CSD_DDR_BUS_WIDTH_4,
EXT_CSD_BUS_WIDTH_8,
EXT_CSD_BUS_WIDTH_4,
EXT_CSD_BUS_WIDTH_1,
};
/* An array to map CSD bus widths to host cap bits */
static const unsigned int ext_to_hostcaps[] = {
[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,
};
/* An array to map chosen bus width to an integer */
static const unsigned int widths[] = {
8, 4, 8, 4, 1,
};
int err;
int idx;
err = mmc_change_freq(mmc);
if (err)
return err;
/* Restrict card's capabilities by what the host can do */
mmc->card_caps &= mmc->cfg->host_caps;
/* Only version 4 of MMC supports wider bus widths */
if (mmc->version < MMC_VERSION_4)
return 0;
for (idx = 0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
unsigned int extw = ext_csd_bits[idx];
unsigned int caps = ext_to_hostcaps[extw];
/*
* If the bus width is still not changed,
* don't try to set the default again.
* Otherwise, recover from switch attempts
* by switching to 1-bit bus width.
*/
if (extw == EXT_CSD_BUS_WIDTH_1 &&
mmc->bus_width == 1) {
err = 0;
break;
}
/*
* Check to make sure the card and controller support
* these capabilities
*/
if ((mmc->card_caps & caps) != caps)
continue;
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH, extw);
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 (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;
err = -EBADMSG;
}
if (err)
return err;
if (mmc->card_caps & MMC_MODE_HS) {
if (mmc->card_caps & MMC_MODE_HS_52MHz)
mmc->tran_speed = 52000000;
else
mmc->tran_speed = 26000000;
}
return err;
}
static int mmc_startup(struct mmc *mmc)
{
int err, i;
@ -1110,7 +1256,6 @@ static int mmc_startup(struct mmc *mmc)
u64 cmult, csize, capacity;
struct mmc_cmd cmd;
ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
bool has_parts = false;
bool part_completed;
struct blk_desc *bdesc;
@ -1415,136 +1560,13 @@ static int mmc_startup(struct mmc *mmc)
return err;
if (IS_SD(mmc))
err = sd_change_freq(mmc);
err = sd_select_bus_freq_width(mmc);
else
err = mmc_change_freq(mmc);
err = mmc_select_bus_freq_width(mmc, ext_csd);
if (err)
return err;
/* Restrict card's capabilities by what the host can do */
mmc->card_caps &= mmc->cfg->host_caps;
if (IS_SD(mmc)) {
if (mmc->card_caps & MMC_MODE_4BIT) {
cmd.cmdidx = MMC_CMD_APP_CMD;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = mmc->rca << 16;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
return err;
cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = 2;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
return err;
mmc_set_bus_width(mmc, 4);
}
err = sd_read_ssr(mmc);
if (err)
return err;
if (mmc->card_caps & MMC_MODE_HS)
mmc->tran_speed = 50000000;
else
mmc->tran_speed = 25000000;
} else if (mmc->version >= MMC_VERSION_4) {
/* Only version 4 of MMC supports wider bus widths */
int idx;
/* An array of possible bus widths in order of preference */
static unsigned ext_csd_bits[] = {
EXT_CSD_DDR_BUS_WIDTH_8,
EXT_CSD_DDR_BUS_WIDTH_4,
EXT_CSD_BUS_WIDTH_8,
EXT_CSD_BUS_WIDTH_4,
EXT_CSD_BUS_WIDTH_1,
};
/* 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 | 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,
};
/* An array to map chosen bus width to an integer */
static unsigned widths[] = {
8, 4, 8, 4, 1,
};
for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
unsigned int extw = ext_csd_bits[idx];
unsigned int caps = ext_to_hostcaps[extw];
/*
* If the bus width is still not changed,
* don't try to set the default again.
* Otherwise, recover from switch attempts
* by switching to 1-bit bus width.
*/
if (extw == EXT_CSD_BUS_WIDTH_1 &&
mmc->bus_width == 1) {
err = 0;
break;
}
/*
* Check to make sure the card and controller support
* these capabilities
*/
if ((mmc->card_caps & caps) != caps)
continue;
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH, extw);
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 (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 = -EBADMSG;
}
if (err)
return err;
if (mmc->card_caps & MMC_MODE_HS) {
if (mmc->card_caps & MMC_MODE_HS_52MHz)
mmc->tran_speed = 52000000;
else
mmc->tran_speed = 26000000;
}
}
mmc_set_clock(mmc, mmc->tran_speed);
/* Fix the block length for DDR mode */

Loading…
Cancel
Save