diff mbox

[v4,3/5] mmc: step power class after final selection of bus mode

Message ID 000301cf48e2$92a77310$b7f65930$%jun@samsung.com (mailing list archive)
State New, archived
Headers show

Commit Message

Seungwon Jeon March 26, 2014, 11 a.m. UTC
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@samsung.com>
Tested-by: Jaehoon Chung <jh80.chung@samsung.com>
Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
---
 drivers/mmc/core/mmc.c |   96 +++++++++++++++++++++++++++--------------------
 1 files changed, 55 insertions(+), 41 deletions(-)

Comments

Ulf Hansson March 28, 2014, 8:43 a.m. UTC | #1
On 26 March 2014 12:00, Seungwon Jeon <tgih.jun@samsung.com> 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@samsung.com>
> Tested-by: Jaehoon Chung <jh80.chung@samsung.com>
> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>

Acked-by: Ulf Hansson <ulf.hansson@linaro.org>

> ---
>  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@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

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) {