Message ID | 1366727227-29848-1-git-send-email-fredrik.soderstedt@stericsson.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi, 2013/4/23 Fredrik Soderstedt <fredrik.soderstedt@stericsson.com>: > Use the saved values in card->ext_csd when selecting power class. > By doing this the power class will be selected even if mmc_init_card > is called with oldcard != NULL, which is the case after a suspend/resume. > > Today ext_csd is NULL if mmc_init_card is called with oldcard != NULL > and power class will not be selected. > > According to the eMMC specification the POWER_CLASS value is reset after > power failure, H/W reset assertion and any CMD0 reset. > > CC: Girish K S <girish.shivananjappa@linaro.org> > Signed-off-by: Fredrik Soderstedt <fredrik.soderstedt@stericsson.com> Looks good to me! Please add my Reviewed-by: Johan Rudholm <jrudholm@gmail.com> Kind regards, Johan -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi, On 23 April 2013 19:57, Fredrik Soderstedt <fredrik.soderstedt@stericsson.com> wrote: > > Use the saved values in card->ext_csd when selecting power class. > By doing this the power class will be selected even if mmc_init_card > is called with oldcard != NULL, which is the case after a suspend/resume. > > Today ext_csd is NULL if mmc_init_card is called with oldcard != NULL > and power class will not be selected. > > According to the eMMC specification the POWER_CLASS value is reset after > power failure, H/W reset assertion and any CMD0 reset. > > CC: Girish K S <girish.shivananjappa@linaro.org> > Signed-off-by: Fredrik Soderstedt <fredrik.soderstedt@stericsson.com> > --- > > Changes since v1: > - Fix typo from card->ext_csd.raw_pwr_cl_52_360 to > card->ext_csd.raw_pwr_cl_ddr_52_360 > > drivers/mmc/core/mmc.c | 74 > ++++++++++++++++++++++++++++++++---------------- > include/linux/mmc/card.h | 10 ++++++- > 2 files changed, 59 insertions(+), 25 deletions(-) > > diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c > index 0cbd1ef..d6d957e 100644 > --- a/drivers/mmc/core/mmc.c > +++ b/drivers/mmc/core/mmc.c > @@ -461,6 +461,24 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 > *ext_csd) > */ > card->ext_csd.boot_ro_lock = ext_csd[EXT_CSD_BOOT_WP]; > card->ext_csd.boot_ro_lockable = true; > + > + /* Save power class values */ > + card->ext_csd.raw_pwr_cl_52_195 = > + ext_csd[EXT_CSD_PWR_CL_52_195]; > + card->ext_csd.raw_pwr_cl_26_195 = > + ext_csd[EXT_CSD_PWR_CL_26_195]; > + card->ext_csd.raw_pwr_cl_52_360 = > + ext_csd[EXT_CSD_PWR_CL_52_360]; > + card->ext_csd.raw_pwr_cl_26_360 = > + ext_csd[EXT_CSD_PWR_CL_26_360]; > + card->ext_csd.raw_pwr_cl_200_195 = > + ext_csd[EXT_CSD_PWR_CL_200_195]; > + card->ext_csd.raw_pwr_cl_200_360 = > + ext_csd[EXT_CSD_PWR_CL_200_360]; > + card->ext_csd.raw_pwr_cl_ddr_52_195 = > + ext_csd[EXT_CSD_PWR_CL_DDR_52_195]; > + card->ext_csd.raw_pwr_cl_ddr_52_360 = > + ext_csd[EXT_CSD_PWR_CL_DDR_52_360]; > } > > if (card->ext_csd.rev >= 5) { > @@ -607,7 +625,23 @@ static int mmc_compare_ext_csds(struct mmc_card > *card, unsigned bus_width) > (card->ext_csd.raw_sectors[2] == > bw_ext_csd[EXT_CSD_SEC_CNT + 2]) && > (card->ext_csd.raw_sectors[3] == > - bw_ext_csd[EXT_CSD_SEC_CNT + 3])); > + bw_ext_csd[EXT_CSD_SEC_CNT + 3]) && > + (card->ext_csd.raw_pwr_cl_52_195 == > + bw_ext_csd[EXT_CSD_PWR_CL_52_195]) && > + (card->ext_csd.raw_pwr_cl_26_195 == > + bw_ext_csd[EXT_CSD_PWR_CL_26_195]) && > + (card->ext_csd.raw_pwr_cl_52_360 == > + bw_ext_csd[EXT_CSD_PWR_CL_52_360]) && > + (card->ext_csd.raw_pwr_cl_26_360 == > + bw_ext_csd[EXT_CSD_PWR_CL_26_360]) && > + (card->ext_csd.raw_pwr_cl_200_195 == > + bw_ext_csd[EXT_CSD_PWR_CL_200_195]) && > + (card->ext_csd.raw_pwr_cl_200_360 == > + bw_ext_csd[EXT_CSD_PWR_CL_200_360]) && > + (card->ext_csd.raw_pwr_cl_ddr_52_195 == > + bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_195]) && > + (card->ext_csd.raw_pwr_cl_ddr_52_360 == > + bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360])); > if (err) > err = -EINVAL; > > @@ -676,11 +710,10 @@ static struct device_type mmc_type = { > * mmc_switch command. > */ > static int mmc_select_powerclass(struct mmc_card *card, > - unsigned int bus_width, u8 *ext_csd) > + unsigned int bus_width) > { > int err = 0; > - unsigned int pwrclass_val; > - unsigned int index = 0; > + unsigned int pwrclass_val = 0; > struct mmc_host *host; > > BUG_ON(!card); > @@ -688,9 +721,6 @@ static int mmc_select_powerclass(struct mmc_card > *card, > host = card->host; > BUG_ON(!host); > > - if (ext_csd == NULL) > - return 0; > - > /* Power class selection is supported for versions >= 4.0 */ > if (card->csd.mmca_vsn < CSD_SPEC_VER_4) > return 0; > @@ -702,13 +732,13 @@ static int mmc_select_powerclass(struct mmc_card > *card, > switch (1 << host->ios.vdd) { > case MMC_VDD_165_195: > if (host->ios.clock <= 26000000) > - index = EXT_CSD_PWR_CL_26_195; > + pwrclass_val = card->ext_csd.raw_pwr_cl_26_195; > else if (host->ios.clock <= 52000000) > - index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? > - EXT_CSD_PWR_CL_52_195 : > - EXT_CSD_PWR_CL_DDR_52_195; > + 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) > - index = EXT_CSD_PWR_CL_200_195; > + pwrclass_val = card->ext_csd.raw_pwr_cl_200_195; > break; > case MMC_VDD_27_28: > case MMC_VDD_28_29: > @@ -720,13 +750,13 @@ static int mmc_select_powerclass(struct mmc_card > *card, > case MMC_VDD_34_35: > case MMC_VDD_35_36: > if (host->ios.clock <= 26000000) > - index = EXT_CSD_PWR_CL_26_360; > + pwrclass_val = card->ext_csd.raw_pwr_cl_26_360; > else if (host->ios.clock <= 52000000) > - index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? > - EXT_CSD_PWR_CL_52_360 : > - EXT_CSD_PWR_CL_DDR_52_360; > + 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) > - index = EXT_CSD_PWR_CL_200_360; > + pwrclass_val = card->ext_csd.raw_pwr_cl_200_360; > break; > default: > pr_warning("%s: Voltage range not supported " > @@ -734,8 +764,6 @@ static int mmc_select_powerclass(struct mmc_card > *card, > return -EINVAL; > } > > - pwrclass_val = ext_csd[index]; > - > if (bus_width & (EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_BUS_WIDTH_8)) > pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_8BIT_MASK) > >> > EXT_CSD_PWR_CL_8BIT_SHIFT; > @@ -1131,7 +1159,7 @@ 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, ext_csd); > + 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), > @@ -1164,8 +1192,7 @@ 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], > - ext_csd); > + err = mmc_select_powerclass(card, > ext_csd_bits[idx][0]); > if (err) > pr_warning("%s: power class selection to " > "bus width %d failed\n", > @@ -1195,8 +1222,7 @@ static int mmc_init_card(struct mmc_host *host, u32 > ocr, > } > > if (!err && ddr) { > - err = mmc_select_powerclass(card, > ext_csd_bits[idx][1], > - ext_csd); > + 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", > diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h > index f31725b..6a98f32 100644 > --- a/include/linux/mmc/card.h > +++ b/include/linux/mmc/card.h > @@ -94,7 +94,11 @@ struct mmc_ext_csd { > u8 raw_ext_csd_structure; /* 194 */ > u8 raw_card_type; /* 196 */ > u8 out_of_int_time; /* 198 */ > - u8 raw_s_a_timeout; /* 217 */ > + u8 raw_pwr_cl_52_195; /* 200 */ > + u8 raw_pwr_cl_26_195; /* 201 */ > + u8 raw_pwr_cl_52_360; /* 202 */ > + u8 raw_pwr_cl_26_360; /* 203 */ > + u8 raw_s_a_timeout; /* 217 */ > u8 raw_hc_erase_gap_size; /* 221 */ > u8 raw_erase_timeout_mult; /* 223 */ > u8 raw_hc_erase_grp_size; /* 224 */ > @@ -102,6 +106,10 @@ struct mmc_ext_csd { > u8 raw_sec_erase_mult; /* 230 */ > u8 raw_sec_feature_support;/* 231 */ > u8 raw_trim_mult; /* 232 */ > + u8 raw_pwr_cl_200_195; /* 236 */ > + u8 raw_pwr_cl_200_360; /* 237 */ > + u8 raw_pwr_cl_ddr_52_195; /* 238 */ > + u8 raw_pwr_cl_ddr_52_360; /* 239 */ > u8 raw_bkops_status; /* 246 */ > u8 raw_sectors[4]; /* 212 - 4 bytes > */ > Looks good. Acked By: Girish K S <girish.shivananjappa@linaro.org> > -- > 1.8.2.1 > -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Fredrik, On Tue, Apr 23 2013, Fredrik Soderstedt wrote: > Use the saved values in card->ext_csd when selecting power class. > By doing this the power class will be selected even if mmc_init_card > is called with oldcard != NULL, which is the case after a suspend/resume. > > Today ext_csd is NULL if mmc_init_card is called with oldcard != NULL > and power class will not be selected. > > According to the eMMC specification the POWER_CLASS value is reset after > power failure, H/W reset assertion and any CMD0 reset. > > CC: Girish K S <girish.shivananjappa@linaro.org> > Signed-off-by: Fredrik Soderstedt <fredrik.soderstedt@stericsson.com> Thanks, pushed to mmc-next for 3.11. - Chris.
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 0cbd1ef..d6d957e 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -461,6 +461,24 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) */ card->ext_csd.boot_ro_lock = ext_csd[EXT_CSD_BOOT_WP]; card->ext_csd.boot_ro_lockable = true; + + /* Save power class values */ + card->ext_csd.raw_pwr_cl_52_195 = + ext_csd[EXT_CSD_PWR_CL_52_195]; + card->ext_csd.raw_pwr_cl_26_195 = + ext_csd[EXT_CSD_PWR_CL_26_195]; + card->ext_csd.raw_pwr_cl_52_360 = + ext_csd[EXT_CSD_PWR_CL_52_360]; + card->ext_csd.raw_pwr_cl_26_360 = + ext_csd[EXT_CSD_PWR_CL_26_360]; + card->ext_csd.raw_pwr_cl_200_195 = + ext_csd[EXT_CSD_PWR_CL_200_195]; + card->ext_csd.raw_pwr_cl_200_360 = + ext_csd[EXT_CSD_PWR_CL_200_360]; + card->ext_csd.raw_pwr_cl_ddr_52_195 = + ext_csd[EXT_CSD_PWR_CL_DDR_52_195]; + card->ext_csd.raw_pwr_cl_ddr_52_360 = + ext_csd[EXT_CSD_PWR_CL_DDR_52_360]; } if (card->ext_csd.rev >= 5) { @@ -607,7 +625,23 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width) (card->ext_csd.raw_sectors[2] == bw_ext_csd[EXT_CSD_SEC_CNT + 2]) && (card->ext_csd.raw_sectors[3] == - bw_ext_csd[EXT_CSD_SEC_CNT + 3])); + bw_ext_csd[EXT_CSD_SEC_CNT + 3]) && + (card->ext_csd.raw_pwr_cl_52_195 == + bw_ext_csd[EXT_CSD_PWR_CL_52_195]) && + (card->ext_csd.raw_pwr_cl_26_195 == + bw_ext_csd[EXT_CSD_PWR_CL_26_195]) && + (card->ext_csd.raw_pwr_cl_52_360 == + bw_ext_csd[EXT_CSD_PWR_CL_52_360]) && + (card->ext_csd.raw_pwr_cl_26_360 == + bw_ext_csd[EXT_CSD_PWR_CL_26_360]) && + (card->ext_csd.raw_pwr_cl_200_195 == + bw_ext_csd[EXT_CSD_PWR_CL_200_195]) && + (card->ext_csd.raw_pwr_cl_200_360 == + bw_ext_csd[EXT_CSD_PWR_CL_200_360]) && + (card->ext_csd.raw_pwr_cl_ddr_52_195 == + bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_195]) && + (card->ext_csd.raw_pwr_cl_ddr_52_360 == + bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360])); if (err) err = -EINVAL; @@ -676,11 +710,10 @@ static struct device_type mmc_type = { * mmc_switch command. */ static int mmc_select_powerclass(struct mmc_card *card, - unsigned int bus_width, u8 *ext_csd) + unsigned int bus_width) { int err = 0; - unsigned int pwrclass_val; - unsigned int index = 0; + unsigned int pwrclass_val = 0; struct mmc_host *host; BUG_ON(!card); @@ -688,9 +721,6 @@ static int mmc_select_powerclass(struct mmc_card *card, host = card->host; BUG_ON(!host); - if (ext_csd == NULL) - return 0; - /* Power class selection is supported for versions >= 4.0 */ if (card->csd.mmca_vsn < CSD_SPEC_VER_4) return 0; @@ -702,13 +732,13 @@ static int mmc_select_powerclass(struct mmc_card *card, switch (1 << host->ios.vdd) { case MMC_VDD_165_195: if (host->ios.clock <= 26000000) - index = EXT_CSD_PWR_CL_26_195; + pwrclass_val = card->ext_csd.raw_pwr_cl_26_195; else if (host->ios.clock <= 52000000) - index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? - EXT_CSD_PWR_CL_52_195 : - EXT_CSD_PWR_CL_DDR_52_195; + 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) - index = EXT_CSD_PWR_CL_200_195; + pwrclass_val = card->ext_csd.raw_pwr_cl_200_195; break; case MMC_VDD_27_28: case MMC_VDD_28_29: @@ -720,13 +750,13 @@ static int mmc_select_powerclass(struct mmc_card *card, case MMC_VDD_34_35: case MMC_VDD_35_36: if (host->ios.clock <= 26000000) - index = EXT_CSD_PWR_CL_26_360; + pwrclass_val = card->ext_csd.raw_pwr_cl_26_360; else if (host->ios.clock <= 52000000) - index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? - EXT_CSD_PWR_CL_52_360 : - EXT_CSD_PWR_CL_DDR_52_360; + 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) - index = EXT_CSD_PWR_CL_200_360; + pwrclass_val = card->ext_csd.raw_pwr_cl_200_360; break; default: pr_warning("%s: Voltage range not supported " @@ -734,8 +764,6 @@ static int mmc_select_powerclass(struct mmc_card *card, return -EINVAL; } - pwrclass_val = ext_csd[index]; - if (bus_width & (EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_BUS_WIDTH_8)) pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_8BIT_MASK) >> EXT_CSD_PWR_CL_8BIT_SHIFT; @@ -1131,7 +1159,7 @@ 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, ext_csd); + 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), @@ -1164,8 +1192,7 @@ 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], - ext_csd); + err = mmc_select_powerclass(card, ext_csd_bits[idx][0]); if (err) pr_warning("%s: power class selection to " "bus width %d failed\n", @@ -1195,8 +1222,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, } if (!err && ddr) { - err = mmc_select_powerclass(card, ext_csd_bits[idx][1], - ext_csd); + 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", diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index f31725b..6a98f32 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -94,7 +94,11 @@ struct mmc_ext_csd { u8 raw_ext_csd_structure; /* 194 */ u8 raw_card_type; /* 196 */ u8 out_of_int_time; /* 198 */ - u8 raw_s_a_timeout; /* 217 */ + u8 raw_pwr_cl_52_195; /* 200 */ + u8 raw_pwr_cl_26_195; /* 201 */ + u8 raw_pwr_cl_52_360; /* 202 */ + u8 raw_pwr_cl_26_360; /* 203 */ + u8 raw_s_a_timeout; /* 217 */ u8 raw_hc_erase_gap_size; /* 221 */ u8 raw_erase_timeout_mult; /* 223 */ u8 raw_hc_erase_grp_size; /* 224 */ @@ -102,6 +106,10 @@ struct mmc_ext_csd { u8 raw_sec_erase_mult; /* 230 */ u8 raw_sec_feature_support;/* 231 */ u8 raw_trim_mult; /* 232 */ + u8 raw_pwr_cl_200_195; /* 236 */ + u8 raw_pwr_cl_200_360; /* 237 */ + u8 raw_pwr_cl_ddr_52_195; /* 238 */ + u8 raw_pwr_cl_ddr_52_360; /* 239 */ u8 raw_bkops_status; /* 246 */ u8 raw_sectors[4]; /* 212 - 4 bytes */
Use the saved values in card->ext_csd when selecting power class. By doing this the power class will be selected even if mmc_init_card is called with oldcard != NULL, which is the case after a suspend/resume. Today ext_csd is NULL if mmc_init_card is called with oldcard != NULL and power class will not be selected. According to the eMMC specification the POWER_CLASS value is reset after power failure, H/W reset assertion and any CMD0 reset. CC: Girish K S <girish.shivananjappa@linaro.org> Signed-off-by: Fredrik Soderstedt <fredrik.soderstedt@stericsson.com> --- Changes since v1: - Fix typo from card->ext_csd.raw_pwr_cl_52_360 to card->ext_csd.raw_pwr_cl_ddr_52_360 drivers/mmc/core/mmc.c | 74 ++++++++++++++++++++++++++++++++---------------- include/linux/mmc/card.h | 10 ++++++- 2 files changed, 59 insertions(+), 25 deletions(-)