Commit 2385049d authored by Seungwon Jeon's avatar Seungwon Jeon Committed by Chris Ball

mmc: step power class after final selection of bus mode

Power class is changed once only after selection of bus modes
including speed and bus-width finishes finally.
Signed-off-by: default avatarSeungwon Jeon <tgih.jun@samsung.com>
Tested-by: default avatarJaehoon Chung <jh80.chung@samsung.com>
Acked-by: default avatarJaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Signed-off-by: default avatarChris Ball <chris@printf.net>
parent 2415c0ef
...@@ -724,17 +724,13 @@ static struct device_type mmc_type = { ...@@ -724,17 +724,13 @@ static struct device_type mmc_type = {
* extended CSD register, select it by executing the * extended CSD register, select it by executing the
* mmc_switch command. * mmc_switch command.
*/ */
static int mmc_select_powerclass(struct mmc_card *card, static int __mmc_select_powerclass(struct mmc_card *card,
unsigned int bus_width) unsigned int bus_width)
{ {
int err = 0; struct mmc_host *host = card->host;
struct mmc_ext_csd *ext_csd = &card->ext_csd;
unsigned int pwrclass_val = 0; unsigned int pwrclass_val = 0;
struct mmc_host *host; int err = 0;
BUG_ON(!card);
host = card->host;
BUG_ON(!host);
/* Power class selection is supported for versions >= 4.0 */ /* Power class selection is supported for versions >= 4.0 */
if (card->csd.mmca_vsn < CSD_SPEC_VER_4) if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
...@@ -746,14 +742,14 @@ static int mmc_select_powerclass(struct mmc_card *card, ...@@ -746,14 +742,14 @@ static int mmc_select_powerclass(struct mmc_card *card,
switch (1 << host->ios.vdd) { switch (1 << host->ios.vdd) {
case MMC_VDD_165_195: case MMC_VDD_165_195:
if (host->ios.clock <= 26000000) if (host->ios.clock <= MMC_HIGH_26_MAX_DTR)
pwrclass_val = card->ext_csd.raw_pwr_cl_26_195; pwrclass_val = ext_csd->raw_pwr_cl_26_195;
else if (host->ios.clock <= 52000000) else if (host->ios.clock <= MMC_HIGH_52_MAX_DTR)
pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
card->ext_csd.raw_pwr_cl_52_195 : ext_csd->raw_pwr_cl_52_195 :
card->ext_csd.raw_pwr_cl_ddr_52_195; ext_csd->raw_pwr_cl_ddr_52_195;
else if (host->ios.clock <= 200000000) else if (host->ios.clock <= MMC_HS200_MAX_DTR)
pwrclass_val = card->ext_csd.raw_pwr_cl_200_195; pwrclass_val = ext_csd->raw_pwr_cl_200_195;
break; break;
case MMC_VDD_27_28: case MMC_VDD_27_28:
case MMC_VDD_28_29: case MMC_VDD_28_29:
...@@ -764,14 +760,14 @@ static int mmc_select_powerclass(struct mmc_card *card, ...@@ -764,14 +760,14 @@ static int mmc_select_powerclass(struct mmc_card *card,
case MMC_VDD_33_34: case MMC_VDD_33_34:
case MMC_VDD_34_35: case MMC_VDD_34_35:
case MMC_VDD_35_36: case MMC_VDD_35_36:
if (host->ios.clock <= 26000000) if (host->ios.clock <= MMC_HIGH_26_MAX_DTR)
pwrclass_val = card->ext_csd.raw_pwr_cl_26_360; pwrclass_val = ext_csd->raw_pwr_cl_26_360;
else if (host->ios.clock <= 52000000) else if (host->ios.clock <= MMC_HIGH_52_MAX_DTR)
pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
card->ext_csd.raw_pwr_cl_52_360 : ext_csd->raw_pwr_cl_52_360 :
card->ext_csd.raw_pwr_cl_ddr_52_360; ext_csd->raw_pwr_cl_ddr_52_360;
else if (host->ios.clock <= 200000000) else if (host->ios.clock <= MMC_HS200_MAX_DTR)
pwrclass_val = card->ext_csd.raw_pwr_cl_200_360; pwrclass_val = ext_csd->raw_pwr_cl_200_360;
break; break;
default: default:
pr_warning("%s: Voltage range not supported " pr_warning("%s: Voltage range not supported "
...@@ -797,6 +793,37 @@ static int mmc_select_powerclass(struct mmc_card *card, ...@@ -797,6 +793,37 @@ static int mmc_select_powerclass(struct mmc_card *card,
return err; return err;
} }
static int mmc_select_powerclass(struct mmc_card *card)
{
struct mmc_host *host = card->host;
u32 bus_width, ext_csd_bits;
int err, ddr;
/* Power class selection is supported for versions >= 4.0 */
if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
return 0;
bus_width = host->ios.bus_width;
/* Power class values are defined only for 4/8 bit bus */
if (bus_width == MMC_BUS_WIDTH_1)
return 0;
ddr = card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
if (ddr)
ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
EXT_CSD_DDR_BUS_WIDTH_8 : EXT_CSD_DDR_BUS_WIDTH_4;
else
ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4;
err = __mmc_select_powerclass(card, ext_csd_bits);
if (err)
pr_warn("%s: power class selection to bus width %d ddr %d failed\n",
mmc_hostname(host), 1 << bus_width, ddr);
return err;
}
/* /*
* Selects the desired buswidth and switch to the HS200 mode * Selects the desired buswidth and switch to the HS200 mode
* if bus width set without error * if bus width set without error
...@@ -1158,11 +1185,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, ...@@ -1158,11 +1185,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4; EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4;
err = mmc_select_powerclass(card, ext_csd_bits);
if (err)
pr_warning("%s: power class selection to bus width %d"
" failed\n", mmc_hostname(card->host),
1 << bus_width);
} }
/* /*
...@@ -1191,12 +1213,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, ...@@ -1191,12 +1213,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
bus_width = bus_widths[idx]; bus_width = bus_widths[idx];
if (bus_width == MMC_BUS_WIDTH_1) if (bus_width == MMC_BUS_WIDTH_1)
ddr = 0; /* no DDR for 1-bit width */ ddr = 0; /* no DDR for 1-bit width */
err = mmc_select_powerclass(card, ext_csd_bits[idx][0]);
if (err)
pr_warning("%s: power class selection to "
"bus width %d failed\n",
mmc_hostname(card->host),
1 << bus_width);
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH,
...@@ -1221,13 +1237,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, ...@@ -1221,13 +1237,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
} }
if (!err && ddr) { if (!err && ddr) {
err = mmc_select_powerclass(card, ext_csd_bits[idx][1]);
if (err)
pr_warning("%s: power class selection to "
"bus width %d ddr %d failed\n",
mmc_hostname(card->host),
1 << bus_width, ddr);
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH,
ext_csd_bits[idx][1], ext_csd_bits[idx][1],
...@@ -1264,6 +1273,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, ...@@ -1264,6 +1273,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
} }
} }
/*
* Choose the power class with selected bus interface
*/
mmc_select_powerclass(card);
/* /*
* Enable HPI feature (if supported) * Enable HPI feature (if supported)
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment