Hi,

On 11/26/2014 12:01 AM, Alex Lemberg wrote:
> In this patch driver should recognize if eMMC device (Rev >=5.0)
> was left in PRE_SOLDERING_POST_WRITES (0x02) state, and switch
> it to NORMAL (0x00).
> PRE_SOLDERING_POST_WRITES (0x02) state - represents a state
> where the device is in production process and the
> host (usually programmer) completed loading the content
> to the device.
> The host (usually programmer) sets the device to this state after
> loading the content and just before soldering.
> After soldering the device to the real host (not programmer),
> the device should be switched to NORMAL (0x00) mode.
> The NORMAL (0x00) mode of PSA register represents a state in
> which the device is running in the field and uses regular operations.
> Leaving device in PRE_SOLDERING_POST_WRITES (0x02) might cause
> unexpected behaviour of eMMC device.
> 
> More details about PSA feature can be found in eMMC5.0 JEDEC spec 
> (JESD84-B50.pdf):
> http://www.jedec.org/standards-documents/technology-focus-areas/flash-memory-ssds-ufs-emmc/e-mmc
> 
> Signed-off-by: Alex Lemberg <alex.lemb...@sandisk.com>
> ---
> Changes in v2:
>  - Remove typo in patch code
> ---
>  drivers/mmc/core/mmc.c   | 28 ++++++++++++++++++++++++++++
>  include/linux/mmc/card.h |  2 ++
>  include/linux/mmc/mmc.h  |  8 ++++++++
>  3 files changed, 38 insertions(+)
> 
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 02ad792..3923c90 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -571,6 +571,16 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 
> *ext_csd)
>               card->ext_csd.ffu_capable =
>                       (ext_csd[EXT_CSD_SUPPORTED_MODE] & 0x1) &&
>                       !(ext_csd[EXT_CSD_FW_CONFIG] & 0x1);
> +             card->ext_csd.psa =
> +                     ext_csd[EXT_CSD_PSA];
> +             if (ext_csd[EXT_CSD_PSA_TIMEOUT] > 0) {
> +                     card->ext_csd.psa_timeout =
> +                             100 *
> +                             (1 << ext_csd[EXT_CSD_PSA_TIMEOUT]);
> +             } else {
> +                     pr_warn("%s: EXT_CSD PSA Timeout is zero\n",
> +                                     mmc_hostname(card->host));

I remembered Ulf's previous comment. Did you check it?

> +             }
>       }
>  out:
>       return err;
> @@ -1331,6 +1341,24 @@ static int mmc_init_card(struct mmc_host *host, u32 
> ocr,
>               mmc_set_dsr(host);
>  
>       /*
> +      * eMMC v5.0 or later
> +      * and Production State Awareness state is
> +      * EXT_CSD_PSA_POST_SOLDERING_WRITES (0x02)
> +      * The host should set the device to NORMAL mode
> +      */
> +     if ((card->ext_csd.rev >= 7) &&
> +             (card->ext_csd.psa == EXT_CSD_PSA_POST_SOLDERING_WRITES)) {

Is it right? how did you get "revision"?

> +             unsigned int timeout;
> +
> +             timeout = DIV_ROUND_UP(card->ext_csd.psa_timeout, 1000);
> +             card->ext_csd.psa = EXT_CSD_PSA_NORMAL;

Why did card->ext_csd.psa assign to EXT_CSD_PSA_NORMAL as hard-coding?

> +             err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> +                     EXT_CSD_PSA, card->ext_csd.psa, timeout);
> +             if (err && err != -EBADMSG)
> +                     goto free_card;
> +     }
> +
> +     /*
>        * Select card, as all following commands rely on that.
>        */
>       if (!mmc_host_is_spi(host)) {
> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
> index 4d69c00..09ac3b0 100644
> --- a/include/linux/mmc/card.h
> +++ b/include/linux/mmc/card.h
> @@ -60,9 +60,11 @@ struct mmc_ext_csd {
>       u8                      packed_event_en;
>       unsigned int            part_time;              /* Units: ms */
>       unsigned int            sa_timeout;             /* Units: 100ns */
> +     unsigned int            psa_timeout;            /* Units: 100us */
>       unsigned int            generic_cmd6_time;      /* Units: 10ms */
>       unsigned int            power_off_longtime;     /* Units: ms */
>       u8                      power_off_notification; /* state */
> +     u8                      psa; /* production state awareness */
>       unsigned int            hs_max_dtr;
>       unsigned int            hs200_max_dtr;
>  #define MMC_HIGH_26_MAX_DTR  26000000
> diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
> index 49ad7a9..458814d 100644
> --- a/include/linux/mmc/mmc.h
> +++ b/include/linux/mmc/mmc.h
> @@ -285,6 +285,7 @@ struct _mmc_csd {
>  #define EXT_CSD_EXP_EVENTS_STATUS    54      /* RO, 2 bytes */
>  #define EXT_CSD_EXP_EVENTS_CTRL              56      /* R/W, 2 bytes */
>  #define EXT_CSD_DATA_SECTOR_SIZE     61      /* R */
> +#define EXT_CSD_PSA                  133     /* R/W/E */
>  #define EXT_CSD_GP_SIZE_MULT         143     /* R/W */
>  #define EXT_CSD_PARTITION_SETTING_COMPLETED 155      /* R/W */
>  #define EXT_CSD_PARTITION_ATTRIBUTE  156     /* R/W */
> @@ -315,6 +316,7 @@ struct _mmc_csd {
>  #define EXT_CSD_PWR_CL_26_360                203     /* RO */
>  #define EXT_CSD_SEC_CNT                      212     /* RO, 4 bytes */
>  #define EXT_CSD_S_A_TIMEOUT          217     /* RO */
> +#define EXT_CSD_PSA_TIMEOUT          218     /* RO */
>  #define EXT_CSD_REL_WR_SEC_C         222     /* RO */
>  #define EXT_CSD_HC_WP_GRP_SIZE               221     /* RO */
>  #define EXT_CSD_ERASE_TIMEOUT_MULT   223     /* RO */
> @@ -433,6 +435,12 @@ struct _mmc_csd {
>  #define EXT_CSD_BKOPS_LEVEL_2                0x2
>  
>  /*
> + * PRODUCTION STATE AWARENESS fields
> + */
> +#define EXT_CSD_PSA_NORMAL           0x00
> +#define EXT_CSD_PSA_POST_SOLDERING_WRITES    0x02
> +
> +/*
>   * MMC_SWITCH access modes
>   */
>  
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to