diff mbox

[V2] mmc: core: Add host capability check for power class

Message ID 000401cd0cd3$4a6be470$df43ad50$@codeaurora.org
State New
Headers show

Commit Message

Subhash Jadavani March 28, 2012, 11:09 a.m. UTC
> -----Original Message-----
> From: linux-mmc-owner@vger.kernel.org [mailto:linux-mmc-
> owner@vger.kernel.org] On Behalf Of Saugata Das
> Sent: Thursday, December 15, 2011 6:35 PM
> To: Girish K S
> Cc: linux-mmc@vger.kernel.org; patches@linaro.org; linux-samsung-
> soc@vger.kernel.org; subhashj@codeaurora.org; Chris Ball
> Subject: Re: [PATCH V2] mmc: core: Add host capability check for power
class
> 
> On 15 December 2011 16:22, Girish K S <girish.shivananjappa@linaro.org>
> wrote:
> > On 15 December 2011 15:34, Saugata Das <saugata.das@linaro.org> wrote:
> >> On 15 December 2011 09:28, Girish K S <girish.shivananjappa@linaro.org>
> wrote:
> >>> This patch adds a check whether the host supports maximum current
> >>> value obtained from the device's extended csd register for a
> >>> selected interface voltage and frequency.
> >>>
> >>> cc: Chris Ball <cjb@laptop.org>
> >>> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
> >>> ---
> >>> Changes in v2:
> >>>        deleted a unnecessary if else condition identified by subhash
> >>> J Changes in v1:
> >>>       reduced the number of comparisons as per Hein's suggestion
> >>>
> >>>  drivers/mmc/core/mmc.c   |   19 +++++++++++++++++++
> >>>  include/linux/mmc/card.h |    4 ++++
> >>>  2 files changed, 23 insertions(+), 0 deletions(-)
> >>>
> >>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index
> >>> 006e932..b9ef777 100644
> >>> --- a/drivers/mmc/core/mmc.c
> >>> +++ b/drivers/mmc/core/mmc.c
> >>> @@ -688,6 +688,25 @@ static int mmc_select_powerclass(struct
> >>> mmc_card *card,
> >>>                pwrclass_val = (pwrclass_val &
> >>> EXT_CSD_PWR_CL_4BIT_MASK) >>
> >>>                                EXT_CSD_PWR_CL_4BIT_SHIFT;
> >>>
> >>> +       if (pwrclass_val >= MMC_MAX_CURRENT_800)
> >>> +               pwrclass_val = MMC_MAX_CURRENT_800;
> >>> +       else if (pwrclass_val >= MMC_MAX_CURRENT_600)
> >>> +               pwrclass_val = MMC_MAX_CURRENT_600;
> >>> +       else if (pwrclass_val >= MMC_MAX_CURRENT_400)
> >>> +               pwrclass_val = MMC_MAX_CURRENT_400;
> >>> +       else
> >>> +               pwrclass_val = MMC_MAX_CURRENT_200;
> >>> +
> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_800) &&
> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_800))
> >>> +               pwrclass_val = MMC_MAX_CURRENT_600;
> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_600) &&
> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_600))
> >>> +               pwrclass_val = MMC_MAX_CURRENT_400;
> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_400) &&
> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_400))
> >>> +               pwrclass_val = MMC_MAX_CURRENT_200;
> >>> +
> >>>        /* If the power class is different from the default value */
> >>>        if (pwrclass_val > 0) {
> >>>                err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> >>
> >> It is not allowed to set the POWER_CLASS with any value other than
> >> what is mentioned in the PWR_CL_ff_vvv or PWR_CL_DDR_ff_vvv  for
> the
> >> corresponding frequency, voltage. That is, if PWR_CL_200_195 is 14
> >> and we want to operate at HS200 then the only value allowed for
> >> POWER_CLASS is 14. So, we need to check the PWR_CL numbers and
> choose
> >> the operating mode (HS200/DDR50/..) based on the platform capability
> >> to support the current consumption and set the corresponding
> >> POWER_CLASS value.
> >>
> >> Please refer to section 6.6.5 of the 4.5 spec.
> >
> > The upstreamed code reads the extended csd value based on the already
> > set voltage level and frequency of host. So it will get the required
> > power class value which can be set directly. Is my understanding
> > correct?
> >
> 
> It is not enough to just check the voltage level and frequency.
> Consider this example, host has capability to support
> MMC_CAP_MAX_CURRENT_400, the PWR_CL_DDR_52_360 has the value 9
> (400mA) and PWR_CL_200_360 has the value 14 (800mA). Then even though
> the host might be capable to run 200MHz clock and 3.6V, it can only enable
> DDR at 52MHz and set 9 in POWER_CLASS.
> 
> I think, in mmc_select_powerclass, we need to loop through the power
> classes of all supported modes of transfer (HS200, DDR52, ... ) and choose
the
> mode which gives maximum bandwidth but falls within host capability of
> current consumption. Then set this to POWER_CLASS byte and also use the
> same information when setting HS_TIMING in mmc_init_card.

Hi Saugata,

Does the spec mandates you to set the power class to what is needed by
frequency/voltage combination? I can't see that mentioned anywhere
explicitly in eMMC4.5 spec (if it is mentioned in spec, please let me know
section and line number). It may be still possible to set the power class
lower than what is needed by frequency/voltage combination. Say for example,
8-bit HS200 (200MHz) with high voltage cards may specify power class
(PWR_CL_200_3_6) value of 14 (800 mA) but that doesn't mean if you want the
card to work in 8-bit HS200 mode, its POWER_CLASS value must be 14 (800mA).
If host's VDD regulator is only capable of say 600mA then it may still set
the POWER_CLASS to 12 (600 mA) which should be the indication to card that
host power supply is capable of sourcing only 600mA and I would assume card
will make sure that it doesn't draw anything more than that. 

Hi Girish,

I see couple of other issues with your original power_class selection patch.
1. mmc_select_powerclass() function considers 2.7v to 3.2v VDD range as
invalid. That's not correct. Valid high voltage range is from 2.7v to 3.6v.
Is there a specific reason you have skipped the 2.7v to 3.2v VDD range? If
not, I should post following change:


2.  Currently in mmc_init_card(), power class selection is done if it's
normal (DS or HS) or DDR or HS200 card.
    If power class selection fails (mmc_select_powerclass() returns error)
for DS/HS/DDR cards, we are just printing the error and going ahead with the
rest of the initialization where as if power class selection fails for HS200
cards, we are simply aborting the  
    initialization and mark it as failed. 

   There are my points:
       1.  Power class failure must be treated in same manner for
DS/HS/DDR/HS200 cards
       2.  If you agree on first point then we need to decide whether power
class selection failure is fatal enough to abort the MMC initialization? or
we can just print the warning and go ahead with rest of the initialization
in same bus speed mode?

Regards,
Subhash

> 
> >>
> >>
> >>> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
> >>> index 9478a6b..c5e031a 100644
> >>> --- a/include/linux/mmc/card.h
> >>> +++ b/include/linux/mmc/card.h
> >>> @@ -195,6 +195,10 @@ struct mmc_part {
> >>>  #define MMC_BLK_DATA_AREA_GP   (1<<2)
> >>>  };
> >>>
> >>> +#define MMC_MAX_CURRENT_200    (0)
> >>> +#define MMC_MAX_CURRENT_400    (7)
> >>> +#define MMC_MAX_CURRENT_600    (11) #define
> MMC_MAX_CURRENT_800
> >>> +(13)
> >>>  /*
> >>>  * MMC device
> >>>  */
> >>> --
> >>> 1.7.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
> --
> 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

Comments

Girish K S March 29, 2012, 5:47 a.m. UTC | #1
On 28 March 2012 16:39, Subhash Jadavani <subhashj@codeaurora.org> wrote:
>
>
>> -----Original Message-----
>> From: linux-mmc-owner@vger.kernel.org [mailto:linux-mmc-
>> owner@vger.kernel.org] On Behalf Of Saugata Das
>> Sent: Thursday, December 15, 2011 6:35 PM
>> To: Girish K S
>> Cc: linux-mmc@vger.kernel.org; patches@linaro.org; linux-samsung-
>> soc@vger.kernel.org; subhashj@codeaurora.org; Chris Ball
>> Subject: Re: [PATCH V2] mmc: core: Add host capability check for power
> class
>>
>> On 15 December 2011 16:22, Girish K S <girish.shivananjappa@linaro.org>
>> wrote:
>> > On 15 December 2011 15:34, Saugata Das <saugata.das@linaro.org> wrote:
>> >> On 15 December 2011 09:28, Girish K S <girish.shivananjappa@linaro.org>
>> wrote:
>> >>> This patch adds a check whether the host supports maximum current
>> >>> value obtained from the device's extended csd register for a
>> >>> selected interface voltage and frequency.
>> >>>
>> >>> cc: Chris Ball <cjb@laptop.org>
>> >>> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
>> >>> ---
>> >>> Changes in v2:
>> >>>        deleted a unnecessary if else condition identified by subhash
>> >>> J Changes in v1:
>> >>>       reduced the number of comparisons as per Hein's suggestion
>> >>>
>> >>>  drivers/mmc/core/mmc.c   |   19 +++++++++++++++++++
>> >>>  include/linux/mmc/card.h |    4 ++++
>> >>>  2 files changed, 23 insertions(+), 0 deletions(-)
>> >>>
>> >>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index
>> >>> 006e932..b9ef777 100644
>> >>> --- a/drivers/mmc/core/mmc.c
>> >>> +++ b/drivers/mmc/core/mmc.c
>> >>> @@ -688,6 +688,25 @@ static int mmc_select_powerclass(struct
>> >>> mmc_card *card,
>> >>>                pwrclass_val = (pwrclass_val &
>> >>> EXT_CSD_PWR_CL_4BIT_MASK) >>
>> >>>                                EXT_CSD_PWR_CL_4BIT_SHIFT;
>> >>>
>> >>> +       if (pwrclass_val >= MMC_MAX_CURRENT_800)
>> >>> +               pwrclass_val = MMC_MAX_CURRENT_800;
>> >>> +       else if (pwrclass_val >= MMC_MAX_CURRENT_600)
>> >>> +               pwrclass_val = MMC_MAX_CURRENT_600;
>> >>> +       else if (pwrclass_val >= MMC_MAX_CURRENT_400)
>> >>> +               pwrclass_val = MMC_MAX_CURRENT_400;
>> >>> +       else
>> >>> +               pwrclass_val = MMC_MAX_CURRENT_200;
>> >>> +
>> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_800) &&
>> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_800))
>> >>> +               pwrclass_val = MMC_MAX_CURRENT_600;
>> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_600) &&
>> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_600))
>> >>> +               pwrclass_val = MMC_MAX_CURRENT_400;
>> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_400) &&
>> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_400))
>> >>> +               pwrclass_val = MMC_MAX_CURRENT_200;
>> >>> +
>> >>>        /* If the power class is different from the default value */
>> >>>        if (pwrclass_val > 0) {
>> >>>                err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>> >>
>> >> It is not allowed to set the POWER_CLASS with any value other than
>> >> what is mentioned in the PWR_CL_ff_vvv or PWR_CL_DDR_ff_vvv  for
>> the
>> >> corresponding frequency, voltage. That is, if PWR_CL_200_195 is 14
>> >> and we want to operate at HS200 then the only value allowed for
>> >> POWER_CLASS is 14. So, we need to check the PWR_CL numbers and
>> choose
>> >> the operating mode (HS200/DDR50/..) based on the platform capability
>> >> to support the current consumption and set the corresponding
>> >> POWER_CLASS value.
>> >>
>> >> Please refer to section 6.6.5 of the 4.5 spec.
>> >
>> > The upstreamed code reads the extended csd value based on the already
>> > set voltage level and frequency of host. So it will get the required
>> > power class value which can be set directly. Is my understanding
>> > correct?
>> >
>>
>> It is not enough to just check the voltage level and frequency.
>> Consider this example, host has capability to support
>> MMC_CAP_MAX_CURRENT_400, the PWR_CL_DDR_52_360 has the value 9
>> (400mA) and PWR_CL_200_360 has the value 14 (800mA). Then even though
>> the host might be capable to run 200MHz clock and 3.6V, it can only enable
>> DDR at 52MHz and set 9 in POWER_CLASS.
>>
>> I think, in mmc_select_powerclass, we need to loop through the power
>> classes of all supported modes of transfer (HS200, DDR52, ... ) and choose
> the
>> mode which gives maximum bandwidth but falls within host capability of
>> current consumption. Then set this to POWER_CLASS byte and also use the
>> same information when setting HS_TIMING in mmc_init_card.
>
> Hi Saugata,
>
> Does the spec mandates you to set the power class to what is needed by
> frequency/voltage combination? I can't see that mentioned anywhere
> explicitly in eMMC4.5 spec (if it is mentioned in spec, please let me know
> section and line number). It may be still possible to set the power class
> lower than what is needed by frequency/voltage combination. Say for example,
> 8-bit HS200 (200MHz) with high voltage cards may specify power class
> (PWR_CL_200_3_6) value of 14 (800 mA) but that doesn't mean if you want the
> card to work in 8-bit HS200 mode, its POWER_CLASS value must be 14 (800mA).
> If host's VDD regulator is only capable of say 600mA then it may still set
> the POWER_CLASS to 12 (600 mA) which should be the indication to card that
> host power supply is capable of sourcing only 600mA and I would assume card
> will make sure that it doesn't draw anything more than that.
>
> Hi Girish,
>
> I see couple of other issues with your original power_class selection patch.
> 1. mmc_select_powerclass() function considers 2.7v to 3.2v VDD range as
> invalid. That's not correct. Valid high voltage range is from 2.7v to 3.6v.
> Is there a specific reason you have skipped the 2.7v to 3.2v VDD range? If
> not, I should post following change:

can post a patch for this

>
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -626,6 +626,11 @@ static int mmc_select_powerclass(struct mmc_card *card,
>                else if (host->ios.clock <= 200000000)
>                        index = EXT_CSD_PWR_CL_200_195;
>                break;
> +       case MMC_VDD_27_28:
> +       case MMC_VDD_28_29:
> +       case MMC_VDD_29_30:
> +       case MMC_VDD_30_31:
> +       case MMC_VDD_31_32:
>        case MMC_VDD_32_33:
>        case MMC_VDD_33_34:
>        case MMC_VDD_34_35:
>
> 2.  Currently in mmc_init_card(), power class selection is done if it's
> normal (DS or HS) or DDR or HS200 card.
>    If power class selection fails (mmc_select_powerclass() returns error)
> for DS/HS/DDR cards, we are just printing the error and going ahead with the
> rest of the initialization where as if power class selection fails for HS200
> cards, we are simply aborting the
>    initialization and mark it as failed.
>
>   There are my points:
>       1.  Power class failure must be treated in same manner for
> DS/HS/DDR/HS200 cards
good find.
Yes will modify and repost for the HS200 case.

>       2.  If you agree on first point then we need to decide whether power
> class selection failure is fatal enough to abort the MMC initialization? or
> we can just print the warning and go ahead with rest of the initialization
> in same bus speed mode?

Should not be treated as fatal, should continue the initialization
with default power class

>
> Regards,
> Subhash
>
>>
>> >>
>> >>
>> >>> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
>> >>> index 9478a6b..c5e031a 100644
>> >>> --- a/include/linux/mmc/card.h
>> >>> +++ b/include/linux/mmc/card.h
>> >>> @@ -195,6 +195,10 @@ struct mmc_part {
>> >>>  #define MMC_BLK_DATA_AREA_GP   (1<<2)
>> >>>  };
>> >>>
>> >>> +#define MMC_MAX_CURRENT_200    (0)
>> >>> +#define MMC_MAX_CURRENT_400    (7)
>> >>> +#define MMC_MAX_CURRENT_600    (11) #define
>> MMC_MAX_CURRENT_800
>> >>> +(13)
>> >>>  /*
>> >>>  * MMC device
>> >>>  */
>> >>> --
>> >>> 1.7.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
>> --
>> 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
>
Girish K S March 30, 2012, 4:58 a.m. UTC | #2
On 29 March 2012 11:17, Girish K S <girish.shivananjappa@linaro.org> wrote:
> On 28 March 2012 16:39, Subhash Jadavani <subhashj@codeaurora.org> wrote:
>>
>>
>>> -----Original Message-----
>>> From: linux-mmc-owner@vger.kernel.org [mailto:linux-mmc-
>>> owner@vger.kernel.org] On Behalf Of Saugata Das
>>> Sent: Thursday, December 15, 2011 6:35 PM
>>> To: Girish K S
>>> Cc: linux-mmc@vger.kernel.org; patches@linaro.org; linux-samsung-
>>> soc@vger.kernel.org; subhashj@codeaurora.org; Chris Ball
>>> Subject: Re: [PATCH V2] mmc: core: Add host capability check for power
>> class
>>>
>>> On 15 December 2011 16:22, Girish K S <girish.shivananjappa@linaro.org>
>>> wrote:
>>> > On 15 December 2011 15:34, Saugata Das <saugata.das@linaro.org> wrote:
>>> >> On 15 December 2011 09:28, Girish K S <girish.shivananjappa@linaro.org>
>>> wrote:
>>> >>> This patch adds a check whether the host supports maximum current
>>> >>> value obtained from the device's extended csd register for a
>>> >>> selected interface voltage and frequency.
>>> >>>
>>> >>> cc: Chris Ball <cjb@laptop.org>
>>> >>> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
>>> >>> ---
>>> >>> Changes in v2:
>>> >>>        deleted a unnecessary if else condition identified by subhash
>>> >>> J Changes in v1:
>>> >>>       reduced the number of comparisons as per Hein's suggestion
>>> >>>
>>> >>>  drivers/mmc/core/mmc.c   |   19 +++++++++++++++++++
>>> >>>  include/linux/mmc/card.h |    4 ++++
>>> >>>  2 files changed, 23 insertions(+), 0 deletions(-)
>>> >>>
>>> >>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index
>>> >>> 006e932..b9ef777 100644
>>> >>> --- a/drivers/mmc/core/mmc.c
>>> >>> +++ b/drivers/mmc/core/mmc.c
>>> >>> @@ -688,6 +688,25 @@ static int mmc_select_powerclass(struct
>>> >>> mmc_card *card,
>>> >>>                pwrclass_val = (pwrclass_val &
>>> >>> EXT_CSD_PWR_CL_4BIT_MASK) >>
>>> >>>                                EXT_CSD_PWR_CL_4BIT_SHIFT;
>>> >>>
>>> >>> +       if (pwrclass_val >= MMC_MAX_CURRENT_800)
>>> >>> +               pwrclass_val = MMC_MAX_CURRENT_800;
>>> >>> +       else if (pwrclass_val >= MMC_MAX_CURRENT_600)
>>> >>> +               pwrclass_val = MMC_MAX_CURRENT_600;
>>> >>> +       else if (pwrclass_val >= MMC_MAX_CURRENT_400)
>>> >>> +               pwrclass_val = MMC_MAX_CURRENT_400;
>>> >>> +       else
>>> >>> +               pwrclass_val = MMC_MAX_CURRENT_200;
>>> >>> +
>>> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_800) &&
>>> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_800))
>>> >>> +               pwrclass_val = MMC_MAX_CURRENT_600;
>>> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_600) &&
>>> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_600))
>>> >>> +               pwrclass_val = MMC_MAX_CURRENT_400;
>>> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_400) &&
>>> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_400))
>>> >>> +               pwrclass_val = MMC_MAX_CURRENT_200;
>>> >>> +
>>> >>>        /* If the power class is different from the default value */
>>> >>>        if (pwrclass_val > 0) {
>>> >>>                err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>>> >>
>>> >> It is not allowed to set the POWER_CLASS with any value other than
>>> >> what is mentioned in the PWR_CL_ff_vvv or PWR_CL_DDR_ff_vvv  for
>>> the
>>> >> corresponding frequency, voltage. That is, if PWR_CL_200_195 is 14
>>> >> and we want to operate at HS200 then the only value allowed for
>>> >> POWER_CLASS is 14. So, we need to check the PWR_CL numbers and
>>> choose
>>> >> the operating mode (HS200/DDR50/..) based on the platform capability
>>> >> to support the current consumption and set the corresponding
>>> >> POWER_CLASS value.
>>> >>
>>> >> Please refer to section 6.6.5 of the 4.5 spec.
>>> >
>>> > The upstreamed code reads the extended csd value based on the already
>>> > set voltage level and frequency of host. So it will get the required
>>> > power class value which can be set directly. Is my understanding
>>> > correct?
>>> >
>>>
>>> It is not enough to just check the voltage level and frequency.
>>> Consider this example, host has capability to support
>>> MMC_CAP_MAX_CURRENT_400, the PWR_CL_DDR_52_360 has the value 9
>>> (400mA) and PWR_CL_200_360 has the value 14 (800mA). Then even though
>>> the host might be capable to run 200MHz clock and 3.6V, it can only enable
>>> DDR at 52MHz and set 9 in POWER_CLASS.
>>>
>>> I think, in mmc_select_powerclass, we need to loop through the power
>>> classes of all supported modes of transfer (HS200, DDR52, ... ) and choose
>> the
>>> mode which gives maximum bandwidth but falls within host capability of
>>> current consumption. Then set this to POWER_CLASS byte and also use the
>>> same information when setting HS_TIMING in mmc_init_card.
>>
>> Hi Saugata,
>>
>> Does the spec mandates you to set the power class to what is needed by
>> frequency/voltage combination? I can't see that mentioned anywhere
>> explicitly in eMMC4.5 spec (if it is mentioned in spec, please let me know
>> section and line number). It may be still possible to set the power class
>> lower than what is needed by frequency/voltage combination. Say for example,
>> 8-bit HS200 (200MHz) with high voltage cards may specify power class
>> (PWR_CL_200_3_6) value of 14 (800 mA) but that doesn't mean if you want the
>> card to work in 8-bit HS200 mode, its POWER_CLASS value must be 14 (800mA).
>> If host's VDD regulator is only capable of say 600mA then it may still set
>> the POWER_CLASS to 12 (600 mA) which should be the indication to card that
>> host power supply is capable of sourcing only 600mA and I would assume card
>> will make sure that it doesn't draw anything more than that.
>>
>> Hi Girish,
>>
>> I see couple of other issues with your original power_class selection patch.
>> 1. mmc_select_powerclass() function considers 2.7v to 3.2v VDD range as
>> invalid. That's not correct. Valid high voltage range is from 2.7v to 3.6v.
>> Is there a specific reason you have skipped the 2.7v to 3.2v VDD range? If
>> not, I should post following change:
>
> can post a patch for this
>
>>
>> --- a/drivers/mmc/core/mmc.c
>> +++ b/drivers/mmc/core/mmc.c
>> @@ -626,6 +626,11 @@ static int mmc_select_powerclass(struct mmc_card *card,
>>                else if (host->ios.clock <= 200000000)
>>                        index = EXT_CSD_PWR_CL_200_195;
>>                break;
>> +       case MMC_VDD_27_28:
>> +       case MMC_VDD_28_29:
>> +       case MMC_VDD_29_30:
>> +       case MMC_VDD_30_31:
>> +       case MMC_VDD_31_32:
>>        case MMC_VDD_32_33:
>>        case MMC_VDD_33_34:
>>        case MMC_VDD_34_35:
>>
>> 2.  Currently in mmc_init_card(), power class selection is done if it's
>> normal (DS or HS) or DDR or HS200 card.
>>    If power class selection fails (mmc_select_powerclass() returns error)
>> for DS/HS/DDR cards, we are just printing the error and going ahead with the
>> rest of the initialization where as if power class selection fails for HS200
>> cards, we are simply aborting the
>>    initialization and mark it as failed.
>>
>>   There are my points:
>>       1.  Power class failure must be treated in same manner for
>> DS/HS/DDR/HS200 cards
> good find.
> Yes will modify and repost for the HS200 case.
>
>>       2.  If you agree on first point then we need to decide whether power
>> class selection failure is fatal enough to abort the MMC initialization? or
>> we can just print the warning and go ahead with rest of the initialization
>> in same bus speed mode?
>
> Should not be treated as fatal, should continue the initialization
> with default power class
Instead of making 2 different patches, can you add this modification
in your above patch. "you need to remove only the return err;
statement"
>
>>
>> Regards,
>> Subhash
>>
>>>
>>> >>
>>> >>
>>> >>> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
>>> >>> index 9478a6b..c5e031a 100644
>>> >>> --- a/include/linux/mmc/card.h
>>> >>> +++ b/include/linux/mmc/card.h
>>> >>> @@ -195,6 +195,10 @@ struct mmc_part {
>>> >>>  #define MMC_BLK_DATA_AREA_GP   (1<<2)
>>> >>>  };
>>> >>>
>>> >>> +#define MMC_MAX_CURRENT_200    (0)
>>> >>> +#define MMC_MAX_CURRENT_400    (7)
>>> >>> +#define MMC_MAX_CURRENT_600    (11) #define
>>> MMC_MAX_CURRENT_800
>>> >>> +(13)
>>> >>>  /*
>>> >>>  * MMC device
>>> >>>  */
>>> >>> --
>>> >>> 1.7.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
>>> --
>>> 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
>>
Subhash Jadavani March 30, 2012, 5:46 a.m. UTC | #3
> -----Original Message-----
> From: linux-mmc-owner@vger.kernel.org [mailto:linux-mmc-
> owner@vger.kernel.org] On Behalf Of Girish K S
> Sent: Friday, March 30, 2012 10:29 AM
> To: Subhash Jadavani
> Cc: Saugata Das; linux-mmc@vger.kernel.org; patches@linaro.org; linux-
> samsung-soc@vger.kernel.org; Chris Ball
> Subject: Re: [PATCH V2] mmc: core: Add host capability check for power
class
> 
> On 29 March 2012 11:17, Girish K S <girish.shivananjappa@linaro.org>
wrote:
> > On 28 March 2012 16:39, Subhash Jadavani <subhashj@codeaurora.org>
> wrote:
> >>
> >>
> >>> -----Original Message-----
> >>> From: linux-mmc-owner@vger.kernel.org [mailto:linux-mmc-
> >>> owner@vger.kernel.org] On Behalf Of Saugata Das
> >>> Sent: Thursday, December 15, 2011 6:35 PM
> >>> To: Girish K S
> >>> Cc: linux-mmc@vger.kernel.org; patches@linaro.org; linux-samsung-
> >>> soc@vger.kernel.org; subhashj@codeaurora.org; Chris Ball
> >>> Subject: Re: [PATCH V2] mmc: core: Add host capability check for
> >>> power
> >> class
> >>>
> >>> On 15 December 2011 16:22, Girish K S
> >>> <girish.shivananjappa@linaro.org>
> >>> wrote:
> >>> > On 15 December 2011 15:34, Saugata Das <saugata.das@linaro.org>
> wrote:
> >>> >> On 15 December 2011 09:28, Girish K S
> >>> >> <girish.shivananjappa@linaro.org>
> >>> wrote:
> >>> >>> This patch adds a check whether the host supports maximum
> >>> >>> current value obtained from the device's extended csd register
> >>> >>> for a selected interface voltage and frequency.
> >>> >>>
> >>> >>> cc: Chris Ball <cjb@laptop.org>
> >>> >>> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
> >>> >>> ---
> >>> >>> Changes in v2:
> >>> >>>        deleted a unnecessary if else condition identified by
> >>> >>> subhash J Changes in v1:
> >>> >>>       reduced the number of comparisons as per Hein's suggestion
> >>> >>>
> >>> >>>  drivers/mmc/core/mmc.c   |   19 +++++++++++++++++++
> >>> >>>  include/linux/mmc/card.h |    4 ++++
> >>> >>>  2 files changed, 23 insertions(+), 0 deletions(-)
> >>> >>>
> >>> >>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> >>> >>> index
> >>> >>> 006e932..b9ef777 100644
> >>> >>> --- a/drivers/mmc/core/mmc.c
> >>> >>> +++ b/drivers/mmc/core/mmc.c
> >>> >>> @@ -688,6 +688,25 @@ static int mmc_select_powerclass(struct
> >>> >>> mmc_card *card,
> >>> >>>                pwrclass_val = (pwrclass_val &
> >>> >>> EXT_CSD_PWR_CL_4BIT_MASK) >>
> >>> >>>                                EXT_CSD_PWR_CL_4BIT_SHIFT;
> >>> >>>
> >>> >>> +       if (pwrclass_val >= MMC_MAX_CURRENT_800)
> >>> >>> +               pwrclass_val = MMC_MAX_CURRENT_800;
> >>> >>> +       else if (pwrclass_val >= MMC_MAX_CURRENT_600)
> >>> >>> +               pwrclass_val = MMC_MAX_CURRENT_600;
> >>> >>> +       else if (pwrclass_val >= MMC_MAX_CURRENT_400)
> >>> >>> +               pwrclass_val = MMC_MAX_CURRENT_400;
> >>> >>> +       else
> >>> >>> +               pwrclass_val = MMC_MAX_CURRENT_200;
> >>> >>> +
> >>> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_800) &&
> >>> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_800))
> >>> >>> +               pwrclass_val = MMC_MAX_CURRENT_600;
> >>> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_600) &&
> >>> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_600))
> >>> >>> +               pwrclass_val = MMC_MAX_CURRENT_400;
> >>> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_400) &&
> >>> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_400))
> >>> >>> +               pwrclass_val = MMC_MAX_CURRENT_200;
> >>> >>> +
> >>> >>>        /* If the power class is different from the default value
> >>> >>> */
> >>> >>>        if (pwrclass_val > 0) {
> >>> >>>                err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> >>> >>
> >>> >> It is not allowed to set the POWER_CLASS with any value other
> >>> >> than what is mentioned in the PWR_CL_ff_vvv or
> PWR_CL_DDR_ff_vvv
> >>> >> for
> >>> the
> >>> >> corresponding frequency, voltage. That is, if PWR_CL_200_195 is
> >>> >> 14 and we want to operate at HS200 then the only value allowed
> >>> >> for POWER_CLASS is 14. So, we need to check the PWR_CL numbers
> >>> >> and
> >>> choose
> >>> >> the operating mode (HS200/DDR50/..) based on the platform
> >>> >> capability to support the current consumption and set the
> >>> >> corresponding POWER_CLASS value.
> >>> >>
> >>> >> Please refer to section 6.6.5 of the 4.5 spec.
> >>> >
> >>> > The upstreamed code reads the extended csd value based on the
> >>> > already set voltage level and frequency of host. So it will get
> >>> > the required power class value which can be set directly. Is my
> >>> > understanding correct?
> >>> >
> >>>
> >>> It is not enough to just check the voltage level and frequency.
> >>> Consider this example, host has capability to support
> >>> MMC_CAP_MAX_CURRENT_400, the PWR_CL_DDR_52_360 has the
> value 9
> >>> (400mA) and PWR_CL_200_360 has the value 14 (800mA). Then even
> >>> though the host might be capable to run 200MHz clock and 3.6V, it
> >>> can only enable DDR at 52MHz and set 9 in POWER_CLASS.
> >>>
> >>> I think, in mmc_select_powerclass, we need to loop through the power
> >>> classes of all supported modes of transfer (HS200, DDR52, ... ) and
> >>> choose
> >> the
> >>> mode which gives maximum bandwidth but falls within host capability
> >>> of current consumption. Then set this to POWER_CLASS byte and also
> >>> use the same information when setting HS_TIMING in mmc_init_card.
> >>
> >> Hi Saugata,
> >>
> >> Does the spec mandates you to set the power class to what is needed
> >> by frequency/voltage combination? I can't see that mentioned anywhere
> >> explicitly in eMMC4.5 spec (if it is mentioned in spec, please let me
> >> know section and line number). It may be still possible to set the
> >> power class lower than what is needed by frequency/voltage
> >> combination. Say for example, 8-bit HS200 (200MHz) with high voltage
> >> cards may specify power class
> >> (PWR_CL_200_3_6) value of 14 (800 mA) but that doesn't mean if you
> >> want the card to work in 8-bit HS200 mode, its POWER_CLASS value must
> be 14 (800mA).
> >> If host's VDD regulator is only capable of say 600mA then it may
> >> still set the POWER_CLASS to 12 (600 mA) which should be the
> >> indication to card that host power supply is capable of sourcing only
> >> 600mA and I would assume card will make sure that it doesn't draw
> anything more than that.
> >>
> >> Hi Girish,
> >>
> >> I see couple of other issues with your original power_class selection
> patch.
> >> 1. mmc_select_powerclass() function considers 2.7v to 3.2v VDD range
> >> as invalid. That's not correct. Valid high voltage range is from 2.7v
to 3.6v.
> >> Is there a specific reason you have skipped the 2.7v to 3.2v VDD
> >> range? If not, I should post following change:
> >
> > can post a patch for this
> >
> >>
> >> --- a/drivers/mmc/core/mmc.c
> >> +++ b/drivers/mmc/core/mmc.c
> >> @@ -626,6 +626,11 @@ static int mmc_select_powerclass(struct
> mmc_card
> >> *card,
> >>                else if (host->ios.clock <= 200000000)
> >>                        index = EXT_CSD_PWR_CL_200_195;
> >>                break;
> >> +       case MMC_VDD_27_28:
> >> +       case MMC_VDD_28_29:
> >> +       case MMC_VDD_29_30:
> >> +       case MMC_VDD_30_31:
> >> +       case MMC_VDD_31_32:
> >>        case MMC_VDD_32_33:
> >>        case MMC_VDD_33_34:
> >>        case MMC_VDD_34_35:
> >>
> >> 2.  Currently in mmc_init_card(), power class selection is done if
> >> it's normal (DS or HS) or DDR or HS200 card.
> >>    If power class selection fails (mmc_select_powerclass() returns
> >> error) for DS/HS/DDR cards, we are just printing the error and going
> >> ahead with the rest of the initialization where as if power class
> >> selection fails for HS200 cards, we are simply aborting the
> >>    initialization and mark it as failed.
> >>
> >>   There are my points:
> >>       1.  Power class failure must be treated in same manner for
> >> DS/HS/DDR/HS200 cards
> > good find.
> > Yes will modify and repost for the HS200 case.
> >
> >>       2.  If you agree on first point then we need to decide whether
> >> power class selection failure is fatal enough to abort the MMC
> >> initialization? or we can just print the warning and go ahead with
> >> rest of the initialization in same bus speed mode?
> >
> > Should not be treated as fatal, should continue the initialization
> > with default power class
> Instead of making 2 different patches, can you add this modification in
your
> above patch. "you need to remove only the return err; statement"

No issues. I will do that.

> >
> >>
> >> Regards,
> >> Subhash
> >>
> >>>
> >>> >>
> >>> >>
> >>> >>> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
> >>> >>> index 9478a6b..c5e031a 100644
> >>> >>> --- a/include/linux/mmc/card.h
> >>> >>> +++ b/include/linux/mmc/card.h
> >>> >>> @@ -195,6 +195,10 @@ struct mmc_part {
> >>> >>>  #define MMC_BLK_DATA_AREA_GP   (1<<2)
> >>> >>>  };
> >>> >>>
> >>> >>> +#define MMC_MAX_CURRENT_200    (0) #define
> MMC_MAX_CURRENT_400
> >>> >>> +(7) #define MMC_MAX_CURRENT_600    (11) #define
> >>> MMC_MAX_CURRENT_800
> >>> >>> +(13)
> >>> >>>  /*
> >>> >>>  * MMC device
> >>> >>>  */
> >>> >>> --
> >>> >>> 1.7.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
> >>> --
> >>> 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
> >>
> --
> 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
Saugata Das April 2, 2012, 7:49 a.m. UTC | #4
On 28 March 2012 16:39, Subhash Jadavani <subhashj@codeaurora.org> wrote:
>
>
>> -----Original Message-----
>> From: linux-mmc-owner@vger.kernel.org [mailto:linux-mmc-
>> owner@vger.kernel.org] On Behalf Of Saugata Das
>> Sent: Thursday, December 15, 2011 6:35 PM
>> To: Girish K S
>> Cc: linux-mmc@vger.kernel.org; patches@linaro.org; linux-samsung-
>> soc@vger.kernel.org; subhashj@codeaurora.org; Chris Ball
>> Subject: Re: [PATCH V2] mmc: core: Add host capability check for power
> class
>>
>> On 15 December 2011 16:22, Girish K S <girish.shivananjappa@linaro.org>
>> wrote:
>> > On 15 December 2011 15:34, Saugata Das <saugata.das@linaro.org> wrote:
>> >> On 15 December 2011 09:28, Girish K S <girish.shivananjappa@linaro.org>
>> wrote:
>> >>> This patch adds a check whether the host supports maximum current
>> >>> value obtained from the device's extended csd register for a
>> >>> selected interface voltage and frequency.
>> >>>
>> >>> cc: Chris Ball <cjb@laptop.org>
>> >>> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
>> >>> ---
>> >>> Changes in v2:
>> >>>        deleted a unnecessary if else condition identified by subhash
>> >>> J Changes in v1:
>> >>>       reduced the number of comparisons as per Hein's suggestion
>> >>>
>> >>>  drivers/mmc/core/mmc.c   |   19 +++++++++++++++++++
>> >>>  include/linux/mmc/card.h |    4 ++++
>> >>>  2 files changed, 23 insertions(+), 0 deletions(-)
>> >>>
>> >>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index
>> >>> 006e932..b9ef777 100644
>> >>> --- a/drivers/mmc/core/mmc.c
>> >>> +++ b/drivers/mmc/core/mmc.c
>> >>> @@ -688,6 +688,25 @@ static int mmc_select_powerclass(struct
>> >>> mmc_card *card,
>> >>>                pwrclass_val = (pwrclass_val &
>> >>> EXT_CSD_PWR_CL_4BIT_MASK) >>
>> >>>                                EXT_CSD_PWR_CL_4BIT_SHIFT;
>> >>>
>> >>> +       if (pwrclass_val >= MMC_MAX_CURRENT_800)
>> >>> +               pwrclass_val = MMC_MAX_CURRENT_800;
>> >>> +       else if (pwrclass_val >= MMC_MAX_CURRENT_600)
>> >>> +               pwrclass_val = MMC_MAX_CURRENT_600;
>> >>> +       else if (pwrclass_val >= MMC_MAX_CURRENT_400)
>> >>> +               pwrclass_val = MMC_MAX_CURRENT_400;
>> >>> +       else
>> >>> +               pwrclass_val = MMC_MAX_CURRENT_200;
>> >>> +
>> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_800) &&
>> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_800))
>> >>> +               pwrclass_val = MMC_MAX_CURRENT_600;
>> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_600) &&
>> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_600))
>> >>> +               pwrclass_val = MMC_MAX_CURRENT_400;
>> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_400) &&
>> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_400))
>> >>> +               pwrclass_val = MMC_MAX_CURRENT_200;
>> >>> +
>> >>>        /* If the power class is different from the default value */
>> >>>        if (pwrclass_val > 0) {
>> >>>                err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>> >>
>> >> It is not allowed to set the POWER_CLASS with any value other than
>> >> what is mentioned in the PWR_CL_ff_vvv or PWR_CL_DDR_ff_vvv  for
>> the
>> >> corresponding frequency, voltage. That is, if PWR_CL_200_195 is 14
>> >> and we want to operate at HS200 then the only value allowed for
>> >> POWER_CLASS is 14. So, we need to check the PWR_CL numbers and
>> choose
>> >> the operating mode (HS200/DDR50/..) based on the platform capability
>> >> to support the current consumption and set the corresponding
>> >> POWER_CLASS value.
>> >>
>> >> Please refer to section 6.6.5 of the 4.5 spec.
>> >
>> > The upstreamed code reads the extended csd value based on the already
>> > set voltage level and frequency of host. So it will get the required
>> > power class value which can be set directly. Is my understanding
>> > correct?
>> >
>>
>> It is not enough to just check the voltage level and frequency.
>> Consider this example, host has capability to support
>> MMC_CAP_MAX_CURRENT_400, the PWR_CL_DDR_52_360 has the value 9
>> (400mA) and PWR_CL_200_360 has the value 14 (800mA). Then even though
>> the host might be capable to run 200MHz clock and 3.6V, it can only enable
>> DDR at 52MHz and set 9 in POWER_CLASS.
>>
>> I think, in mmc_select_powerclass, we need to loop through the power
>> classes of all supported modes of transfer (HS200, DDR52, ... ) and choose
> the
>> mode which gives maximum bandwidth but falls within host capability of
>> current consumption. Then set this to POWER_CLASS byte and also use the
>> same information when setting HS_TIMING in mmc_init_card.
>
> Hi Saugata,
>
> Does the spec mandates you to set the power class to what is needed by
> frequency/voltage combination? I can't see that mentioned anywhere
> explicitly in eMMC4.5 spec (if it is mentioned in spec, please let me know
> section and line number). It may be still possible to set the power class
> lower than what is needed by frequency/voltage combination. Say for example,
> 8-bit HS200 (200MHz) with high voltage cards may specify power class
> (PWR_CL_200_3_6) value of 14 (800 mA) but that doesn't mean if you want the
> card to work in 8-bit HS200 mode, its POWER_CLASS value must be 14 (800mA).
> If host's VDD regulator is only capable of say 600mA then it may still set
> the POWER_CLASS to 12 (600 mA) which should be the indication to card that
> host power supply is capable of sourcing only 600mA and I would assume card
> will make sure that it doesn't draw anything more than that.

Please refer to section 6.6.5 of MMC-4.5. It says that the valid
values are defined in the PWR_CL_ff_vvv and PWR_CL_DDR_ff_vvv. We are
allowed to set only that value, depending on the mode, to POWER_CLASS.
Any other value will result in SWITCH_ERROR.


>
> Hi Girish,
>
> I see couple of other issues with your original power_class selection patch.
> 1. mmc_select_powerclass() function considers 2.7v to 3.2v VDD range as
> invalid. That's not correct. Valid high voltage range is from 2.7v to 3.6v.
> Is there a specific reason you have skipped the 2.7v to 3.2v VDD range? If
> not, I should post following change:
>
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -626,6 +626,11 @@ static int mmc_select_powerclass(struct mmc_card *card,
>                else if (host->ios.clock <= 200000000)
>                        index = EXT_CSD_PWR_CL_200_195;
>                break;
> +       case MMC_VDD_27_28:
> +       case MMC_VDD_28_29:
> +       case MMC_VDD_29_30:
> +       case MMC_VDD_30_31:
> +       case MMC_VDD_31_32:
>        case MMC_VDD_32_33:
>        case MMC_VDD_33_34:
>        case MMC_VDD_34_35:
>
> 2.  Currently in mmc_init_card(), power class selection is done if it's
> normal (DS or HS) or DDR or HS200 card.
>    If power class selection fails (mmc_select_powerclass() returns error)
> for DS/HS/DDR cards, we are just printing the error and going ahead with the
> rest of the initialization where as if power class selection fails for HS200
> cards, we are simply aborting the
>    initialization and mark it as failed.
>
>   There are my points:
>       1.  Power class failure must be treated in same manner for
> DS/HS/DDR/HS200 cards
>       2.  If you agree on first point then we need to decide whether power
> class selection failure is fatal enough to abort the MMC initialization? or
> we can just print the warning and go ahead with rest of the initialization
> in same bus speed mode?
>
> Regards,
> Subhash
>
>>
>> >>
>> >>
>> >>> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
>> >>> index 9478a6b..c5e031a 100644
>> >>> --- a/include/linux/mmc/card.h
>> >>> +++ b/include/linux/mmc/card.h
>> >>> @@ -195,6 +195,10 @@ struct mmc_part {
>> >>>  #define MMC_BLK_DATA_AREA_GP   (1<<2)
>> >>>  };
>> >>>
>> >>> +#define MMC_MAX_CURRENT_200    (0)
>> >>> +#define MMC_MAX_CURRENT_400    (7)
>> >>> +#define MMC_MAX_CURRENT_600    (11) #define
>> MMC_MAX_CURRENT_800
>> >>> +(13)
>> >>>  /*
>> >>>  * MMC device
>> >>>  */
>> >>> --
>> >>> 1.7.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
>> --
>> 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
>
Subhash Jadavani April 2, 2012, 10:54 a.m. UTC | #5
> -----Original Message-----
> From: Saugata Das [mailto:saugata.das@linaro.org]
> Sent: Monday, April 02, 2012 1:20 PM
> To: Subhash Jadavani
> Cc: Girish K S; linux-mmc@vger.kernel.org; patches@linaro.org; linux-
> samsung-soc@vger.kernel.org; Chris Ball
> Subject: Re: [PATCH V2] mmc: core: Add host capability check for power
class
> 
> On 28 March 2012 16:39, Subhash Jadavani <subhashj@codeaurora.org>
> wrote:
> >
> >
> >> -----Original Message-----
> >> From: linux-mmc-owner@vger.kernel.org [mailto:linux-mmc-
> >> owner@vger.kernel.org] On Behalf Of Saugata Das
> >> Sent: Thursday, December 15, 2011 6:35 PM
> >> To: Girish K S
> >> Cc: linux-mmc@vger.kernel.org; patches@linaro.org; linux-samsung-
> >> soc@vger.kernel.org; subhashj@codeaurora.org; Chris Ball
> >> Subject: Re: [PATCH V2] mmc: core: Add host capability check for
> >> power
> > class
> >>
> >> On 15 December 2011 16:22, Girish K S
> >> <girish.shivananjappa@linaro.org>
> >> wrote:
> >> > On 15 December 2011 15:34, Saugata Das <saugata.das@linaro.org>
> wrote:
> >> >> On 15 December 2011 09:28, Girish K S
> >> >> <girish.shivananjappa@linaro.org>
> >> wrote:
> >> >>> This patch adds a check whether the host supports maximum current
> >> >>> value obtained from the device's extended csd register for a
> >> >>> selected interface voltage and frequency.
> >> >>>
> >> >>> cc: Chris Ball <cjb@laptop.org>
> >> >>> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
> >> >>> ---
> >> >>> Changes in v2:
> >> >>>        deleted a unnecessary if else condition identified by
> >> >>> subhash J Changes in v1:
> >> >>>       reduced the number of comparisons as per Hein's suggestion
> >> >>>
> >> >>>  drivers/mmc/core/mmc.c   |   19 +++++++++++++++++++
> >> >>>  include/linux/mmc/card.h |    4 ++++
> >> >>>  2 files changed, 23 insertions(+), 0 deletions(-)
> >> >>>
> >> >>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> >> >>> index
> >> >>> 006e932..b9ef777 100644
> >> >>> --- a/drivers/mmc/core/mmc.c
> >> >>> +++ b/drivers/mmc/core/mmc.c
> >> >>> @@ -688,6 +688,25 @@ static int mmc_select_powerclass(struct
> >> >>> mmc_card *card,
> >> >>>                pwrclass_val = (pwrclass_val &
> >> >>> EXT_CSD_PWR_CL_4BIT_MASK) >>
> >> >>>                                EXT_CSD_PWR_CL_4BIT_SHIFT;
> >> >>>
> >> >>> +       if (pwrclass_val >= MMC_MAX_CURRENT_800)
> >> >>> +               pwrclass_val = MMC_MAX_CURRENT_800;
> >> >>> +       else if (pwrclass_val >= MMC_MAX_CURRENT_600)
> >> >>> +               pwrclass_val = MMC_MAX_CURRENT_600;
> >> >>> +       else if (pwrclass_val >= MMC_MAX_CURRENT_400)
> >> >>> +               pwrclass_val = MMC_MAX_CURRENT_400;
> >> >>> +       else
> >> >>> +               pwrclass_val = MMC_MAX_CURRENT_200;
> >> >>> +
> >> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_800) &&
> >> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_800))
> >> >>> +               pwrclass_val = MMC_MAX_CURRENT_600;
> >> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_600) &&
> >> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_600))
> >> >>> +               pwrclass_val = MMC_MAX_CURRENT_400;
> >> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_400) &&
> >> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_400))
> >> >>> +               pwrclass_val = MMC_MAX_CURRENT_200;
> >> >>> +
> >> >>>        /* If the power class is different from the default value
> >> >>> */
> >> >>>        if (pwrclass_val > 0) {
> >> >>>                err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> >> >>
> >> >> It is not allowed to set the POWER_CLASS with any value other than
> >> >> what is mentioned in the PWR_CL_ff_vvv or PWR_CL_DDR_ff_vvv  for
> >> the
> >> >> corresponding frequency, voltage. That is, if PWR_CL_200_195 is 14
> >> >> and we want to operate at HS200 then the only value allowed for
> >> >> POWER_CLASS is 14. So, we need to check the PWR_CL numbers and
> >> choose
> >> >> the operating mode (HS200/DDR50/..) based on the platform
> >> >> capability to support the current consumption and set the
> >> >> corresponding POWER_CLASS value.
> >> >>
> >> >> Please refer to section 6.6.5 of the 4.5 spec.
> >> >
> >> > The upstreamed code reads the extended csd value based on the
> >> > already set voltage level and frequency of host. So it will get the
> >> > required power class value which can be set directly. Is my
> >> > understanding correct?
> >> >
> >>
> >> It is not enough to just check the voltage level and frequency.
> >> Consider this example, host has capability to support
> >> MMC_CAP_MAX_CURRENT_400, the PWR_CL_DDR_52_360 has the value
> 9
> >> (400mA) and PWR_CL_200_360 has the value 14 (800mA). Then even
> though
> >> the host might be capable to run 200MHz clock and 3.6V, it can only
> >> enable DDR at 52MHz and set 9 in POWER_CLASS.
> >>
> >> I think, in mmc_select_powerclass, we need to loop through the power
> >> classes of all supported modes of transfer (HS200, DDR52, ... ) and
> >> choose
> > the
> >> mode which gives maximum bandwidth but falls within host capability
> >> of current consumption. Then set this to POWER_CLASS byte and also
> >> use the same information when setting HS_TIMING in mmc_init_card.
> >
> > Hi Saugata,
> >
> > Does the spec mandates you to set the power class to what is needed by
> > frequency/voltage combination? I can't see that mentioned anywhere
> > explicitly in eMMC4.5 spec (if it is mentioned in spec, please let me
> > know section and line number). It may be still possible to set the
> > power class lower than what is needed by frequency/voltage
> > combination. Say for example, 8-bit HS200 (200MHz) with high voltage
> > cards may specify power class
> > (PWR_CL_200_3_6) value of 14 (800 mA) but that doesn't mean if you
> > want the card to work in 8-bit HS200 mode, its POWER_CLASS value must
> be 14 (800mA).
> > If host's VDD regulator is only capable of say 600mA then it may still
> > set the POWER_CLASS to 12 (600 mA) which should be the indication to
> > card that host power supply is capable of sourcing only 600mA and I
> > would assume card will make sure that it doesn't draw anything more than
> that.
> 
> Please refer to section 6.6.5 of MMC-4.5. It says that the valid values
are
> defined in the PWR_CL_ff_vvv and PWR_CL_DDR_ff_vvv. We are allowed to
> set only that value, depending on the mode, to POWER_CLASS.
> Any other value will result in SWITCH_ERROR.

Thanks for the details. Just curious, do you have any cards where you have
seen such SWITCH_ERROR while setting the power class?

> 
> 
> >
> > Hi Girish,
> >
> > I see couple of other issues with your original power_class selection
patch.
> > 1. mmc_select_powerclass() function considers 2.7v to 3.2v VDD range
> > as invalid. That's not correct. Valid high voltage range is from 2.7v to
3.6v.
> > Is there a specific reason you have skipped the 2.7v to 3.2v VDD
> > range? If not, I should post following change:
> >
> > --- a/drivers/mmc/core/mmc.c
> > +++ b/drivers/mmc/core/mmc.c
> > @@ -626,6 +626,11 @@ static int mmc_select_powerclass(struct mmc_card
> > *card,
> >                else if (host->ios.clock <= 200000000)
> >                        index = EXT_CSD_PWR_CL_200_195;
> >                break;
> > +       case MMC_VDD_27_28:
> > +       case MMC_VDD_28_29:
> > +       case MMC_VDD_29_30:
> > +       case MMC_VDD_30_31:
> > +       case MMC_VDD_31_32:
> >        case MMC_VDD_32_33:
> >        case MMC_VDD_33_34:
> >        case MMC_VDD_34_35:
> >
> > 2.  Currently in mmc_init_card(), power class selection is done if
> > it's normal (DS or HS) or DDR or HS200 card.
> >    If power class selection fails (mmc_select_powerclass() returns
> > error) for DS/HS/DDR cards, we are just printing the error and going
> > ahead with the rest of the initialization where as if power class
> > selection fails for HS200 cards, we are simply aborting the
> >    initialization and mark it as failed.
> >
> >   There are my points:
> >       1.  Power class failure must be treated in same manner for
> > DS/HS/DDR/HS200 cards
> >       2.  If you agree on first point then we need to decide whether
> > power class selection failure is fatal enough to abort the MMC
> > initialization? or we can just print the warning and go ahead with
> > rest of the initialization in same bus speed mode?
> >
> > Regards,
> > Subhash
> >
> >>
> >> >>
> >> >>
> >> >>> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
> >> >>> index 9478a6b..c5e031a 100644
> >> >>> --- a/include/linux/mmc/card.h
> >> >>> +++ b/include/linux/mmc/card.h
> >> >>> @@ -195,6 +195,10 @@ struct mmc_part {
> >> >>>  #define MMC_BLK_DATA_AREA_GP   (1<<2)
> >> >>>  };
> >> >>>
> >> >>> +#define MMC_MAX_CURRENT_200    (0) #define
> MMC_MAX_CURRENT_400
> >> >>> +(7) #define MMC_MAX_CURRENT_600    (11) #define
> >> MMC_MAX_CURRENT_800
> >> >>> +(13)
> >> >>>  /*
> >> >>>  * MMC device
> >> >>>  */
> >> >>> --
> >> >>> 1.7.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
> >> --
> >> 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
> >
Saugata Das April 3, 2012, 10:42 a.m. UTC | #6
On 2 April 2012 16:24, Subhash Jadavani <subhashj@codeaurora.org> wrote:
>
>
>> -----Original Message-----
>> From: Saugata Das [mailto:saugata.das@linaro.org]
>> Sent: Monday, April 02, 2012 1:20 PM
>> To: Subhash Jadavani
>> Cc: Girish K S; linux-mmc@vger.kernel.org; patches@linaro.org; linux-
>> samsung-soc@vger.kernel.org; Chris Ball
>> Subject: Re: [PATCH V2] mmc: core: Add host capability check for power
> class
>>
>> On 28 March 2012 16:39, Subhash Jadavani <subhashj@codeaurora.org>
>> wrote:
>> >
>> >
>> >> -----Original Message-----
>> >> From: linux-mmc-owner@vger.kernel.org [mailto:linux-mmc-
>> >> owner@vger.kernel.org] On Behalf Of Saugata Das
>> >> Sent: Thursday, December 15, 2011 6:35 PM
>> >> To: Girish K S
>> >> Cc: linux-mmc@vger.kernel.org; patches@linaro.org; linux-samsung-
>> >> soc@vger.kernel.org; subhashj@codeaurora.org; Chris Ball
>> >> Subject: Re: [PATCH V2] mmc: core: Add host capability check for
>> >> power
>> > class
>> >>
>> >> On 15 December 2011 16:22, Girish K S
>> >> <girish.shivananjappa@linaro.org>
>> >> wrote:
>> >> > On 15 December 2011 15:34, Saugata Das <saugata.das@linaro.org>
>> wrote:
>> >> >> On 15 December 2011 09:28, Girish K S
>> >> >> <girish.shivananjappa@linaro.org>
>> >> wrote:
>> >> >>> This patch adds a check whether the host supports maximum current
>> >> >>> value obtained from the device's extended csd register for a
>> >> >>> selected interface voltage and frequency.
>> >> >>>
>> >> >>> cc: Chris Ball <cjb@laptop.org>
>> >> >>> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
>> >> >>> ---
>> >> >>> Changes in v2:
>> >> >>>        deleted a unnecessary if else condition identified by
>> >> >>> subhash J Changes in v1:
>> >> >>>       reduced the number of comparisons as per Hein's suggestion
>> >> >>>
>> >> >>>  drivers/mmc/core/mmc.c   |   19 +++++++++++++++++++
>> >> >>>  include/linux/mmc/card.h |    4 ++++
>> >> >>>  2 files changed, 23 insertions(+), 0 deletions(-)
>> >> >>>
>> >> >>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
>> >> >>> index
>> >> >>> 006e932..b9ef777 100644
>> >> >>> --- a/drivers/mmc/core/mmc.c
>> >> >>> +++ b/drivers/mmc/core/mmc.c
>> >> >>> @@ -688,6 +688,25 @@ static int mmc_select_powerclass(struct
>> >> >>> mmc_card *card,
>> >> >>>                pwrclass_val = (pwrclass_val &
>> >> >>> EXT_CSD_PWR_CL_4BIT_MASK) >>
>> >> >>>                                EXT_CSD_PWR_CL_4BIT_SHIFT;
>> >> >>>
>> >> >>> +       if (pwrclass_val >= MMC_MAX_CURRENT_800)
>> >> >>> +               pwrclass_val = MMC_MAX_CURRENT_800;
>> >> >>> +       else if (pwrclass_val >= MMC_MAX_CURRENT_600)
>> >> >>> +               pwrclass_val = MMC_MAX_CURRENT_600;
>> >> >>> +       else if (pwrclass_val >= MMC_MAX_CURRENT_400)
>> >> >>> +               pwrclass_val = MMC_MAX_CURRENT_400;
>> >> >>> +       else
>> >> >>> +               pwrclass_val = MMC_MAX_CURRENT_200;
>> >> >>> +
>> >> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_800) &&
>> >> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_800))
>> >> >>> +               pwrclass_val = MMC_MAX_CURRENT_600;
>> >> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_600) &&
>> >> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_600))
>> >> >>> +               pwrclass_val = MMC_MAX_CURRENT_400;
>> >> >>> +       if ((pwrclass_val == MMC_MAX_CURRENT_400) &&
>> >> >>> +           !(card->host->caps & MMC_CAP_MAX_CURRENT_400))
>> >> >>> +               pwrclass_val = MMC_MAX_CURRENT_200;
>> >> >>> +
>> >> >>>        /* If the power class is different from the default value
>> >> >>> */
>> >> >>>        if (pwrclass_val > 0) {
>> >> >>>                err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>> >> >>
>> >> >> It is not allowed to set the POWER_CLASS with any value other than
>> >> >> what is mentioned in the PWR_CL_ff_vvv or PWR_CL_DDR_ff_vvv  for
>> >> the
>> >> >> corresponding frequency, voltage. That is, if PWR_CL_200_195 is 14
>> >> >> and we want to operate at HS200 then the only value allowed for
>> >> >> POWER_CLASS is 14. So, we need to check the PWR_CL numbers and
>> >> choose
>> >> >> the operating mode (HS200/DDR50/..) based on the platform
>> >> >> capability to support the current consumption and set the
>> >> >> corresponding POWER_CLASS value.
>> >> >>
>> >> >> Please refer to section 6.6.5 of the 4.5 spec.
>> >> >
>> >> > The upstreamed code reads the extended csd value based on the
>> >> > already set voltage level and frequency of host. So it will get the
>> >> > required power class value which can be set directly. Is my
>> >> > understanding correct?
>> >> >
>> >>
>> >> It is not enough to just check the voltage level and frequency.
>> >> Consider this example, host has capability to support
>> >> MMC_CAP_MAX_CURRENT_400, the PWR_CL_DDR_52_360 has the value
>> 9
>> >> (400mA) and PWR_CL_200_360 has the value 14 (800mA). Then even
>> though
>> >> the host might be capable to run 200MHz clock and 3.6V, it can only
>> >> enable DDR at 52MHz and set 9 in POWER_CLASS.
>> >>
>> >> I think, in mmc_select_powerclass, we need to loop through the power
>> >> classes of all supported modes of transfer (HS200, DDR52, ... ) and
>> >> choose
>> > the
>> >> mode which gives maximum bandwidth but falls within host capability
>> >> of current consumption. Then set this to POWER_CLASS byte and also
>> >> use the same information when setting HS_TIMING in mmc_init_card.
>> >
>> > Hi Saugata,
>> >
>> > Does the spec mandates you to set the power class to what is needed by
>> > frequency/voltage combination? I can't see that mentioned anywhere
>> > explicitly in eMMC4.5 spec (if it is mentioned in spec, please let me
>> > know section and line number). It may be still possible to set the
>> > power class lower than what is needed by frequency/voltage
>> > combination. Say for example, 8-bit HS200 (200MHz) with high voltage
>> > cards may specify power class
>> > (PWR_CL_200_3_6) value of 14 (800 mA) but that doesn't mean if you
>> > want the card to work in 8-bit HS200 mode, its POWER_CLASS value must
>> be 14 (800mA).
>> > If host's VDD regulator is only capable of say 600mA then it may still
>> > set the POWER_CLASS to 12 (600 mA) which should be the indication to
>> > card that host power supply is capable of sourcing only 600mA and I
>> > would assume card will make sure that it doesn't draw anything more than
>> that.
>>
>> Please refer to section 6.6.5 of MMC-4.5. It says that the valid values
> are
>> defined in the PWR_CL_ff_vvv and PWR_CL_DDR_ff_vvv. We are allowed to
>> set only that value, depending on the mode, to POWER_CLASS.
>> Any other value will result in SWITCH_ERROR.
>
> Thanks for the details. Just curious, do you have any cards where you have
> seen such SWITCH_ERROR while setting the power class?
>

Typically, the host design takes care of the maximum power budget
needed for the highest speed modes. So, I have not encountered such
issues so far.


>>
>>
>> >
>> > Hi Girish,
>> >
>> > I see couple of other issues with your original power_class selection
> patch.
>> > 1. mmc_select_powerclass() function considers 2.7v to 3.2v VDD range
>> > as invalid. That's not correct. Valid high voltage range is from 2.7v to
> 3.6v.
>> > Is there a specific reason you have skipped the 2.7v to 3.2v VDD
>> > range? If not, I should post following change:
>> >
>> > --- a/drivers/mmc/core/mmc.c
>> > +++ b/drivers/mmc/core/mmc.c
>> > @@ -626,6 +626,11 @@ static int mmc_select_powerclass(struct mmc_card
>> > *card,
>> >                else if (host->ios.clock <= 200000000)
>> >                        index = EXT_CSD_PWR_CL_200_195;
>> >                break;
>> > +       case MMC_VDD_27_28:
>> > +       case MMC_VDD_28_29:
>> > +       case MMC_VDD_29_30:
>> > +       case MMC_VDD_30_31:
>> > +       case MMC_VDD_31_32:
>> >        case MMC_VDD_32_33:
>> >        case MMC_VDD_33_34:
>> >        case MMC_VDD_34_35:
>> >
>> > 2.  Currently in mmc_init_card(), power class selection is done if
>> > it's normal (DS or HS) or DDR or HS200 card.
>> >    If power class selection fails (mmc_select_powerclass() returns
>> > error) for DS/HS/DDR cards, we are just printing the error and going
>> > ahead with the rest of the initialization where as if power class
>> > selection fails for HS200 cards, we are simply aborting the
>> >    initialization and mark it as failed.
>> >
>> >   There are my points:
>> >       1.  Power class failure must be treated in same manner for
>> > DS/HS/DDR/HS200 cards
>> >       2.  If you agree on first point then we need to decide whether
>> > power class selection failure is fatal enough to abort the MMC
>> > initialization? or we can just print the warning and go ahead with
>> > rest of the initialization in same bus speed mode?
>> >
>> > Regards,
>> > Subhash
>> >
>> >>
>> >> >>
>> >> >>
>> >> >>> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
>> >> >>> index 9478a6b..c5e031a 100644
>> >> >>> --- a/include/linux/mmc/card.h
>> >> >>> +++ b/include/linux/mmc/card.h
>> >> >>> @@ -195,6 +195,10 @@ struct mmc_part {
>> >> >>>  #define MMC_BLK_DATA_AREA_GP   (1<<2)
>> >> >>>  };
>> >> >>>
>> >> >>> +#define MMC_MAX_CURRENT_200    (0) #define
>> MMC_MAX_CURRENT_400
>> >> >>> +(7) #define MMC_MAX_CURRENT_600    (11) #define
>> >> MMC_MAX_CURRENT_800
>> >> >>> +(13)
>> >> >>>  /*
>> >> >>>  * MMC device
>> >> >>>  */
>> >> >>> --
>> >> >>> 1.7.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
>> >> --
>> >> 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

--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -626,6 +626,11 @@  static int mmc_select_powerclass(struct mmc_card *card,
                else if (host->ios.clock <= 200000000)
                        index = EXT_CSD_PWR_CL_200_195;
                break;
+       case MMC_VDD_27_28:
+       case MMC_VDD_28_29:
+       case MMC_VDD_29_30:
+       case MMC_VDD_30_31:
+       case MMC_VDD_31_32:
        case MMC_VDD_32_33:
        case MMC_VDD_33_34:
        case MMC_VDD_34_35: