@@ -571,6 +571,29 @@ 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);
+
+ /*
+ * PSA ext_csd parsing
+ * Note: Only Manual mode needs to be supported
+ */
+ card->ext_csd.psa_enablement =
+ (ext_csd[EXT_CSD_PSA_ENABLEMENT] & 1);
+ if (card->ext_csd.psa_enablement) {
+ 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));
+ }
+ } else {
+ card->ext_csd.psa = EXT_CSD_PSA_NORMAL;
+ card->ext_csd.psa_timeout = 0;
+ }
+
}
out:
return err;
@@ -1358,6 +1381,24 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
}
/*
+ * 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_enablement) &&
+ (card->ext_csd.psa == EXT_CSD_PSA_POST_SOLDERING_WRITES)) {
+ unsigned int timeout;
+
+ timeout = DIV_ROUND_UP(card->ext_csd.psa_timeout, 1000);
+ card->ext_csd.psa = EXT_CSD_PSA_NORMAL;
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_PSA, card->ext_csd.psa, timeout);
+ if (err && err != -EBADMSG)
+ goto free_card;
+ }
+
+ /*
* If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF
* bit. This bit will be lost every time after a reset or power off.
*/
@@ -60,9 +60,12 @@ struct mmc_ext_csd {
u8 packed_event_en;
unsigned int part_time; /* Units: ms */
unsigned int sa_timeout; /* Units: 100ns */
- unsigned int generic_cmd6_time; /* Units: 10ms */
+ 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_enablement; /* production state awareness enablement*/
+ u8 psa; /* production state awareness */
unsigned int hs_max_dtr;
unsigned int hs200_max_dtr;
#define MMC_HIGH_26_MAX_DTR 26000000
@@ -277,6 +277,7 @@ struct _mmc_csd {
* EXT_CSD fields
*/
+#define EXT_CSD_PSA_ENABLEMENT 17 /* RO */
#define EXT_CSD_FLUSH_CACHE 32 /* W */
#define EXT_CSD_CACHE_CTRL 33 /* R/W */
#define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */
@@ -285,6 +286,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 +317,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 */
@@ -428,6 +431,12 @@ struct _mmc_csd {
#define EXT_CSD_PACKED_INDEXED_ERROR BIT(1)
/*
+ * PRODUCTION STATE AWARENESS fields
+ */
+#define EXT_CSD_PSA_NORMAL 0x00
+#define EXT_CSD_PSA_POST_SOLDERING_WRITES 0x02
+
+/*
* BKOPS status level
*/
#define EXT_CSD_BKOPS_LEVEL_2 0x2