On 26 March 2014 12:00, Seungwon Jeon <tgih.jun@xxxxxxxxxxx> wrote: > Power class is changed once only after selection of bus modes > including speed and bus-width finishes finally. > > Signed-off-by: Seungwon Jeon <tgih.jun@xxxxxxxxxxx> > Tested-by: Jaehoon Chung <jh80.chung@xxxxxxxxxxx> > Acked-by: Jaehoon Chung <jh80.chung@xxxxxxxxxxx> Acked-by: Ulf Hansson <ulf.hansson@xxxxxxxxxx> > --- > drivers/mmc/core/mmc.c | 96 +++++++++++++++++++++++++++-------------------- > 1 files changed, 55 insertions(+), 41 deletions(-) > > diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c > index 97f1912..480c100 100644 > --- a/drivers/mmc/core/mmc.c > +++ b/drivers/mmc/core/mmc.c > @@ -732,17 +732,13 @@ static struct device_type mmc_type = { > * extended CSD register, select it by executing the > * mmc_switch command. > */ > -static int mmc_select_powerclass(struct mmc_card *card, > - unsigned int bus_width) > +static int __mmc_select_powerclass(struct mmc_card *card, > + 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; > - struct mmc_host *host; > - > - BUG_ON(!card); > - > - host = card->host; > - BUG_ON(!host); > + int err = 0; > > /* Power class selection is supported for versions >= 4.0 */ > if (card->csd.mmca_vsn < CSD_SPEC_VER_4) > @@ -754,14 +750,14 @@ static int mmc_select_powerclass(struct mmc_card *card, > > switch (1 << host->ios.vdd) { > case MMC_VDD_165_195: > - if (host->ios.clock <= 26000000) > - pwrclass_val = card->ext_csd.raw_pwr_cl_26_195; > - else if (host->ios.clock <= 52000000) > + if (host->ios.clock <= MMC_HIGH_26_MAX_DTR) > + pwrclass_val = ext_csd->raw_pwr_cl_26_195; > + else if (host->ios.clock <= MMC_HIGH_52_MAX_DTR) > pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? > - card->ext_csd.raw_pwr_cl_52_195 : > - card->ext_csd.raw_pwr_cl_ddr_52_195; > - else if (host->ios.clock <= 200000000) > - pwrclass_val = card->ext_csd.raw_pwr_cl_200_195; > + ext_csd->raw_pwr_cl_52_195 : > + ext_csd->raw_pwr_cl_ddr_52_195; > + else if (host->ios.clock <= MMC_HS200_MAX_DTR) > + pwrclass_val = ext_csd->raw_pwr_cl_200_195; > break; > case MMC_VDD_27_28: > case MMC_VDD_28_29: > @@ -772,14 +768,14 @@ static int mmc_select_powerclass(struct mmc_card *card, > case MMC_VDD_33_34: > case MMC_VDD_34_35: > case MMC_VDD_35_36: > - if (host->ios.clock <= 26000000) > - pwrclass_val = card->ext_csd.raw_pwr_cl_26_360; > - else if (host->ios.clock <= 52000000) > + if (host->ios.clock <= MMC_HIGH_26_MAX_DTR) > + pwrclass_val = ext_csd->raw_pwr_cl_26_360; > + else if (host->ios.clock <= MMC_HIGH_52_MAX_DTR) > pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? > - card->ext_csd.raw_pwr_cl_52_360 : > - card->ext_csd.raw_pwr_cl_ddr_52_360; > - else if (host->ios.clock <= 200000000) > - pwrclass_val = card->ext_csd.raw_pwr_cl_200_360; > + ext_csd->raw_pwr_cl_52_360 : > + ext_csd->raw_pwr_cl_ddr_52_360; > + else if (host->ios.clock <= MMC_HS200_MAX_DTR) > + pwrclass_val = ext_csd->raw_pwr_cl_200_360; > break; > default: > pr_warning("%s: Voltage range not supported " > @@ -805,6 +801,37 @@ static int mmc_select_powerclass(struct mmc_card *card, > 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 > * if bus width set without error > @@ -1166,11 +1193,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, > > 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_warning("%s: power class selection to bus width %d" > - " failed\n", mmc_hostname(card->host), > - 1 << bus_width); > } > > /* > @@ -1199,12 +1221,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, > bus_width = bus_widths[idx]; > if (bus_width == MMC_BUS_WIDTH_1) > 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, > EXT_CSD_BUS_WIDTH, > @@ -1229,13 +1245,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, > } > > 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, > EXT_CSD_BUS_WIDTH, > ext_csd_bits[idx][1], > @@ -1273,6 +1282,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) > */ > if (card->ext_csd.hpi) { > -- > 1.7.0.4 > > -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html