aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFredrik Soderstedt <fredrik.soderstedt@stericsson.com>2013-04-23 10:27:07 -0400
committerChris Ball <cjb@laptop.org>2013-05-26 14:23:18 -0400
commit60443712195bbcbbff9af189bdd9d2c1ef0a5cae (patch)
tree8556da51a7cc4f852f49cca47dff38bec7bee1a6
parent07a682160866e302d696f5c76d74024d575fb79d (diff)
mmc: core: Fix select power class after resume
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. Signed-off-by: Fredrik Soderstedt <fredrik.soderstedt@stericsson.com> Reviewed-by: Johan Rudholm <jrudholm@gmail.com> Acked By: Girish K S <girish.shivananjappa@linaro.org> Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r--drivers/mmc/core/mmc.c74
-rw-r--r--include/linux/mmc/card.h10
2 files changed, 59 insertions, 25 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index dd6810eebd3f..3a69b947130b 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)
461 */ 461 */
462 card->ext_csd.boot_ro_lock = ext_csd[EXT_CSD_BOOT_WP]; 462 card->ext_csd.boot_ro_lock = ext_csd[EXT_CSD_BOOT_WP];
463 card->ext_csd.boot_ro_lockable = true; 463 card->ext_csd.boot_ro_lockable = true;
464
465 /* Save power class values */
466 card->ext_csd.raw_pwr_cl_52_195 =
467 ext_csd[EXT_CSD_PWR_CL_52_195];
468 card->ext_csd.raw_pwr_cl_26_195 =
469 ext_csd[EXT_CSD_PWR_CL_26_195];
470 card->ext_csd.raw_pwr_cl_52_360 =
471 ext_csd[EXT_CSD_PWR_CL_52_360];
472 card->ext_csd.raw_pwr_cl_26_360 =
473 ext_csd[EXT_CSD_PWR_CL_26_360];
474 card->ext_csd.raw_pwr_cl_200_195 =
475 ext_csd[EXT_CSD_PWR_CL_200_195];
476 card->ext_csd.raw_pwr_cl_200_360 =
477 ext_csd[EXT_CSD_PWR_CL_200_360];
478 card->ext_csd.raw_pwr_cl_ddr_52_195 =
479 ext_csd[EXT_CSD_PWR_CL_DDR_52_195];
480 card->ext_csd.raw_pwr_cl_ddr_52_360 =
481 ext_csd[EXT_CSD_PWR_CL_DDR_52_360];
464 } 482 }
465 483
466 if (card->ext_csd.rev >= 5) { 484 if (card->ext_csd.rev >= 5) {
@@ -607,7 +625,23 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
607 (card->ext_csd.raw_sectors[2] == 625 (card->ext_csd.raw_sectors[2] ==
608 bw_ext_csd[EXT_CSD_SEC_CNT + 2]) && 626 bw_ext_csd[EXT_CSD_SEC_CNT + 2]) &&
609 (card->ext_csd.raw_sectors[3] == 627 (card->ext_csd.raw_sectors[3] ==
610 bw_ext_csd[EXT_CSD_SEC_CNT + 3])); 628 bw_ext_csd[EXT_CSD_SEC_CNT + 3]) &&
629 (card->ext_csd.raw_pwr_cl_52_195 ==
630 bw_ext_csd[EXT_CSD_PWR_CL_52_195]) &&
631 (card->ext_csd.raw_pwr_cl_26_195 ==
632 bw_ext_csd[EXT_CSD_PWR_CL_26_195]) &&
633 (card->ext_csd.raw_pwr_cl_52_360 ==
634 bw_ext_csd[EXT_CSD_PWR_CL_52_360]) &&
635 (card->ext_csd.raw_pwr_cl_26_360 ==
636 bw_ext_csd[EXT_CSD_PWR_CL_26_360]) &&
637 (card->ext_csd.raw_pwr_cl_200_195 ==
638 bw_ext_csd[EXT_CSD_PWR_CL_200_195]) &&
639 (card->ext_csd.raw_pwr_cl_200_360 ==
640 bw_ext_csd[EXT_CSD_PWR_CL_200_360]) &&
641 (card->ext_csd.raw_pwr_cl_ddr_52_195 ==
642 bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_195]) &&
643 (card->ext_csd.raw_pwr_cl_ddr_52_360 ==
644 bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360]));
611 if (err) 645 if (err)
612 err = -EINVAL; 646 err = -EINVAL;
613 647
@@ -676,11 +710,10 @@ static struct device_type mmc_type = {
676 * mmc_switch command. 710 * mmc_switch command.
677 */ 711 */
678static int mmc_select_powerclass(struct mmc_card *card, 712static int mmc_select_powerclass(struct mmc_card *card,
679 unsigned int bus_width, u8 *ext_csd) 713 unsigned int bus_width)
680{ 714{
681 int err = 0; 715 int err = 0;
682 unsigned int pwrclass_val; 716 unsigned int pwrclass_val = 0;
683 unsigned int index = 0;
684 struct mmc_host *host; 717 struct mmc_host *host;
685 718
686 BUG_ON(!card); 719 BUG_ON(!card);
@@ -688,9 +721,6 @@ static int mmc_select_powerclass(struct mmc_card *card,
688 host = card->host; 721 host = card->host;
689 BUG_ON(!host); 722 BUG_ON(!host);
690 723
691 if (ext_csd == NULL)
692 return 0;
693
694 /* Power class selection is supported for versions >= 4.0 */ 724 /* Power class selection is supported for versions >= 4.0 */
695 if (card->csd.mmca_vsn < CSD_SPEC_VER_4) 725 if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
696 return 0; 726 return 0;
@@ -702,13 +732,13 @@ static int mmc_select_powerclass(struct mmc_card *card,
702 switch (1 << host->ios.vdd) { 732 switch (1 << host->ios.vdd) {
703 case MMC_VDD_165_195: 733 case MMC_VDD_165_195:
704 if (host->ios.clock <= 26000000) 734 if (host->ios.clock <= 26000000)
705 index = EXT_CSD_PWR_CL_26_195; 735 pwrclass_val = card->ext_csd.raw_pwr_cl_26_195;
706 else if (host->ios.clock <= 52000000) 736 else if (host->ios.clock <= 52000000)
707 index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? 737 pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
708 EXT_CSD_PWR_CL_52_195 : 738 card->ext_csd.raw_pwr_cl_52_195 :
709 EXT_CSD_PWR_CL_DDR_52_195; 739 card->ext_csd.raw_pwr_cl_ddr_52_195;
710 else if (host->ios.clock <= 200000000) 740 else if (host->ios.clock <= 200000000)
711 index = EXT_CSD_PWR_CL_200_195; 741 pwrclass_val = card->ext_csd.raw_pwr_cl_200_195;
712 break; 742 break;
713 case MMC_VDD_27_28: 743 case MMC_VDD_27_28:
714 case MMC_VDD_28_29: 744 case MMC_VDD_28_29:
@@ -720,13 +750,13 @@ static int mmc_select_powerclass(struct mmc_card *card,
720 case MMC_VDD_34_35: 750 case MMC_VDD_34_35:
721 case MMC_VDD_35_36: 751 case MMC_VDD_35_36:
722 if (host->ios.clock <= 26000000) 752 if (host->ios.clock <= 26000000)
723 index = EXT_CSD_PWR_CL_26_360; 753 pwrclass_val = card->ext_csd.raw_pwr_cl_26_360;
724 else if (host->ios.clock <= 52000000) 754 else if (host->ios.clock <= 52000000)
725 index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ? 755 pwrclass_val = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
726 EXT_CSD_PWR_CL_52_360 : 756 card->ext_csd.raw_pwr_cl_52_360 :
727 EXT_CSD_PWR_CL_DDR_52_360; 757 card->ext_csd.raw_pwr_cl_ddr_52_360;
728 else if (host->ios.clock <= 200000000) 758 else if (host->ios.clock <= 200000000)
729 index = EXT_CSD_PWR_CL_200_360; 759 pwrclass_val = card->ext_csd.raw_pwr_cl_200_360;
730 break; 760 break;
731 default: 761 default:
732 pr_warning("%s: Voltage range not supported " 762 pr_warning("%s: Voltage range not supported "
@@ -734,8 +764,6 @@ static int mmc_select_powerclass(struct mmc_card *card,
734 return -EINVAL; 764 return -EINVAL;
735 } 765 }
736 766
737 pwrclass_val = ext_csd[index];
738
739 if (bus_width & (EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_BUS_WIDTH_8)) 767 if (bus_width & (EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_BUS_WIDTH_8))
740 pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_8BIT_MASK) >> 768 pwrclass_val = (pwrclass_val & EXT_CSD_PWR_CL_8BIT_MASK) >>
741 EXT_CSD_PWR_CL_8BIT_SHIFT; 769 EXT_CSD_PWR_CL_8BIT_SHIFT;
@@ -1131,7 +1159,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
1131 1159
1132 ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? 1160 ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
1133 EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4; 1161 EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4;
1134 err = mmc_select_powerclass(card, ext_csd_bits, ext_csd); 1162 err = mmc_select_powerclass(card, ext_csd_bits);
1135 if (err) 1163 if (err)
1136 pr_warning("%s: power class selection to bus width %d" 1164 pr_warning("%s: power class selection to bus width %d"
1137 " failed\n", mmc_hostname(card->host), 1165 " failed\n", mmc_hostname(card->host),
@@ -1164,8 +1192,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
1164 bus_width = bus_widths[idx]; 1192 bus_width = bus_widths[idx];
1165 if (bus_width == MMC_BUS_WIDTH_1) 1193 if (bus_width == MMC_BUS_WIDTH_1)
1166 ddr = 0; /* no DDR for 1-bit width */ 1194 ddr = 0; /* no DDR for 1-bit width */
1167 err = mmc_select_powerclass(card, ext_csd_bits[idx][0], 1195 err = mmc_select_powerclass(card, ext_csd_bits[idx][0]);
1168 ext_csd);
1169 if (err) 1196 if (err)
1170 pr_warning("%s: power class selection to " 1197 pr_warning("%s: power class selection to "
1171 "bus width %d failed\n", 1198 "bus width %d failed\n",
@@ -1195,8 +1222,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
1195 } 1222 }
1196 1223
1197 if (!err && ddr) { 1224 if (!err && ddr) {
1198 err = mmc_select_powerclass(card, ext_csd_bits[idx][1], 1225 err = mmc_select_powerclass(card, ext_csd_bits[idx][1]);
1199 ext_csd);
1200 if (err) 1226 if (err)
1201 pr_warning("%s: power class selection to " 1227 pr_warning("%s: power class selection to "
1202 "bus width %d ddr %d failed\n", 1228 "bus width %d ddr %d failed\n",
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index f31725ba49f3..6a98f32670b8 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -94,7 +94,11 @@ struct mmc_ext_csd {
94 u8 raw_ext_csd_structure; /* 194 */ 94 u8 raw_ext_csd_structure; /* 194 */
95 u8 raw_card_type; /* 196 */ 95 u8 raw_card_type; /* 196 */
96 u8 out_of_int_time; /* 198 */ 96 u8 out_of_int_time; /* 198 */
97 u8 raw_s_a_timeout; /* 217 */ 97 u8 raw_pwr_cl_52_195; /* 200 */
98 u8 raw_pwr_cl_26_195; /* 201 */
99 u8 raw_pwr_cl_52_360; /* 202 */
100 u8 raw_pwr_cl_26_360; /* 203 */
101 u8 raw_s_a_timeout; /* 217 */
98 u8 raw_hc_erase_gap_size; /* 221 */ 102 u8 raw_hc_erase_gap_size; /* 221 */
99 u8 raw_erase_timeout_mult; /* 223 */ 103 u8 raw_erase_timeout_mult; /* 223 */
100 u8 raw_hc_erase_grp_size; /* 224 */ 104 u8 raw_hc_erase_grp_size; /* 224 */
@@ -102,6 +106,10 @@ struct mmc_ext_csd {
102 u8 raw_sec_erase_mult; /* 230 */ 106 u8 raw_sec_erase_mult; /* 230 */
103 u8 raw_sec_feature_support;/* 231 */ 107 u8 raw_sec_feature_support;/* 231 */
104 u8 raw_trim_mult; /* 232 */ 108 u8 raw_trim_mult; /* 232 */
109 u8 raw_pwr_cl_200_195; /* 236 */
110 u8 raw_pwr_cl_200_360; /* 237 */
111 u8 raw_pwr_cl_ddr_52_195; /* 238 */
112 u8 raw_pwr_cl_ddr_52_360; /* 239 */
105 u8 raw_bkops_status; /* 246 */ 113 u8 raw_bkops_status; /* 246 */
106 u8 raw_sectors[4]; /* 212 - 4 bytes */ 114 u8 raw_sectors[4]; /* 212 - 4 bytes */
107 115