mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-11 07:34:31 +00:00
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>
This commit is contained in:
parent
06ec045fee
commit
8ac8a26304
1 changed files with 148 additions and 126 deletions
|
@ -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…
Reference in a new issue