Skip to contentSkip to conversation

mmc: tmio: Use modern PM ops

PATCH In review Ulf Hansson 7 participants 181 messages Nov 5, 2013 – May 5, 2014 Page 2 of 3

Subsystems (9)
lore
Share & tools
lore
author Acked-by on v5 2/5
#109 lore raw

Re: [PATCH v5 2/5] mmc: identify available device type to select

In reply to Seungwon Jeon
Quoted 7 lines · Seungwon Jeon

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

Quoted 221 lines
---
 drivers/mmc/core/mmc.c   |   72 +++++++++++++++++++++++++---------------------
 include/linux/mmc/card.h |    2 +-
 include/linux/mmc/host.h |    6 ----
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 48 insertions(+), 44 deletions(-)
drivers/mmc/core/mmc.c +39 -33
index db9655f..97f1912 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
        u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
        u32 caps = host->caps, caps2 = host->caps2;
        unsigned int hs_max_dtr = 0;
+       unsigned int avail_type = 0;
 
-       if (card_type & EXT_CSD_CARD_TYPE_26)
+       if (caps & MMC_CAP_MMC_HIGHSPEED &&
+           card_type & EXT_CSD_CARD_TYPE_HS_26) {
                hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+       }
 
        if (caps & MMC_CAP_MMC_HIGHSPEED &&
-                       card_type & EXT_CSD_CARD_TYPE_52)
+           card_type & EXT_CSD_CARD_TYPE_HS_52) {
                hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+       }
 
-       if ((caps & MMC_CAP_1_8V_DDR &&
-                       card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-           (caps & MMC_CAP_1_2V_DDR &&
-                       card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+       if (caps & MMC_CAP_1_8V_DDR &&
+           card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
                hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+       }
+
+       if (caps & MMC_CAP_1_2V_DDR &&
+           card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+               hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+       }
 
-       if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-                       card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-           (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-                       card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+       if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+           card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
                hs_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+       }
+
+       if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+           card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+               hs_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+       }
 
        card->ext_csd.hs_max_dtr = hs_max_dtr;
-       card->ext_csd.card_type = card_type;
+       card->mmc_avail_type = avail_type;
 }
 
 /*
@@ -808,12 +826,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
        host = card->host;
 
-       if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-                       host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
                err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-       if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-                       host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+       if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
                err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
        /* If fails try again during next card power cycle */
@@ -1072,10 +1088,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
         */
        if (card->ext_csd.hs_max_dtr != 0) {
                err = 0;
-               if (card->ext_csd.hs_max_dtr > 52000000 &&
-                   host->caps2 & MMC_CAP2_HS200)
+               if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
                        err = mmc_select_hs200(card);
-               else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
+               else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
                        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                        EXT_CSD_HS_TIMING, 1,
                                        card->ext_csd.generic_cmd6_time,
@@ -1089,13 +1104,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                               mmc_hostname(card->host));
                        err = 0;
                } else {
-                       if (card->ext_csd.hs_max_dtr > 52000000 &&
-                           host->caps2 & MMC_CAP2_HS200) {
+                       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
                                mmc_set_timing(card->host,
                                               MMC_TIMING_MMC_HS200);
-                       } else {
+                       else
                                mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-                       }
                }
        }
 
@@ -1118,14 +1131,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        /*
         * Indicate DDR mode (if supported).
         */
-       if (mmc_card_hs(card)) {
-               if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
-                       && (host->caps & MMC_CAP_1_8V_DDR))
-                               ddr = MMC_1_8V_DDR_MODE;
-               else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
-                       && (host->caps & MMC_CAP_1_2V_DDR))
-                               ddr = MMC_1_2V_DDR_MODE;
-       }
+       if (mmc_card_hs(card))
+               ddr = card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
 
        /*
         * Indicate HS200 SDR mode (if supported).
@@ -1145,8 +1152,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                 * 3. set the clock to > 52Mhz <=200MHz and
                 * 4. execute tuning for HS200
                 */
-               if ((host->caps2 & MMC_CAP2_HS200) &&
-                   card->host->ops->execute_tuning) {
+               if (card->host->ops->execute_tuning) {
                        mmc_host_clk_hold(card->host);
                        err = card->host->ops->execute_tuning(card->host,
                                MMC_SEND_TUNING_BLOCK_HS200);
@@ -1255,7 +1261,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                         *
                         * WARNING: eMMC rules are NOT the same as SD DDR
                         */
-                       if (ddr == MMC_1_2V_DDR_MODE) {
+                       if (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) {
                                err = __mmc_set_signal_voltage(host,
                                        MMC_SIGNAL_VOLTAGE_120);
                                if (err)
include/linux/mmc/card.h +1 -1
index 5473133..b9f194a 100644
@@ -68,7 +68,6 @@ struct mmc_ext_csd {
 #define MMC_HIGH_DDR_MAX_DTR   52000000
 #define MMC_HS200_MAX_DTR      200000000
        unsigned int            sectors;
-       unsigned int            card_type;
        unsigned int            hc_erase_size;          /* In sectors */
        unsigned int            hc_erase_timeout;       /* In milliseconds */
        unsigned int            sec_trim_mult;  /* Secure trim multiplier  */
@@ -298,6 +297,7 @@ struct mmc_card {
        struct sdio_func_tuple  *tuples;        /* unknown common tuples */
 
        unsigned int            sd_bus_speed;   /* Bus Speed Mode set for the card */
+       unsigned int            mmc_avail_type; /* supported device type by both host and card */
 
        struct dentry           *debugfs_root;
        struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
include/linux/mmc/host.h +0 -6
index 2f263ae..1ee3c10 100644
@@ -62,12 +62,6 @@ struct mmc_ios {
 #define MMC_TIMING_MMC_DDR52   8
 #define MMC_TIMING_MMC_HS200   9
 
-#define MMC_SDR_MODE           0
-#define MMC_1_2V_DDR_MODE      1
-#define MMC_1_8V_DDR_MODE      2
-#define MMC_1_2V_SDR_MODE      3
-#define MMC_1_8V_SDR_MODE      4
-
        unsigned char   signal_voltage;         /* signalling voltage (1.8V or 3.3V) */
 
 #define MMC_SIGNAL_VOLTAGE_330 0
include/linux/mmc/mmc.h +8 -5
index 50bcde3..f734c0c 100644
@@ -354,18 +354,22 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE         (1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE       (1<<2)
 
-#define EXT_CSD_CARD_TYPE_26   (1<<0)  /* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52   (1<<1)  /* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_MASK 0x3F    /* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_HS_26        (1<<0)  /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_HS_52        (1<<1)  /* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_HS   (EXT_CSD_CARD_TYPE_HS_26 | \
+                                EXT_CSD_CARD_TYPE_HS_52)
 #define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
                                             /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
                                             /* DDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
                                        | EXT_CSD_CARD_TYPE_DDR_1_2V)
-#define EXT_CSD_CARD_TYPE_SDR_1_8V     (1<<4)  /* Card can run at 200MHz */
-#define EXT_CSD_CARD_TYPE_SDR_1_2V     (1<<5)  /* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_8V   (1<<4)  /* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V   (1<<5)  /* Card can run at 200MHz */
                                                /* SDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS200                (EXT_CSD_CARD_TYPE_HS200_1_8V | \
+                                        EXT_CSD_CARD_TYPE_HS200_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
--

1.7.0.4

#110 lore raw

PATCH v5 3/5 mmc: step power class after final selection of bus mode

In reply to Seungwon Jeon

Power class is changed once only after selection of bus modes including speed and bus-width finishes finally.

---
 drivers/mmc/core/mmc.c |   96 +++++++++++++++++++++++++++--------------------
 1 files changed, 55 insertions(+), 41 deletions(-)
drivers/mmc/core/mmc.c +55 -41
index 97f1912..480c100 100644
@@ -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) {
Signature · 1 line
1.7.0.4
#111 lore raw

PATCH v5 4/5 mmc: rework selection of bus speed mode

In reply to Seungwon Jeon

Current implementation for bus speed mode selection is too complicated. This patch is to simplify the codes and remove some duplicate parts.

The following changes are including:
* Adds functions for each mode selection(HS, HS-DDR, HS200 and etc)
* Rearranged the mode selection sequence with supported device type
* Adds maximum speed for HS200 mode(hs200_max_dtr)
* Adds field definition for HS_TIMING of EXT_CSD

---
 drivers/mmc/core/debugfs.c |    2 +-
 drivers/mmc/core/mmc.c     |  431 ++++++++++++++++++++++++--------------------
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/mmc.h    |    4 +
 4 files changed, 238 insertions(+), 200 deletions(-)
drivers/mmc/core/debugfs.c +1 -1
index 509229b..1f730db 100644
@@ -139,7 +139,7 @@ static int mmc_ios_show(struct seq_file *s, void *data)
 		str = "mmc DDR52";
 		break;
 	case MMC_TIMING_MMC_HS200:
-		str = "mmc high-speed SDR200";
+		str = "mmc HS200";
 		break;
 	default:
 		str = "invalid";
drivers/mmc/core/mmc.c +232 -199

510 lines not on this page · raw message

include/linux/mmc/card.h +1 -0
index b9f194a..c422349 100644
@@ -63,6 +63,7 @@ struct mmc_ext_csd {
 	unsigned int            power_off_longtime;     /* Units: ms */
 	u8			power_off_notification;	/* state */
 	unsigned int		hs_max_dtr;
+	unsigned int		hs200_max_dtr;
 #define MMC_HIGH_26_MAX_DTR	26000000
 #define MMC_HIGH_52_MAX_DTR	52000000
 #define MMC_HIGH_DDR_MAX_DTR	52000000
include/linux/mmc/mmc.h +4 -0
index f734c0c..f429f13 100644
@@ -377,6 +377,10 @@ struct _mmc_csd {
 #define EXT_CSD_DDR_BUS_WIDTH_4	5	/* Card is in 4 bit DDR mode */
 #define EXT_CSD_DDR_BUS_WIDTH_8	6	/* Card is in 8 bit DDR mode */
 
+#define EXT_CSD_TIMING_BC	0	/* Backwards compatility */
+#define EXT_CSD_TIMING_HS	1	/* High speed */
+#define EXT_CSD_TIMING_HS200	2	/* HS200 */
+
 #define EXT_CSD_SEC_ER_EN	BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN	BIT(2)
 #define EXT_CSD_SEC_GB_CL_EN	BIT(4)
Signature · 1 line
1.7.0.4
#112 lore raw

PATCH v5 5/5 mmc: add support for HS400 mode of eMMC5.0

In reply to Seungwon Jeon

This patch adds HS400 mode support for eMMC5.0 device. HS400 mode is high speed DDR interface timing from HS200. Clock frequency is up to 200MHz and only 8-bit bus width is supported. In addition, tuning process of HS200 is required to synchronize the command response on the CMD line because CMD input timing for HS400 mode is the same as HS200 mode.

---
 drivers/mmc/core/bus.c     |    1 +
 drivers/mmc/core/debugfs.c |    3 +
 drivers/mmc/core/mmc.c     |   98 +++++++++++++++++++++++++++++++++++++++++--
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/host.h   |   14 ++++++
 include/linux/mmc/mmc.h    |    7 +++-
 6 files changed, 118 insertions(+), 6 deletions(-)
drivers/mmc/core/bus.c +1 -0
index f37e9d6..d2dbf02 100644
@@ -349,6 +349,7 @@ int mmc_add_card(struct mmc_card *card)
 			mmc_hostname(card->host),
 			mmc_card_uhs(card) ? "ultra high speed " :
 			(mmc_card_hs(card) ? "high speed " : ""),
+			mmc_card_hs400(card) ? "HS400 " :
 			(mmc_card_hs200(card) ? "HS200 " : ""),
 			mmc_card_ddr52(card) ? "DDR " : "",
 			uhs_bus_speed_mode, type, card->rca);
drivers/mmc/core/debugfs.c +3 -0
index 1f730db..91eb162 100644
@@ -141,6 +141,9 @@ static int mmc_ios_show(struct seq_file *s, void *data)
 	case MMC_TIMING_MMC_HS200:
 		str = "mmc HS200";
 		break;
+	case MMC_TIMING_MMC_HS400:
+		str = "mmc HS400";
+		break;
 	default:
 		str = "invalid";
 		break;
drivers/mmc/core/mmc.c +93 -5

158 lines not on this page · raw message

include/linux/mmc/card.h +1 -0
index c422349..e68bbeb 100644
@@ -110,6 +110,7 @@ struct mmc_ext_csd {
 	u8			raw_pwr_cl_200_360;	/* 237 */
 	u8			raw_pwr_cl_ddr_52_195;	/* 238 */
 	u8			raw_pwr_cl_ddr_52_360;	/* 239 */
+	u8			raw_pwr_cl_ddr_200_360;	/* 253 */
 	u8			raw_bkops_status;	/* 246 */
 	u8			raw_sectors[4];		/* 212 - 4 bytes */
 
include/linux/mmc/host.h +14 -0
index 1ee3c10..1a3ced2 100644
@@ -61,6 +61,7 @@ struct mmc_ios {
 #define MMC_TIMING_UHS_DDR50	7
 #define MMC_TIMING_MMC_DDR52	8
 #define MMC_TIMING_MMC_HS200	9
+#define MMC_TIMING_MMC_HS400	10
 
 	unsigned char	signal_voltage;		/* signalling voltage (1.8V or 3.3V) */
 
@@ -132,6 +133,9 @@ struct mmc_host_ops {
 
 	/* The tuning command opcode value is different for SD and eMMC cards */
 	int	(*execute_tuning)(struct mmc_host *host, u32 opcode);
+
+	/* Prepare HS400 target operating frequency depending host driver */
+	int	(*prepare_hs400_tuning)(struct mmc_host *host, struct mmc_ios *ios);
 	int	(*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv);
 	void	(*hw_reset)(struct mmc_host *host);
 	void	(*card_event)(struct mmc_host *host);
@@ -274,6 +278,10 @@ struct mmc_host {
 #define MMC_CAP2_PACKED_CMD	(MMC_CAP2_PACKED_RD | \
 				 MMC_CAP2_PACKED_WR)
 #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)	/* Don't power up before scan */
+#define MMC_CAP2_HS400_1_8V	(1 << 15)	/* Can support HS400 1.8V */
+#define MMC_CAP2_HS400_1_2V	(1 << 16)	/* Can support HS400 1.2V */
+#define MMC_CAP2_HS400		(MMC_CAP2_HS400_1_8V | \
+				 MMC_CAP2_HS400_1_2V)
 
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
 
@@ -493,4 +501,10 @@ static inline bool mmc_card_ddr52(struct mmc_card *card)
 {
 	return card->host->ios.timing == MMC_TIMING_MMC_DDR52;
 }
+
+static inline bool mmc_card_hs400(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_MMC_HS400;
+}
+
 #endif /* LINUX_MMC_HOST_H */
include/linux/mmc/mmc.h +6 -1
index f429f13..64ec963 100644
@@ -325,6 +325,7 @@ struct _mmc_csd {
 #define EXT_CSD_POWER_OFF_LONG_TIME	247	/* RO */
 #define EXT_CSD_GENERIC_CMD6_TIME	248	/* RO */
 #define EXT_CSD_CACHE_SIZE		249	/* RO, 4 bytes */
+#define EXT_CSD_PWR_CL_DDR_200_360	253	/* RO */
 #define EXT_CSD_TAG_UNIT_SIZE		498	/* RO */
 #define EXT_CSD_DATA_TAG_SUPPORT	499	/* RO */
 #define EXT_CSD_MAX_PACKED_WRITES	500	/* RO */
@@ -354,7 +355,6 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-#define EXT_CSD_CARD_TYPE_MASK	0x3F	/* Mask out reserved bits */
 #define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
 #define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
@@ -370,6 +370,10 @@ struct _mmc_csd {
 						/* SDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
 					 EXT_CSD_CARD_TYPE_HS200_1_2V)
+#define EXT_CSD_CARD_TYPE_HS400_1_8V	(1<<6)	/* Card can run at 200MHz DDR, 1.8V */
+#define EXT_CSD_CARD_TYPE_HS400_1_2V	(1<<7)	/* Card can run at 200MHz DDR, 1.2V */
+#define EXT_CSD_CARD_TYPE_HS400		(EXT_CSD_CARD_TYPE_HS400_1_8V | \
+					 EXT_CSD_CARD_TYPE_HS400_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
@@ -380,6 +384,7 @@ struct _mmc_csd {
 #define EXT_CSD_TIMING_BC	0	/* Backwards compatility */
 #define EXT_CSD_TIMING_HS	1	/* High speed */
 #define EXT_CSD_TIMING_HS200	2	/* HS200 */
+#define EXT_CSD_TIMING_HS400	3	/* HS400 */
 
 #define EXT_CSD_SEC_ER_EN	BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN	BIT(2)
Signature · 1 line
1.7.0.4
author Acked-by on v5 5/5
#113 lore raw

Re: [PATCH v5 5/5] mmc: add support for HS400 mode of eMMC5.0

Quoted 10 lines · Seungwon Jeon

This patch adds HS400 mode support for eMMC5.0 device. HS400 mode is high speed DDR interface timing from HS200. Clock frequency is up to 200MHz and only 8-bit bus width is supported. In addition, tuning process of HS200 is required to synchronize the command response on the CMD line because CMD input timing for HS400 mode is the same as HS200 mode.

Quoted 305 lines
---
 drivers/mmc/core/bus.c     |    1 +
 drivers/mmc/core/debugfs.c |    3 +
 drivers/mmc/core/mmc.c     |   98 +++++++++++++++++++++++++++++++++++++++++--
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/host.h   |   14 ++++++
 include/linux/mmc/mmc.h    |    7 +++-
 6 files changed, 118 insertions(+), 6 deletions(-)
drivers/mmc/core/bus.c +1 -0
index f37e9d6..d2dbf02 100644
@@ -349,6 +349,7 @@ int mmc_add_card(struct mmc_card *card)
                        mmc_hostname(card->host),
                        mmc_card_uhs(card) ? "ultra high speed " :
                        (mmc_card_hs(card) ? "high speed " : ""),
+                       mmc_card_hs400(card) ? "HS400 " :
                        (mmc_card_hs200(card) ? "HS200 " : ""),
                        mmc_card_ddr52(card) ? "DDR " : "",
                        uhs_bus_speed_mode, type, card->rca);
drivers/mmc/core/debugfs.c +3 -0
index 1f730db..91eb162 100644
@@ -141,6 +141,9 @@ static int mmc_ios_show(struct seq_file *s, void *data)
        case MMC_TIMING_MMC_HS200:
                str = "mmc HS200";
                break;
+       case MMC_TIMING_MMC_HS400:
+               str = "mmc HS400";
+               break;
        default:
                str = "invalid";
                break;
drivers/mmc/core/mmc.c +93 -5
index 7e9b424..c12e247 100644
@@ -240,7 +240,7 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
 static void mmc_select_card_type(struct mmc_card *card)
 {
        struct mmc_host *host = card->host;
-       u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
+       u8 card_type = card->ext_csd.raw_card_type;
        u32 caps = host->caps, caps2 = host->caps2;
        unsigned int hs_max_dtr = 0, hs200_max_dtr = 0;
        unsigned int avail_type = 0;
@@ -281,6 +281,18 @@ static void mmc_select_card_type(struct mmc_card *card)
                avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
        }
 
+       if (caps2 & MMC_CAP2_HS400_1_8V &&
+           card_type & EXT_CSD_CARD_TYPE_HS400_1_8V) {
+               hs200_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS400_1_8V;
+       }
+
+       if (caps2 & MMC_CAP2_HS400_1_2V &&
+           card_type & EXT_CSD_CARD_TYPE_HS400_1_2V) {
+               hs200_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS400_1_2V;
+       }
+
        card->ext_csd.hs_max_dtr = hs_max_dtr;
        card->ext_csd.hs200_max_dtr = hs200_max_dtr;
        card->mmc_avail_type = avail_type;
@@ -499,6 +511,8 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
                        ext_csd[EXT_CSD_PWR_CL_DDR_52_195];
                card->ext_csd.raw_pwr_cl_ddr_52_360 =
                        ext_csd[EXT_CSD_PWR_CL_DDR_52_360];
+               card->ext_csd.raw_pwr_cl_ddr_200_360 =
+                       ext_csd[EXT_CSD_PWR_CL_DDR_200_360];
        }
 
        if (card->ext_csd.rev >= 5) {
@@ -665,7 +679,10 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
                (card->ext_csd.raw_pwr_cl_ddr_52_195 ==
                        bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_195]) &&
                (card->ext_csd.raw_pwr_cl_ddr_52_360 ==
-                       bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360]));
+                       bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360]) &&
+               (card->ext_csd.raw_pwr_cl_ddr_200_360 ==
+                       bw_ext_csd[EXT_CSD_PWR_CL_DDR_200_360]));
+
        if (err)
                err = -EINVAL;
 
@@ -776,7 +793,9 @@ static int __mmc_select_powerclass(struct mmc_card *card,
                                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;
+                       pwrclass_val = (bus_width == EXT_CSD_DDR_BUS_WIDTH_8) ?
+                               ext_csd->raw_pwr_cl_ddr_200_360 :
+                               ext_csd->raw_pwr_cl_200_360;
                break;
        default:
                pr_warning("%s: Voltage range not supported "
@@ -840,7 +859,8 @@ static void mmc_set_bus_speed(struct mmc_card *card)
 {
        unsigned int max_dtr = (unsigned int)-1;
 
-       if (mmc_card_hs200(card) && max_dtr > card->ext_csd.hs200_max_dtr)
+       if ((mmc_card_hs200(card) || mmc_card_hs400(card)) &&
+            max_dtr > card->ext_csd.hs200_max_dtr)
                max_dtr = card->ext_csd.hs200_max_dtr;
        else if (mmc_card_hs(card) && max_dtr > card->ext_csd.hs_max_dtr)
                max_dtr = card->ext_csd.hs_max_dtr;
@@ -993,6 +1013,61 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
        return err;
 }
 
+static int mmc_select_hs400(struct mmc_card *card)
+{
+       struct mmc_host *host = card->host;
+       int err = 0;
+
+       /*
+        * HS400 mode requires 8-bit bus width
+        */
+       if (!(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 &&
+             host->ios.bus_width == MMC_BUS_WIDTH_8))
+               return 0;
+
+       /*
+        * Before switching to dual data rate operation for HS400,
+        * it is required to convert from HS200 mode to HS mode.
+        */
+       mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+       mmc_set_bus_speed(card);
+
+       err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                          EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
+                          card->ext_csd.generic_cmd6_time,
+                          true, true, true);
+       if (err) {
+               pr_warn("%s: switch to high-speed from hs200 failed, err:%d\n",
+                       mmc_hostname(host), err);
+               return err;
+       }
+
+       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                        EXT_CSD_BUS_WIDTH,
+                        EXT_CSD_DDR_BUS_WIDTH_8,
+                        card->ext_csd.generic_cmd6_time);
+       if (err) {
+               pr_warn("%s: switch to bus width for hs400 failed, err:%d\n",
+                       mmc_hostname(host), err);
+               return err;
+       }
+
+       err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                          EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400,
+                          card->ext_csd.generic_cmd6_time,
+                          true, true, true);
+       if (err) {
+               pr_warn("%s: switch to hs400 failed, err:%d\n",
+                        mmc_hostname(host), err);
+               return err;
+       }
+
+       mmc_set_timing(host, MMC_TIMING_MMC_HS400);
+       mmc_set_bus_speed(card);
+
+       return 0;
+}
+
 /*
  * For device supporting HS200 mode, the following sequence
  * should be done before executing the tuning process.
@@ -1070,13 +1145,22 @@ bus_speed:
 
 /*
  * Execute tuning sequence to seek the proper bus operating
- * conditions for HS200, which sends CMD21 to the device.
+ * conditions for HS200 and HS400, which sends CMD21 to the device.
  */
 static int mmc_hs200_tuning(struct mmc_card *card)
 {
        struct mmc_host *host = card->host;
        int err = 0;
 
+       /*
+        * Timing should be adjusted to the HS400 target
+        * operation frequency for tuning process
+        */
+       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 &&
+           host->ios.bus_width == MMC_BUS_WIDTH_8)
+               if (host->ops->prepare_hs400_tuning)
+                       host->ops->prepare_hs400_tuning(host, &host->ios);
+
        if (host->ops->execute_tuning) {
                mmc_host_clk_hold(host);
                err = host->ops->execute_tuning(host,
@@ -1304,6 +1388,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                err = mmc_hs200_tuning(card);
                if (err)
                        goto err;
+
+               err = mmc_select_hs400(card);
+               if (err)
+                       goto err;
        } else if (mmc_card_hs(card)) {
                /* Select the desired bus width optionally */
                err = mmc_select_bus_width(card);
include/linux/mmc/card.h +1 -0
index c422349..e68bbeb 100644
@@ -110,6 +110,7 @@ struct mmc_ext_csd {
        u8                      raw_pwr_cl_200_360;     /* 237 */
        u8                      raw_pwr_cl_ddr_52_195;  /* 238 */
        u8                      raw_pwr_cl_ddr_52_360;  /* 239 */
+       u8                      raw_pwr_cl_ddr_200_360; /* 253 */
        u8                      raw_bkops_status;       /* 246 */
        u8                      raw_sectors[4];         /* 212 - 4 bytes */
 
include/linux/mmc/host.h +14 -0
index 1ee3c10..1a3ced2 100644
@@ -61,6 +61,7 @@ struct mmc_ios {
 #define MMC_TIMING_UHS_DDR50   7
 #define MMC_TIMING_MMC_DDR52   8
 #define MMC_TIMING_MMC_HS200   9
+#define MMC_TIMING_MMC_HS400   10
 
        unsigned char   signal_voltage;         /* signalling voltage (1.8V or 3.3V) */
 
@@ -132,6 +133,9 @@ struct mmc_host_ops {
 
        /* The tuning command opcode value is different for SD and eMMC cards */
        int     (*execute_tuning)(struct mmc_host *host, u32 opcode);
+
+       /* Prepare HS400 target operating frequency depending host driver */
+       int     (*prepare_hs400_tuning)(struct mmc_host *host, struct mmc_ios *ios);
        int     (*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv);
        void    (*hw_reset)(struct mmc_host *host);
        void    (*card_event)(struct mmc_host *host);
@@ -274,6 +278,10 @@ struct mmc_host {
 #define MMC_CAP2_PACKED_CMD    (MMC_CAP2_PACKED_RD | \
                                 MMC_CAP2_PACKED_WR)
 #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)  /* Don't power up before scan */
+#define MMC_CAP2_HS400_1_8V    (1 << 15)       /* Can support HS400 1.8V */
+#define MMC_CAP2_HS400_1_2V    (1 << 16)       /* Can support HS400 1.2V */
+#define MMC_CAP2_HS400         (MMC_CAP2_HS400_1_8V | \
+                                MMC_CAP2_HS400_1_2V)
 
        mmc_pm_flag_t           pm_caps;        /* supported pm features */
 
@@ -493,4 +501,10 @@ static inline bool mmc_card_ddr52(struct mmc_card *card)
 {
        return card->host->ios.timing == MMC_TIMING_MMC_DDR52;
 }
+
+static inline bool mmc_card_hs400(struct mmc_card *card)
+{
+       return card->host->ios.timing == MMC_TIMING_MMC_HS400;
+}
+
 #endif /* LINUX_MMC_HOST_H */
include/linux/mmc/mmc.h +6 -2
index f429f13..64ec963 100644
@@ -325,6 +325,7 @@ struct _mmc_csd {
 #define EXT_CSD_POWER_OFF_LONG_TIME    247     /* RO */
 #define EXT_CSD_GENERIC_CMD6_TIME      248     /* RO */
 #define EXT_CSD_CACHE_SIZE             249     /* RO, 4 bytes */
+#define EXT_CSD_PWR_CL_DDR_200_360     253     /* RO */
 #define EXT_CSD_TAG_UNIT_SIZE          498     /* RO */
 #define EXT_CSD_DATA_TAG_SUPPORT       499     /* RO */
 #define EXT_CSD_MAX_PACKED_WRITES      500     /* RO */
@@ -354,7 +355,6 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE         (1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE       (1<<2)
 
-#define EXT_CSD_CARD_TYPE_MASK 0x3F    /* Mask out reserved bits */
 #define EXT_CSD_CARD_TYPE_HS_26        (1<<0)  /* Card can run at 26MHz */
 #define EXT_CSD_CARD_TYPE_HS_52        (1<<1)  /* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_HS   (EXT_CSD_CARD_TYPE_HS_26 | \
@@ -370,6 +370,10 @@ struct _mmc_csd {
                                                /* SDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_HS200                (EXT_CSD_CARD_TYPE_HS200_1_8V | \
                                         EXT_CSD_CARD_TYPE_HS200_1_2V)
+#define EXT_CSD_CARD_TYPE_HS400_1_8V   (1<<6)  /* Card can run at 200MHz DDR, 1.8V */
+#define EXT_CSD_CARD_TYPE_HS400_1_2V   (1<<7)  /* Card can run at 200MHz DDR, 1.2V */
+#define EXT_CSD_CARD_TYPE_HS400                (EXT_CSD_CARD_TYPE_HS400_1_8V | \
+                                        EXT_CSD_CARD_TYPE_HS400_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
@@ -380,6 +384,7 @@ struct _mmc_csd {
 #define EXT_CSD_TIMING_BC      0       /* Backwards compatility */
 #define EXT_CSD_TIMING_HS      1       /* High speed */
 #define EXT_CSD_TIMING_HS200   2       /* HS200 */
+#define EXT_CSD_TIMING_HS400   3       /* HS400 */
 
 #define EXT_CSD_SEC_ER_EN      BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN  BIT(2)
--

1.7.0.4

#114 lore raw

v6 cover update selection of bus speed mode for eMMC

In reply to Seungwon Jeon

This series contains the change for selection of bus speed mode. Previous implementation is complicated and some sequence is duplicated. And specially, HS400 mode eMMC5.0 is introduced this time. This patch-set has been tested in Exynos SoC.

Note:
This patch-set depends on "[PATCH RESEND v3 1/7] mmc: clarify DDR timing mode between SD-UHS and eMMC".

Changes in v6:

	(6/6) Included "mmc: core: add DT bindings for eMMC HS400 1.8/1.2V" into this patch-set
	(5/6) Changed return type of prepare_hs400_tuning callback(int -> void)

Changes in v5:
(5/5) Added callback operation for HS400 target operation frequency
instead of specific timing identifier.
(2/5) Removed using union declaration.

Changes in v4:
(5/5)Reverting to HS mode is included in mmc_select_hs400() using __mmc_switch().

Changes in v3:
Removed the function to check DDR type(mmc_snoop_ddr). Rebased with the latest branch.

Seungwon Jeon (6):
mmc: drop the speed mode of card's state
mmc: identify available device type to select
mmc: step power class after final selection of bus mode
mmc: rework selection of bus speed mode
mmc: add support for HS400 mode of eMMC5.0
mmc: add DT bindings for eMMC HS400 1.8/1.2V

 Documentation/devicetree/bindings/mmc/mmc.txt |    2 +
 drivers/mmc/core/bus.c                        |    9 +-
 drivers/mmc/core/core.c                       |    3 +-
 drivers/mmc/core/debugfs.c                    |    5 +-
 drivers/mmc/core/host.c                       |    4 +
 drivers/mmc/core/mmc.c                        |  666 +++++++++++++++----------
 drivers/mmc/core/sd.c                         |   16 +-
 drivers/mmc/core/sd.h                         |    1 -
 drivers/mmc/core/sdio.c                       |    8 +-
 include/linux/mmc/card.h                      |   27 +-
 include/linux/mmc/host.h                      |   43 ++-
 include/linux/mmc/mmc.h                       |   23 +-
 12 files changed, 486 insertions(+), 321 deletions(-)

Thanks,
sw-j

#115 lore raw

Re: [PATCH v6 0/6] update selection of bus speed mode for eMMC

Hi Seungwon,

Quoted 11 lines · Seungwon Jeon

This series contains the change for selection of bus speed mode. Previous implementation is complicated and some sequence is duplicated. And specially, HS400 mode eMMC5.0 is introduced this time. This patch-set has been tested in Exynos SoC.

Note:
This patch-set depends on "[PATCH RESEND v3 1/7] mmc: clarify DDR timing mode between SD-UHS and eMMC".

Changes in v6:
(6/6) Included "mmc: core: add DT bindings for eMMC HS400 1.8/1.2V" into this patch-set (5/6) Changed return type of prepare_hs400_tuning callback(int -> void)

I would favour the int return type, that leaves room for the possibility of drivers to fail.

Moreover, I have already sent a pull request to Chris, with the v5 version of this patchset, which I think is fine.

Kind regards
Uffe

Quoted 37 lines

Changes in v5:
(5/5) Added callback operation for HS400 target operation frequency
instead of specific timing identifier.
(2/5) Removed using union declaration.

Changes in v4:
(5/5)Reverting to HS mode is included in mmc_select_hs400() using __mmc_switch().

Changes in v3:
Removed the function to check DDR type(mmc_snoop_ddr). Rebased with the latest branch.

Seungwon Jeon (6):
mmc: drop the speed mode of card's state
mmc: identify available device type to select
mmc: step power class after final selection of bus mode
mmc: rework selection of bus speed mode
mmc: add support for HS400 mode of eMMC5.0
mmc: add DT bindings for eMMC HS400 1.8/1.2V

 Documentation/devicetree/bindings/mmc/mmc.txt |    2 +
 drivers/mmc/core/bus.c                        |    9 +-
 drivers/mmc/core/core.c                       |    3 +-
 drivers/mmc/core/debugfs.c                    |    5 +-
 drivers/mmc/core/host.c                       |    4 +
 drivers/mmc/core/mmc.c                        |  666 +++++++++++++++----------
 drivers/mmc/core/sd.c                         |   16 +-
 drivers/mmc/core/sd.h                         |    1 -
 drivers/mmc/core/sdio.c                       |    8 +-
 include/linux/mmc/card.h                      |   27 +-
 include/linux/mmc/host.h                      |   43 ++-
 include/linux/mmc/mmc.h                       |   23 +-
 12 files changed, 486 insertions(+), 321 deletions(-)

Thanks,
sw-j

#116 lore raw

RE: [PATCH v6 0/6] update selection of bus speed mode for eMMC

Quoted 16 lines · Ulf Hansson

Hi Seungwon,

Quoted 7 lines · Seungwon Jeon

This series contains the change for selection of bus speed mode. Previous implementation is complicated and some sequence is duplicated. And specially, HS400 mode eMMC5.0 is introduced this time. This patch-set has been tested in Exynos SoC.

Note:
This patch-set depends on "[PATCH RESEND v3 1/7] mmc: clarify DDR timing mode between SD-UHS and

eMMC".

Quoted 4 lines

Changes in v6:
(6/6) Included "mmc: core: add DT bindings for eMMC HS400 1.8/1.2V" into this patch-set (5/6) Changed return type of prepare_hs400_tuning callback(int -> void)

Quoted 5 lines

I would favour the int return type, that leaves room for the possibility of drivers to fail.

Moreover, I have already sent a pull request to Chris, with the v5 version of this patchset, which I think is fine.

OK. It would be fine.

Thanks,
Seungwon Jeon

#117 lore raw

PATCH v6 1/6 mmc: drop the speed mode of card's state

In reply to Seungwon Jeon

Timing mode identifier has same role and can take the place of speed mode. This change removes all related speed mode.

---
 drivers/mmc/core/bus.c   |    8 ++++----
 drivers/mmc/core/core.c  |    3 +--
 drivers/mmc/core/mmc.c   |   11 +++--------
 drivers/mmc/core/sd.c    |   16 +++-------------
 drivers/mmc/core/sd.h    |    1 -
 drivers/mmc/core/sdio.c  |    8 ++------
 include/linux/mmc/card.h |   23 ++++++-----------------
 include/linux/mmc/host.h |   23 +++++++++++++++++++++++
 8 files changed, 42 insertions(+), 51 deletions(-)
drivers/mmc/core/bus.c +4 -4
index 8246448..f37e9d6 100644
@@ -341,16 +341,16 @@ int mmc_add_card(struct mmc_card *card)
 	if (mmc_host_is_spi(card->host)) {
 		pr_info("%s: new %s%s%s card on SPI\n",
 			mmc_hostname(card->host),
-			mmc_card_highspeed(card) ? "high speed " : "",
-			mmc_card_ddr_mode(card) ? "DDR " : "",
+			mmc_card_hs(card) ? "high speed " : "",
+			mmc_card_ddr52(card) ? "DDR " : "",
 			type);
 	} else {
 		pr_info("%s: new %s%s%s%s%s card at address %04x\n",
 			mmc_hostname(card->host),
 			mmc_card_uhs(card) ? "ultra high speed " :
-			(mmc_card_highspeed(card) ? "high speed " : ""),
+			(mmc_card_hs(card) ? "high speed " : ""),
 			(mmc_card_hs200(card) ? "HS200 " : ""),
-			mmc_card_ddr_mode(card) ? "DDR " : "",
+			mmc_card_ddr52(card) ? "DDR " : "",
 			uhs_bus_speed_mode, type, card->rca);
 	}
 
drivers/mmc/core/core.c +1 -2
index acbc3f2..aa9f679 100644
@@ -2183,7 +2183,7 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
 {
 	struct mmc_command cmd = {0};
 
-	if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card))
+	if (mmc_card_blockaddr(card) || mmc_card_ddr52(card))
 		return 0;
 
 	cmd.opcode = MMC_SET_BLOCKLEN;
@@ -2263,7 +2263,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
 		}
 	}
 
-	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_DDR);
 	if (mmc_host_is_spi(host)) {
 		host->ios.chip_select = MMC_CS_HIGH;
 		host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
drivers/mmc/core/mmc.c +3 -8
index e22d851..db9655f 100644
@@ -1091,11 +1091,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		} else {
 			if (card->ext_csd.hs_max_dtr > 52000000 &&
 			    host->caps2 & MMC_CAP2_HS200) {
-				mmc_card_set_hs200(card);
 				mmc_set_timing(card->host,
 					       MMC_TIMING_MMC_HS200);
 			} else {
-				mmc_card_set_highspeed(card);
 				mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
 			}
 		}
@@ -1106,10 +1104,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	max_dtr = (unsigned int)-1;
 
-	if (mmc_card_highspeed(card) || mmc_card_hs200(card)) {
+	if (mmc_card_hs(card) || mmc_card_hs200(card)) {
 		if (max_dtr > card->ext_csd.hs_max_dtr)
 			max_dtr = card->ext_csd.hs_max_dtr;
-		if (mmc_card_highspeed(card) && (max_dtr > 52000000))
+		if (mmc_card_hs(card) && (max_dtr > 52000000))
 			max_dtr = 52000000;
 	} else if (max_dtr > card->csd.max_dtr) {
 		max_dtr = card->csd.max_dtr;
@@ -1120,7 +1118,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	/*
 	 * Indicate DDR mode (if supported).
 	 */
-	if (mmc_card_highspeed(card)) {
+	if (mmc_card_hs(card)) {
 		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
 			&& (host->caps & MMC_CAP_1_8V_DDR))
 				ddr = MMC_1_8V_DDR_MODE;
@@ -1263,7 +1261,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 				if (err)
 					goto err;
 			}
-			mmc_card_set_ddr_mode(card);
 			mmc_set_timing(card->host, MMC_TIMING_MMC_DDR52);
 			mmc_set_bus_width(card->host, bus_width);
 		}
@@ -1507,7 +1504,6 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
 		err = mmc_sleep(host);
 	else if (!mmc_host_is_spi(host))
 		err = mmc_deselect_cards(host);
-	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
 
 	if (!err) {
 		mmc_power_off(host);
@@ -1637,7 +1633,6 @@ static int mmc_power_restore(struct mmc_host *host)
 {
 	int ret;
 
-	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
 	mmc_claim_host(host);
 	ret = mmc_init_card(host, host->card->ocr, host->card);
 	mmc_release_host(host);
drivers/mmc/core/sd.c +3 -13
index 2dd359d..9fc5b31 100644
@@ -895,7 +895,7 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
 {
 	unsigned max_dtr = (unsigned int)-1;
 
-	if (mmc_card_highspeed(card)) {
+	if (mmc_card_hs(card)) {
 		if (max_dtr > card->sw_caps.hs_max_dtr)
 			max_dtr = card->sw_caps.hs_max_dtr;
 	} else if (max_dtr > card->csd.max_dtr) {
@@ -905,12 +905,6 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
 	return max_dtr;
 }
 
-void mmc_sd_go_highspeed(struct mmc_card *card)
-{
-	mmc_card_set_highspeed(card);
-	mmc_set_timing(card->host, MMC_TIMING_SD_HS);
-}
-
 /*
  * Handle the detection and initialisation of a card.
  *
@@ -985,16 +979,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
 		err = mmc_sd_init_uhs_card(card);
 		if (err)
 			goto free_card;
-
-		/* Card is an ultra-high-speed card */
-		mmc_card_set_uhs(card);
 	} else {
 		/*
 		 * Attempt to change to high-speed (if supported)
 		 */
 		err = mmc_sd_switch_hs(card);
 		if (err > 0)
-			mmc_sd_go_highspeed(card);
+			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
 		else if (err)
 			goto free_card;
 
@@ -1089,7 +1080,7 @@ static int _mmc_sd_suspend(struct mmc_host *host)
 
 	if (!mmc_host_is_spi(host))
 		err = mmc_deselect_cards(host);
-	host->card->state &= ~MMC_STATE_HIGHSPEED;
+
 	if (!err) {
 		mmc_power_off(host);
 		mmc_card_set_suspended(host->card);
@@ -1198,7 +1189,6 @@ static int mmc_sd_power_restore(struct mmc_host *host)
 {
 	int ret;
 
-	host->card->state &= ~MMC_STATE_HIGHSPEED;
 	mmc_claim_host(host);
 	ret = mmc_sd_init_card(host, host->card->ocr, host->card);
 	mmc_release_host(host);
drivers/mmc/core/sd.h +0 -1
index 4b34b24..aab824a 100644
@@ -12,6 +12,5 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
 	bool reinit);
 unsigned mmc_sd_get_max_clock(struct mmc_card *card);
 int mmc_sd_switch_hs(struct mmc_card *card);
-void mmc_sd_go_highspeed(struct mmc_card *card);
 
 #endif
drivers/mmc/core/sdio.c +2 -6
index 4d721c6..ef57d2d 100644
@@ -363,7 +363,7 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card)
 {
 	unsigned max_dtr;
 
-	if (mmc_card_highspeed(card)) {
+	if (mmc_card_hs(card)) {
 		/*
 		 * The SDIO specification doesn't mention how
 		 * the CIS transfer speed register relates to
@@ -733,7 +733,6 @@ try_again:
 		mmc_set_clock(host, card->cis.max_dtr);
 
 		if (card->cccr.high_speed) {
-			mmc_card_set_highspeed(card);
 			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
 		}
 
@@ -792,16 +791,13 @@ try_again:
 		err = mmc_sdio_init_uhs_card(card);
 		if (err)
 			goto remove;
-
-		/* Card is an ultra-high-speed card */
-		mmc_card_set_uhs(card);
 	} else {
 		/*
 		 * Switch to high-speed (if supported).
 		 */
 		err = sdio_enable_hs(card);
 		if (err > 0)
-			mmc_sd_go_highspeed(card);
+			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
 		else if (err)
 			goto remove;
 
include/linux/mmc/card.h +6 -17
index b730272..5473133 100644
@@ -194,6 +194,7 @@ struct sdio_cis {
 };
 
 struct mmc_host;
+struct mmc_ios;
 struct sdio_func;
 struct sdio_func_tuple;
 
@@ -250,15 +251,11 @@ struct mmc_card {
 	unsigned int		state;		/* (our) card state */
 #define MMC_STATE_PRESENT	(1<<0)		/* present in sysfs */
 #define MMC_STATE_READONLY	(1<<1)		/* card is read-only */
-#define MMC_STATE_HIGHSPEED	(1<<2)		/* card is in high speed mode */
-#define MMC_STATE_BLOCKADDR	(1<<3)		/* card uses block-addressing */
-#define MMC_STATE_HIGHSPEED_DDR (1<<4)		/* card is in high speed mode */
-#define MMC_STATE_ULTRAHIGHSPEED (1<<5)		/* card is in ultra high speed mode */
-#define MMC_CARD_SDXC		(1<<6)		/* card is SDXC */
-#define MMC_CARD_REMOVED	(1<<7)		/* card has been removed */
-#define MMC_STATE_HIGHSPEED_200	(1<<8)		/* card is in HS200 mode */
-#define MMC_STATE_DOING_BKOPS	(1<<10)		/* card is doing BKOPS */
-#define MMC_STATE_SUSPENDED	(1<<11)		/* card is suspended */
+#define MMC_STATE_BLOCKADDR	(1<<2)		/* card uses block-addressing */
+#define MMC_CARD_SDXC		(1<<3)		/* card is SDXC */
+#define MMC_CARD_REMOVED	(1<<4)		/* card has been removed */
+#define MMC_STATE_DOING_BKOPS	(1<<5)		/* card is doing BKOPS */
+#define MMC_STATE_SUSPENDED	(1<<6)		/* card is suspended */
 	unsigned int		quirks; 	/* card quirks */
 #define MMC_QUIRK_LENIENT_FN0	(1<<0)		/* allow SDIO FN0 writes outside of the VS CCCR range */
 #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1)	/* use func->cur_blksize */
@@ -418,11 +415,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 
 #define mmc_card_present(c)	((c)->state & MMC_STATE_PRESENT)
 #define mmc_card_readonly(c)	((c)->state & MMC_STATE_READONLY)
-#define mmc_card_highspeed(c)	((c)->state & MMC_STATE_HIGHSPEED)
-#define mmc_card_hs200(c)	((c)->state & MMC_STATE_HIGHSPEED_200)
 #define mmc_card_blockaddr(c)	((c)->state & MMC_STATE_BLOCKADDR)
-#define mmc_card_ddr_mode(c)	((c)->state & MMC_STATE_HIGHSPEED_DDR)
-#define mmc_card_uhs(c)		((c)->state & MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
 #define mmc_card_removed(c)	((c) && ((c)->state & MMC_CARD_REMOVED))
 #define mmc_card_doing_bkops(c)	((c)->state & MMC_STATE_DOING_BKOPS)
@@ -430,11 +423,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 
 #define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
-#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
-#define mmc_card_set_hs200(c)	((c)->state |= MMC_STATE_HIGHSPEED_200)
 #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
-#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
-#define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
 #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
 #define mmc_card_set_doing_bkops(c)	((c)->state |= MMC_STATE_DOING_BKOPS)
include/linux/mmc/host.h +23 -0
index 3535420..2f263ae 100644
@@ -17,6 +17,7 @@
 #include <linux/fault-inject.h>
 
 #include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
 #include <linux/mmc/pm.h>
 
 struct mmc_ios {
@@ -476,4 +477,26 @@ static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
 	return host->ios.clock;
 }
 #endif
+
+static inline int mmc_card_hs(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_SD_HS ||
+		card->host->ios.timing == MMC_TIMING_MMC_HS;
+}
+
+static inline int mmc_card_uhs(struct mmc_card *card)
+{
+	return card->host->ios.timing >= MMC_TIMING_UHS_SDR12 &&
+		card->host->ios.timing <= MMC_TIMING_UHS_DDR50;
+}
+
+static inline bool mmc_card_hs200(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_MMC_HS200;
+}
+
+static inline bool mmc_card_ddr52(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_MMC_DDR52;
+}
 #endif /* LINUX_MMC_HOST_H */
Signature · 1 line
1.7.0.4
#118 lore raw

PATCH v6 2/6 mmc: identify available device type to select

In reply to Seungwon Jeon

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

---
 drivers/mmc/core/mmc.c   |   72 +++++++++++++++++++++++++---------------------
 include/linux/mmc/card.h |    2 +-
 include/linux/mmc/host.h |    6 ----
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 48 insertions(+), 44 deletions(-)
drivers/mmc/core/mmc.c +39 -33
index db9655f..97f1912 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
 	u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
 	u32 caps = host->caps, caps2 = host->caps2;
 	unsigned int hs_max_dtr = 0;
+	unsigned int avail_type = 0;
 
-	if (card_type & EXT_CSD_CARD_TYPE_26)
+	if (caps & MMC_CAP_MMC_HIGHSPEED &&
+	    card_type & EXT_CSD_CARD_TYPE_HS_26) {
 		hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+	}
 
 	if (caps & MMC_CAP_MMC_HIGHSPEED &&
-			card_type & EXT_CSD_CARD_TYPE_52)
+	    card_type & EXT_CSD_CARD_TYPE_HS_52) {
 		hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+	}
 
-	if ((caps & MMC_CAP_1_8V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-	    (caps & MMC_CAP_1_2V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+	if (caps & MMC_CAP_1_8V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
 		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+	}
+
+	if (caps & MMC_CAP_1_2V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+	}
 
-	if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-	    (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+	if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
 		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+	}
 
 	card->ext_csd.hs_max_dtr = hs_max_dtr;
-	card->ext_csd.card_type = card_type;
+	card->mmc_avail_type = avail_type;
 }
 
 /*
@@ -808,12 +826,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
 	host = card->host;
 
-	if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-			host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+	if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-	if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-			host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+	if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
 	/* If fails try again during next card power cycle */
@@ -1072,10 +1088,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	if (card->ext_csd.hs_max_dtr != 0) {
 		err = 0;
-		if (card->ext_csd.hs_max_dtr > 52000000 &&
-		    host->caps2 & MMC_CAP2_HS200)
+		if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
 			err = mmc_select_hs200(card);
-		else if	(host->caps & MMC_CAP_MMC_HIGHSPEED)
+		else if	(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
 			err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 					EXT_CSD_HS_TIMING, 1,
 					card->ext_csd.generic_cmd6_time,
@@ -1089,13 +1104,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			       mmc_hostname(card->host));
 			err = 0;
 		} else {
-			if (card->ext_csd.hs_max_dtr > 52000000 &&
-			    host->caps2 & MMC_CAP2_HS200) {
+			if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
 				mmc_set_timing(card->host,
 					       MMC_TIMING_MMC_HS200);
-			} else {
+			else
 				mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-			}
 		}
 	}
 
@@ -1118,14 +1131,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	/*
 	 * Indicate DDR mode (if supported).
 	 */
-	if (mmc_card_hs(card)) {
-		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
-			&& (host->caps & MMC_CAP_1_8V_DDR))
-				ddr = MMC_1_8V_DDR_MODE;
-		else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
-			&& (host->caps & MMC_CAP_1_2V_DDR))
-				ddr = MMC_1_2V_DDR_MODE;
-	}
+	if (mmc_card_hs(card))
+		ddr = card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
 
 	/*
 	 * Indicate HS200 SDR mode (if supported).
@@ -1145,8 +1152,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		 * 3. set the clock to > 52Mhz <=200MHz and
 		 * 4. execute tuning for HS200
 		 */
-		if ((host->caps2 & MMC_CAP2_HS200) &&
-		    card->host->ops->execute_tuning) {
+		if (card->host->ops->execute_tuning) {
 			mmc_host_clk_hold(card->host);
 			err = card->host->ops->execute_tuning(card->host,
 				MMC_SEND_TUNING_BLOCK_HS200);
@@ -1255,7 +1261,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			 *
 			 * WARNING: eMMC rules are NOT the same as SD DDR
 			 */
-			if (ddr == MMC_1_2V_DDR_MODE) {
+			if (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) {
 				err = __mmc_set_signal_voltage(host,
 					MMC_SIGNAL_VOLTAGE_120);
 				if (err)
include/linux/mmc/card.h +1 -1
index 5473133..b9f194a 100644
@@ -68,7 +68,6 @@ struct mmc_ext_csd {
 #define MMC_HIGH_DDR_MAX_DTR	52000000
 #define MMC_HS200_MAX_DTR	200000000
 	unsigned int		sectors;
-	unsigned int		card_type;
 	unsigned int		hc_erase_size;		/* In sectors */
 	unsigned int		hc_erase_timeout;	/* In milliseconds */
 	unsigned int		sec_trim_mult;	/* Secure trim multiplier  */
@@ -298,6 +297,7 @@ struct mmc_card {
 	struct sdio_func_tuple	*tuples;	/* unknown common tuples */
 
 	unsigned int		sd_bus_speed;	/* Bus Speed Mode set for the card */
+	unsigned int		mmc_avail_type;	/* supported device type by both host and card */
 
 	struct dentry		*debugfs_root;
 	struct mmc_part	part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
include/linux/mmc/host.h +0 -6
index 2f263ae..1ee3c10 100644
@@ -62,12 +62,6 @@ struct mmc_ios {
 #define MMC_TIMING_MMC_DDR52	8
 #define MMC_TIMING_MMC_HS200	9
 
-#define MMC_SDR_MODE		0
-#define MMC_1_2V_DDR_MODE	1
-#define MMC_1_8V_DDR_MODE	2
-#define MMC_1_2V_SDR_MODE	3
-#define MMC_1_8V_SDR_MODE	4
-
 	unsigned char	signal_voltage;		/* signalling voltage (1.8V or 3.3V) */
 
 #define MMC_SIGNAL_VOLTAGE_330	0
include/linux/mmc/mmc.h +8 -4
index 50bcde3..f734c0c 100644
@@ -354,18 +354,22 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-#define EXT_CSD_CARD_TYPE_26	(1<<0)	/* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52	(1<<1)	/* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_MASK	0x3F	/* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
+				 EXT_CSD_CARD_TYPE_HS_52)
 #define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
 					     /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
 					     /* DDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
 					| EXT_CSD_CARD_TYPE_DDR_1_2V)
-#define EXT_CSD_CARD_TYPE_SDR_1_8V	(1<<4)	/* Card can run at 200MHz */
-#define EXT_CSD_CARD_TYPE_SDR_1_2V	(1<<5)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_8V	(1<<4)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V	(1<<5)	/* Card can run at 200MHz */
 						/* SDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
+					 EXT_CSD_CARD_TYPE_HS200_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
Signature · 1 line
1.7.0.4
#119 lore raw

PATCH v6 3/6 mmc: step power class after final selection of bus mode

In reply to Seungwon Jeon

Power class is changed once only after selection of bus modes including speed and bus-width finishes finally.

---
 drivers/mmc/core/mmc.c |   96 +++++++++++++++++++++++++++--------------------
 1 files changed, 55 insertions(+), 41 deletions(-)
drivers/mmc/core/mmc.c +55 -41
index 97f1912..480c100 100644
@@ -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) {
Signature · 1 line
1.7.0.4
#120 lore raw

PATCH v6 4/6 mmc: rework selection of bus speed mode

In reply to Seungwon Jeon

Current implementation for bus speed mode selection is too complicated. This patch is to simplify the codes and remove some duplicate parts.

The following changes are including:
* Adds functions for each mode selection(HS, HS-DDR, HS200 and etc)
* Rearranged the mode selection sequence with supported device type
* Adds maximum speed for HS200 mode(hs200_max_dtr)
* Adds field definition for HS_TIMING of EXT_CSD

---
 drivers/mmc/core/debugfs.c |    2 +-
 drivers/mmc/core/mmc.c     |  431 ++++++++++++++++++++++++--------------------
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/mmc.h    |    4 +
 4 files changed, 238 insertions(+), 200 deletions(-)
drivers/mmc/core/debugfs.c +1 -1
index 509229b..1f730db 100644
@@ -139,7 +139,7 @@ static int mmc_ios_show(struct seq_file *s, void *data)
 		str = "mmc DDR52";
 		break;
 	case MMC_TIMING_MMC_HS200:
-		str = "mmc high-speed SDR200";
+		str = "mmc HS200";
 		break;
 	default:
 		str = "invalid";
drivers/mmc/core/mmc.c +232 -199

510 lines not on this page · raw message

include/linux/mmc/card.h +1 -0
index b9f194a..c422349 100644
@@ -63,6 +63,7 @@ struct mmc_ext_csd {
 	unsigned int            power_off_longtime;     /* Units: ms */
 	u8			power_off_notification;	/* state */
 	unsigned int		hs_max_dtr;
+	unsigned int		hs200_max_dtr;
 #define MMC_HIGH_26_MAX_DTR	26000000
 #define MMC_HIGH_52_MAX_DTR	52000000
 #define MMC_HIGH_DDR_MAX_DTR	52000000
include/linux/mmc/mmc.h +4 -0
index f734c0c..f429f13 100644
@@ -377,6 +377,10 @@ struct _mmc_csd {
 #define EXT_CSD_DDR_BUS_WIDTH_4	5	/* Card is in 4 bit DDR mode */
 #define EXT_CSD_DDR_BUS_WIDTH_8	6	/* Card is in 8 bit DDR mode */
 
+#define EXT_CSD_TIMING_BC	0	/* Backwards compatility */
+#define EXT_CSD_TIMING_HS	1	/* High speed */
+#define EXT_CSD_TIMING_HS200	2	/* HS200 */
+
 #define EXT_CSD_SEC_ER_EN	BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN	BIT(2)
 #define EXT_CSD_SEC_GB_CL_EN	BIT(4)
Signature · 1 line
1.7.0.4
#121 lore raw

PATCH v6 5/6 mmc: add support for HS400 mode of eMMC5.0

In reply to Seungwon Jeon

This patch adds HS400 mode support for eMMC5.0 device. HS400 mode is high speed DDR interface timing from HS200. Clock frequency is up to 200MHz and only 8-bit bus width is supported. In addition, tuning process of HS200 is required to synchronize the command response on the CMD line because CMD input timing for HS400 mode is the same as HS200 mode.

---
 drivers/mmc/core/bus.c     |    1 +
 drivers/mmc/core/debugfs.c |    3 +
 drivers/mmc/core/mmc.c     |   98 +++++++++++++++++++++++++++++++++++++++++--
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/host.h   |   14 ++++++
 include/linux/mmc/mmc.h    |    7 +++-
 6 files changed, 118 insertions(+), 6 deletions(-)
drivers/mmc/core/bus.c +1 -0
index f37e9d6..d2dbf02 100644
@@ -349,6 +349,7 @@ int mmc_add_card(struct mmc_card *card)
 			mmc_hostname(card->host),
 			mmc_card_uhs(card) ? "ultra high speed " :
 			(mmc_card_hs(card) ? "high speed " : ""),
+			mmc_card_hs400(card) ? "HS400 " :
 			(mmc_card_hs200(card) ? "HS200 " : ""),
 			mmc_card_ddr52(card) ? "DDR " : "",
 			uhs_bus_speed_mode, type, card->rca);
drivers/mmc/core/debugfs.c +3 -0
index 1f730db..91eb162 100644
@@ -141,6 +141,9 @@ static int mmc_ios_show(struct seq_file *s, void *data)
 	case MMC_TIMING_MMC_HS200:
 		str = "mmc HS200";
 		break;
+	case MMC_TIMING_MMC_HS400:
+		str = "mmc HS400";
+		break;
 	default:
 		str = "invalid";
 		break;
drivers/mmc/core/mmc.c +93 -5

158 lines not on this page · raw message

include/linux/mmc/card.h +1 -0
index c422349..e68bbeb 100644
@@ -110,6 +110,7 @@ struct mmc_ext_csd {
 	u8			raw_pwr_cl_200_360;	/* 237 */
 	u8			raw_pwr_cl_ddr_52_195;	/* 238 */
 	u8			raw_pwr_cl_ddr_52_360;	/* 239 */
+	u8			raw_pwr_cl_ddr_200_360;	/* 253 */
 	u8			raw_bkops_status;	/* 246 */
 	u8			raw_sectors[4];		/* 212 - 4 bytes */
 
include/linux/mmc/host.h +14 -0
index 1ee3c10..5664d57 100644
@@ -61,6 +61,7 @@ struct mmc_ios {
 #define MMC_TIMING_UHS_DDR50	7
 #define MMC_TIMING_MMC_DDR52	8
 #define MMC_TIMING_MMC_HS200	9
+#define MMC_TIMING_MMC_HS400	10
 
 	unsigned char	signal_voltage;		/* signalling voltage (1.8V or 3.3V) */
 
@@ -132,6 +133,9 @@ struct mmc_host_ops {
 
 	/* The tuning command opcode value is different for SD and eMMC cards */
 	int	(*execute_tuning)(struct mmc_host *host, u32 opcode);
+
+	/* Prepare HS400 target operating frequency depending host driver */
+	void	(*prepare_hs400_tuning)(struct mmc_host *host, struct mmc_ios *ios);
 	int	(*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv);
 	void	(*hw_reset)(struct mmc_host *host);
 	void	(*card_event)(struct mmc_host *host);
@@ -274,6 +278,10 @@ struct mmc_host {
 #define MMC_CAP2_PACKED_CMD	(MMC_CAP2_PACKED_RD | \
 				 MMC_CAP2_PACKED_WR)
 #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)	/* Don't power up before scan */
+#define MMC_CAP2_HS400_1_8V	(1 << 15)	/* Can support HS400 1.8V */
+#define MMC_CAP2_HS400_1_2V	(1 << 16)	/* Can support HS400 1.2V */
+#define MMC_CAP2_HS400		(MMC_CAP2_HS400_1_8V | \
+				 MMC_CAP2_HS400_1_2V)
 
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
 
@@ -493,4 +501,10 @@ static inline bool mmc_card_ddr52(struct mmc_card *card)
 {
 	return card->host->ios.timing == MMC_TIMING_MMC_DDR52;
 }
+
+static inline bool mmc_card_hs400(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_MMC_HS400;
+}
+
 #endif /* LINUX_MMC_HOST_H */
include/linux/mmc/mmc.h +6 -1
index f429f13..64ec963 100644
@@ -325,6 +325,7 @@ struct _mmc_csd {
 #define EXT_CSD_POWER_OFF_LONG_TIME	247	/* RO */
 #define EXT_CSD_GENERIC_CMD6_TIME	248	/* RO */
 #define EXT_CSD_CACHE_SIZE		249	/* RO, 4 bytes */
+#define EXT_CSD_PWR_CL_DDR_200_360	253	/* RO */
 #define EXT_CSD_TAG_UNIT_SIZE		498	/* RO */
 #define EXT_CSD_DATA_TAG_SUPPORT	499	/* RO */
 #define EXT_CSD_MAX_PACKED_WRITES	500	/* RO */
@@ -354,7 +355,6 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-#define EXT_CSD_CARD_TYPE_MASK	0x3F	/* Mask out reserved bits */
 #define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
 #define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
@@ -370,6 +370,10 @@ struct _mmc_csd {
 						/* SDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
 					 EXT_CSD_CARD_TYPE_HS200_1_2V)
+#define EXT_CSD_CARD_TYPE_HS400_1_8V	(1<<6)	/* Card can run at 200MHz DDR, 1.8V */
+#define EXT_CSD_CARD_TYPE_HS400_1_2V	(1<<7)	/* Card can run at 200MHz DDR, 1.2V */
+#define EXT_CSD_CARD_TYPE_HS400		(EXT_CSD_CARD_TYPE_HS400_1_8V | \
+					 EXT_CSD_CARD_TYPE_HS400_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
@@ -380,6 +384,7 @@ struct _mmc_csd {
 #define EXT_CSD_TIMING_BC	0	/* Backwards compatility */
 #define EXT_CSD_TIMING_HS	1	/* High speed */
 #define EXT_CSD_TIMING_HS200	2	/* HS200 */
+#define EXT_CSD_TIMING_HS400	3	/* HS400 */
 
 #define EXT_CSD_SEC_ER_EN	BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN	BIT(2)
Signature · 1 line
1.7.0.4
#122 lore raw

PATCH v6 6/6 mmc: core: add DT bindings for eMMC HS400 1.8/1.2V

In reply to Seungwon Jeon

Provide the option to configure these speed modes per host, for those host driver's that can't distinguish this in runtime. Specially, if host can support HS400, it means that host can also support HS200.

---
 Documentation/devicetree/bindings/mmc/mmc.txt |    2 ++
 drivers/mmc/core/host.c                       |    4 ++++
 2 files changed, 6 insertions(+), 0 deletions(-)
Documentation/devicetree/bindings/mmc/mmc.txt +2 -0
index 9dce540..3c18001 100644
@@ -38,6 +38,8 @@ Optional properties:
 - mmc-highspeed-ddr-1_2v: eMMC high-speed DDR mode(1.2V I/O) is supported
 - mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported
 - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
+- mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported
+- mmc-hs400-1_2v: eMMC HS400 mode(1.2V I/O) is supported
 
 *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
 polarity properties, we have to fix the meaning of the "normal" and "inverted"
drivers/mmc/core/host.c +4 -0
index fdea825..95cceae 100644
@@ -447,6 +447,10 @@ int mmc_of_parse(struct mmc_host *host)
 		host->caps2 |= MMC_CAP2_HS200_1_8V_SDR;
 	if (of_find_property(np, "mmc-hs200-1_2v", &len))
 		host->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
+	if (of_find_property(np, "mmc-hs400-1_8v", &len))
+		host->caps2 |= MMC_CAP2_HS400_1_8V | MMC_CAP2_HS200_1_8V_SDR;
+	if (of_find_property(np, "mmc-hs400-1_2v", &len))
+		host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;
 
 	return 0;
 
Signature · 1 line
1.7.0.4
author Acked-by on v6 6/6
#123 lore raw

Re: [PATCH v6 6/6] mmc: core: add DT bindings for eMMC HS400 1.8/1.2V

Quoted 6 lines · Seungwon Jeon

Provide the option to configure these speed modes per host, for those host driver's that can't distinguish this in runtime. Specially, if host can support HS400, it means that host can also support HS200.

Quoted 37 lines
---
 Documentation/devicetree/bindings/mmc/mmc.txt |    2 ++
 drivers/mmc/core/host.c                       |    4 ++++
 2 files changed, 6 insertions(+), 0 deletions(-)
Documentation/devicetree/bindings/mmc/mmc.txt +2 -0
index 9dce540..3c18001 100644
@@ -38,6 +38,8 @@ Optional properties:
 - mmc-highspeed-ddr-1_2v: eMMC high-speed DDR mode(1.2V I/O) is supported
 - mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported
 - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
+- mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported
+- mmc-hs400-1_2v: eMMC HS400 mode(1.2V I/O) is supported
 
 *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
 polarity properties, we have to fix the meaning of the "normal" and "inverted"
drivers/mmc/core/host.c +4 -1
index fdea825..95cceae 100644
@@ -447,6 +447,10 @@ int mmc_of_parse(struct mmc_host *host)
                host->caps2 |= MMC_CAP2_HS200_1_8V_SDR;
        if (of_find_property(np, "mmc-hs200-1_2v", &len))
                host->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
+       if (of_find_property(np, "mmc-hs400-1_8v", &len))
+               host->caps2 |= MMC_CAP2_HS400_1_8V | MMC_CAP2_HS200_1_8V_SDR;
+       if (of_find_property(np, "mmc-hs400-1_2v", &len))
+               host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;
 
        return 0;
 
--

1.7.0.4

#124 lore raw

cover update selection of bus speed mode for eMMC

In reply to Seungwon Jeon

This series contains the change for selection of bus speed mode. Previous implementation is complicated and some sequence is duplicated. And specially, HS400 mode eMMC5.0 is introduced this time. This patch-set has been tested in Exynos SoC.

Note:
As RS9113 wireless driver has been introduced newly in Linux-3.15-rc1, we meet some dependency with this patch-set
which has been in the works all the while.
Thus, related modification is applied through " mmc: drop the speed mode of card's state"
---
Changes in v6:
(6/6) Included "mmc: core: add DT bindings for eMMC HS400 1.8/1.2V" into this patch-set

Changes in v5:
(5/5) Added callback operation for HS400 target operation frequency
instead of specific timing identifier.
(2/5) Removed using union declaration.

Changes in v4:
(5/5)Reverting to HS mode is included in mmc_select_hs400() using __mmc_switch().

Changes in v3:
Removed the function to check DDR type(mmc_snoop_ddr). Rebased with the latest branch.

Seungwon Jeon (6):
mmc: drop the speed mode of card's state
mmc: identify available device type to select
mmc: step power class after final selection of bus mode
mmc: rework selection of bus speed mode
mmc: add support for HS400 mode of eMMC5.0
mmc: add DT bindings for eMMC HS400 1.8/1.2V

 Documentation/devicetree/bindings/mmc/mmc.txt |    2 +
 drivers/mmc/core/bus.c                        |    9 +-
 drivers/mmc/core/core.c                       |    3 +-
 drivers/mmc/core/debugfs.c                    |    5 +-
 drivers/mmc/core/host.c                       |    4 +
 drivers/mmc/core/mmc.c                        |  666 +++++++++++++++----------
 drivers/mmc/core/sd.c                         |   16 +-
 drivers/mmc/core/sd.h                         |    1 -
 drivers/mmc/core/sdio.c                       |    8 +-
 drivers/net/wireless/rsi/rsi_91x_sdio.c       |    4 +-
 include/linux/mmc/card.h                      |   27 +-
 include/linux/mmc/host.h                      |   43 ++-
 include/linux/mmc/mmc.h                       |   23 +-
 13 files changed, 487 insertions(+), 324 deletions(-)

Thanks,
sw-j

#125 lore raw

PATCH 1/6 mmc: drop the speed mode of card's state

In reply to Seungwon Jeon

Timing mode identifier has same role and can take the place of speed mode. This change removes all related speed mode.

---
 drivers/mmc/core/bus.c                  |    8 ++++----
 drivers/mmc/core/core.c                 |    3 +--
 drivers/mmc/core/mmc.c                  |   11 +++--------
 drivers/mmc/core/sd.c                   |   16 +++-------------
 drivers/mmc/core/sd.h                   |    1 -
 drivers/mmc/core/sdio.c                 |    8 ++------
 drivers/net/wireless/rsi/rsi_91x_sdio.c |    4 +---
 include/linux/mmc/card.h                |   23 ++++++-----------------
 include/linux/mmc/host.h                |   23 +++++++++++++++++++++++
 9 files changed, 43 insertions(+), 54 deletions(-)
drivers/mmc/core/bus.c +4 -4
index 8246448..f37e9d6 100644
@@ -341,16 +341,16 @@ int mmc_add_card(struct mmc_card *card)
 	if (mmc_host_is_spi(card->host)) {
 		pr_info("%s: new %s%s%s card on SPI\n",
 			mmc_hostname(card->host),
-			mmc_card_highspeed(card) ? "high speed " : "",
-			mmc_card_ddr_mode(card) ? "DDR " : "",
+			mmc_card_hs(card) ? "high speed " : "",
+			mmc_card_ddr52(card) ? "DDR " : "",
 			type);
 	} else {
 		pr_info("%s: new %s%s%s%s%s card at address %04x\n",
 			mmc_hostname(card->host),
 			mmc_card_uhs(card) ? "ultra high speed " :
-			(mmc_card_highspeed(card) ? "high speed " : ""),
+			(mmc_card_hs(card) ? "high speed " : ""),
 			(mmc_card_hs200(card) ? "HS200 " : ""),
-			mmc_card_ddr_mode(card) ? "DDR " : "",
+			mmc_card_ddr52(card) ? "DDR " : "",
 			uhs_bus_speed_mode, type, card->rca);
 	}
 
drivers/mmc/core/core.c +1 -2
index 79ba3a5..4b058ae 100644
@@ -2187,7 +2187,7 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
 {
 	struct mmc_command cmd = {0};
 
-	if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card))
+	if (mmc_card_blockaddr(card) || mmc_card_ddr52(card))
 		return 0;
 
 	cmd.opcode = MMC_SET_BLOCKLEN;
@@ -2267,7 +2267,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
 		}
 	}
 
-	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_DDR);
 	if (mmc_host_is_spi(host)) {
 		host->ios.chip_select = MMC_CS_HIGH;
 		host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
drivers/mmc/core/mmc.c +3 -8
index fbcf93d..3122052 100644
@@ -1083,11 +1083,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		} else {
 			if (card->ext_csd.hs_max_dtr > 52000000 &&
 			    host->caps2 & MMC_CAP2_HS200) {
-				mmc_card_set_hs200(card);
 				mmc_set_timing(card->host,
 					       MMC_TIMING_MMC_HS200);
 			} else {
-				mmc_card_set_highspeed(card);
 				mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
 			}
 		}
@@ -1098,10 +1096,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	max_dtr = (unsigned int)-1;
 
-	if (mmc_card_highspeed(card) || mmc_card_hs200(card)) {
+	if (mmc_card_hs(card) || mmc_card_hs200(card)) {
 		if (max_dtr > card->ext_csd.hs_max_dtr)
 			max_dtr = card->ext_csd.hs_max_dtr;
-		if (mmc_card_highspeed(card) && (max_dtr > 52000000))
+		if (mmc_card_hs(card) && (max_dtr > 52000000))
 			max_dtr = 52000000;
 	} else if (max_dtr > card->csd.max_dtr) {
 		max_dtr = card->csd.max_dtr;
@@ -1112,7 +1110,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	/*
 	 * Indicate DDR mode (if supported).
 	 */
-	if (mmc_card_highspeed(card)) {
+	if (mmc_card_hs(card)) {
 		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
 			&& (host->caps & MMC_CAP_1_8V_DDR))
 				ddr = MMC_1_8V_DDR_MODE;
@@ -1255,7 +1253,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 				if (err)
 					goto err;
 			}
-			mmc_card_set_ddr_mode(card);
 			mmc_set_timing(card->host, MMC_TIMING_MMC_DDR52);
 			mmc_set_bus_width(card->host, bus_width);
 		}
@@ -1499,7 +1496,6 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
 		err = mmc_sleep(host);
 	else if (!mmc_host_is_spi(host))
 		err = mmc_deselect_cards(host);
-	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
 
 	if (!err) {
 		mmc_power_off(host);
@@ -1629,7 +1625,6 @@ static int mmc_power_restore(struct mmc_host *host)
 {
 	int ret;
 
-	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
 	mmc_claim_host(host);
 	ret = mmc_init_card(host, host->card->ocr, host->card);
 	mmc_release_host(host);
drivers/mmc/core/sd.c +3 -13
index aef5157..0c44510 100644
@@ -887,7 +887,7 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
 {
 	unsigned max_dtr = (unsigned int)-1;
 
-	if (mmc_card_highspeed(card)) {
+	if (mmc_card_hs(card)) {
 		if (max_dtr > card->sw_caps.hs_max_dtr)
 			max_dtr = card->sw_caps.hs_max_dtr;
 	} else if (max_dtr > card->csd.max_dtr) {
@@ -897,12 +897,6 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
 	return max_dtr;
 }
 
-void mmc_sd_go_highspeed(struct mmc_card *card)
-{
-	mmc_card_set_highspeed(card);
-	mmc_set_timing(card->host, MMC_TIMING_SD_HS);
-}
-
 /*
  * Handle the detection and initialisation of a card.
  *
@@ -977,16 +971,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
 		err = mmc_sd_init_uhs_card(card);
 		if (err)
 			goto free_card;
-
-		/* Card is an ultra-high-speed card */
-		mmc_card_set_uhs(card);
 	} else {
 		/*
 		 * Attempt to change to high-speed (if supported)
 		 */
 		err = mmc_sd_switch_hs(card);
 		if (err > 0)
-			mmc_sd_go_highspeed(card);
+			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
 		else if (err)
 			goto free_card;
 
@@ -1081,7 +1072,7 @@ static int _mmc_sd_suspend(struct mmc_host *host)
 
 	if (!mmc_host_is_spi(host))
 		err = mmc_deselect_cards(host);
-	host->card->state &= ~MMC_STATE_HIGHSPEED;
+
 	if (!err) {
 		mmc_power_off(host);
 		mmc_card_set_suspended(host->card);
@@ -1190,7 +1181,6 @@ static int mmc_sd_power_restore(struct mmc_host *host)
 {
 	int ret;
 
-	host->card->state &= ~MMC_STATE_HIGHSPEED;
 	mmc_claim_host(host);
 	ret = mmc_sd_init_card(host, host->card->ocr, host->card);
 	mmc_release_host(host);
drivers/mmc/core/sd.h +0 -1
index 4b34b24..aab824a 100644
@@ -12,6 +12,5 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
 	bool reinit);
 unsigned mmc_sd_get_max_clock(struct mmc_card *card);
 int mmc_sd_switch_hs(struct mmc_card *card);
-void mmc_sd_go_highspeed(struct mmc_card *card);
 
 #endif
drivers/mmc/core/sdio.c +2 -6
index 9933e42..e636d9e 100644
@@ -363,7 +363,7 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card)
 {
 	unsigned max_dtr;
 
-	if (mmc_card_highspeed(card)) {
+	if (mmc_card_hs(card)) {
 		/*
 		 * The SDIO specification doesn't mention how
 		 * the CIS transfer speed register relates to
@@ -733,7 +733,6 @@ try_again:
 		mmc_set_clock(host, card->cis.max_dtr);
 
 		if (card->cccr.high_speed) {
-			mmc_card_set_highspeed(card);
 			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
 		}
 
@@ -792,16 +791,13 @@ try_again:
 		err = mmc_sdio_init_uhs_card(card);
 		if (err)
 			goto remove;
-
-		/* Card is an ultra-high-speed card */
-		mmc_card_set_uhs(card);
 	} else {
 		/*
 		 * Switch to high-speed (if supported).
 		 */
 		err = sdio_enable_hs(card);
 		if (err > 0)
-			mmc_sd_go_highspeed(card);
+			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
 		else if (err)
 			goto remove;
 
drivers/net/wireless/rsi/rsi_91x_sdio.c +1 -3
index 2e39d38..46e7af4 100644
@@ -285,7 +285,6 @@ static void rsi_reset_card(struct sdio_func *pfunction)
 		if (err) {
 			rsi_dbg(ERR_ZONE, "%s: CCCR speed reg read failed: %d\n",
 				__func__, err);
-			card->state &= ~MMC_STATE_HIGHSPEED;
 		} else {
 			err = rsi_cmd52writebyte(card,
 						 SDIO_CCCR_SPEED,
@@ -296,14 +295,13 @@ static void rsi_reset_card(struct sdio_func *pfunction)
 					__func__, err);
 				return;
 			}
-			mmc_card_set_highspeed(card);
 			host->ios.timing = MMC_TIMING_SD_HS;
 			host->ops->set_ios(host, &host->ios);
 		}
 	}
 
 	/* Set clock */
-	if (mmc_card_highspeed(card))
+	if (mmc_card_hs(card))
 		clock = 50000000;
 	else
 		clock = card->cis.max_dtr;
include/linux/mmc/card.h +6 -17
index aa7e57f..aadeaf1 100644
@@ -194,6 +194,7 @@ struct sdio_cis {
 };
 
 struct mmc_host;
+struct mmc_ios;
 struct sdio_func;
 struct sdio_func_tuple;
 
@@ -250,15 +251,11 @@ struct mmc_card {
 	unsigned int		state;		/* (our) card state */
 #define MMC_STATE_PRESENT	(1<<0)		/* present in sysfs */
 #define MMC_STATE_READONLY	(1<<1)		/* card is read-only */
-#define MMC_STATE_HIGHSPEED	(1<<2)		/* card is in high speed mode */
-#define MMC_STATE_BLOCKADDR	(1<<3)		/* card uses block-addressing */
-#define MMC_STATE_HIGHSPEED_DDR (1<<4)		/* card is in high speed mode */
-#define MMC_STATE_ULTRAHIGHSPEED (1<<5)		/* card is in ultra high speed mode */
-#define MMC_CARD_SDXC		(1<<6)		/* card is SDXC */
-#define MMC_CARD_REMOVED	(1<<7)		/* card has been removed */
-#define MMC_STATE_HIGHSPEED_200	(1<<8)		/* card is in HS200 mode */
-#define MMC_STATE_DOING_BKOPS	(1<<10)		/* card is doing BKOPS */
-#define MMC_STATE_SUSPENDED	(1<<11)		/* card is suspended */
+#define MMC_STATE_BLOCKADDR	(1<<2)		/* card uses block-addressing */
+#define MMC_CARD_SDXC		(1<<3)		/* card is SDXC */
+#define MMC_CARD_REMOVED	(1<<4)		/* card has been removed */
+#define MMC_STATE_DOING_BKOPS	(1<<5)		/* card is doing BKOPS */
+#define MMC_STATE_SUSPENDED	(1<<6)		/* card is suspended */
 	unsigned int		quirks; 	/* card quirks */
 #define MMC_QUIRK_LENIENT_FN0	(1<<0)		/* allow SDIO FN0 writes outside of the VS CCCR range */
 #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1)	/* use func->cur_blksize */
@@ -418,11 +415,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 
 #define mmc_card_present(c)	((c)->state & MMC_STATE_PRESENT)
 #define mmc_card_readonly(c)	((c)->state & MMC_STATE_READONLY)
-#define mmc_card_highspeed(c)	((c)->state & MMC_STATE_HIGHSPEED)
-#define mmc_card_hs200(c)	((c)->state & MMC_STATE_HIGHSPEED_200)
 #define mmc_card_blockaddr(c)	((c)->state & MMC_STATE_BLOCKADDR)
-#define mmc_card_ddr_mode(c)	((c)->state & MMC_STATE_HIGHSPEED_DDR)
-#define mmc_card_uhs(c)		((c)->state & MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
 #define mmc_card_removed(c)	((c) && ((c)->state & MMC_CARD_REMOVED))
 #define mmc_card_doing_bkops(c)	((c)->state & MMC_STATE_DOING_BKOPS)
@@ -430,11 +423,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 
 #define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
-#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
-#define mmc_card_set_hs200(c)	((c)->state |= MMC_STATE_HIGHSPEED_200)
 #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
-#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
-#define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
 #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
 #define mmc_card_set_doing_bkops(c)	((c)->state |= MMC_STATE_DOING_BKOPS)
include/linux/mmc/host.h +23 -0
index 0cf705c..a438537 100644
@@ -17,6 +17,7 @@
 #include <linux/fault-inject.h>
 
 #include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
 #include <linux/mmc/pm.h>
 
 struct mmc_ios {
@@ -478,4 +479,26 @@ static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
 	return host->ios.clock;
 }
 #endif
+
+static inline int mmc_card_hs(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_SD_HS ||
+		card->host->ios.timing == MMC_TIMING_MMC_HS;
+}
+
+static inline int mmc_card_uhs(struct mmc_card *card)
+{
+	return card->host->ios.timing >= MMC_TIMING_UHS_SDR12 &&
+		card->host->ios.timing <= MMC_TIMING_UHS_DDR50;
+}
+
+static inline bool mmc_card_hs200(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_MMC_HS200;
+}
+
+static inline bool mmc_card_ddr52(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_MMC_DDR52;
+}
 #endif /* LINUX_MMC_HOST_H */
Signature · 7 lines
1.7.0.4


--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#126 lore raw

Re: [PATCH 1/6] mmc: drop the speed mode of card's state

Quoted 8 lines · Seungwon Jeon

Timing mode identifier has same role and can take the place of speed mode. This change removes all related speed mode.

Quoted 11 lines
---
 drivers/mmc/core/bus.c                  |    8 ++++----
 drivers/mmc/core/core.c                 |    3 +--
 drivers/mmc/core/mmc.c                  |   11 +++--------
 drivers/mmc/core/sd.c                   |   16 +++-------------
 drivers/mmc/core/sd.h                   |    1 -
 drivers/mmc/core/sdio.c                 |    8 ++------
 drivers/net/wireless/rsi/rsi_91x_sdio.c |    4 +---
 include/linux/mmc/card.h                |   23 ++++++-----------------
 include/linux/mmc/host.h                |   23 +++++++++++++++++++++++
 9 files changed, 43 insertions(+), 54 deletions(-)

Hi John,

We would like to queue this patch through Chris' mmc tree for 3.16.

Since it touches the rsi wireless driver, could you please have a look and let's us know if you have any concerns.

Kind regards
Ulf Hansson

#127 lore raw

PATCH 2/6 mmc: identify available device type to select

In reply to Seungwon Jeon

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

---
 drivers/mmc/core/mmc.c   |   72 +++++++++++++++++++++++++---------------------
 include/linux/mmc/card.h |    2 +-
 include/linux/mmc/host.h |    6 ----
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 48 insertions(+), 44 deletions(-)
drivers/mmc/core/mmc.c +39 -33
index 3122052..b5691fe 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
 	u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
 	u32 caps = host->caps, caps2 = host->caps2;
 	unsigned int hs_max_dtr = 0;
+	unsigned int avail_type = 0;
 
-	if (card_type & EXT_CSD_CARD_TYPE_26)
+	if (caps & MMC_CAP_MMC_HIGHSPEED &&
+	    card_type & EXT_CSD_CARD_TYPE_HS_26) {
 		hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+	}
 
 	if (caps & MMC_CAP_MMC_HIGHSPEED &&
-			card_type & EXT_CSD_CARD_TYPE_52)
+	    card_type & EXT_CSD_CARD_TYPE_HS_52) {
 		hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+	}
 
-	if ((caps & MMC_CAP_1_8V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-	    (caps & MMC_CAP_1_2V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+	if (caps & MMC_CAP_1_8V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
 		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+	}
+
+	if (caps & MMC_CAP_1_2V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+	}
 
-	if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-	    (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+	if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
 		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+	}
 
 	card->ext_csd.hs_max_dtr = hs_max_dtr;
-	card->ext_csd.card_type = card_type;
+	card->mmc_avail_type = avail_type;
 }
 
 /*
@@ -800,12 +818,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
 	host = card->host;
 
-	if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-			host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+	if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-	if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-			host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+	if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
 	/* If fails try again during next card power cycle */
@@ -1064,10 +1080,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	if (card->ext_csd.hs_max_dtr != 0) {
 		err = 0;
-		if (card->ext_csd.hs_max_dtr > 52000000 &&
-		    host->caps2 & MMC_CAP2_HS200)
+		if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
 			err = mmc_select_hs200(card);
-		else if	(host->caps & MMC_CAP_MMC_HIGHSPEED)
+		else if	(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
 			err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 					EXT_CSD_HS_TIMING, 1,
 					card->ext_csd.generic_cmd6_time,
@@ -1081,13 +1096,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			       mmc_hostname(card->host));
 			err = 0;
 		} else {
-			if (card->ext_csd.hs_max_dtr > 52000000 &&
-			    host->caps2 & MMC_CAP2_HS200) {
+			if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
 				mmc_set_timing(card->host,
 					       MMC_TIMING_MMC_HS200);
-			} else {
+			else
 				mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-			}
 		}
 	}
 
@@ -1110,14 +1123,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	/*
 	 * Indicate DDR mode (if supported).
 	 */
-	if (mmc_card_hs(card)) {
-		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
-			&& (host->caps & MMC_CAP_1_8V_DDR))
-				ddr = MMC_1_8V_DDR_MODE;
-		else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
-			&& (host->caps & MMC_CAP_1_2V_DDR))
-				ddr = MMC_1_2V_DDR_MODE;
-	}
+	if (mmc_card_hs(card))
+		ddr = card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
 
 	/*
 	 * Indicate HS200 SDR mode (if supported).
@@ -1137,8 +1144,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		 * 3. set the clock to > 52Mhz <=200MHz and
 		 * 4. execute tuning for HS200
 		 */
-		if ((host->caps2 & MMC_CAP2_HS200) &&
-		    card->host->ops->execute_tuning) {
+		if (card->host->ops->execute_tuning) {
 			mmc_host_clk_hold(card->host);
 			err = card->host->ops->execute_tuning(card->host,
 				MMC_SEND_TUNING_BLOCK_HS200);
@@ -1247,7 +1253,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			 *
 			 * WARNING: eMMC rules are NOT the same as SD DDR
 			 */
-			if (ddr == MMC_1_2V_DDR_MODE) {
+			if (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) {
 				err = __mmc_set_signal_voltage(host,
 					MMC_SIGNAL_VOLTAGE_120);
 				if (err)
include/linux/mmc/card.h +1 -1
index aadeaf1..fe31f8d 100644
@@ -68,7 +68,6 @@ struct mmc_ext_csd {
 #define MMC_HIGH_DDR_MAX_DTR	52000000
 #define MMC_HS200_MAX_DTR	200000000
 	unsigned int		sectors;
-	unsigned int		card_type;
 	unsigned int		hc_erase_size;		/* In sectors */
 	unsigned int		hc_erase_timeout;	/* In milliseconds */
 	unsigned int		sec_trim_mult;	/* Secure trim multiplier  */
@@ -298,6 +297,7 @@ struct mmc_card {
 	struct sdio_func_tuple	*tuples;	/* unknown common tuples */
 
 	unsigned int		sd_bus_speed;	/* Bus Speed Mode set for the card */
+	unsigned int		mmc_avail_type;	/* supported device type by both host and card */
 
 	struct dentry		*debugfs_root;
 	struct mmc_part	part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
include/linux/mmc/host.h +0 -6
index a438537..6b1e9ee 100644
@@ -62,12 +62,6 @@ struct mmc_ios {
 #define MMC_TIMING_MMC_DDR52	8
 #define MMC_TIMING_MMC_HS200	9
 
-#define MMC_SDR_MODE		0
-#define MMC_1_2V_DDR_MODE	1
-#define MMC_1_8V_DDR_MODE	2
-#define MMC_1_2V_SDR_MODE	3
-#define MMC_1_8V_SDR_MODE	4
-
 	unsigned char	signal_voltage;		/* signalling voltage (1.8V or 3.3V) */
 
 #define MMC_SIGNAL_VOLTAGE_330	0
include/linux/mmc/mmc.h +8 -4
index 50bcde3..f734c0c 100644
@@ -354,18 +354,22 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-#define EXT_CSD_CARD_TYPE_26	(1<<0)	/* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52	(1<<1)	/* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_MASK	0x3F	/* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
+				 EXT_CSD_CARD_TYPE_HS_52)
 #define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
 					     /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
 					     /* DDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
 					| EXT_CSD_CARD_TYPE_DDR_1_2V)
-#define EXT_CSD_CARD_TYPE_SDR_1_8V	(1<<4)	/* Card can run at 200MHz */
-#define EXT_CSD_CARD_TYPE_SDR_1_2V	(1<<5)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_8V	(1<<4)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V	(1<<5)	/* Card can run at 200MHz */
 						/* SDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
+					 EXT_CSD_CARD_TYPE_HS200_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
Signature · 1 line
1.7.0.4
#128 lore raw

PATCH 3/6 mmc: step power class after final selection of bus mode

In reply to Seungwon Jeon

Power class is changed once only after selection of bus modes including speed and bus-width finishes finally.

---
 drivers/mmc/core/mmc.c |   96 +++++++++++++++++++++++++++--------------------
 1 files changed, 55 insertions(+), 41 deletions(-)
drivers/mmc/core/mmc.c +55 -41
index b5691fe..4538541 100644
@@ -724,17 +724,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)
@@ -746,14 +742,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:
@@ -764,14 +760,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 "
@@ -797,6 +793,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
@@ -1158,11 +1185,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);
 	}
 
 	/*
@@ -1191,12 +1213,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,
@@ -1221,13 +1237,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],
@@ -1265,6 +1274,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) {
Signature · 1 line
1.7.0.4
#129 lore raw

PATCH 4/6 mmc: rework selection of bus speed mode

In reply to Seungwon Jeon

Current implementation for bus speed mode selection is too complicated. This patch is to simplify the codes and remove some duplicate parts.

The following changes are including:
* Adds functions for each mode selection(HS, HS-DDR, HS200 and etc)
* Rearranged the mode selection sequence with supported device type
* Adds maximum speed for HS200 mode(hs200_max_dtr)
* Adds field definition for HS_TIMING of EXT_CSD

---
 drivers/mmc/core/debugfs.c |    2 +-
 drivers/mmc/core/mmc.c     |  431 ++++++++++++++++++++++++--------------------
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/mmc.h    |    4 +
 4 files changed, 238 insertions(+), 200 deletions(-)
drivers/mmc/core/debugfs.c +1 -1
index 509229b..1f730db 100644
@@ -139,7 +139,7 @@ static int mmc_ios_show(struct seq_file *s, void *data)
 		str = "mmc DDR52";
 		break;
 	case MMC_TIMING_MMC_HS200:
-		str = "mmc high-speed SDR200";
+		str = "mmc HS200";
 		break;
 	default:
 		str = "invalid";
drivers/mmc/core/mmc.c +232 -199

510 lines not on this page · raw message

include/linux/mmc/card.h +1 -0
index fe31f8d..1760736 100644
@@ -63,6 +63,7 @@ struct mmc_ext_csd {
 	unsigned int            power_off_longtime;     /* Units: ms */
 	u8			power_off_notification;	/* state */
 	unsigned int		hs_max_dtr;
+	unsigned int		hs200_max_dtr;
 #define MMC_HIGH_26_MAX_DTR	26000000
 #define MMC_HIGH_52_MAX_DTR	52000000
 #define MMC_HIGH_DDR_MAX_DTR	52000000
include/linux/mmc/mmc.h +4 -0
index f734c0c..f429f13 100644
@@ -377,6 +377,10 @@ struct _mmc_csd {
 #define EXT_CSD_DDR_BUS_WIDTH_4	5	/* Card is in 4 bit DDR mode */
 #define EXT_CSD_DDR_BUS_WIDTH_8	6	/* Card is in 8 bit DDR mode */
 
+#define EXT_CSD_TIMING_BC	0	/* Backwards compatility */
+#define EXT_CSD_TIMING_HS	1	/* High speed */
+#define EXT_CSD_TIMING_HS200	2	/* HS200 */
+
 #define EXT_CSD_SEC_ER_EN	BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN	BIT(2)
 #define EXT_CSD_SEC_GB_CL_EN	BIT(4)
Signature · 1 line
1.7.0.4
#130 lore raw

PATCH 5/6 mmc: add support for HS400 mode of eMMC5.0

In reply to Seungwon Jeon

This patch adds HS400 mode support for eMMC5.0 device. HS400 mode is high speed DDR interface timing from HS200. Clock frequency is up to 200MHz and only 8-bit bus width is supported. In addition, tuning process of HS200 is required to synchronize the command response on the CMD line because CMD input timing for HS400 mode is the same as HS200 mode.

---
 drivers/mmc/core/bus.c     |    1 +
 drivers/mmc/core/debugfs.c |    3 +
 drivers/mmc/core/mmc.c     |   98 +++++++++++++++++++++++++++++++++++++++++--
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/host.h   |   14 ++++++
 include/linux/mmc/mmc.h    |    7 +++-
 6 files changed, 118 insertions(+), 6 deletions(-)
drivers/mmc/core/bus.c +1 -0
index f37e9d6..d2dbf02 100644
@@ -349,6 +349,7 @@ int mmc_add_card(struct mmc_card *card)
 			mmc_hostname(card->host),
 			mmc_card_uhs(card) ? "ultra high speed " :
 			(mmc_card_hs(card) ? "high speed " : ""),
+			mmc_card_hs400(card) ? "HS400 " :
 			(mmc_card_hs200(card) ? "HS200 " : ""),
 			mmc_card_ddr52(card) ? "DDR " : "",
 			uhs_bus_speed_mode, type, card->rca);
drivers/mmc/core/debugfs.c +3 -0
index 1f730db..91eb162 100644
@@ -141,6 +141,9 @@ static int mmc_ios_show(struct seq_file *s, void *data)
 	case MMC_TIMING_MMC_HS200:
 		str = "mmc HS200";
 		break;
+	case MMC_TIMING_MMC_HS400:
+		str = "mmc HS400";
+		break;
 	default:
 		str = "invalid";
 		break;
drivers/mmc/core/mmc.c +93 -5

158 lines not on this page · raw message

include/linux/mmc/card.h +1 -0
index 1760736..d424b9d 100644
@@ -110,6 +110,7 @@ struct mmc_ext_csd {
 	u8			raw_pwr_cl_200_360;	/* 237 */
 	u8			raw_pwr_cl_ddr_52_195;	/* 238 */
 	u8			raw_pwr_cl_ddr_52_360;	/* 239 */
+	u8			raw_pwr_cl_ddr_200_360;	/* 253 */
 	u8			raw_bkops_status;	/* 246 */
 	u8			raw_sectors[4];		/* 212 - 4 bytes */
 
include/linux/mmc/host.h +14 -0
index 6b1e9ee..1830873 100644
@@ -61,6 +61,7 @@ struct mmc_ios {
 #define MMC_TIMING_UHS_DDR50	7
 #define MMC_TIMING_MMC_DDR52	8
 #define MMC_TIMING_MMC_HS200	9
+#define MMC_TIMING_MMC_HS400	10
 
 	unsigned char	signal_voltage;		/* signalling voltage (1.8V or 3.3V) */
 
@@ -132,6 +133,9 @@ struct mmc_host_ops {
 
 	/* The tuning command opcode value is different for SD and eMMC cards */
 	int	(*execute_tuning)(struct mmc_host *host, u32 opcode);
+
+	/* Prepare HS400 target operating frequency depending host driver */
+	int	(*prepare_hs400_tuning)(struct mmc_host *host, struct mmc_ios *ios);
 	int	(*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv);
 	void	(*hw_reset)(struct mmc_host *host);
 	void	(*card_event)(struct mmc_host *host);
@@ -274,6 +278,10 @@ struct mmc_host {
 #define MMC_CAP2_PACKED_CMD	(MMC_CAP2_PACKED_RD | \
 				 MMC_CAP2_PACKED_WR)
 #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)	/* Don't power up before scan */
+#define MMC_CAP2_HS400_1_8V	(1 << 15)	/* Can support HS400 1.8V */
+#define MMC_CAP2_HS400_1_2V	(1 << 16)	/* Can support HS400 1.2V */
+#define MMC_CAP2_HS400		(MMC_CAP2_HS400_1_8V | \
+				 MMC_CAP2_HS400_1_2V)
 
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
 
@@ -495,4 +503,10 @@ static inline bool mmc_card_ddr52(struct mmc_card *card)
 {
 	return card->host->ios.timing == MMC_TIMING_MMC_DDR52;
 }
+
+static inline bool mmc_card_hs400(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_MMC_HS400;
+}
+
 #endif /* LINUX_MMC_HOST_H */
include/linux/mmc/mmc.h +6 -1
index f429f13..64ec963 100644
@@ -325,6 +325,7 @@ struct _mmc_csd {
 #define EXT_CSD_POWER_OFF_LONG_TIME	247	/* RO */
 #define EXT_CSD_GENERIC_CMD6_TIME	248	/* RO */
 #define EXT_CSD_CACHE_SIZE		249	/* RO, 4 bytes */
+#define EXT_CSD_PWR_CL_DDR_200_360	253	/* RO */
 #define EXT_CSD_TAG_UNIT_SIZE		498	/* RO */
 #define EXT_CSD_DATA_TAG_SUPPORT	499	/* RO */
 #define EXT_CSD_MAX_PACKED_WRITES	500	/* RO */
@@ -354,7 +355,6 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-#define EXT_CSD_CARD_TYPE_MASK	0x3F	/* Mask out reserved bits */
 #define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
 #define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
@@ -370,6 +370,10 @@ struct _mmc_csd {
 						/* SDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
 					 EXT_CSD_CARD_TYPE_HS200_1_2V)
+#define EXT_CSD_CARD_TYPE_HS400_1_8V	(1<<6)	/* Card can run at 200MHz DDR, 1.8V */
+#define EXT_CSD_CARD_TYPE_HS400_1_2V	(1<<7)	/* Card can run at 200MHz DDR, 1.2V */
+#define EXT_CSD_CARD_TYPE_HS400		(EXT_CSD_CARD_TYPE_HS400_1_8V | \
+					 EXT_CSD_CARD_TYPE_HS400_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
@@ -380,6 +384,7 @@ struct _mmc_csd {
 #define EXT_CSD_TIMING_BC	0	/* Backwards compatility */
 #define EXT_CSD_TIMING_HS	1	/* High speed */
 #define EXT_CSD_TIMING_HS200	2	/* HS200 */
+#define EXT_CSD_TIMING_HS400	3	/* HS400 */
 
 #define EXT_CSD_SEC_ER_EN	BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN	BIT(2)
Signature · 1 line
1.7.0.4
#131 lore raw

PATCH 6/6 mmc: core: add DT bindings for eMMC HS400 1.8/1.2V

In reply to Seungwon Jeon

Provide the option to configure these speed modes per host, for those host driver's that can't distinguish this in runtime. Specially, if host can support HS400, it means that host can also support HS200.

---
 Documentation/devicetree/bindings/mmc/mmc.txt |    2 ++
 drivers/mmc/core/host.c                       |    4 ++++
 2 files changed, 6 insertions(+), 0 deletions(-)
Documentation/devicetree/bindings/mmc/mmc.txt +2 -0
index 9dce540..3c18001 100644
@@ -38,6 +38,8 @@ Optional properties:
 - mmc-highspeed-ddr-1_2v: eMMC high-speed DDR mode(1.2V I/O) is supported
 - mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported
 - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
+- mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported
+- mmc-hs400-1_2v: eMMC HS400 mode(1.2V I/O) is supported
 
 *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
 polarity properties, we have to fix the meaning of the "normal" and "inverted"
drivers/mmc/core/host.c +4 -0
index fdea825..95cceae 100644
@@ -447,6 +447,10 @@ int mmc_of_parse(struct mmc_host *host)
 		host->caps2 |= MMC_CAP2_HS200_1_8V_SDR;
 	if (of_find_property(np, "mmc-hs200-1_2v", &len))
 		host->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
+	if (of_find_property(np, "mmc-hs400-1_8v", &len))
+		host->caps2 |= MMC_CAP2_HS400_1_8V | MMC_CAP2_HS200_1_8V_SDR;
+	if (of_find_property(np, "mmc-hs400-1_2v", &len))
+		host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR;
 
 	return 0;
 
Signature · 1 line
1.7.0.4
#132 lore raw

PATCH RESEND 1/5 mmc: drop the speed mode of card's state

In reply to Ulf Hansson

Timing mode identifier has same role and can take the place of speed mode. This change removes all related speed mode.

---
 drivers/mmc/core/bus.c   |    9 +++++----
 drivers/mmc/core/core.c  |    3 +--
 drivers/mmc/core/mmc.c   |   11 +++--------
 drivers/mmc/core/sd.c    |   16 +++-------------
 drivers/mmc/core/sd.h    |    1 -
 drivers/mmc/core/sdio.c  |    8 ++------
 include/linux/mmc/card.h |   24 +++++++-----------------
 include/linux/mmc/host.h |   23 +++++++++++++++++++++++
 8 files changed, 44 insertions(+), 51 deletions(-)
drivers/mmc/core/bus.c +5 -4
index 64145a3..e8a21fb 100644
@@ -286,6 +286,7 @@ struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)
 		return ERR_PTR(-ENOMEM);
 
 	card->host = host;
+	card->ios = &host->ios;
 
 	device_initialize(&card->dev);
 
@@ -349,16 +350,16 @@ int mmc_add_card(struct mmc_card *card)
 	if (mmc_host_is_spi(card->host)) {
 		pr_info("%s: new %s%s%s card on SPI\n",
 			mmc_hostname(card->host),
-			mmc_card_highspeed(card) ? "high speed " : "",
-			mmc_card_ddr_mode(card) ? "DDR " : "",
+			mmc_card_hs(card) ? "high speed " : "",
+			mmc_card_ddr52(card) ? "DDR " : "",
 			type);
 	} else {
 		pr_info("%s: new %s%s%s%s%s card at address %04x\n",
 			mmc_hostname(card->host),
 			mmc_card_uhs(card) ? "ultra high speed " :
-			(mmc_card_highspeed(card) ? "high speed " : ""),
+			(mmc_card_hs(card) ? "high speed " : ""),
 			(mmc_card_hs200(card) ? "HS200 " : ""),
-			mmc_card_ddr_mode(card) ? "DDR " : "",
+			mmc_card_ddr52(card) ? "DDR " : "",
 			uhs_bus_speed_mode, type, card->rca);
 	}
 
drivers/mmc/core/core.c +1 -2
index 098374b..88433bd 100644
@@ -2198,7 +2198,7 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
 {
 	struct mmc_command cmd = {0};
 
-	if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card))
+	if (mmc_card_blockaddr(card) || mmc_card_ddr52(card))
 		return 0;
 
 	cmd.opcode = MMC_SET_BLOCKLEN;
@@ -2281,7 +2281,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
 		}
 	}
 
-	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_DDR);
 	if (mmc_host_is_spi(host)) {
 		host->ios.chip_select = MMC_CS_HIGH;
 		host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
drivers/mmc/core/mmc.c +3 -8
index 6d91ff7..613e641 100644
@@ -1088,11 +1088,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		} else {
 			if (card->ext_csd.hs_max_dtr > 52000000 &&
 			    host->caps2 & MMC_CAP2_HS200) {
-				mmc_card_set_hs200(card);
 				mmc_set_timing(card->host,
 					       MMC_TIMING_MMC_HS200);
 			} else {
-				mmc_card_set_highspeed(card);
 				mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
 			}
 		}
@@ -1103,10 +1101,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	max_dtr = (unsigned int)-1;
 
-	if (mmc_card_highspeed(card) || mmc_card_hs200(card)) {
+	if (mmc_card_hs(card) || mmc_card_hs200(card)) {
 		if (max_dtr > card->ext_csd.hs_max_dtr)
 			max_dtr = card->ext_csd.hs_max_dtr;
-		if (mmc_card_highspeed(card) && (max_dtr > 52000000))
+		if (mmc_card_hs(card) && (max_dtr > 52000000))
 			max_dtr = 52000000;
 	} else if (max_dtr > card->csd.max_dtr) {
 		max_dtr = card->csd.max_dtr;
@@ -1117,7 +1115,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	/*
 	 * Indicate DDR mode (if supported).
 	 */
-	if (mmc_card_highspeed(card)) {
+	if (mmc_card_hs(card)) {
 		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
 			&& (host->caps & MMC_CAP_1_8V_DDR))
 				ddr = MMC_1_8V_DDR_MODE;
@@ -1260,7 +1258,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 				if (err)
 					goto err;
 			}
-			mmc_card_set_ddr_mode(card);
 			mmc_set_timing(card->host, MMC_TIMING_MMC_DDR52);
 			mmc_set_bus_width(card->host, bus_width);
 		}
@@ -1495,7 +1492,6 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
 		err = mmc_sleep(host);
 	else if (!mmc_host_is_spi(host))
 		err = mmc_deselect_cards(host);
-	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
 
 	if (!err) {
 		mmc_power_off(host);
@@ -1625,7 +1621,6 @@ static int mmc_power_restore(struct mmc_host *host)
 {
 	int ret;
 
-	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
 	mmc_claim_host(host);
 	ret = mmc_init_card(host, host->card->ocr, host->card);
 	mmc_release_host(host);
drivers/mmc/core/sd.c +3 -13
index 692fdb1..54dd3d1 100644
@@ -895,7 +895,7 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
 {
 	unsigned max_dtr = (unsigned int)-1;
 
-	if (mmc_card_highspeed(card)) {
+	if (mmc_card_hs(card)) {
 		if (max_dtr > card->sw_caps.hs_max_dtr)
 			max_dtr = card->sw_caps.hs_max_dtr;
 	} else if (max_dtr > card->csd.max_dtr) {
@@ -905,12 +905,6 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
 	return max_dtr;
 }
 
-void mmc_sd_go_highspeed(struct mmc_card *card)
-{
-	mmc_card_set_highspeed(card);
-	mmc_set_timing(card->host, MMC_TIMING_SD_HS);
-}
-
 /*
  * Handle the detection and initialisation of a card.
  *
@@ -985,16 +979,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
 		err = mmc_sd_init_uhs_card(card);
 		if (err)
 			goto free_card;
-
-		/* Card is an ultra-high-speed card */
-		mmc_card_set_uhs(card);
 	} else {
 		/*
 		 * Attempt to change to high-speed (if supported)
 		 */
 		err = mmc_sd_switch_hs(card);
 		if (err > 0)
-			mmc_sd_go_highspeed(card);
+			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
 		else if (err)
 			goto free_card;
 
@@ -1089,7 +1080,7 @@ static int _mmc_sd_suspend(struct mmc_host *host)
 
 	if (!mmc_host_is_spi(host))
 		err = mmc_deselect_cards(host);
-	host->card->state &= ~MMC_STATE_HIGHSPEED;
+
 	if (!err) {
 		mmc_power_off(host);
 		mmc_card_set_suspended(host->card);
@@ -1198,7 +1189,6 @@ static int mmc_sd_power_restore(struct mmc_host *host)
 {
 	int ret;
 
-	host->card->state &= ~MMC_STATE_HIGHSPEED;
 	mmc_claim_host(host);
 	ret = mmc_sd_init_card(host, host->card->ocr, host->card);
 	mmc_release_host(host);
drivers/mmc/core/sd.h +0 -1
index 4b34b24..aab824a 100644
@@ -12,6 +12,5 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
 	bool reinit);
 unsigned mmc_sd_get_max_clock(struct mmc_card *card);
 int mmc_sd_switch_hs(struct mmc_card *card);
-void mmc_sd_go_highspeed(struct mmc_card *card);
 
 #endif
drivers/mmc/core/sdio.c +2 -6
index 4d721c6..ef57d2d 100644
@@ -363,7 +363,7 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card)
 {
 	unsigned max_dtr;
 
-	if (mmc_card_highspeed(card)) {
+	if (mmc_card_hs(card)) {
 		/*
 		 * The SDIO specification doesn't mention how
 		 * the CIS transfer speed register relates to
@@ -733,7 +733,6 @@ try_again:
 		mmc_set_clock(host, card->cis.max_dtr);
 
 		if (card->cccr.high_speed) {
-			mmc_card_set_highspeed(card);
 			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
 		}
 
@@ -792,16 +791,13 @@ try_again:
 		err = mmc_sdio_init_uhs_card(card);
 		if (err)
 			goto remove;
-
-		/* Card is an ultra-high-speed card */
-		mmc_card_set_uhs(card);
 	} else {
 		/*
 		 * Switch to high-speed (if supported).
 		 */
 		err = sdio_enable_hs(card);
 		if (err > 0)
-			mmc_sd_go_highspeed(card);
+			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
 		else if (err)
 			goto remove;
 
include/linux/mmc/card.h +7 -17
index b730272..e6ce178 100644
@@ -194,6 +194,7 @@ struct sdio_cis {
 };
 
 struct mmc_host;
+struct mmc_ios;
 struct sdio_func;
 struct sdio_func_tuple;
 
@@ -239,6 +240,7 @@ struct mmc_part {
  */
 struct mmc_card {
 	struct mmc_host		*host;		/* the host this device belongs to */
+	struct mmc_ios		*ios;		/* bus settings of host */
 	struct device		dev;		/* the device */
 	u32			ocr;		/* the current OCR setting */
 	unsigned int		rca;		/* relative card address of device */
@@ -250,15 +252,11 @@ struct mmc_card {
 	unsigned int		state;		/* (our) card state */
 #define MMC_STATE_PRESENT	(1<<0)		/* present in sysfs */
 #define MMC_STATE_READONLY	(1<<1)		/* card is read-only */
-#define MMC_STATE_HIGHSPEED	(1<<2)		/* card is in high speed mode */
-#define MMC_STATE_BLOCKADDR	(1<<3)		/* card uses block-addressing */
-#define MMC_STATE_HIGHSPEED_DDR (1<<4)		/* card is in high speed mode */
-#define MMC_STATE_ULTRAHIGHSPEED (1<<5)		/* card is in ultra high speed mode */
-#define MMC_CARD_SDXC		(1<<6)		/* card is SDXC */
-#define MMC_CARD_REMOVED	(1<<7)		/* card has been removed */
-#define MMC_STATE_HIGHSPEED_200	(1<<8)		/* card is in HS200 mode */
-#define MMC_STATE_DOING_BKOPS	(1<<10)		/* card is doing BKOPS */
-#define MMC_STATE_SUSPENDED	(1<<11)		/* card is suspended */
+#define MMC_STATE_BLOCKADDR	(1<<2)		/* card uses block-addressing */
+#define MMC_CARD_SDXC		(1<<3)		/* card is SDXC */
+#define MMC_CARD_REMOVED	(1<<4)		/* card has been removed */
+#define MMC_STATE_DOING_BKOPS	(1<<5)		/* card is doing BKOPS */
+#define MMC_STATE_SUSPENDED	(1<<6)		/* card is suspended */
 	unsigned int		quirks; 	/* card quirks */
 #define MMC_QUIRK_LENIENT_FN0	(1<<0)		/* allow SDIO FN0 writes outside of the VS CCCR range */
 #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1)	/* use func->cur_blksize */
@@ -418,11 +416,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 
 #define mmc_card_present(c)	((c)->state & MMC_STATE_PRESENT)
 #define mmc_card_readonly(c)	((c)->state & MMC_STATE_READONLY)
-#define mmc_card_highspeed(c)	((c)->state & MMC_STATE_HIGHSPEED)
-#define mmc_card_hs200(c)	((c)->state & MMC_STATE_HIGHSPEED_200)
 #define mmc_card_blockaddr(c)	((c)->state & MMC_STATE_BLOCKADDR)
-#define mmc_card_ddr_mode(c)	((c)->state & MMC_STATE_HIGHSPEED_DDR)
-#define mmc_card_uhs(c)		((c)->state & MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
 #define mmc_card_removed(c)	((c) && ((c)->state & MMC_CARD_REMOVED))
 #define mmc_card_doing_bkops(c)	((c)->state & MMC_STATE_DOING_BKOPS)
@@ -430,11 +424,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 
 #define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
-#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
-#define mmc_card_set_hs200(c)	((c)->state |= MMC_STATE_HIGHSPEED_200)
 #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
-#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
-#define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
 #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
 #define mmc_card_set_doing_bkops(c)	((c)->state |= MMC_STATE_DOING_BKOPS)
include/linux/mmc/host.h +23 -0
index 87b1f4f..71977f4 100644
@@ -17,6 +17,7 @@
 #include <linux/fault-inject.h>
 
 #include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
 #include <linux/mmc/pm.h>
 
 struct mmc_ios {
@@ -485,4 +486,26 @@ static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
 	return host->ios.clock;
 }
 #endif
+
+static inline int mmc_card_hs(struct mmc_card *card)
+{
+	return card->ios->timing == MMC_TIMING_SD_HS ||
+		card->ios->timing == MMC_TIMING_MMC_HS;
+}
+
+static inline int mmc_card_uhs(struct mmc_card *card)
+{
+	return card->ios->timing >= MMC_TIMING_UHS_SDR12 &&
+		card->ios->timing <= MMC_TIMING_UHS_DDR50;
+}
+
+static inline bool mmc_card_hs200(struct mmc_card *card)
+{
+	return card->ios->timing == MMC_TIMING_MMC_HS200;
+}
+
+static inline bool mmc_card_ddr52(struct mmc_card *card)
+{
+	return card->ios->timing == MMC_TIMING_MMC_DDR52;
+}
 #endif /* LINUX_MMC_HOST_H */
Signature · 1 line
1.7.0.4
#133 lore raw

Re: [PATCH RESEND 1/5] mmc: drop the speed mode of card's state

Quoted 20 lines · Seungwon Jeon

Timing mode identifier has same role and can take the place of speed mode. This change removes all related speed mode.

---
 drivers/mmc/core/bus.c   |    9 +++++----
 drivers/mmc/core/core.c  |    3 +--
 drivers/mmc/core/mmc.c   |   11 +++--------
 drivers/mmc/core/sd.c    |   16 +++-------------
 drivers/mmc/core/sd.h    |    1 -
 drivers/mmc/core/sdio.c  |    8 ++------
 include/linux/mmc/card.h |   24 +++++++-----------------
 include/linux/mmc/host.h |   23 +++++++++++++++++++++++
 8 files changed, 44 insertions(+), 51 deletions(-)
drivers/mmc/core/bus.c +0 -0
index 64145a3..e8a21fb 100644

drivers/mmc/core/bus.c struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type) · line 289

Quoted 4 lines
drivers/mmc/core/bus.c +1 -0
@@ -286,6 +286,7 @@ struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)
                return ERR_PTR(-ENOMEM);
 
        card->host = host;
+       card->ios = &host->ios;

Please remove this. The ios is connected and controlled by the host.

Once you need the ios pointer I think it's better to reference it from the card->host.

Quoted 231 lines
drivers/mmc/core/bus.c +4 -4
        device_initialize(&card->dev);
 
@@ -349,16 +350,16 @@ int mmc_add_card(struct mmc_card *card)
        if (mmc_host_is_spi(card->host)) {
                pr_info("%s: new %s%s%s card on SPI\n",
                        mmc_hostname(card->host),
-                       mmc_card_highspeed(card) ? "high speed " : "",
-                       mmc_card_ddr_mode(card) ? "DDR " : "",
+                       mmc_card_hs(card) ? "high speed " : "",
+                       mmc_card_ddr52(card) ? "DDR " : "",
                        type);
        } else {
                pr_info("%s: new %s%s%s%s%s card at address %04x\n",
                        mmc_hostname(card->host),
                        mmc_card_uhs(card) ? "ultra high speed " :
-                       (mmc_card_highspeed(card) ? "high speed " : ""),
+                       (mmc_card_hs(card) ? "high speed " : ""),
                        (mmc_card_hs200(card) ? "HS200 " : ""),
-                       mmc_card_ddr_mode(card) ? "DDR " : "",
+                       mmc_card_ddr52(card) ? "DDR " : "",
                        uhs_bus_speed_mode, type, card->rca);
        }
 
drivers/mmc/core/core.c +1 -2
index 098374b..88433bd 100644
@@ -2198,7 +2198,7 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
 {
        struct mmc_command cmd = {0};
 
-       if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card))
+       if (mmc_card_blockaddr(card) || mmc_card_ddr52(card))
                return 0;
 
        cmd.opcode = MMC_SET_BLOCKLEN;
@@ -2281,7 +2281,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
                }
        }
 
-       host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_DDR);
        if (mmc_host_is_spi(host)) {
                host->ios.chip_select = MMC_CS_HIGH;
                host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
drivers/mmc/core/mmc.c +3 -8
index 6d91ff7..613e641 100644
@@ -1088,11 +1088,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                } else {
                        if (card->ext_csd.hs_max_dtr > 52000000 &&
                            host->caps2 & MMC_CAP2_HS200) {
-                               mmc_card_set_hs200(card);
                                mmc_set_timing(card->host,
                                               MMC_TIMING_MMC_HS200);
                        } else {
-                               mmc_card_set_highspeed(card);
                                mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
                        }
                }
@@ -1103,10 +1101,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
         */
        max_dtr = (unsigned int)-1;
 
-       if (mmc_card_highspeed(card) || mmc_card_hs200(card)) {
+       if (mmc_card_hs(card) || mmc_card_hs200(card)) {
                if (max_dtr > card->ext_csd.hs_max_dtr)
                        max_dtr = card->ext_csd.hs_max_dtr;
-               if (mmc_card_highspeed(card) && (max_dtr > 52000000))
+               if (mmc_card_hs(card) && (max_dtr > 52000000))
                        max_dtr = 52000000;
        } else if (max_dtr > card->csd.max_dtr) {
                max_dtr = card->csd.max_dtr;
@@ -1117,7 +1115,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        /*
         * Indicate DDR mode (if supported).
         */
-       if (mmc_card_highspeed(card)) {
+       if (mmc_card_hs(card)) {
                if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
                        && (host->caps & MMC_CAP_1_8V_DDR))
                                ddr = MMC_1_8V_DDR_MODE;
@@ -1260,7 +1258,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                                if (err)
                                        goto err;
                        }
-                       mmc_card_set_ddr_mode(card);
                        mmc_set_timing(card->host, MMC_TIMING_MMC_DDR52);
                        mmc_set_bus_width(card->host, bus_width);
                }
@@ -1495,7 +1492,6 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
                err = mmc_sleep(host);
        else if (!mmc_host_is_spi(host))
                err = mmc_deselect_cards(host);
-       host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
 
        if (!err) {
                mmc_power_off(host);
@@ -1625,7 +1621,6 @@ static int mmc_power_restore(struct mmc_host *host)
 {
        int ret;
 
-       host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
        mmc_claim_host(host);
        ret = mmc_init_card(host, host->card->ocr, host->card);
        mmc_release_host(host);
drivers/mmc/core/sd.c +3 -13
index 692fdb1..54dd3d1 100644
@@ -895,7 +895,7 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
 {
        unsigned max_dtr = (unsigned int)-1;
 
-       if (mmc_card_highspeed(card)) {
+       if (mmc_card_hs(card)) {
                if (max_dtr > card->sw_caps.hs_max_dtr)
                        max_dtr = card->sw_caps.hs_max_dtr;
        } else if (max_dtr > card->csd.max_dtr) {
@@ -905,12 +905,6 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
        return max_dtr;
 }
 
-void mmc_sd_go_highspeed(struct mmc_card *card)
-{
-       mmc_card_set_highspeed(card);
-       mmc_set_timing(card->host, MMC_TIMING_SD_HS);
-}
-
 /*
  * Handle the detection and initialisation of a card.
  *
@@ -985,16 +979,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
                err = mmc_sd_init_uhs_card(card);
                if (err)
                        goto free_card;
-
-               /* Card is an ultra-high-speed card */
-               mmc_card_set_uhs(card);
        } else {
                /*
                 * Attempt to change to high-speed (if supported)
                 */
                err = mmc_sd_switch_hs(card);
                if (err > 0)
-                       mmc_sd_go_highspeed(card);
+                       mmc_set_timing(card->host, MMC_TIMING_SD_HS);
                else if (err)
                        goto free_card;
 
@@ -1089,7 +1080,7 @@ static int _mmc_sd_suspend(struct mmc_host *host)
 
        if (!mmc_host_is_spi(host))
                err = mmc_deselect_cards(host);
-       host->card->state &= ~MMC_STATE_HIGHSPEED;
+
        if (!err) {
                mmc_power_off(host);
                mmc_card_set_suspended(host->card);
@@ -1198,7 +1189,6 @@ static int mmc_sd_power_restore(struct mmc_host *host)
 {
        int ret;
 
-       host->card->state &= ~MMC_STATE_HIGHSPEED;
        mmc_claim_host(host);
        ret = mmc_sd_init_card(host, host->card->ocr, host->card);
        mmc_release_host(host);
drivers/mmc/core/sd.h +0 -1
index 4b34b24..aab824a 100644
@@ -12,6 +12,5 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
        bool reinit);
 unsigned mmc_sd_get_max_clock(struct mmc_card *card);
 int mmc_sd_switch_hs(struct mmc_card *card);
-void mmc_sd_go_highspeed(struct mmc_card *card);
 
 #endif
drivers/mmc/core/sdio.c +2 -6
index 4d721c6..ef57d2d 100644
@@ -363,7 +363,7 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card)
 {
        unsigned max_dtr;
 
-       if (mmc_card_highspeed(card)) {
+       if (mmc_card_hs(card)) {
                /*
                 * The SDIO specification doesn't mention how
                 * the CIS transfer speed register relates to
@@ -733,7 +733,6 @@ try_again:
                mmc_set_clock(host, card->cis.max_dtr);
 
                if (card->cccr.high_speed) {
-                       mmc_card_set_highspeed(card);
                        mmc_set_timing(card->host, MMC_TIMING_SD_HS);
                }
 
@@ -792,16 +791,13 @@ try_again:
                err = mmc_sdio_init_uhs_card(card);
                if (err)
                        goto remove;
-
-               /* Card is an ultra-high-speed card */
-               mmc_card_set_uhs(card);
        } else {
                /*
                 * Switch to high-speed (if supported).
                 */
                err = sdio_enable_hs(card);
                if (err > 0)
-                       mmc_sd_go_highspeed(card);
+                       mmc_set_timing(card->host, MMC_TIMING_SD_HS);
                else if (err)
                        goto remove;
 
include/linux/mmc/card.h +1 -0
index b730272..e6ce178 100644
@@ -194,6 +194,7 @@ struct sdio_cis {
 };
 
 struct mmc_host;
+struct mmc_ios;
 struct sdio_func;
 struct sdio_func_tuple;
 

include/linux/mmc/card.h struct mmc_part { · line 243

Quoted 4 lines
include/linux/mmc/card.h +1 -0
@@ -239,6 +240,7 @@ struct mmc_part {
  */
 struct mmc_card {
        struct mmc_host         *host;          /* the host this device belongs to */
+       struct mmc_ios          *ios;           /* bus settings of host */

Please remove, see comment above.

Quoted 88 lines
include/linux/mmc/card.h +5 -17
        struct device           dev;            /* the device */
        u32                     ocr;            /* the current OCR setting */
        unsigned int            rca;            /* relative card address of device */
@@ -250,15 +252,11 @@ struct mmc_card {
        unsigned int            state;          /* (our) card state */
 #define MMC_STATE_PRESENT      (1<<0)          /* present in sysfs */
 #define MMC_STATE_READONLY     (1<<1)          /* card is read-only */
-#define MMC_STATE_HIGHSPEED    (1<<2)          /* card is in high speed mode */
-#define MMC_STATE_BLOCKADDR    (1<<3)          /* card uses block-addressing */
-#define MMC_STATE_HIGHSPEED_DDR (1<<4)         /* card is in high speed mode */
-#define MMC_STATE_ULTRAHIGHSPEED (1<<5)                /* card is in ultra high speed mode */
-#define MMC_CARD_SDXC          (1<<6)          /* card is SDXC */
-#define MMC_CARD_REMOVED       (1<<7)          /* card has been removed */
-#define MMC_STATE_HIGHSPEED_200        (1<<8)          /* card is in HS200 mode */
-#define MMC_STATE_DOING_BKOPS  (1<<10)         /* card is doing BKOPS */
-#define MMC_STATE_SUSPENDED    (1<<11)         /* card is suspended */
+#define MMC_STATE_BLOCKADDR    (1<<2)          /* card uses block-addressing */
+#define MMC_CARD_SDXC          (1<<3)          /* card is SDXC */
+#define MMC_CARD_REMOVED       (1<<4)          /* card has been removed */
+#define MMC_STATE_DOING_BKOPS  (1<<5)          /* card is doing BKOPS */
+#define MMC_STATE_SUSPENDED    (1<<6)          /* card is suspended */
        unsigned int            quirks;         /* card quirks */
 #define MMC_QUIRK_LENIENT_FN0  (1<<0)          /* allow SDIO FN0 writes outside of the VS CCCR range */
 #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1)   /* use func->cur_blksize */
@@ -418,11 +416,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 
 #define mmc_card_present(c)    ((c)->state & MMC_STATE_PRESENT)
 #define mmc_card_readonly(c)   ((c)->state & MMC_STATE_READONLY)
-#define mmc_card_highspeed(c)  ((c)->state & MMC_STATE_HIGHSPEED)
-#define mmc_card_hs200(c)      ((c)->state & MMC_STATE_HIGHSPEED_200)
 #define mmc_card_blockaddr(c)  ((c)->state & MMC_STATE_BLOCKADDR)
-#define mmc_card_ddr_mode(c)   ((c)->state & MMC_STATE_HIGHSPEED_DDR)
-#define mmc_card_uhs(c)                ((c)->state & MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
 #define mmc_card_removed(c)    ((c) && ((c)->state & MMC_CARD_REMOVED))
 #define mmc_card_doing_bkops(c)        ((c)->state & MMC_STATE_DOING_BKOPS)
@@ -430,11 +424,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 
 #define mmc_card_set_present(c)        ((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
-#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
-#define mmc_card_set_hs200(c)  ((c)->state |= MMC_STATE_HIGHSPEED_200)
 #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
-#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
-#define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
 #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
 #define mmc_card_set_doing_bkops(c)    ((c)->state |= MMC_STATE_DOING_BKOPS)
include/linux/mmc/host.h +23 -1
index 87b1f4f..71977f4 100644
@@ -17,6 +17,7 @@
 #include <linux/fault-inject.h>
 
 #include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
 #include <linux/mmc/pm.h>
 
 struct mmc_ios {
@@ -485,4 +486,26 @@ static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
        return host->ios.clock;
 }
 #endif
+
+static inline int mmc_card_hs(struct mmc_card *card)
+{
+       return card->ios->timing == MMC_TIMING_SD_HS ||
+               card->ios->timing == MMC_TIMING_MMC_HS;
+}
+
+static inline int mmc_card_uhs(struct mmc_card *card)
+{
+       return card->ios->timing >= MMC_TIMING_UHS_SDR12 &&
+               card->ios->timing <= MMC_TIMING_UHS_DDR50;
+}
+
+static inline bool mmc_card_hs200(struct mmc_card *card)
+{
+       return card->ios->timing == MMC_TIMING_MMC_HS200;
+}
+
+static inline bool mmc_card_ddr52(struct mmc_card *card)
+{
+       return card->ios->timing == MMC_TIMING_MMC_DDR52;
+}
 #endif /* LINUX_MMC_HOST_H */
--
Quoted 3 lines

1.7.0.4

Nice clean-up!

Besides my minor comment above, you have my ack.

Kind regards
Ulf Hansson

#134 lore raw

RE: [PATCH RESEND 1/5] mmc: drop the speed mode of card's state

Quoted 347 lines · Ulf Hansson
Quoted 20 lines · Seungwon Jeon

Timing mode identifier has same role and can take the place of speed mode. This change removes all related speed mode.

---
 drivers/mmc/core/bus.c   |    9 +++++----
 drivers/mmc/core/core.c  |    3 +--
 drivers/mmc/core/mmc.c   |   11 +++--------
 drivers/mmc/core/sd.c    |   16 +++-------------
 drivers/mmc/core/sd.h    |    1 -
 drivers/mmc/core/sdio.c  |    8 ++------
 include/linux/mmc/card.h |   24 +++++++-----------------
 include/linux/mmc/host.h |   23 +++++++++++++++++++++++
 8 files changed, 44 insertions(+), 51 deletions(-)
drivers/mmc/core/bus.c +0 -0
index 64145a3..e8a21fb 100644

drivers/mmc/core/bus.c struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type) · line 289

Quoted 4 lines
drivers/mmc/core/bus.c +1 -0
@@ -286,6 +286,7 @@ struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)
                return ERR_PTR(-ENOMEM);
 
        card->host = host;
+       card->ios = &host->ios;

Please remove this. The ios is connected and controlled by the host.

Once you need the ios pointer I think it's better to reference it from the card->host.

Quoted 231 lines
drivers/mmc/core/bus.c +4 -4
        device_initialize(&card->dev);
 
@@ -349,16 +350,16 @@ int mmc_add_card(struct mmc_card *card)
        if (mmc_host_is_spi(card->host)) {
                pr_info("%s: new %s%s%s card on SPI\n",
                        mmc_hostname(card->host),
-                       mmc_card_highspeed(card) ? "high speed " : "",
-                       mmc_card_ddr_mode(card) ? "DDR " : "",
+                       mmc_card_hs(card) ? "high speed " : "",
+                       mmc_card_ddr52(card) ? "DDR " : "",
                        type);
        } else {
                pr_info("%s: new %s%s%s%s%s card at address %04x\n",
                        mmc_hostname(card->host),
                        mmc_card_uhs(card) ? "ultra high speed " :
-                       (mmc_card_highspeed(card) ? "high speed " : ""),
+                       (mmc_card_hs(card) ? "high speed " : ""),
                        (mmc_card_hs200(card) ? "HS200 " : ""),
-                       mmc_card_ddr_mode(card) ? "DDR " : "",
+                       mmc_card_ddr52(card) ? "DDR " : "",
                        uhs_bus_speed_mode, type, card->rca);
        }
 
drivers/mmc/core/core.c +1 -2
index 098374b..88433bd 100644
@@ -2198,7 +2198,7 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
 {
        struct mmc_command cmd = {0};
 
-       if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card))
+       if (mmc_card_blockaddr(card) || mmc_card_ddr52(card))
                return 0;
 
        cmd.opcode = MMC_SET_BLOCKLEN;
@@ -2281,7 +2281,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
                }
        }
 
-       host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_DDR);
        if (mmc_host_is_spi(host)) {
                host->ios.chip_select = MMC_CS_HIGH;
                host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
drivers/mmc/core/mmc.c +3 -8
index 6d91ff7..613e641 100644
@@ -1088,11 +1088,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                } else {
                        if (card->ext_csd.hs_max_dtr > 52000000 &&
                            host->caps2 & MMC_CAP2_HS200) {
-                               mmc_card_set_hs200(card);
                                mmc_set_timing(card->host,
                                               MMC_TIMING_MMC_HS200);
                        } else {
-                               mmc_card_set_highspeed(card);
                                mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
                        }
                }
@@ -1103,10 +1101,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
         */
        max_dtr = (unsigned int)-1;
 
-       if (mmc_card_highspeed(card) || mmc_card_hs200(card)) {
+       if (mmc_card_hs(card) || mmc_card_hs200(card)) {
                if (max_dtr > card->ext_csd.hs_max_dtr)
                        max_dtr = card->ext_csd.hs_max_dtr;
-               if (mmc_card_highspeed(card) && (max_dtr > 52000000))
+               if (mmc_card_hs(card) && (max_dtr > 52000000))
                        max_dtr = 52000000;
        } else if (max_dtr > card->csd.max_dtr) {
                max_dtr = card->csd.max_dtr;
@@ -1117,7 +1115,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        /*
         * Indicate DDR mode (if supported).
         */
-       if (mmc_card_highspeed(card)) {
+       if (mmc_card_hs(card)) {
                if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
                        && (host->caps & MMC_CAP_1_8V_DDR))
                                ddr = MMC_1_8V_DDR_MODE;
@@ -1260,7 +1258,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                                if (err)
                                        goto err;
                        }
-                       mmc_card_set_ddr_mode(card);
                        mmc_set_timing(card->host, MMC_TIMING_MMC_DDR52);
                        mmc_set_bus_width(card->host, bus_width);
                }
@@ -1495,7 +1492,6 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
                err = mmc_sleep(host);
        else if (!mmc_host_is_spi(host))
                err = mmc_deselect_cards(host);
-       host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
 
        if (!err) {
                mmc_power_off(host);
@@ -1625,7 +1621,6 @@ static int mmc_power_restore(struct mmc_host *host)
 {
        int ret;
 
-       host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
        mmc_claim_host(host);
        ret = mmc_init_card(host, host->card->ocr, host->card);
        mmc_release_host(host);
drivers/mmc/core/sd.c +3 -13
index 692fdb1..54dd3d1 100644
@@ -895,7 +895,7 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
 {
        unsigned max_dtr = (unsigned int)-1;
 
-       if (mmc_card_highspeed(card)) {
+       if (mmc_card_hs(card)) {
                if (max_dtr > card->sw_caps.hs_max_dtr)
                        max_dtr = card->sw_caps.hs_max_dtr;
        } else if (max_dtr > card->csd.max_dtr) {
@@ -905,12 +905,6 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
        return max_dtr;
 }
 
-void mmc_sd_go_highspeed(struct mmc_card *card)
-{
-       mmc_card_set_highspeed(card);
-       mmc_set_timing(card->host, MMC_TIMING_SD_HS);
-}
-
 /*
  * Handle the detection and initialisation of a card.
  *
@@ -985,16 +979,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
                err = mmc_sd_init_uhs_card(card);
                if (err)
                        goto free_card;
-
-               /* Card is an ultra-high-speed card */
-               mmc_card_set_uhs(card);
        } else {
                /*
                 * Attempt to change to high-speed (if supported)
                 */
                err = mmc_sd_switch_hs(card);
                if (err > 0)
-                       mmc_sd_go_highspeed(card);
+                       mmc_set_timing(card->host, MMC_TIMING_SD_HS);
                else if (err)
                        goto free_card;
 
@@ -1089,7 +1080,7 @@ static int _mmc_sd_suspend(struct mmc_host *host)
 
        if (!mmc_host_is_spi(host))
                err = mmc_deselect_cards(host);
-       host->card->state &= ~MMC_STATE_HIGHSPEED;
+
        if (!err) {
                mmc_power_off(host);
                mmc_card_set_suspended(host->card);
@@ -1198,7 +1189,6 @@ static int mmc_sd_power_restore(struct mmc_host *host)
 {
        int ret;
 
-       host->card->state &= ~MMC_STATE_HIGHSPEED;
        mmc_claim_host(host);
        ret = mmc_sd_init_card(host, host->card->ocr, host->card);
        mmc_release_host(host);
drivers/mmc/core/sd.h +0 -1
index 4b34b24..aab824a 100644
@@ -12,6 +12,5 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
        bool reinit);
 unsigned mmc_sd_get_max_clock(struct mmc_card *card);
 int mmc_sd_switch_hs(struct mmc_card *card);
-void mmc_sd_go_highspeed(struct mmc_card *card);
 
 #endif
drivers/mmc/core/sdio.c +2 -6
index 4d721c6..ef57d2d 100644
@@ -363,7 +363,7 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card)
 {
        unsigned max_dtr;
 
-       if (mmc_card_highspeed(card)) {
+       if (mmc_card_hs(card)) {
                /*
                 * The SDIO specification doesn't mention how
                 * the CIS transfer speed register relates to
@@ -733,7 +733,6 @@ try_again:
                mmc_set_clock(host, card->cis.max_dtr);
 
                if (card->cccr.high_speed) {
-                       mmc_card_set_highspeed(card);
                        mmc_set_timing(card->host, MMC_TIMING_SD_HS);
                }
 
@@ -792,16 +791,13 @@ try_again:
                err = mmc_sdio_init_uhs_card(card);
                if (err)
                        goto remove;
-
-               /* Card is an ultra-high-speed card */
-               mmc_card_set_uhs(card);
        } else {
                /*
                 * Switch to high-speed (if supported).
                 */
                err = sdio_enable_hs(card);
                if (err > 0)
-                       mmc_sd_go_highspeed(card);
+                       mmc_set_timing(card->host, MMC_TIMING_SD_HS);
                else if (err)
                        goto remove;
 
include/linux/mmc/card.h +1 -0
index b730272..e6ce178 100644
@@ -194,6 +194,7 @@ struct sdio_cis {
 };
 
 struct mmc_host;
+struct mmc_ios;
 struct sdio_func;
 struct sdio_func_tuple;
 

include/linux/mmc/card.h struct mmc_part { · line 243

Quoted 4 lines
include/linux/mmc/card.h +1 -0
@@ -239,6 +240,7 @@ struct mmc_part {
  */
 struct mmc_card {
        struct mmc_host         *host;          /* the host this device belongs to */
+       struct mmc_ios          *ios;           /* bus settings of host */

Please remove, see comment above.

Quoted 13 lines
include/linux/mmc/card.h +0 -6
        struct device           dev;            /* the device */
        u32                     ocr;            /* the current OCR setting */
        unsigned int            rca;            /* relative card address of device */
@@ -250,15 +252,11 @@ struct mmc_card {
        unsigned int            state;          /* (our) card state */
 #define MMC_STATE_PRESENT      (1<<0)          /* present in sysfs */
 #define MMC_STATE_READONLY     (1<<1)          /* card is read-only */
-#define MMC_STATE_HIGHSPEED    (1<<2)          /* card is in high speed mode */
-#define MMC_STATE_BLOCKADDR    (1<<3)          /* card uses block-addressing */
-#define MMC_STATE_HIGHSPEED_DDR (1<<4)         /* card is in high speed mode */
-#define MMC_STATE_ULTRAHIGHSPEED (1<<5)                /* card is in ultra high speed mode */
-#define MMC_CARD_SDXC          (1<<6)          /* card is SDXC */
-#define MMC_CARD_REMOVED       (1<<7)          /* card has been removed */

include/linux/mmc/card.h struct mmc_card { · line 261

Quoted 10 lines
include/linux/mmc/card.h +5 -3
-#define MMC_STATE_HIGHSPEED_200        (1<<8)          /* card is in HS200 mode */
-#define MMC_STATE_DOING_BKOPS  (1<<10)         /* card is doing BKOPS */
-#define MMC_STATE_SUSPENDED    (1<<11)         /* card is suspended */
+#define MMC_STATE_BLOCKADDR    (1<<2)          /* card uses block-addressing */
+#define MMC_CARD_SDXC          (1<<3)          /* card is SDXC */
+#define MMC_CARD_REMOVED       (1<<4)          /* card has been removed */
+#define MMC_STATE_DOING_BKOPS  (1<<5)          /* card is doing BKOPS */
+#define MMC_STATE_SUSPENDED    (1<<6)          /* card is suspended */
        unsigned int            quirks;         /* card quirks */
 #define MMC_QUIRK_LENIENT_FN0  (1<<0)          /* allow SDIO FN0 writes outside of the VS CCCR range

*/

Quoted 54 lines
include/linux/mmc/card.h +0 -8
 #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1)   /* use func->cur_blksize */
@@ -418,11 +416,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 
 #define mmc_card_present(c)    ((c)->state & MMC_STATE_PRESENT)
 #define mmc_card_readonly(c)   ((c)->state & MMC_STATE_READONLY)
-#define mmc_card_highspeed(c)  ((c)->state & MMC_STATE_HIGHSPEED)
-#define mmc_card_hs200(c)      ((c)->state & MMC_STATE_HIGHSPEED_200)
 #define mmc_card_blockaddr(c)  ((c)->state & MMC_STATE_BLOCKADDR)
-#define mmc_card_ddr_mode(c)   ((c)->state & MMC_STATE_HIGHSPEED_DDR)
-#define mmc_card_uhs(c)                ((c)->state & MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
 #define mmc_card_removed(c)    ((c) && ((c)->state & MMC_CARD_REMOVED))
 #define mmc_card_doing_bkops(c)        ((c)->state & MMC_STATE_DOING_BKOPS)
@@ -430,11 +424,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 
 #define mmc_card_set_present(c)        ((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
-#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
-#define mmc_card_set_hs200(c)  ((c)->state |= MMC_STATE_HIGHSPEED_200)
 #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
-#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
-#define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
 #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
 #define mmc_card_set_doing_bkops(c)    ((c)->state |= MMC_STATE_DOING_BKOPS)
include/linux/mmc/host.h +14 -0
index 87b1f4f..71977f4 100644
@@ -17,6 +17,7 @@
 #include <linux/fault-inject.h>
 
 #include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
 #include <linux/mmc/pm.h>
 
 struct mmc_ios {
@@ -485,4 +486,26 @@ static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
        return host->ios.clock;
 }
 #endif
+
+static inline int mmc_card_hs(struct mmc_card *card)
+{
+       return card->ios->timing == MMC_TIMING_SD_HS ||
+               card->ios->timing == MMC_TIMING_MMC_HS;
+}
+
+static inline int mmc_card_uhs(struct mmc_card *card)
+{
+       return card->ios->timing >= MMC_TIMING_UHS_SDR12 &&
+               card->ios->timing <= MMC_TIMING_UHS_DDR50;
+}
+
Quoted 8 lines

include/linux/mmc/host.h static inline unsigned int mmc_host_clk_rate(struct mmc_host *host) · line 509

Quoted 8 lines
include/linux/mmc/host.h +8 -0
+static inline bool mmc_card_hs200(struct mmc_card *card)
+{
+       return card->ios->timing == MMC_TIMING_MMC_HS200;
+}
+
+static inline bool mmc_card_ddr52(struct mmc_card *card)
+{
+       return card->ios->timing == MMC_TIMING_MMC_DDR52;

I just added another reference toward ios.
Do you expect like below?
return card->host->ios->timing == MMC_TIMING_MMC_DDR52; I'm fine if you checked that.

Thanks,
Seungwon Jeon

Quoted 17 lines
Quoted 6 lines
include/linux/mmc/host.h +1 -1
+}
 #endif /* LINUX_MMC_HOST_H */
--

1.7.0.4

Nice clean-up!

Besides my minor comment above, you have my ack.

Kind regards
Ulf Hansson
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#135 lore raw

Re: [PATCH RESEND 1/5] mmc: drop the speed mode of card's state

Quoted 352 lines · Seungwon Jeon
Quoted 351 lines · Ulf Hansson
Quoted 20 lines · Seungwon Jeon

Timing mode identifier has same role and can take the place of speed mode. This change removes all related speed mode.

---
 drivers/mmc/core/bus.c   |    9 +++++----
 drivers/mmc/core/core.c  |    3 +--
 drivers/mmc/core/mmc.c   |   11 +++--------
 drivers/mmc/core/sd.c    |   16 +++-------------
 drivers/mmc/core/sd.h    |    1 -
 drivers/mmc/core/sdio.c  |    8 ++------
 include/linux/mmc/card.h |   24 +++++++-----------------
 include/linux/mmc/host.h |   23 +++++++++++++++++++++++
 8 files changed, 44 insertions(+), 51 deletions(-)
drivers/mmc/core/bus.c +0 -0
index 64145a3..e8a21fb 100644

drivers/mmc/core/bus.c struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type) · line 289

Quoted 4 lines
drivers/mmc/core/bus.c +1 -0
@@ -286,6 +286,7 @@ struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)
                return ERR_PTR(-ENOMEM);
 
        card->host = host;
+       card->ios = &host->ios;

Please remove this. The ios is connected and controlled by the host.

Once you need the ios pointer I think it's better to reference it from the card->host.

Quoted 231 lines
drivers/mmc/core/bus.c +4 -4
        device_initialize(&card->dev);
 
@@ -349,16 +350,16 @@ int mmc_add_card(struct mmc_card *card)
        if (mmc_host_is_spi(card->host)) {
                pr_info("%s: new %s%s%s card on SPI\n",
                        mmc_hostname(card->host),
-                       mmc_card_highspeed(card) ? "high speed " : "",
-                       mmc_card_ddr_mode(card) ? "DDR " : "",
+                       mmc_card_hs(card) ? "high speed " : "",
+                       mmc_card_ddr52(card) ? "DDR " : "",
                        type);
        } else {
                pr_info("%s: new %s%s%s%s%s card at address %04x\n",
                        mmc_hostname(card->host),
                        mmc_card_uhs(card) ? "ultra high speed " :
-                       (mmc_card_highspeed(card) ? "high speed " : ""),
+                       (mmc_card_hs(card) ? "high speed " : ""),
                        (mmc_card_hs200(card) ? "HS200 " : ""),
-                       mmc_card_ddr_mode(card) ? "DDR " : "",
+                       mmc_card_ddr52(card) ? "DDR " : "",
                        uhs_bus_speed_mode, type, card->rca);
        }
 
drivers/mmc/core/core.c +1 -2
index 098374b..88433bd 100644
@@ -2198,7 +2198,7 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
 {
        struct mmc_command cmd = {0};
 
-       if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card))
+       if (mmc_card_blockaddr(card) || mmc_card_ddr52(card))
                return 0;
 
        cmd.opcode = MMC_SET_BLOCKLEN;
@@ -2281,7 +2281,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
                }
        }
 
-       host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_DDR);
        if (mmc_host_is_spi(host)) {
                host->ios.chip_select = MMC_CS_HIGH;
                host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
drivers/mmc/core/mmc.c +3 -8
index 6d91ff7..613e641 100644
@@ -1088,11 +1088,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                } else {
                        if (card->ext_csd.hs_max_dtr > 52000000 &&
                            host->caps2 & MMC_CAP2_HS200) {
-                               mmc_card_set_hs200(card);
                                mmc_set_timing(card->host,
                                               MMC_TIMING_MMC_HS200);
                        } else {
-                               mmc_card_set_highspeed(card);
                                mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
                        }
                }
@@ -1103,10 +1101,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
         */
        max_dtr = (unsigned int)-1;
 
-       if (mmc_card_highspeed(card) || mmc_card_hs200(card)) {
+       if (mmc_card_hs(card) || mmc_card_hs200(card)) {
                if (max_dtr > card->ext_csd.hs_max_dtr)
                        max_dtr = card->ext_csd.hs_max_dtr;
-               if (mmc_card_highspeed(card) && (max_dtr > 52000000))
+               if (mmc_card_hs(card) && (max_dtr > 52000000))
                        max_dtr = 52000000;
        } else if (max_dtr > card->csd.max_dtr) {
                max_dtr = card->csd.max_dtr;
@@ -1117,7 +1115,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        /*
         * Indicate DDR mode (if supported).
         */
-       if (mmc_card_highspeed(card)) {
+       if (mmc_card_hs(card)) {
                if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
                        && (host->caps & MMC_CAP_1_8V_DDR))
                                ddr = MMC_1_8V_DDR_MODE;
@@ -1260,7 +1258,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                                if (err)
                                        goto err;
                        }
-                       mmc_card_set_ddr_mode(card);
                        mmc_set_timing(card->host, MMC_TIMING_MMC_DDR52);
                        mmc_set_bus_width(card->host, bus_width);
                }
@@ -1495,7 +1492,6 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
                err = mmc_sleep(host);
        else if (!mmc_host_is_spi(host))
                err = mmc_deselect_cards(host);
-       host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
 
        if (!err) {
                mmc_power_off(host);
@@ -1625,7 +1621,6 @@ static int mmc_power_restore(struct mmc_host *host)
 {
        int ret;
 
-       host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
        mmc_claim_host(host);
        ret = mmc_init_card(host, host->card->ocr, host->card);
        mmc_release_host(host);
drivers/mmc/core/sd.c +3 -13
index 692fdb1..54dd3d1 100644
@@ -895,7 +895,7 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
 {
        unsigned max_dtr = (unsigned int)-1;
 
-       if (mmc_card_highspeed(card)) {
+       if (mmc_card_hs(card)) {
                if (max_dtr > card->sw_caps.hs_max_dtr)
                        max_dtr = card->sw_caps.hs_max_dtr;
        } else if (max_dtr > card->csd.max_dtr) {
@@ -905,12 +905,6 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
        return max_dtr;
 }
 
-void mmc_sd_go_highspeed(struct mmc_card *card)
-{
-       mmc_card_set_highspeed(card);
-       mmc_set_timing(card->host, MMC_TIMING_SD_HS);
-}
-
 /*
  * Handle the detection and initialisation of a card.
  *
@@ -985,16 +979,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
                err = mmc_sd_init_uhs_card(card);
                if (err)
                        goto free_card;
-
-               /* Card is an ultra-high-speed card */
-               mmc_card_set_uhs(card);
        } else {
                /*
                 * Attempt to change to high-speed (if supported)
                 */
                err = mmc_sd_switch_hs(card);
                if (err > 0)
-                       mmc_sd_go_highspeed(card);
+                       mmc_set_timing(card->host, MMC_TIMING_SD_HS);
                else if (err)
                        goto free_card;
 
@@ -1089,7 +1080,7 @@ static int _mmc_sd_suspend(struct mmc_host *host)
 
        if (!mmc_host_is_spi(host))
                err = mmc_deselect_cards(host);
-       host->card->state &= ~MMC_STATE_HIGHSPEED;
+
        if (!err) {
                mmc_power_off(host);
                mmc_card_set_suspended(host->card);
@@ -1198,7 +1189,6 @@ static int mmc_sd_power_restore(struct mmc_host *host)
 {
        int ret;
 
-       host->card->state &= ~MMC_STATE_HIGHSPEED;
        mmc_claim_host(host);
        ret = mmc_sd_init_card(host, host->card->ocr, host->card);
        mmc_release_host(host);
drivers/mmc/core/sd.h +0 -1
index 4b34b24..aab824a 100644
@@ -12,6 +12,5 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
        bool reinit);
 unsigned mmc_sd_get_max_clock(struct mmc_card *card);
 int mmc_sd_switch_hs(struct mmc_card *card);
-void mmc_sd_go_highspeed(struct mmc_card *card);
 
 #endif
drivers/mmc/core/sdio.c +2 -6
index 4d721c6..ef57d2d 100644
@@ -363,7 +363,7 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card)
 {
        unsigned max_dtr;
 
-       if (mmc_card_highspeed(card)) {
+       if (mmc_card_hs(card)) {
                /*
                 * The SDIO specification doesn't mention how
                 * the CIS transfer speed register relates to
@@ -733,7 +733,6 @@ try_again:
                mmc_set_clock(host, card->cis.max_dtr);
 
                if (card->cccr.high_speed) {
-                       mmc_card_set_highspeed(card);
                        mmc_set_timing(card->host, MMC_TIMING_SD_HS);
                }
 
@@ -792,16 +791,13 @@ try_again:
                err = mmc_sdio_init_uhs_card(card);
                if (err)
                        goto remove;
-
-               /* Card is an ultra-high-speed card */
-               mmc_card_set_uhs(card);
        } else {
                /*
                 * Switch to high-speed (if supported).
                 */
                err = sdio_enable_hs(card);
                if (err > 0)
-                       mmc_sd_go_highspeed(card);
+                       mmc_set_timing(card->host, MMC_TIMING_SD_HS);
                else if (err)
                        goto remove;
 
include/linux/mmc/card.h +1 -0
index b730272..e6ce178 100644
@@ -194,6 +194,7 @@ struct sdio_cis {
 };
 
 struct mmc_host;
+struct mmc_ios;
 struct sdio_func;
 struct sdio_func_tuple;
 

include/linux/mmc/card.h struct mmc_part { · line 243

Quoted 4 lines
include/linux/mmc/card.h +1 -0
@@ -239,6 +240,7 @@ struct mmc_part {
  */
 struct mmc_card {
        struct mmc_host         *host;          /* the host this device belongs to */
+       struct mmc_ios          *ios;           /* bus settings of host */

Please remove, see comment above.

Quoted 13 lines
include/linux/mmc/card.h +0 -6
        struct device           dev;            /* the device */
        u32                     ocr;            /* the current OCR setting */
        unsigned int            rca;            /* relative card address of device */
@@ -250,15 +252,11 @@ struct mmc_card {
        unsigned int            state;          /* (our) card state */
 #define MMC_STATE_PRESENT      (1<<0)          /* present in sysfs */
 #define MMC_STATE_READONLY     (1<<1)          /* card is read-only */
-#define MMC_STATE_HIGHSPEED    (1<<2)          /* card is in high speed mode */
-#define MMC_STATE_BLOCKADDR    (1<<3)          /* card uses block-addressing */
-#define MMC_STATE_HIGHSPEED_DDR (1<<4)         /* card is in high speed mode */
-#define MMC_STATE_ULTRAHIGHSPEED (1<<5)                /* card is in ultra high speed mode */
-#define MMC_CARD_SDXC          (1<<6)          /* card is SDXC */
-#define MMC_CARD_REMOVED       (1<<7)          /* card has been removed */

include/linux/mmc/card.h struct mmc_card { · line 261

Quoted 10 lines
include/linux/mmc/card.h +5 -3
-#define MMC_STATE_HIGHSPEED_200        (1<<8)          /* card is in HS200 mode */
-#define MMC_STATE_DOING_BKOPS  (1<<10)         /* card is doing BKOPS */
-#define MMC_STATE_SUSPENDED    (1<<11)         /* card is suspended */
+#define MMC_STATE_BLOCKADDR    (1<<2)          /* card uses block-addressing */
+#define MMC_CARD_SDXC          (1<<3)          /* card is SDXC */
+#define MMC_CARD_REMOVED       (1<<4)          /* card has been removed */
+#define MMC_STATE_DOING_BKOPS  (1<<5)          /* card is doing BKOPS */
+#define MMC_STATE_SUSPENDED    (1<<6)          /* card is suspended */
        unsigned int            quirks;         /* card quirks */
 #define MMC_QUIRK_LENIENT_FN0  (1<<0)          /* allow SDIO FN0 writes outside of the VS CCCR range

*/

Quoted 58 lines
include/linux/mmc/card.h +0 -8
 #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1)   /* use func->cur_blksize */
@@ -418,11 +416,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 
 #define mmc_card_present(c)    ((c)->state & MMC_STATE_PRESENT)
 #define mmc_card_readonly(c)   ((c)->state & MMC_STATE_READONLY)
-#define mmc_card_highspeed(c)  ((c)->state & MMC_STATE_HIGHSPEED)
-#define mmc_card_hs200(c)      ((c)->state & MMC_STATE_HIGHSPEED_200)
 #define mmc_card_blockaddr(c)  ((c)->state & MMC_STATE_BLOCKADDR)
-#define mmc_card_ddr_mode(c)   ((c)->state & MMC_STATE_HIGHSPEED_DDR)
-#define mmc_card_uhs(c)                ((c)->state & MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
 #define mmc_card_removed(c)    ((c) && ((c)->state & MMC_CARD_REMOVED))
 #define mmc_card_doing_bkops(c)        ((c)->state & MMC_STATE_DOING_BKOPS)
@@ -430,11 +424,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 
 #define mmc_card_set_present(c)        ((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
-#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
-#define mmc_card_set_hs200(c)  ((c)->state |= MMC_STATE_HIGHSPEED_200)
 #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
-#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
-#define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
 #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
 #define mmc_card_set_doing_bkops(c)    ((c)->state |= MMC_STATE_DOING_BKOPS)
include/linux/mmc/host.h +18 -0
index 87b1f4f..71977f4 100644
@@ -17,6 +17,7 @@
 #include <linux/fault-inject.h>
 
 #include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
 #include <linux/mmc/pm.h>
 
 struct mmc_ios {
@@ -485,4 +486,26 @@ static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
        return host->ios.clock;
 }
 #endif
+
+static inline int mmc_card_hs(struct mmc_card *card)
+{
+       return card->ios->timing == MMC_TIMING_SD_HS ||
+               card->ios->timing == MMC_TIMING_MMC_HS;
+}
+
+static inline int mmc_card_uhs(struct mmc_card *card)
+{
+       return card->ios->timing >= MMC_TIMING_UHS_SDR12 &&
+               card->ios->timing <= MMC_TIMING_UHS_DDR50;
+}
+
+static inline bool mmc_card_hs200(struct mmc_card *card)
+{
+       return card->ios->timing == MMC_TIMING_MMC_HS200;
+}
Quoted 8 lines
Quoted 4 lines

include/linux/mmc/host.h static inline unsigned int mmc_host_clk_rate(struct mmc_host *host) · line 509

Quoted 4 lines
include/linux/mmc/host.h +4 -0
+
+static inline bool mmc_card_ddr52(struct mmc_card *card)
+{
+       return card->ios->timing == MMC_TIMING_MMC_DDR52;

I just added another reference toward ios.
Do you expect like below?
return card->host->ios->timing == MMC_TIMING_MMC_DDR52; I'm fine if you checked that.

That looks okay to me! Please adopt to this.

Kind regards
Uffe

Quoted 22 lines

Thanks,
Seungwon Jeon

Quoted 17 lines
Quoted 6 lines
include/linux/mmc/host.h +1 -1
+}
 #endif /* LINUX_MMC_HOST_H */
--

1.7.0.4

Nice clean-up!

Besides my minor comment above, you have my ack.

Kind regards
Ulf Hansson
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#136 lore raw

PATCH v2 1/5 mmc: drop the speed mode of card's state

In reply to Seungwon Jeon

Timing mode identifier has same role and can take the place of speed mode. This change removes all related speed mode.

---
Changes in v2:
Removed reference pointer to 'ios'.

 drivers/mmc/core/bus.c   |    8 ++++----
 drivers/mmc/core/core.c  |    3 +--
 drivers/mmc/core/mmc.c   |   11 +++--------
 drivers/mmc/core/sd.c    |   16 +++-------------
 drivers/mmc/core/sd.h    |    1 -
 drivers/mmc/core/sdio.c  |    8 ++------
 include/linux/mmc/card.h |   23 ++++++-----------------
 include/linux/mmc/host.h |   23 +++++++++++++++++++++++
 8 files changed, 42 insertions(+), 51 deletions(-)
drivers/mmc/core/bus.c +4 -4
index 8246448..f37e9d6 100644
@@ -341,16 +341,16 @@ int mmc_add_card(struct mmc_card *card)
 	if (mmc_host_is_spi(card->host)) {
 		pr_info("%s: new %s%s%s card on SPI\n",
 			mmc_hostname(card->host),
-			mmc_card_highspeed(card) ? "high speed " : "",
-			mmc_card_ddr_mode(card) ? "DDR " : "",
+			mmc_card_hs(card) ? "high speed " : "",
+			mmc_card_ddr52(card) ? "DDR " : "",
 			type);
 	} else {
 		pr_info("%s: new %s%s%s%s%s card at address %04x\n",
 			mmc_hostname(card->host),
 			mmc_card_uhs(card) ? "ultra high speed " :
-			(mmc_card_highspeed(card) ? "high speed " : ""),
+			(mmc_card_hs(card) ? "high speed " : ""),
 			(mmc_card_hs200(card) ? "HS200 " : ""),
-			mmc_card_ddr_mode(card) ? "DDR " : "",
+			mmc_card_ddr52(card) ? "DDR " : "",
 			uhs_bus_speed_mode, type, card->rca);
 	}
 
drivers/mmc/core/core.c +1 -2
index dc7a5fb..5967889 100644
@@ -2182,7 +2182,7 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
 {
 	struct mmc_command cmd = {0};
 
-	if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card))
+	if (mmc_card_blockaddr(card) || mmc_card_ddr52(card))
 		return 0;
 
 	cmd.opcode = MMC_SET_BLOCKLEN;
@@ -2262,7 +2262,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
 		}
 	}
 
-	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_DDR);
 	if (mmc_host_is_spi(host)) {
 		host->ios.chip_select = MMC_CS_HIGH;
 		host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
drivers/mmc/core/mmc.c +3 -8
index e22d851..db9655f 100644
@@ -1091,11 +1091,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		} else {
 			if (card->ext_csd.hs_max_dtr > 52000000 &&
 			    host->caps2 & MMC_CAP2_HS200) {
-				mmc_card_set_hs200(card);
 				mmc_set_timing(card->host,
 					       MMC_TIMING_MMC_HS200);
 			} else {
-				mmc_card_set_highspeed(card);
 				mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
 			}
 		}
@@ -1106,10 +1104,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	max_dtr = (unsigned int)-1;
 
-	if (mmc_card_highspeed(card) || mmc_card_hs200(card)) {
+	if (mmc_card_hs(card) || mmc_card_hs200(card)) {
 		if (max_dtr > card->ext_csd.hs_max_dtr)
 			max_dtr = card->ext_csd.hs_max_dtr;
-		if (mmc_card_highspeed(card) && (max_dtr > 52000000))
+		if (mmc_card_hs(card) && (max_dtr > 52000000))
 			max_dtr = 52000000;
 	} else if (max_dtr > card->csd.max_dtr) {
 		max_dtr = card->csd.max_dtr;
@@ -1120,7 +1118,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	/*
 	 * Indicate DDR mode (if supported).
 	 */
-	if (mmc_card_highspeed(card)) {
+	if (mmc_card_hs(card)) {
 		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
 			&& (host->caps & MMC_CAP_1_8V_DDR))
 				ddr = MMC_1_8V_DDR_MODE;
@@ -1263,7 +1261,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 				if (err)
 					goto err;
 			}
-			mmc_card_set_ddr_mode(card);
 			mmc_set_timing(card->host, MMC_TIMING_MMC_DDR52);
 			mmc_set_bus_width(card->host, bus_width);
 		}
@@ -1507,7 +1504,6 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
 		err = mmc_sleep(host);
 	else if (!mmc_host_is_spi(host))
 		err = mmc_deselect_cards(host);
-	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
 
 	if (!err) {
 		mmc_power_off(host);
@@ -1637,7 +1633,6 @@ static int mmc_power_restore(struct mmc_host *host)
 {
 	int ret;
 
-	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
 	mmc_claim_host(host);
 	ret = mmc_init_card(host, host->card->ocr, host->card);
 	mmc_release_host(host);
drivers/mmc/core/sd.c +3 -13
index 2dd359d..9fc5b31 100644
@@ -895,7 +895,7 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
 {
 	unsigned max_dtr = (unsigned int)-1;
 
-	if (mmc_card_highspeed(card)) {
+	if (mmc_card_hs(card)) {
 		if (max_dtr > card->sw_caps.hs_max_dtr)
 			max_dtr = card->sw_caps.hs_max_dtr;
 	} else if (max_dtr > card->csd.max_dtr) {
@@ -905,12 +905,6 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
 	return max_dtr;
 }
 
-void mmc_sd_go_highspeed(struct mmc_card *card)
-{
-	mmc_card_set_highspeed(card);
-	mmc_set_timing(card->host, MMC_TIMING_SD_HS);
-}
-
 /*
  * Handle the detection and initialisation of a card.
  *
@@ -985,16 +979,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
 		err = mmc_sd_init_uhs_card(card);
 		if (err)
 			goto free_card;
-
-		/* Card is an ultra-high-speed card */
-		mmc_card_set_uhs(card);
 	} else {
 		/*
 		 * Attempt to change to high-speed (if supported)
 		 */
 		err = mmc_sd_switch_hs(card);
 		if (err > 0)
-			mmc_sd_go_highspeed(card);
+			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
 		else if (err)
 			goto free_card;
 
@@ -1089,7 +1080,7 @@ static int _mmc_sd_suspend(struct mmc_host *host)
 
 	if (!mmc_host_is_spi(host))
 		err = mmc_deselect_cards(host);
-	host->card->state &= ~MMC_STATE_HIGHSPEED;
+
 	if (!err) {
 		mmc_power_off(host);
 		mmc_card_set_suspended(host->card);
@@ -1198,7 +1189,6 @@ static int mmc_sd_power_restore(struct mmc_host *host)
 {
 	int ret;
 
-	host->card->state &= ~MMC_STATE_HIGHSPEED;
 	mmc_claim_host(host);
 	ret = mmc_sd_init_card(host, host->card->ocr, host->card);
 	mmc_release_host(host);
drivers/mmc/core/sd.h +0 -1
index 4b34b24..aab824a 100644
@@ -12,6 +12,5 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
 	bool reinit);
 unsigned mmc_sd_get_max_clock(struct mmc_card *card);
 int mmc_sd_switch_hs(struct mmc_card *card);
-void mmc_sd_go_highspeed(struct mmc_card *card);
 
 #endif
drivers/mmc/core/sdio.c +2 -6
index 4d721c6..ef57d2d 100644
@@ -363,7 +363,7 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card)
 {
 	unsigned max_dtr;
 
-	if (mmc_card_highspeed(card)) {
+	if (mmc_card_hs(card)) {
 		/*
 		 * The SDIO specification doesn't mention how
 		 * the CIS transfer speed register relates to
@@ -733,7 +733,6 @@ try_again:
 		mmc_set_clock(host, card->cis.max_dtr);
 
 		if (card->cccr.high_speed) {
-			mmc_card_set_highspeed(card);
 			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
 		}
 
@@ -792,16 +791,13 @@ try_again:
 		err = mmc_sdio_init_uhs_card(card);
 		if (err)
 			goto remove;
-
-		/* Card is an ultra-high-speed card */
-		mmc_card_set_uhs(card);
 	} else {
 		/*
 		 * Switch to high-speed (if supported).
 		 */
 		err = sdio_enable_hs(card);
 		if (err > 0)
-			mmc_sd_go_highspeed(card);
+			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
 		else if (err)
 			goto remove;
 
include/linux/mmc/card.h +6 -17
index b730272..5473133 100644
@@ -194,6 +194,7 @@ struct sdio_cis {
 };
 
 struct mmc_host;
+struct mmc_ios;
 struct sdio_func;
 struct sdio_func_tuple;
 
@@ -250,15 +251,11 @@ struct mmc_card {
 	unsigned int		state;		/* (our) card state */
 #define MMC_STATE_PRESENT	(1<<0)		/* present in sysfs */
 #define MMC_STATE_READONLY	(1<<1)		/* card is read-only */
-#define MMC_STATE_HIGHSPEED	(1<<2)		/* card is in high speed mode */
-#define MMC_STATE_BLOCKADDR	(1<<3)		/* card uses block-addressing */
-#define MMC_STATE_HIGHSPEED_DDR (1<<4)		/* card is in high speed mode */
-#define MMC_STATE_ULTRAHIGHSPEED (1<<5)		/* card is in ultra high speed mode */
-#define MMC_CARD_SDXC		(1<<6)		/* card is SDXC */
-#define MMC_CARD_REMOVED	(1<<7)		/* card has been removed */
-#define MMC_STATE_HIGHSPEED_200	(1<<8)		/* card is in HS200 mode */
-#define MMC_STATE_DOING_BKOPS	(1<<10)		/* card is doing BKOPS */
-#define MMC_STATE_SUSPENDED	(1<<11)		/* card is suspended */
+#define MMC_STATE_BLOCKADDR	(1<<2)		/* card uses block-addressing */
+#define MMC_CARD_SDXC		(1<<3)		/* card is SDXC */
+#define MMC_CARD_REMOVED	(1<<4)		/* card has been removed */
+#define MMC_STATE_DOING_BKOPS	(1<<5)		/* card is doing BKOPS */
+#define MMC_STATE_SUSPENDED	(1<<6)		/* card is suspended */
 	unsigned int		quirks; 	/* card quirks */
 #define MMC_QUIRK_LENIENT_FN0	(1<<0)		/* allow SDIO FN0 writes outside of the VS CCCR range */
 #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1)	/* use func->cur_blksize */
@@ -418,11 +415,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 
 #define mmc_card_present(c)	((c)->state & MMC_STATE_PRESENT)
 #define mmc_card_readonly(c)	((c)->state & MMC_STATE_READONLY)
-#define mmc_card_highspeed(c)	((c)->state & MMC_STATE_HIGHSPEED)
-#define mmc_card_hs200(c)	((c)->state & MMC_STATE_HIGHSPEED_200)
 #define mmc_card_blockaddr(c)	((c)->state & MMC_STATE_BLOCKADDR)
-#define mmc_card_ddr_mode(c)	((c)->state & MMC_STATE_HIGHSPEED_DDR)
-#define mmc_card_uhs(c)		((c)->state & MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
 #define mmc_card_removed(c)	((c) && ((c)->state & MMC_CARD_REMOVED))
 #define mmc_card_doing_bkops(c)	((c)->state & MMC_STATE_DOING_BKOPS)
@@ -430,11 +423,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 
 #define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
-#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
-#define mmc_card_set_hs200(c)	((c)->state |= MMC_STATE_HIGHSPEED_200)
 #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
-#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
-#define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
 #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
 #define mmc_card_set_doing_bkops(c)	((c)->state |= MMC_STATE_DOING_BKOPS)
include/linux/mmc/host.h +23 -0
index 3535420..2f263ae 100644
@@ -17,6 +17,7 @@
 #include <linux/fault-inject.h>
 
 #include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
 #include <linux/mmc/pm.h>
 
 struct mmc_ios {
@@ -476,4 +477,26 @@ static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
 	return host->ios.clock;
 }
 #endif
+
+static inline int mmc_card_hs(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_SD_HS ||
+		card->host->ios.timing == MMC_TIMING_MMC_HS;
+}
+
+static inline int mmc_card_uhs(struct mmc_card *card)
+{
+	return card->host->ios.timing >= MMC_TIMING_UHS_SDR12 &&
+		card->host->ios.timing <= MMC_TIMING_UHS_DDR50;
+}
+
+static inline bool mmc_card_hs200(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_MMC_HS200;
+}
+
+static inline bool mmc_card_ddr52(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_MMC_DDR52;
+}
 #endif /* LINUX_MMC_HOST_H */
Signature · 1 line
1.7.0.4
#137 lore raw

PATCH v3 1/5 mmc: drop the speed mode of card's state

In reply to Seungwon Jeon

Timing mode identifier has same role and can take the place of speed mode. This change removes all related speed mode.

---
 drivers/mmc/core/bus.c   |    8 ++++----
 drivers/mmc/core/core.c  |    3 +--
 drivers/mmc/core/mmc.c   |   11 +++--------
 drivers/mmc/core/sd.c    |   16 +++-------------
 drivers/mmc/core/sd.h    |    1 -
 drivers/mmc/core/sdio.c  |    8 ++------
 include/linux/mmc/card.h |   23 ++++++-----------------
 include/linux/mmc/host.h |   23 +++++++++++++++++++++++
 8 files changed, 42 insertions(+), 51 deletions(-)
drivers/mmc/core/bus.c +4 -4
index 8246448..f37e9d6 100644
@@ -341,16 +341,16 @@ int mmc_add_card(struct mmc_card *card)
 	if (mmc_host_is_spi(card->host)) {
 		pr_info("%s: new %s%s%s card on SPI\n",
 			mmc_hostname(card->host),
-			mmc_card_highspeed(card) ? "high speed " : "",
-			mmc_card_ddr_mode(card) ? "DDR " : "",
+			mmc_card_hs(card) ? "high speed " : "",
+			mmc_card_ddr52(card) ? "DDR " : "",
 			type);
 	} else {
 		pr_info("%s: new %s%s%s%s%s card at address %04x\n",
 			mmc_hostname(card->host),
 			mmc_card_uhs(card) ? "ultra high speed " :
-			(mmc_card_highspeed(card) ? "high speed " : ""),
+			(mmc_card_hs(card) ? "high speed " : ""),
 			(mmc_card_hs200(card) ? "HS200 " : ""),
-			mmc_card_ddr_mode(card) ? "DDR " : "",
+			mmc_card_ddr52(card) ? "DDR " : "",
 			uhs_bus_speed_mode, type, card->rca);
 	}
 
drivers/mmc/core/core.c +1 -2
index dc7a5fb..5967889 100644
@@ -2182,7 +2182,7 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
 {
 	struct mmc_command cmd = {0};
 
-	if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card))
+	if (mmc_card_blockaddr(card) || mmc_card_ddr52(card))
 		return 0;
 
 	cmd.opcode = MMC_SET_BLOCKLEN;
@@ -2262,7 +2262,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
 		}
 	}
 
-	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_DDR);
 	if (mmc_host_is_spi(host)) {
 		host->ios.chip_select = MMC_CS_HIGH;
 		host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
drivers/mmc/core/mmc.c +3 -8
index e22d851..db9655f 100644
@@ -1091,11 +1091,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		} else {
 			if (card->ext_csd.hs_max_dtr > 52000000 &&
 			    host->caps2 & MMC_CAP2_HS200) {
-				mmc_card_set_hs200(card);
 				mmc_set_timing(card->host,
 					       MMC_TIMING_MMC_HS200);
 			} else {
-				mmc_card_set_highspeed(card);
 				mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
 			}
 		}
@@ -1106,10 +1104,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	max_dtr = (unsigned int)-1;
 
-	if (mmc_card_highspeed(card) || mmc_card_hs200(card)) {
+	if (mmc_card_hs(card) || mmc_card_hs200(card)) {
 		if (max_dtr > card->ext_csd.hs_max_dtr)
 			max_dtr = card->ext_csd.hs_max_dtr;
-		if (mmc_card_highspeed(card) && (max_dtr > 52000000))
+		if (mmc_card_hs(card) && (max_dtr > 52000000))
 			max_dtr = 52000000;
 	} else if (max_dtr > card->csd.max_dtr) {
 		max_dtr = card->csd.max_dtr;
@@ -1120,7 +1118,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	/*
 	 * Indicate DDR mode (if supported).
 	 */
-	if (mmc_card_highspeed(card)) {
+	if (mmc_card_hs(card)) {
 		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
 			&& (host->caps & MMC_CAP_1_8V_DDR))
 				ddr = MMC_1_8V_DDR_MODE;
@@ -1263,7 +1261,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 				if (err)
 					goto err;
 			}
-			mmc_card_set_ddr_mode(card);
 			mmc_set_timing(card->host, MMC_TIMING_MMC_DDR52);
 			mmc_set_bus_width(card->host, bus_width);
 		}
@@ -1507,7 +1504,6 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
 		err = mmc_sleep(host);
 	else if (!mmc_host_is_spi(host))
 		err = mmc_deselect_cards(host);
-	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
 
 	if (!err) {
 		mmc_power_off(host);
@@ -1637,7 +1633,6 @@ static int mmc_power_restore(struct mmc_host *host)
 {
 	int ret;
 
-	host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
 	mmc_claim_host(host);
 	ret = mmc_init_card(host, host->card->ocr, host->card);
 	mmc_release_host(host);
drivers/mmc/core/sd.c +3 -13
index 2dd359d..9fc5b31 100644
@@ -895,7 +895,7 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
 {
 	unsigned max_dtr = (unsigned int)-1;
 
-	if (mmc_card_highspeed(card)) {
+	if (mmc_card_hs(card)) {
 		if (max_dtr > card->sw_caps.hs_max_dtr)
 			max_dtr = card->sw_caps.hs_max_dtr;
 	} else if (max_dtr > card->csd.max_dtr) {
@@ -905,12 +905,6 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
 	return max_dtr;
 }
 
-void mmc_sd_go_highspeed(struct mmc_card *card)
-{
-	mmc_card_set_highspeed(card);
-	mmc_set_timing(card->host, MMC_TIMING_SD_HS);
-}
-
 /*
  * Handle the detection and initialisation of a card.
  *
@@ -985,16 +979,13 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
 		err = mmc_sd_init_uhs_card(card);
 		if (err)
 			goto free_card;
-
-		/* Card is an ultra-high-speed card */
-		mmc_card_set_uhs(card);
 	} else {
 		/*
 		 * Attempt to change to high-speed (if supported)
 		 */
 		err = mmc_sd_switch_hs(card);
 		if (err > 0)
-			mmc_sd_go_highspeed(card);
+			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
 		else if (err)
 			goto free_card;
 
@@ -1089,7 +1080,7 @@ static int _mmc_sd_suspend(struct mmc_host *host)
 
 	if (!mmc_host_is_spi(host))
 		err = mmc_deselect_cards(host);
-	host->card->state &= ~MMC_STATE_HIGHSPEED;
+
 	if (!err) {
 		mmc_power_off(host);
 		mmc_card_set_suspended(host->card);
@@ -1198,7 +1189,6 @@ static int mmc_sd_power_restore(struct mmc_host *host)
 {
 	int ret;
 
-	host->card->state &= ~MMC_STATE_HIGHSPEED;
 	mmc_claim_host(host);
 	ret = mmc_sd_init_card(host, host->card->ocr, host->card);
 	mmc_release_host(host);
drivers/mmc/core/sd.h +0 -1
index 4b34b24..aab824a 100644
@@ -12,6 +12,5 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
 	bool reinit);
 unsigned mmc_sd_get_max_clock(struct mmc_card *card);
 int mmc_sd_switch_hs(struct mmc_card *card);
-void mmc_sd_go_highspeed(struct mmc_card *card);
 
 #endif
drivers/mmc/core/sdio.c +2 -6
index 4d721c6..ef57d2d 100644
@@ -363,7 +363,7 @@ static unsigned mmc_sdio_get_max_clock(struct mmc_card *card)
 {
 	unsigned max_dtr;
 
-	if (mmc_card_highspeed(card)) {
+	if (mmc_card_hs(card)) {
 		/*
 		 * The SDIO specification doesn't mention how
 		 * the CIS transfer speed register relates to
@@ -733,7 +733,6 @@ try_again:
 		mmc_set_clock(host, card->cis.max_dtr);
 
 		if (card->cccr.high_speed) {
-			mmc_card_set_highspeed(card);
 			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
 		}
 
@@ -792,16 +791,13 @@ try_again:
 		err = mmc_sdio_init_uhs_card(card);
 		if (err)
 			goto remove;
-
-		/* Card is an ultra-high-speed card */
-		mmc_card_set_uhs(card);
 	} else {
 		/*
 		 * Switch to high-speed (if supported).
 		 */
 		err = sdio_enable_hs(card);
 		if (err > 0)
-			mmc_sd_go_highspeed(card);
+			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
 		else if (err)
 			goto remove;
 
include/linux/mmc/card.h +6 -17
index b730272..5473133 100644
@@ -194,6 +194,7 @@ struct sdio_cis {
 };
 
 struct mmc_host;
+struct mmc_ios;
 struct sdio_func;
 struct sdio_func_tuple;
 
@@ -250,15 +251,11 @@ struct mmc_card {
 	unsigned int		state;		/* (our) card state */
 #define MMC_STATE_PRESENT	(1<<0)		/* present in sysfs */
 #define MMC_STATE_READONLY	(1<<1)		/* card is read-only */
-#define MMC_STATE_HIGHSPEED	(1<<2)		/* card is in high speed mode */
-#define MMC_STATE_BLOCKADDR	(1<<3)		/* card uses block-addressing */
-#define MMC_STATE_HIGHSPEED_DDR (1<<4)		/* card is in high speed mode */
-#define MMC_STATE_ULTRAHIGHSPEED (1<<5)		/* card is in ultra high speed mode */
-#define MMC_CARD_SDXC		(1<<6)		/* card is SDXC */
-#define MMC_CARD_REMOVED	(1<<7)		/* card has been removed */
-#define MMC_STATE_HIGHSPEED_200	(1<<8)		/* card is in HS200 mode */
-#define MMC_STATE_DOING_BKOPS	(1<<10)		/* card is doing BKOPS */
-#define MMC_STATE_SUSPENDED	(1<<11)		/* card is suspended */
+#define MMC_STATE_BLOCKADDR	(1<<2)		/* card uses block-addressing */
+#define MMC_CARD_SDXC		(1<<3)		/* card is SDXC */
+#define MMC_CARD_REMOVED	(1<<4)		/* card has been removed */
+#define MMC_STATE_DOING_BKOPS	(1<<5)		/* card is doing BKOPS */
+#define MMC_STATE_SUSPENDED	(1<<6)		/* card is suspended */
 	unsigned int		quirks; 	/* card quirks */
 #define MMC_QUIRK_LENIENT_FN0	(1<<0)		/* allow SDIO FN0 writes outside of the VS CCCR range */
 #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1)	/* use func->cur_blksize */
@@ -418,11 +415,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 
 #define mmc_card_present(c)	((c)->state & MMC_STATE_PRESENT)
 #define mmc_card_readonly(c)	((c)->state & MMC_STATE_READONLY)
-#define mmc_card_highspeed(c)	((c)->state & MMC_STATE_HIGHSPEED)
-#define mmc_card_hs200(c)	((c)->state & MMC_STATE_HIGHSPEED_200)
 #define mmc_card_blockaddr(c)	((c)->state & MMC_STATE_BLOCKADDR)
-#define mmc_card_ddr_mode(c)	((c)->state & MMC_STATE_HIGHSPEED_DDR)
-#define mmc_card_uhs(c)		((c)->state & MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
 #define mmc_card_removed(c)	((c) && ((c)->state & MMC_CARD_REMOVED))
 #define mmc_card_doing_bkops(c)	((c)->state & MMC_STATE_DOING_BKOPS)
@@ -430,11 +423,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 
 #define mmc_card_set_present(c)	((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
-#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
-#define mmc_card_set_hs200(c)	((c)->state |= MMC_STATE_HIGHSPEED_200)
 #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
-#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
-#define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
 #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
 #define mmc_card_set_doing_bkops(c)	((c)->state |= MMC_STATE_DOING_BKOPS)
include/linux/mmc/host.h +23 -0
index 3535420..2f263ae 100644
@@ -17,6 +17,7 @@
 #include <linux/fault-inject.h>
 
 #include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
 #include <linux/mmc/pm.h>
 
 struct mmc_ios {
@@ -476,4 +477,26 @@ static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
 	return host->ios.clock;
 }
 #endif
+
+static inline int mmc_card_hs(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_SD_HS ||
+		card->host->ios.timing == MMC_TIMING_MMC_HS;
+}
+
+static inline int mmc_card_uhs(struct mmc_card *card)
+{
+	return card->host->ios.timing >= MMC_TIMING_UHS_SDR12 &&
+		card->host->ios.timing <= MMC_TIMING_UHS_DDR50;
+}
+
+static inline bool mmc_card_hs200(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_MMC_HS200;
+}
+
+static inline bool mmc_card_ddr52(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_MMC_DDR52;
+}
 #endif /* LINUX_MMC_HOST_H */
Signature · 1 line
1.7.0.4
#138 lore raw

PATCH RESEND 2/5 mmc: identify available device type to select

In reply to Ulf Hansson

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

---
 drivers/mmc/core/mmc.c   |   77 ++++++++++++++++++++++++++-------------------
 include/linux/mmc/card.h |    6 ++-
 include/linux/mmc/host.h |    6 ---
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 56 insertions(+), 45 deletions(-)
drivers/mmc/core/mmc.c +44 -33
index 613e641..1ea155a 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
 	u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
 	u32 caps = host->caps, caps2 = host->caps2;
 	unsigned int hs_max_dtr = 0;
+	unsigned int avail_type = 0;
 
-	if (card_type & EXT_CSD_CARD_TYPE_26)
+	if (caps & MMC_CAP_MMC_HIGHSPEED &&
+	    card_type & EXT_CSD_CARD_TYPE_HS_26) {
 		hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+	}
 
 	if (caps & MMC_CAP_MMC_HIGHSPEED &&
-			card_type & EXT_CSD_CARD_TYPE_52)
+	    card_type & EXT_CSD_CARD_TYPE_HS_52) {
 		hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+	}
 
-	if ((caps & MMC_CAP_1_8V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-	    (caps & MMC_CAP_1_2V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+	if (caps & MMC_CAP_1_8V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
 		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+	}
 
-	if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-	    (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+	if (caps & MMC_CAP_1_2V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
 		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+	}
 
 	card->ext_csd.hs_max_dtr = hs_max_dtr;
-	card->ext_csd.card_type = card_type;
+	card->mmc_avail_type = avail_type;
 }
 
 /*
@@ -708,6 +726,11 @@ static struct device_type mmc_type = {
 	.groups = mmc_attr_groups,
 };
 
+static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
+{
+	return card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+}
+
 /*
  * Select the PowerClass for the current bus width
  * If power class is defined for 4/8 bit bus in the
@@ -808,12 +831,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
 	host = card->host;
 
-	if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-			host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+	if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-	if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-			host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+	if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
 	/* If fails try again during next card power cycle */
@@ -1070,10 +1091,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	if (card->ext_csd.hs_max_dtr != 0) {
 		err = 0;
-		if (card->ext_csd.hs_max_dtr > 52000000 &&
-		    host->caps2 & MMC_CAP2_HS200)
+		if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
 			err = mmc_select_hs200(card);
-		else if	(host->caps & MMC_CAP_MMC_HIGHSPEED)
+		else if	(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
 			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 					 EXT_CSD_HS_TIMING, 1,
 					 card->ext_csd.generic_cmd6_time);
@@ -1086,13 +1106,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			       mmc_hostname(card->host));
 			err = 0;
 		} else {
-			if (card->ext_csd.hs_max_dtr > 52000000 &&
-			    host->caps2 & MMC_CAP2_HS200) {
+			if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
 				mmc_set_timing(card->host,
 					       MMC_TIMING_MMC_HS200);
-			} else {
+			else
 				mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-			}
 		}
 	}
 
@@ -1115,14 +1133,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	/*
 	 * Indicate DDR mode (if supported).
 	 */
-	if (mmc_card_hs(card)) {
-		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
-			&& (host->caps & MMC_CAP_1_8V_DDR))
-				ddr = MMC_1_8V_DDR_MODE;
-		else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
-			&& (host->caps & MMC_CAP_1_2V_DDR))
-				ddr = MMC_1_2V_DDR_MODE;
-	}
+	if (mmc_card_hs(card))
+		ddr = mmc_snoop_ddr(card);
 
 	/*
 	 * Indicate HS200 SDR mode (if supported).
@@ -1142,8 +1154,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		 * 3. set the clock to > 52Mhz <=200MHz and
 		 * 4. execute tuning for HS200
 		 */
-		if ((host->caps2 & MMC_CAP2_HS200) &&
-		    card->host->ops->execute_tuning) {
+		if (card->host->ops->execute_tuning) {
 			mmc_host_clk_hold(card->host);
 			err = card->host->ops->execute_tuning(card->host,
 				MMC_SEND_TUNING_BLOCK_HS200);
@@ -1252,7 +1263,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			 *
 			 * WARNING: eMMC rules are NOT the same as SD DDR
 			 */
-			if (ddr == MMC_1_2V_DDR_MODE) {
+			if (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) {
 				err = __mmc_set_signal_voltage(host,
 					MMC_SIGNAL_VOLTAGE_120);
 				if (err)
include/linux/mmc/card.h +4 -2
index e6ce178..c1ded09 100644
@@ -68,7 +68,6 @@ struct mmc_ext_csd {
 #define MMC_HIGH_DDR_MAX_DTR	52000000
 #define MMC_HS200_MAX_DTR	200000000
 	unsigned int		sectors;
-	unsigned int		card_type;
 	unsigned int		hc_erase_size;		/* In sectors */
 	unsigned int		hc_erase_timeout;	/* In milliseconds */
 	unsigned int		sec_trim_mult;	/* Secure trim multiplier  */
@@ -298,7 +297,10 @@ struct mmc_card {
 	const char		**info;		/* info strings */
 	struct sdio_func_tuple	*tuples;	/* unknown common tuples */
 
-	unsigned int		sd_bus_speed;	/* Bus Speed Mode set for the card */
+	union {
+		unsigned int		sd_bus_speed;	/* Bus Speed Mode set for the card */
+		unsigned int		mmc_avail_type;	/* supported device type by both host and card */
+	};
 
 	struct dentry		*debugfs_root;
 	struct mmc_part	part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
include/linux/mmc/host.h +0 -6
index 71977f4..66e632c 100644
@@ -62,12 +62,6 @@ struct mmc_ios {
 #define MMC_TIMING_MMC_DDR52	8
 #define MMC_TIMING_MMC_HS200	9
 
-#define MMC_SDR_MODE		0
-#define MMC_1_2V_DDR_MODE	1
-#define MMC_1_8V_DDR_MODE	2
-#define MMC_1_2V_SDR_MODE	3
-#define MMC_1_8V_SDR_MODE	4
-
 	unsigned char	signal_voltage;		/* signalling voltage (1.8V or 3.3V) */
 
 #define MMC_SIGNAL_VOLTAGE_330	0
include/linux/mmc/mmc.h +8 -4
index 50bcde3..f734c0c 100644
@@ -354,18 +354,22 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-#define EXT_CSD_CARD_TYPE_26	(1<<0)	/* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52	(1<<1)	/* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_MASK	0x3F	/* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
+				 EXT_CSD_CARD_TYPE_HS_52)
 #define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
 					     /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
 					     /* DDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
 					| EXT_CSD_CARD_TYPE_DDR_1_2V)
-#define EXT_CSD_CARD_TYPE_SDR_1_8V	(1<<4)	/* Card can run at 200MHz */
-#define EXT_CSD_CARD_TYPE_SDR_1_2V	(1<<5)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_8V	(1<<4)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V	(1<<5)	/* Card can run at 200MHz */
 						/* SDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
+					 EXT_CSD_CARD_TYPE_HS200_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
Signature · 1 line
1.7.0.4
#139 lore raw

PATCH v2 2/5 mmc: identify available device type to select

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

---
Changes in v2:
Just rebased with latest one.

 drivers/mmc/core/mmc.c   |   77 ++++++++++++++++++++++++++-------------------
 include/linux/mmc/card.h |    6 ++-
 include/linux/mmc/host.h |    6 ---
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 56 insertions(+), 45 deletions(-)
drivers/mmc/core/mmc.c +44 -33
index db9655f..0abece0 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
 	u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
 	u32 caps = host->caps, caps2 = host->caps2;
 	unsigned int hs_max_dtr = 0;
+	unsigned int avail_type = 0;
 
-	if (card_type & EXT_CSD_CARD_TYPE_26)
+	if (caps & MMC_CAP_MMC_HIGHSPEED &&
+	    card_type & EXT_CSD_CARD_TYPE_HS_26) {
 		hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+	}
 
 	if (caps & MMC_CAP_MMC_HIGHSPEED &&
-			card_type & EXT_CSD_CARD_TYPE_52)
+	    card_type & EXT_CSD_CARD_TYPE_HS_52) {
 		hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+	}
 
-	if ((caps & MMC_CAP_1_8V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-	    (caps & MMC_CAP_1_2V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+	if (caps & MMC_CAP_1_8V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
 		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+	}
 
-	if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-	    (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+	if (caps & MMC_CAP_1_2V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
 		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+	}
 
 	card->ext_csd.hs_max_dtr = hs_max_dtr;
-	card->ext_csd.card_type = card_type;
+	card->mmc_avail_type = avail_type;
 }
 
 /*
@@ -708,6 +726,11 @@ static struct device_type mmc_type = {
 	.groups = mmc_attr_groups,
 };
 
+static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
+{
+	return card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+}
+
 /*
  * Select the PowerClass for the current bus width
  * If power class is defined for 4/8 bit bus in the
@@ -808,12 +831,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
 	host = card->host;
 
-	if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-			host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+	if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-	if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-			host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+	if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
 	/* If fails try again during next card power cycle */
@@ -1072,10 +1093,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	if (card->ext_csd.hs_max_dtr != 0) {
 		err = 0;
-		if (card->ext_csd.hs_max_dtr > 52000000 &&
-		    host->caps2 & MMC_CAP2_HS200)
+		if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
 			err = mmc_select_hs200(card);
-		else if	(host->caps & MMC_CAP_MMC_HIGHSPEED)
+		else if	(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
 			err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 					EXT_CSD_HS_TIMING, 1,
 					card->ext_csd.generic_cmd6_time,
@@ -1089,13 +1109,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			       mmc_hostname(card->host));
 			err = 0;
 		} else {
-			if (card->ext_csd.hs_max_dtr > 52000000 &&
-			    host->caps2 & MMC_CAP2_HS200) {
+			if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
 				mmc_set_timing(card->host,
 					       MMC_TIMING_MMC_HS200);
-			} else {
+			else
 				mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-			}
 		}
 	}
 
@@ -1118,14 +1136,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	/*
 	 * Indicate DDR mode (if supported).
 	 */
-	if (mmc_card_hs(card)) {
-		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
-			&& (host->caps & MMC_CAP_1_8V_DDR))
-				ddr = MMC_1_8V_DDR_MODE;
-		else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
-			&& (host->caps & MMC_CAP_1_2V_DDR))
-				ddr = MMC_1_2V_DDR_MODE;
-	}
+	if (mmc_card_hs(card))
+		ddr = mmc_snoop_ddr(card);
 
 	/*
 	 * Indicate HS200 SDR mode (if supported).
@@ -1145,8 +1157,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		 * 3. set the clock to > 52Mhz <=200MHz and
 		 * 4. execute tuning for HS200
 		 */
-		if ((host->caps2 & MMC_CAP2_HS200) &&
-		    card->host->ops->execute_tuning) {
+		if (card->host->ops->execute_tuning) {
 			mmc_host_clk_hold(card->host);
 			err = card->host->ops->execute_tuning(card->host,
 				MMC_SEND_TUNING_BLOCK_HS200);
@@ -1255,7 +1266,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			 *
 			 * WARNING: eMMC rules are NOT the same as SD DDR
 			 */
-			if (ddr == MMC_1_2V_DDR_MODE) {
+			if (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) {
 				err = __mmc_set_signal_voltage(host,
 					MMC_SIGNAL_VOLTAGE_120);
 				if (err)
include/linux/mmc/card.h +4 -2
index 5473133..c232b10 100644
@@ -68,7 +68,6 @@ struct mmc_ext_csd {
 #define MMC_HIGH_DDR_MAX_DTR	52000000
 #define MMC_HS200_MAX_DTR	200000000
 	unsigned int		sectors;
-	unsigned int		card_type;
 	unsigned int		hc_erase_size;		/* In sectors */
 	unsigned int		hc_erase_timeout;	/* In milliseconds */
 	unsigned int		sec_trim_mult;	/* Secure trim multiplier  */
@@ -297,7 +296,10 @@ struct mmc_card {
 	const char		**info;		/* info strings */
 	struct sdio_func_tuple	*tuples;	/* unknown common tuples */
 
-	unsigned int		sd_bus_speed;	/* Bus Speed Mode set for the card */
+	union {
+		unsigned int		sd_bus_speed;	/* Bus Speed Mode set for the card */
+		unsigned int		mmc_avail_type;	/* supported device type by both host and card */
+	};
 
 	struct dentry		*debugfs_root;
 	struct mmc_part	part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
include/linux/mmc/host.h +0 -6
index 2f263ae..1ee3c10 100644
@@ -62,12 +62,6 @@ struct mmc_ios {
 #define MMC_TIMING_MMC_DDR52	8
 #define MMC_TIMING_MMC_HS200	9
 
-#define MMC_SDR_MODE		0
-#define MMC_1_2V_DDR_MODE	1
-#define MMC_1_8V_DDR_MODE	2
-#define MMC_1_2V_SDR_MODE	3
-#define MMC_1_8V_SDR_MODE	4
-
 	unsigned char	signal_voltage;		/* signalling voltage (1.8V or 3.3V) */
 
 #define MMC_SIGNAL_VOLTAGE_330	0
include/linux/mmc/mmc.h +8 -4
index 50bcde3..f734c0c 100644
@@ -354,18 +354,22 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-#define EXT_CSD_CARD_TYPE_26	(1<<0)	/* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52	(1<<1)	/* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_MASK	0x3F	/* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
+				 EXT_CSD_CARD_TYPE_HS_52)
 #define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
 					     /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
 					     /* DDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
 					| EXT_CSD_CARD_TYPE_DDR_1_2V)
-#define EXT_CSD_CARD_TYPE_SDR_1_8V	(1<<4)	/* Card can run at 200MHz */
-#define EXT_CSD_CARD_TYPE_SDR_1_2V	(1<<5)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_8V	(1<<4)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V	(1<<5)	/* Card can run at 200MHz */
 						/* SDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
+					 EXT_CSD_CARD_TYPE_HS200_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
Signature · 1 line
1.7.0.4
maintainer
#140 lore raw

Re: [PATCH v2 2/5] mmc: identify available device type to select

Quoted 28 lines · Seungwon Jeon

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

---
Changes in v2:
Just rebased with latest one.

 drivers/mmc/core/mmc.c   |   77 ++++++++++++++++++++++++++-------------------
 include/linux/mmc/card.h |    6 ++-
 include/linux/mmc/host.h |    6 ---
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 56 insertions(+), 45 deletions(-)
drivers/mmc/core/mmc.c +3 -1
index db9655f..0abece0 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
 	u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
 	u32 caps = host->caps, caps2 = host->caps2;
 	unsigned int hs_max_dtr = 0;
+	unsigned int avail_type = 0;
 
-	if (card_type & EXT_CSD_CARD_TYPE_26)
+	if (caps & MMC_CAP_MMC_HIGHSPEED &&
+	    card_type & EXT_CSD_CARD_TYPE_HS_26) {

drivers/mmc/core/mmc.c static void mmc_select_card_type(struct mmc_card *card) · line 258

Quoted 10 lines
drivers/mmc/core/mmc.c +5 -1
 		hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+	}
 
 	if (caps & MMC_CAP_MMC_HIGHSPEED &&
-			card_type & EXT_CSD_CARD_TYPE_52)
+	    card_type & EXT_CSD_CARD_TYPE_HS_52) {
 		hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+	}

Can it bind with "caps & MMC_CAP_MMC_HIGHSPEED"?

if (caps & MMC_CAP_MMC_HIGH_SPEED) {
	if (card_type & EXT_CSD_CARD_TYPE_HS_26) {
		...
	}
	if (card_type & EXT_CSD_CARD_TYPE_HS_52) {
		...
	}
}
Quoted 67 lines
drivers/mmc/core/mmc.c +28 -13
-	if ((caps & MMC_CAP_1_8V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-	    (caps & MMC_CAP_1_2V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+	if (caps & MMC_CAP_1_8V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
 		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+	}
 
-	if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-	    (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+	if (caps & MMC_CAP_1_2V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
 		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+	}
 
 	card->ext_csd.hs_max_dtr = hs_max_dtr;
-	card->ext_csd.card_type = card_type;
+	card->mmc_avail_type = avail_type;
 }
 
 /*
@@ -708,6 +726,11 @@ static struct device_type mmc_type = {
 	.groups = mmc_attr_groups,
 };
 
+static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
+{
+	return card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+}
+
 /*
  * Select the PowerClass for the current bus width
  * If power class is defined for 4/8 bit bus in the
@@ -808,12 +831,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
 	host = card->host;
 
-	if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-			host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+	if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-	if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-			host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+	if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
 	/* If fails try again during next card power cycle */

drivers/mmc/core/mmc.c static int mmc_init_card(struct mmc_host *host, u32 ocr, · line 1076

Quoted 5 lines
drivers/mmc/core/mmc.c +0 -2
@@ -1072,10 +1093,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	if (card->ext_csd.hs_max_dtr != 0) {
 		err = 0;
-		if (card->ext_csd.hs_max_dtr > 52000000 &&
-		    host->caps2 & MMC_CAP2_HS200)

MMC_CAP2_HS200 need no more, doesn't?

Quoted 132 lines
drivers/mmc/core/mmc.c +8 -16
+		if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
 			err = mmc_select_hs200(card);
-		else if	(host->caps & MMC_CAP_MMC_HIGHSPEED)
+		else if	(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
 			err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 					EXT_CSD_HS_TIMING, 1,
 					card->ext_csd.generic_cmd6_time,
@@ -1089,13 +1109,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			       mmc_hostname(card->host));
 			err = 0;
 		} else {
-			if (card->ext_csd.hs_max_dtr > 52000000 &&
-			    host->caps2 & MMC_CAP2_HS200) {
+			if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
 				mmc_set_timing(card->host,
 					       MMC_TIMING_MMC_HS200);
-			} else {
+			else
 				mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-			}
 		}
 	}
 
@@ -1118,14 +1136,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	/*
 	 * Indicate DDR mode (if supported).
 	 */
-	if (mmc_card_hs(card)) {
-		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
-			&& (host->caps & MMC_CAP_1_8V_DDR))
-				ddr = MMC_1_8V_DDR_MODE;
-		else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
-			&& (host->caps & MMC_CAP_1_2V_DDR))
-				ddr = MMC_1_2V_DDR_MODE;
-	}
+	if (mmc_card_hs(card))
+		ddr = mmc_snoop_ddr(card);
 
 	/*
 	 * Indicate HS200 SDR mode (if supported).
@@ -1145,8 +1157,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		 * 3. set the clock to > 52Mhz <=200MHz and
 		 * 4. execute tuning for HS200
 		 */
-		if ((host->caps2 & MMC_CAP2_HS200) &&
-		    card->host->ops->execute_tuning) {
+		if (card->host->ops->execute_tuning) {
 			mmc_host_clk_hold(card->host);
 			err = card->host->ops->execute_tuning(card->host,
 				MMC_SEND_TUNING_BLOCK_HS200);
@@ -1255,7 +1266,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			 *
 			 * WARNING: eMMC rules are NOT the same as SD DDR
 			 */
-			if (ddr == MMC_1_2V_DDR_MODE) {
+			if (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) {
 				err = __mmc_set_signal_voltage(host,
 					MMC_SIGNAL_VOLTAGE_120);
 				if (err)
include/linux/mmc/card.h +4 -2
index 5473133..c232b10 100644
@@ -68,7 +68,6 @@ struct mmc_ext_csd {
 #define MMC_HIGH_DDR_MAX_DTR	52000000
 #define MMC_HS200_MAX_DTR	200000000
 	unsigned int		sectors;
-	unsigned int		card_type;
 	unsigned int		hc_erase_size;		/* In sectors */
 	unsigned int		hc_erase_timeout;	/* In milliseconds */
 	unsigned int		sec_trim_mult;	/* Secure trim multiplier  */
@@ -297,7 +296,10 @@ struct mmc_card {
 	const char		**info;		/* info strings */
 	struct sdio_func_tuple	*tuples;	/* unknown common tuples */
 
-	unsigned int		sd_bus_speed;	/* Bus Speed Mode set for the card */
+	union {
+		unsigned int		sd_bus_speed;	/* Bus Speed Mode set for the card */
+		unsigned int		mmc_avail_type;	/* supported device type by both host and card */
+	};
 
 	struct dentry		*debugfs_root;
 	struct mmc_part	part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
include/linux/mmc/host.h +0 -6
index 2f263ae..1ee3c10 100644
@@ -62,12 +62,6 @@ struct mmc_ios {
 #define MMC_TIMING_MMC_DDR52	8
 #define MMC_TIMING_MMC_HS200	9
 
-#define MMC_SDR_MODE		0
-#define MMC_1_2V_DDR_MODE	1
-#define MMC_1_8V_DDR_MODE	2
-#define MMC_1_2V_SDR_MODE	3
-#define MMC_1_8V_SDR_MODE	4
-
 	unsigned char	signal_voltage;		/* signalling voltage (1.8V or 3.3V) */
 
 #define MMC_SIGNAL_VOLTAGE_330	0
include/linux/mmc/mmc.h +8 -4
index 50bcde3..f734c0c 100644
@@ -354,18 +354,22 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-#define EXT_CSD_CARD_TYPE_26	(1<<0)	/* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52	(1<<1)	/* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_MASK	0x3F	/* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
+				 EXT_CSD_CARD_TYPE_HS_52)
 #define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
 					     /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
 					     /* DDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
 					| EXT_CSD_CARD_TYPE_DDR_1_2V)
-#define EXT_CSD_CARD_TYPE_SDR_1_8V	(1<<4)	/* Card can run at 200MHz */
-#define EXT_CSD_CARD_TYPE_SDR_1_2V	(1<<5)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_8V	(1<<4)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V	(1<<5)	/* Card can run at 200MHz */
 						/* SDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
+					 EXT_CSD_CARD_TYPE_HS200_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
#141 lore raw

RE: [PATCH v2 2/5] mmc: identify available device type to select

Quoted 33 lines · Jaehoon Chung
Quoted 32 lines · Seungwon Jeon

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

---
Changes in v2:
Just rebased with latest one.

 drivers/mmc/core/mmc.c   |   77 ++++++++++++++++++++++++++-------------------
 include/linux/mmc/card.h |    6 ++-
 include/linux/mmc/host.h |    6 ---
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 56 insertions(+), 45 deletions(-)
drivers/mmc/core/mmc.c +5 -1
index db9655f..0abece0 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
 	u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
 	u32 caps = host->caps, caps2 = host->caps2;
 	unsigned int hs_max_dtr = 0;
+	unsigned int avail_type = 0;
 
-	if (card_type & EXT_CSD_CARD_TYPE_26)
+	if (caps & MMC_CAP_MMC_HIGHSPEED &&
+	    card_type & EXT_CSD_CARD_TYPE_HS_26) {
 		hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+	}
 
Quoted 7 lines

drivers/mmc/core/mmc.c static void mmc_select_card_type(struct mmc_card *card) · line 258

Quoted 6 lines
drivers/mmc/core/mmc.c +3 -1
 	if (caps & MMC_CAP_MMC_HIGHSPEED &&
-			card_type & EXT_CSD_CARD_TYPE_52)
+	    card_type & EXT_CSD_CARD_TYPE_HS_52) {
 		hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+	}

Can it bind with "caps & MMC_CAP_MMC_HIGHSPEED"?

Yes, 'nested if' may be possible here.
I just think current style is more harmonious though.

Quoted 73 lines
if (caps & MMC_CAP_MMC_HIGH_SPEED) {
	if (card_type & EXT_CSD_CARD_TYPE_HS_26) {
		...
	}
	if (card_type & EXT_CSD_CARD_TYPE_HS_52) {
		...
	}
}
Quoted 65 lines
drivers/mmc/core/mmc.c +28 -13
-	if ((caps & MMC_CAP_1_8V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-	    (caps & MMC_CAP_1_2V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+	if (caps & MMC_CAP_1_8V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
 		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+	}
 
-	if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-	    (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+	if (caps & MMC_CAP_1_2V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
 		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+	}
 
 	card->ext_csd.hs_max_dtr = hs_max_dtr;
-	card->ext_csd.card_type = card_type;
+	card->mmc_avail_type = avail_type;
 }
 
 /*
@@ -708,6 +726,11 @@ static struct device_type mmc_type = {
 	.groups = mmc_attr_groups,
 };
 
+static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
+{
+	return card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+}
+
 /*
  * Select the PowerClass for the current bus width
  * If power class is defined for 4/8 bit bus in the
@@ -808,12 +831,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
 	host = card->host;
 
-	if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-			host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+	if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-	if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-			host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+	if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
Quoted 8 lines

drivers/mmc/core/mmc.c static int mmc_init_card(struct mmc_host *host, u32 ocr, · line 1076

Quoted 7 lines
drivers/mmc/core/mmc.c +0 -2
 	/* If fails try again during next card power cycle */
@@ -1072,10 +1093,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	if (card->ext_csd.hs_max_dtr != 0) {
 		err = 0;
-		if (card->ext_csd.hs_max_dtr > 52000000 &&
-		    host->caps2 & MMC_CAP2_HS200)

MMC_CAP2_HS200 need no more, doesn't?

If you mean to remove 'MMC_CAP2_HS200' definition, it is currently used in sdhci.c

Thanks,
Seungwon Jeon

Quoted 138 lines
Quoted 123 lines
drivers/mmc/core/mmc.c +8 -16
+		if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
 			err = mmc_select_hs200(card);
-		else if	(host->caps & MMC_CAP_MMC_HIGHSPEED)
+		else if	(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
 			err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 					EXT_CSD_HS_TIMING, 1,
 					card->ext_csd.generic_cmd6_time,
@@ -1089,13 +1109,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			       mmc_hostname(card->host));
 			err = 0;
 		} else {
-			if (card->ext_csd.hs_max_dtr > 52000000 &&
-			    host->caps2 & MMC_CAP2_HS200) {
+			if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
 				mmc_set_timing(card->host,
 					       MMC_TIMING_MMC_HS200);
-			} else {
+			else
 				mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-			}
 		}
 	}
 
@@ -1118,14 +1136,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	/*
 	 * Indicate DDR mode (if supported).
 	 */
-	if (mmc_card_hs(card)) {
-		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
-			&& (host->caps & MMC_CAP_1_8V_DDR))
-				ddr = MMC_1_8V_DDR_MODE;
-		else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
-			&& (host->caps & MMC_CAP_1_2V_DDR))
-				ddr = MMC_1_2V_DDR_MODE;
-	}
+	if (mmc_card_hs(card))
+		ddr = mmc_snoop_ddr(card);
 
 	/*
 	 * Indicate HS200 SDR mode (if supported).
@@ -1145,8 +1157,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		 * 3. set the clock to > 52Mhz <=200MHz and
 		 * 4. execute tuning for HS200
 		 */
-		if ((host->caps2 & MMC_CAP2_HS200) &&
-		    card->host->ops->execute_tuning) {
+		if (card->host->ops->execute_tuning) {
 			mmc_host_clk_hold(card->host);
 			err = card->host->ops->execute_tuning(card->host,
 				MMC_SEND_TUNING_BLOCK_HS200);
@@ -1255,7 +1266,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			 *
 			 * WARNING: eMMC rules are NOT the same as SD DDR
 			 */
-			if (ddr == MMC_1_2V_DDR_MODE) {
+			if (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) {
 				err = __mmc_set_signal_voltage(host,
 					MMC_SIGNAL_VOLTAGE_120);
 				if (err)
include/linux/mmc/card.h +4 -2
index 5473133..c232b10 100644
@@ -68,7 +68,6 @@ struct mmc_ext_csd {
 #define MMC_HIGH_DDR_MAX_DTR	52000000
 #define MMC_HS200_MAX_DTR	200000000
 	unsigned int		sectors;
-	unsigned int		card_type;
 	unsigned int		hc_erase_size;		/* In sectors */
 	unsigned int		hc_erase_timeout;	/* In milliseconds */
 	unsigned int		sec_trim_mult;	/* Secure trim multiplier  */
@@ -297,7 +296,10 @@ struct mmc_card {
 	const char		**info;		/* info strings */
 	struct sdio_func_tuple	*tuples;	/* unknown common tuples */
 
-	unsigned int		sd_bus_speed;	/* Bus Speed Mode set for the card */
+	union {
+		unsigned int		sd_bus_speed;	/* Bus Speed Mode set for the card */
+		unsigned int		mmc_avail_type;	/* supported device type by both host and card */
+	};
 
 	struct dentry		*debugfs_root;
 	struct mmc_part	part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
include/linux/mmc/host.h +0 -6
index 2f263ae..1ee3c10 100644
@@ -62,12 +62,6 @@ struct mmc_ios {
 #define MMC_TIMING_MMC_DDR52	8
 #define MMC_TIMING_MMC_HS200	9
 
-#define MMC_SDR_MODE		0
-#define MMC_1_2V_DDR_MODE	1
-#define MMC_1_8V_DDR_MODE	2
-#define MMC_1_2V_SDR_MODE	3
-#define MMC_1_8V_SDR_MODE	4
-
 	unsigned char	signal_voltage;		/* signalling voltage (1.8V or 3.3V) */
 
 #define MMC_SIGNAL_VOLTAGE_330	0
include/linux/mmc/mmc.h +4 -2
index 50bcde3..f734c0c 100644
@@ -354,18 +354,22 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-#define EXT_CSD_CARD_TYPE_26	(1<<0)	/* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52	(1<<1)	/* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_MASK	0x3F	/* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
+				 EXT_CSD_CARD_TYPE_HS_52)
 #define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
 					     /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
 					     /* DDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
 					| EXT_CSD_CARD_TYPE_DDR_1_2V)

include/linux/mmc/mmc.h struct _mmc_csd { · line 375

Quoted 10 lines
include/linux/mmc/mmc.h +4 -2
-#define EXT_CSD_CARD_TYPE_SDR_1_8V	(1<<4)	/* Card can run at 200MHz */
-#define EXT_CSD_CARD_TYPE_SDR_1_2V	(1<<5)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_8V	(1<<4)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V	(1<<5)	/* Card can run at 200MHz */
 						/* SDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
+					 EXT_CSD_CARD_TYPE_HS200_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */

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

maintainer
#142 lore raw

Re: [PATCH v2 2/5] mmc: identify available device type to select

Dear, Seungwon.

Quoted 41 lines · Seungwon Jeon
Quoted 33 lines · Jaehoon Chung
Quoted 32 lines · Seungwon Jeon

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

---
Changes in v2:
Just rebased with latest one.

 drivers/mmc/core/mmc.c   |   77 ++++++++++++++++++++++++++-------------------
 include/linux/mmc/card.h |    6 ++-
 include/linux/mmc/host.h |    6 ---
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 56 insertions(+), 45 deletions(-)
drivers/mmc/core/mmc.c +5 -1
index db9655f..0abece0 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
 	u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
 	u32 caps = host->caps, caps2 = host->caps2;
 	unsigned int hs_max_dtr = 0;
+	unsigned int avail_type = 0;
 
-	if (card_type & EXT_CSD_CARD_TYPE_26)
+	if (caps & MMC_CAP_MMC_HIGHSPEED &&
+	    card_type & EXT_CSD_CARD_TYPE_HS_26) {
 		hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+	}
 
Quoted 7 lines

drivers/mmc/core/mmc.c static void mmc_select_card_type(struct mmc_card *card) · line 258

Quoted 6 lines
drivers/mmc/core/mmc.c +3 -1
 	if (caps & MMC_CAP_MMC_HIGHSPEED &&
-			card_type & EXT_CSD_CARD_TYPE_52)
+	    card_type & EXT_CSD_CARD_TYPE_HS_52) {
 		hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+	}

Can it bind with "caps & MMC_CAP_MMC_HIGHSPEED"?

Quoted 2 lines

Yes, 'nested if' may be possible here.
I just think current style is more harmonious though.

Don't mind. it's ok. :)

Quoted 82 lines
Quoted 74 lines
if (caps & MMC_CAP_MMC_HIGH_SPEED) {
	if (card_type & EXT_CSD_CARD_TYPE_HS_26) {
		...
	}
	if (card_type & EXT_CSD_CARD_TYPE_HS_52) {
		...
	}
}
Quoted 65 lines
drivers/mmc/core/mmc.c +28 -13
-	if ((caps & MMC_CAP_1_8V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-	    (caps & MMC_CAP_1_2V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+	if (caps & MMC_CAP_1_8V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
 		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+	}
 
-	if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-	    (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+	if (caps & MMC_CAP_1_2V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
 		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+	}
 
 	card->ext_csd.hs_max_dtr = hs_max_dtr;
-	card->ext_csd.card_type = card_type;
+	card->mmc_avail_type = avail_type;
 }
 
 /*
@@ -708,6 +726,11 @@ static struct device_type mmc_type = {
 	.groups = mmc_attr_groups,
 };
 
+static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
+{
+	return card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+}
+
 /*
  * Select the PowerClass for the current bus width
  * If power class is defined for 4/8 bit bus in the
@@ -808,12 +831,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
 	host = card->host;
 
-	if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-			host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+	if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-	if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-			host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+	if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
Quoted 8 lines

drivers/mmc/core/mmc.c static int mmc_init_card(struct mmc_host *host, u32 ocr, · line 1076

Quoted 7 lines
drivers/mmc/core/mmc.c +0 -2
 	/* If fails try again during next card power cycle */
@@ -1072,10 +1093,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	if (card->ext_csd.hs_max_dtr != 0) {
 		err = 0;
-		if (card->ext_csd.hs_max_dtr > 52000000 &&
-		    host->caps2 & MMC_CAP2_HS200)

MMC_CAP2_HS200 need no more, doesn't?

Quoted 1 line

If you mean to remove 'MMC_CAP2_HS200' definition, it is currently used in sdhci.c

I have also checked that it is used in sdhci.c.
but I think that capability like MMC_CAP2_HS200 was defined to use for core, not controller. It can be changed other quirks instead of MMC_CAP2_HS200 into sdhci.c
how about?

Best Regards,
Jaehoon Chung

Quoted 148 lines

Thanks,
Seungwon Jeon

Quoted 130 lines
Quoted 130 lines
drivers/mmc/core/mmc.c +8 -16
+		if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
 			err = mmc_select_hs200(card);
-		else if	(host->caps & MMC_CAP_MMC_HIGHSPEED)
+		else if	(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
 			err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 					EXT_CSD_HS_TIMING, 1,
 					card->ext_csd.generic_cmd6_time,
@@ -1089,13 +1109,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			       mmc_hostname(card->host));
 			err = 0;
 		} else {
-			if (card->ext_csd.hs_max_dtr > 52000000 &&
-			    host->caps2 & MMC_CAP2_HS200) {
+			if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
 				mmc_set_timing(card->host,
 					       MMC_TIMING_MMC_HS200);
-			} else {
+			else
 				mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-			}
 		}
 	}
 
@@ -1118,14 +1136,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	/*
 	 * Indicate DDR mode (if supported).
 	 */
-	if (mmc_card_hs(card)) {
-		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
-			&& (host->caps & MMC_CAP_1_8V_DDR))
-				ddr = MMC_1_8V_DDR_MODE;
-		else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
-			&& (host->caps & MMC_CAP_1_2V_DDR))
-				ddr = MMC_1_2V_DDR_MODE;
-	}
+	if (mmc_card_hs(card))
+		ddr = mmc_snoop_ddr(card);
 
 	/*
 	 * Indicate HS200 SDR mode (if supported).
@@ -1145,8 +1157,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		 * 3. set the clock to > 52Mhz <=200MHz and
 		 * 4. execute tuning for HS200
 		 */
-		if ((host->caps2 & MMC_CAP2_HS200) &&
-		    card->host->ops->execute_tuning) {
+		if (card->host->ops->execute_tuning) {
 			mmc_host_clk_hold(card->host);
 			err = card->host->ops->execute_tuning(card->host,
 				MMC_SEND_TUNING_BLOCK_HS200);
@@ -1255,7 +1266,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			 *
 			 * WARNING: eMMC rules are NOT the same as SD DDR
 			 */
-			if (ddr == MMC_1_2V_DDR_MODE) {
+			if (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) {
 				err = __mmc_set_signal_voltage(host,
 					MMC_SIGNAL_VOLTAGE_120);
 				if (err)
include/linux/mmc/card.h +4 -2
index 5473133..c232b10 100644
@@ -68,7 +68,6 @@ struct mmc_ext_csd {
 #define MMC_HIGH_DDR_MAX_DTR	52000000
 #define MMC_HS200_MAX_DTR	200000000
 	unsigned int		sectors;
-	unsigned int		card_type;
 	unsigned int		hc_erase_size;		/* In sectors */
 	unsigned int		hc_erase_timeout;	/* In milliseconds */
 	unsigned int		sec_trim_mult;	/* Secure trim multiplier  */
@@ -297,7 +296,10 @@ struct mmc_card {
 	const char		**info;		/* info strings */
 	struct sdio_func_tuple	*tuples;	/* unknown common tuples */
 
-	unsigned int		sd_bus_speed;	/* Bus Speed Mode set for the card */
+	union {
+		unsigned int		sd_bus_speed;	/* Bus Speed Mode set for the card */
+		unsigned int		mmc_avail_type;	/* supported device type by both host and card */
+	};
 
 	struct dentry		*debugfs_root;
 	struct mmc_part	part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
include/linux/mmc/host.h +0 -6
index 2f263ae..1ee3c10 100644
@@ -62,12 +62,6 @@ struct mmc_ios {
 #define MMC_TIMING_MMC_DDR52	8
 #define MMC_TIMING_MMC_HS200	9
 
-#define MMC_SDR_MODE		0
-#define MMC_1_2V_DDR_MODE	1
-#define MMC_1_8V_DDR_MODE	2
-#define MMC_1_2V_SDR_MODE	3
-#define MMC_1_8V_SDR_MODE	4
-
 	unsigned char	signal_voltage;		/* signalling voltage (1.8V or 3.3V) */
 
 #define MMC_SIGNAL_VOLTAGE_330	0
include/linux/mmc/mmc.h +8 -4
index 50bcde3..f734c0c 100644
@@ -354,18 +354,22 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-#define EXT_CSD_CARD_TYPE_26	(1<<0)	/* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52	(1<<1)	/* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_MASK	0x3F	/* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
+				 EXT_CSD_CARD_TYPE_HS_52)
 #define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
 					     /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
 					     /* DDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
 					| EXT_CSD_CARD_TYPE_DDR_1_2V)
-#define EXT_CSD_CARD_TYPE_SDR_1_8V	(1<<4)	/* Card can run at 200MHz */
-#define EXT_CSD_CARD_TYPE_SDR_1_2V	(1<<5)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_8V	(1<<4)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V	(1<<5)	/* Card can run at 200MHz */
 						/* SDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
+					 EXT_CSD_CARD_TYPE_HS200_1_2V)
 
Quoted 8 lines

include/linux/mmc/mmc.h struct _mmc_csd { · line 375

Quoted 3 lines
include/linux/mmc/mmc.h +0 -0
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to [email protected]
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#143 lore raw

RE: [PATCH v2 2/5] mmc: identify available device type to select

Quoted 130 lines · Jaehoon Chung

Dear, Seungwon.

Quoted 41 lines · Seungwon Jeon
Quoted 33 lines · Jaehoon Chung
Quoted 32 lines · Seungwon Jeon

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

---
Changes in v2:
Just rebased with latest one.

 drivers/mmc/core/mmc.c   |   77 ++++++++++++++++++++++++++-------------------
 include/linux/mmc/card.h |    6 ++-
 include/linux/mmc/host.h |    6 ---
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 56 insertions(+), 45 deletions(-)
drivers/mmc/core/mmc.c +5 -1
index db9655f..0abece0 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
 	u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
 	u32 caps = host->caps, caps2 = host->caps2;
 	unsigned int hs_max_dtr = 0;
+	unsigned int avail_type = 0;
 
-	if (card_type & EXT_CSD_CARD_TYPE_26)
+	if (caps & MMC_CAP_MMC_HIGHSPEED &&
+	    card_type & EXT_CSD_CARD_TYPE_HS_26) {
 		hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+	}
 
Quoted 7 lines

drivers/mmc/core/mmc.c static void mmc_select_card_type(struct mmc_card *card) · line 258

Quoted 6 lines
drivers/mmc/core/mmc.c +3 -1
 	if (caps & MMC_CAP_MMC_HIGHSPEED &&
-			card_type & EXT_CSD_CARD_TYPE_52)
+	    card_type & EXT_CSD_CARD_TYPE_HS_52) {
 		hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+	}

Can it bind with "caps & MMC_CAP_MMC_HIGHSPEED"?

Quoted 2 lines

Yes, 'nested if' may be possible here.
I just think current style is more harmonious though.

Don't mind. it's ok. :)

Quoted 82 lines
Quoted 82 lines
if (caps & MMC_CAP_MMC_HIGH_SPEED) {
	if (card_type & EXT_CSD_CARD_TYPE_HS_26) {
		...
	}
	if (card_type & EXT_CSD_CARD_TYPE_HS_52) {
		...
	}
}
Quoted 67 lines
drivers/mmc/core/mmc.c +28 -13
-	if ((caps & MMC_CAP_1_8V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-	    (caps & MMC_CAP_1_2V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+	if (caps & MMC_CAP_1_8V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
 		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+	}
 
-	if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-	    (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+	if (caps & MMC_CAP_1_2V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
 		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+	}
 
 	card->ext_csd.hs_max_dtr = hs_max_dtr;
-	card->ext_csd.card_type = card_type;
+	card->mmc_avail_type = avail_type;
 }
 
 /*
@@ -708,6 +726,11 @@ static struct device_type mmc_type = {
 	.groups = mmc_attr_groups,
 };
 
+static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
+{
+	return card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+}
+
 /*
  * Select the PowerClass for the current bus width
  * If power class is defined for 4/8 bit bus in the
@@ -808,12 +831,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
 	host = card->host;
 
-	if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-			host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+	if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-	if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-			host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+	if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
 	/* If fails try again during next card power cycle */

drivers/mmc/core/mmc.c static int mmc_init_card(struct mmc_host *host, u32 ocr, · line 1076

Quoted 5 lines
drivers/mmc/core/mmc.c +0 -2
@@ -1072,10 +1093,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	if (card->ext_csd.hs_max_dtr != 0) {
 		err = 0;
-		if (card->ext_csd.hs_max_dtr > 52000000 &&
-		    host->caps2 & MMC_CAP2_HS200)

MMC_CAP2_HS200 need no more, doesn't?

Quoted 5 lines
Quoted 1 line

If you mean to remove 'MMC_CAP2_HS200' definition, it is currently used in sdhci.c

I have also checked that it is used in sdhci.c.
but I think that capability like MMC_CAP2_HS200 was defined to use for core, not controller. It can be changed other quirks instead of MMC_CAP2_HS200 into sdhci.c
how about?

Hmm.
I feel like current way is not bad in sdhci.c, but if you have an idea, it would be different patch.

Thanks,
Seungwon Jeon

maintainer
#144 lore raw

Re: [PATCH v2 2/5] mmc: identify available device type to select

Quoted 131 lines · Seungwon Jeon
Quoted 130 lines · Jaehoon Chung

Dear, Seungwon.

Quoted 41 lines · Seungwon Jeon
Quoted 33 lines · Jaehoon Chung
Quoted 32 lines · Seungwon Jeon

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

---
Changes in v2:
Just rebased with latest one.

 drivers/mmc/core/mmc.c   |   77 ++++++++++++++++++++++++++-------------------
 include/linux/mmc/card.h |    6 ++-
 include/linux/mmc/host.h |    6 ---
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 56 insertions(+), 45 deletions(-)
drivers/mmc/core/mmc.c +5 -1
index db9655f..0abece0 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
 	u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
 	u32 caps = host->caps, caps2 = host->caps2;
 	unsigned int hs_max_dtr = 0;
+	unsigned int avail_type = 0;
 
-	if (card_type & EXT_CSD_CARD_TYPE_26)
+	if (caps & MMC_CAP_MMC_HIGHSPEED &&
+	    card_type & EXT_CSD_CARD_TYPE_HS_26) {
 		hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+	}
 
Quoted 7 lines

drivers/mmc/core/mmc.c static void mmc_select_card_type(struct mmc_card *card) · line 258

Quoted 6 lines
drivers/mmc/core/mmc.c +3 -1
 	if (caps & MMC_CAP_MMC_HIGHSPEED &&
-			card_type & EXT_CSD_CARD_TYPE_52)
+	    card_type & EXT_CSD_CARD_TYPE_HS_52) {
 		hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+	}

Can it bind with "caps & MMC_CAP_MMC_HIGHSPEED"?

Quoted 2 lines

Yes, 'nested if' may be possible here.
I just think current style is more harmonious though.

Don't mind. it's ok. :)

Quoted 82 lines
Quoted 82 lines
if (caps & MMC_CAP_MMC_HIGH_SPEED) {
	if (card_type & EXT_CSD_CARD_TYPE_HS_26) {
		...
	}
	if (card_type & EXT_CSD_CARD_TYPE_HS_52) {
		...
	}
}
Quoted 67 lines
drivers/mmc/core/mmc.c +28 -13
-	if ((caps & MMC_CAP_1_8V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-	    (caps & MMC_CAP_1_2V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+	if (caps & MMC_CAP_1_8V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
 		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+	}
 
-	if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-	    (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+	if (caps & MMC_CAP_1_2V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
 		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+	}
 
 	card->ext_csd.hs_max_dtr = hs_max_dtr;
-	card->ext_csd.card_type = card_type;
+	card->mmc_avail_type = avail_type;
 }
 
 /*
@@ -708,6 +726,11 @@ static struct device_type mmc_type = {
 	.groups = mmc_attr_groups,
 };
 
+static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
+{
+	return card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+}
+
 /*
  * Select the PowerClass for the current bus width
  * If power class is defined for 4/8 bit bus in the
@@ -808,12 +831,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
 	host = card->host;
 
-	if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-			host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+	if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-	if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-			host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+	if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
 	/* If fails try again during next card power cycle */

drivers/mmc/core/mmc.c static int mmc_init_card(struct mmc_host *host, u32 ocr, · line 1076

Quoted 5 lines
drivers/mmc/core/mmc.c +0 -2
@@ -1072,10 +1093,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	if (card->ext_csd.hs_max_dtr != 0) {
 		err = 0;
-		if (card->ext_csd.hs_max_dtr > 52000000 &&
-		    host->caps2 & MMC_CAP2_HS200)

MMC_CAP2_HS200 need no more, doesn't?

Quoted 7 lines
Quoted 5 lines
Quoted 1 line

If you mean to remove 'MMC_CAP2_HS200' definition, it is currently used in sdhci.c

I have also checked that it is used in sdhci.c.
but I think that capability like MMC_CAP2_HS200 was defined to use for core, not controller. It can be changed other quirks instead of MMC_CAP2_HS200 into sdhci.c
how about?

Hmm.
I feel like current way is not bad in sdhci.c, but if you have an idea, it would be different patch.

Sure..Then when your patch-set is merged, i will send the other patch.

Best Regards,
Jaehoon Chung

Quoted 9 lines

Thanks,
Seungwon Jeon

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

#145 lore raw

Re: [PATCH v2 2/5] mmc: identify available device type to select

In reply to Seungwon Jeon
Quoted 78 lines · Seungwon Jeon

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

---
Changes in v2:
Just rebased with latest one.

 drivers/mmc/core/mmc.c   |   77 ++++++++++++++++++++++++++-------------------
 include/linux/mmc/card.h |    6 ++-
 include/linux/mmc/host.h |    6 ---
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 56 insertions(+), 45 deletions(-)
drivers/mmc/core/mmc.c +29 -11
index db9655f..0abece0 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
        u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
        u32 caps = host->caps, caps2 = host->caps2;
        unsigned int hs_max_dtr = 0;
+       unsigned int avail_type = 0;
 
-       if (card_type & EXT_CSD_CARD_TYPE_26)
+       if (caps & MMC_CAP_MMC_HIGHSPEED &&
+           card_type & EXT_CSD_CARD_TYPE_HS_26) {
                hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+       }
 
        if (caps & MMC_CAP_MMC_HIGHSPEED &&
-                       card_type & EXT_CSD_CARD_TYPE_52)
+           card_type & EXT_CSD_CARD_TYPE_HS_52) {
                hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+       }
 
-       if ((caps & MMC_CAP_1_8V_DDR &&
-                       card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-           (caps & MMC_CAP_1_2V_DDR &&
-                       card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+       if (caps & MMC_CAP_1_8V_DDR &&
+           card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
                hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+       }
 
-       if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-                       card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-           (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-                       card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+       if (caps & MMC_CAP_1_2V_DDR &&
+           card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+               hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+       }
+
+       if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+           card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
                hs_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+       }
+
+       if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+           card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+               hs_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+       }
 
        card->ext_csd.hs_max_dtr = hs_max_dtr;
-       card->ext_csd.card_type = card_type;
+       card->mmc_avail_type = avail_type;
 }
 
 /*

drivers/mmc/core/mmc.c static struct device_type mmc_type = { · line 733

Quoted 8 lines
drivers/mmc/core/mmc.c +5 -0
@@ -708,6 +726,11 @@ static struct device_type mmc_type = {
        .groups = mmc_attr_groups,
 };
 
+static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
+{
+       return card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+}
+

Having a separate function for this seem a bit silly. Similar checks is performed all over the code. I suggest you remove this.

Quoted 96 lines
drivers/mmc/core/mmc.c +10 -22
 /*
  * Select the PowerClass for the current bus width
  * If power class is defined for 4/8 bit bus in the
@@ -808,12 +831,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
        host = card->host;
 
-       if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-                       host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
                err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-       if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-                       host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+       if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
                err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
        /* If fails try again during next card power cycle */
@@ -1072,10 +1093,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
         */
        if (card->ext_csd.hs_max_dtr != 0) {
                err = 0;
-               if (card->ext_csd.hs_max_dtr > 52000000 &&
-                   host->caps2 & MMC_CAP2_HS200)
+               if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
                        err = mmc_select_hs200(card);
-               else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
+               else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
                        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                        EXT_CSD_HS_TIMING, 1,
                                        card->ext_csd.generic_cmd6_time,
@@ -1089,13 +1109,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                               mmc_hostname(card->host));
                        err = 0;
                } else {
-                       if (card->ext_csd.hs_max_dtr > 52000000 &&
-                           host->caps2 & MMC_CAP2_HS200) {
+                       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
                                mmc_set_timing(card->host,
                                               MMC_TIMING_MMC_HS200);
-                       } else {
+                       else
                                mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-                       }
                }
        }
 
@@ -1118,14 +1136,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        /*
         * Indicate DDR mode (if supported).
         */
-       if (mmc_card_hs(card)) {
-               if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
-                       && (host->caps & MMC_CAP_1_8V_DDR))
-                               ddr = MMC_1_8V_DDR_MODE;
-               else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
-                       && (host->caps & MMC_CAP_1_2V_DDR))
-                               ddr = MMC_1_2V_DDR_MODE;
-       }
+       if (mmc_card_hs(card))
+               ddr = mmc_snoop_ddr(card);
 
        /*
         * Indicate HS200 SDR mode (if supported).
@@ -1145,8 +1157,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                 * 3. set the clock to > 52Mhz <=200MHz and
                 * 4. execute tuning for HS200
                 */
-               if ((host->caps2 & MMC_CAP2_HS200) &&
-                   card->host->ops->execute_tuning) {
+               if (card->host->ops->execute_tuning) {
                        mmc_host_clk_hold(card->host);
                        err = card->host->ops->execute_tuning(card->host,
                                MMC_SEND_TUNING_BLOCK_HS200);
@@ -1255,7 +1266,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                         *
                         * WARNING: eMMC rules are NOT the same as SD DDR
                         */
-                       if (ddr == MMC_1_2V_DDR_MODE) {
+                       if (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) {
                                err = __mmc_set_signal_voltage(host,
                                        MMC_SIGNAL_VOLTAGE_120);
                                if (err)
include/linux/mmc/card.h +0 -1
index 5473133..c232b10 100644
@@ -68,7 +68,6 @@ struct mmc_ext_csd {
 #define MMC_HIGH_DDR_MAX_DTR   52000000
 #define MMC_HS200_MAX_DTR      200000000
        unsigned int            sectors;
-       unsigned int            card_type;
        unsigned int            hc_erase_size;          /* In sectors */
        unsigned int            hc_erase_timeout;       /* In milliseconds */
        unsigned int            sec_trim_mult;  /* Secure trim multiplier  */

include/linux/mmc/card.h struct mmc_card { · line 301

Quoted 7 lines
include/linux/mmc/card.h +3 -1
@@ -297,7 +296,10 @@ struct mmc_card {
        const char              **info;         /* info strings */
        struct sdio_func_tuple  *tuples;        /* unknown common tuples */
 
-       unsigned int            sd_bus_speed;   /* Bus Speed Mode set for the card */
+       union {
+               unsigned int            sd_bus_speed;   /* Bus Speed Mode set for the card */
+               unsigned int            mmc_avail_type; /* supported device type by both host and card */

Using a union here won't be that much of a gain since there are only few instances of the struct. Please remove.

Quoted 53 lines
include/linux/mmc/card.h +1 -0
+       };
 
        struct dentry           *debugfs_root;
        struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
include/linux/mmc/host.h +0 -6
index 2f263ae..1ee3c10 100644
@@ -62,12 +62,6 @@ struct mmc_ios {
 #define MMC_TIMING_MMC_DDR52   8
 #define MMC_TIMING_MMC_HS200   9
 
-#define MMC_SDR_MODE           0
-#define MMC_1_2V_DDR_MODE      1
-#define MMC_1_8V_DDR_MODE      2
-#define MMC_1_2V_SDR_MODE      3
-#define MMC_1_8V_SDR_MODE      4
-
        unsigned char   signal_voltage;         /* signalling voltage (1.8V or 3.3V) */
 
 #define MMC_SIGNAL_VOLTAGE_330 0
include/linux/mmc/mmc.h +8 -5
index 50bcde3..f734c0c 100644
@@ -354,18 +354,22 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE         (1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE       (1<<2)
 
-#define EXT_CSD_CARD_TYPE_26   (1<<0)  /* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52   (1<<1)  /* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_MASK 0x3F    /* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_HS_26        (1<<0)  /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_HS_52        (1<<1)  /* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_HS   (EXT_CSD_CARD_TYPE_HS_26 | \
+                                EXT_CSD_CARD_TYPE_HS_52)
 #define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
                                             /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
                                             /* DDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
                                        | EXT_CSD_CARD_TYPE_DDR_1_2V)
-#define EXT_CSD_CARD_TYPE_SDR_1_8V     (1<<4)  /* Card can run at 200MHz */
-#define EXT_CSD_CARD_TYPE_SDR_1_2V     (1<<5)  /* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_8V   (1<<4)  /* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V   (1<<5)  /* Card can run at 200MHz */
                                                /* SDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS200                (EXT_CSD_CARD_TYPE_HS200_1_8V | \
+                                        EXT_CSD_CARD_TYPE_HS200_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
--
Quoted 3 lines

1.7.0.4

Besides the minor stuff, looks good.

Kind regards
Ulf Hansson

#146 lore raw

RE: [PATCH v2 2/5] mmc: identify available device type to select

Quoted 82 lines · Ulf Hansson
Quoted 81 lines · Seungwon Jeon

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

---
Changes in v2:
Just rebased with latest one.

 drivers/mmc/core/mmc.c   |   77 ++++++++++++++++++++++++++-------------------
 include/linux/mmc/card.h |    6 ++-
 include/linux/mmc/host.h |    6 ---
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 56 insertions(+), 45 deletions(-)
drivers/mmc/core/mmc.c +29 -11
index db9655f..0abece0 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
        u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
        u32 caps = host->caps, caps2 = host->caps2;
        unsigned int hs_max_dtr = 0;
+       unsigned int avail_type = 0;
 
-       if (card_type & EXT_CSD_CARD_TYPE_26)
+       if (caps & MMC_CAP_MMC_HIGHSPEED &&
+           card_type & EXT_CSD_CARD_TYPE_HS_26) {
                hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+       }
 
        if (caps & MMC_CAP_MMC_HIGHSPEED &&
-                       card_type & EXT_CSD_CARD_TYPE_52)
+           card_type & EXT_CSD_CARD_TYPE_HS_52) {
                hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+       }
 
-       if ((caps & MMC_CAP_1_8V_DDR &&
-                       card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-           (caps & MMC_CAP_1_2V_DDR &&
-                       card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+       if (caps & MMC_CAP_1_8V_DDR &&
+           card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
                hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+       }
 
-       if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-                       card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-           (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-                       card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+       if (caps & MMC_CAP_1_2V_DDR &&
+           card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+               hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+       }
+
+       if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+           card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
                hs_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+       }
+
+       if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+           card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+               hs_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+       }
 
        card->ext_csd.hs_max_dtr = hs_max_dtr;
-       card->ext_csd.card_type = card_type;
+       card->mmc_avail_type = avail_type;
 }
 
 /*
@@ -708,6 +726,11 @@ static struct device_type mmc_type = {
        .groups = mmc_attr_groups,
 };
 
Quoted 8 lines

drivers/mmc/core/mmc.c static struct device_type mmc_type = { · line 733

Quoted 5 lines
drivers/mmc/core/mmc.c +5 -0
+static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
+{
+       return card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+}
+

Having a separate function for this seem a bit silly. Similar checks is performed all over the code. I suggest you remove this.

I understand your meaning.
Yes, actually similar checking card type is done.
But checking DDR type is required several times unlike other type case.
I considered for that. I think it's pretty useful in terms of avoiding duplication and enhancement of readability.

Quoted 100 lines
Quoted 100 lines
drivers/mmc/core/mmc.c +10 -22
 /*
  * Select the PowerClass for the current bus width
  * If power class is defined for 4/8 bit bus in the
@@ -808,12 +831,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
        host = card->host;
 
-       if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-                       host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
                err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-       if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-                       host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+       if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
                err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
        /* If fails try again during next card power cycle */
@@ -1072,10 +1093,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
         */
        if (card->ext_csd.hs_max_dtr != 0) {
                err = 0;
-               if (card->ext_csd.hs_max_dtr > 52000000 &&
-                   host->caps2 & MMC_CAP2_HS200)
+               if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
                        err = mmc_select_hs200(card);
-               else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
+               else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
                        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                        EXT_CSD_HS_TIMING, 1,
                                        card->ext_csd.generic_cmd6_time,
@@ -1089,13 +1109,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                               mmc_hostname(card->host));
                        err = 0;
                } else {
-                       if (card->ext_csd.hs_max_dtr > 52000000 &&
-                           host->caps2 & MMC_CAP2_HS200) {
+                       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
                                mmc_set_timing(card->host,
                                               MMC_TIMING_MMC_HS200);
-                       } else {
+                       else
                                mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-                       }
                }
        }
 
@@ -1118,14 +1136,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        /*
         * Indicate DDR mode (if supported).
         */
-       if (mmc_card_hs(card)) {
-               if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
-                       && (host->caps & MMC_CAP_1_8V_DDR))
-                               ddr = MMC_1_8V_DDR_MODE;
-               else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
-                       && (host->caps & MMC_CAP_1_2V_DDR))
-                               ddr = MMC_1_2V_DDR_MODE;
-       }
+       if (mmc_card_hs(card))
+               ddr = mmc_snoop_ddr(card);
 
        /*
         * Indicate HS200 SDR mode (if supported).
@@ -1145,8 +1157,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                 * 3. set the clock to > 52Mhz <=200MHz and
                 * 4. execute tuning for HS200
                 */
-               if ((host->caps2 & MMC_CAP2_HS200) &&
-                   card->host->ops->execute_tuning) {
+               if (card->host->ops->execute_tuning) {
                        mmc_host_clk_hold(card->host);
                        err = card->host->ops->execute_tuning(card->host,
                                MMC_SEND_TUNING_BLOCK_HS200);
@@ -1255,7 +1266,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                         *
                         * WARNING: eMMC rules are NOT the same as SD DDR
                         */
-                       if (ddr == MMC_1_2V_DDR_MODE) {
+                       if (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) {
                                err = __mmc_set_signal_voltage(host,
                                        MMC_SIGNAL_VOLTAGE_120);
                                if (err)
include/linux/mmc/card.h +0 -1
index 5473133..c232b10 100644
@@ -68,7 +68,6 @@ struct mmc_ext_csd {
 #define MMC_HIGH_DDR_MAX_DTR   52000000
 #define MMC_HS200_MAX_DTR      200000000
        unsigned int            sectors;
-       unsigned int            card_type;
        unsigned int            hc_erase_size;          /* In sectors */
        unsigned int            hc_erase_timeout;       /* In milliseconds */
        unsigned int            sec_trim_mult;  /* Secure trim multiplier  */
@@ -297,7 +296,10 @@ struct mmc_card {
        const char              **info;         /* info strings */
        struct sdio_func_tuple  *tuples;        /* unknown common tuples */
 
Quoted 7 lines

include/linux/mmc/card.h struct mmc_card { · line 301

Quoted 4 lines
include/linux/mmc/card.h +3 -1
-       unsigned int            sd_bus_speed;   /* Bus Speed Mode set for the card */
+       union {
+               unsigned int            sd_bus_speed;   /* Bus Speed Mode set for the card */
+               unsigned int            mmc_avail_type; /* supported device type by both host and card */

Using a union here won't be that much of a gain since there are only few instances of the struct. Please remove.

Yes, you're right. It's not much in gain.
I intended to distinguish these two similar members respectively. It's used only in each specific type domain and not used at the same time. If no meaningful, I can remove as your suggestion.

Thanks,
Seungwon Jeon

Quoted 62 lines
Quoted 54 lines
include/linux/mmc/card.h +1 -0
+       };
 
        struct dentry           *debugfs_root;
        struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
include/linux/mmc/host.h +0 -6
index 2f263ae..1ee3c10 100644
@@ -62,12 +62,6 @@ struct mmc_ios {
 #define MMC_TIMING_MMC_DDR52   8
 #define MMC_TIMING_MMC_HS200   9
 
-#define MMC_SDR_MODE           0
-#define MMC_1_2V_DDR_MODE      1
-#define MMC_1_8V_DDR_MODE      2
-#define MMC_1_2V_SDR_MODE      3
-#define MMC_1_8V_SDR_MODE      4
-
        unsigned char   signal_voltage;         /* signalling voltage (1.8V or 3.3V) */
 
 #define MMC_SIGNAL_VOLTAGE_330 0
include/linux/mmc/mmc.h +8 -5
index 50bcde3..f734c0c 100644
@@ -354,18 +354,22 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE         (1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE       (1<<2)
 
-#define EXT_CSD_CARD_TYPE_26   (1<<0)  /* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52   (1<<1)  /* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_MASK 0x3F    /* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_HS_26        (1<<0)  /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_HS_52        (1<<1)  /* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_HS   (EXT_CSD_CARD_TYPE_HS_26 | \
+                                EXT_CSD_CARD_TYPE_HS_52)
 #define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
                                             /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
                                             /* DDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
                                        | EXT_CSD_CARD_TYPE_DDR_1_2V)
-#define EXT_CSD_CARD_TYPE_SDR_1_8V     (1<<4)  /* Card can run at 200MHz */
-#define EXT_CSD_CARD_TYPE_SDR_1_2V     (1<<5)  /* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_8V   (1<<4)  /* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V   (1<<5)  /* Card can run at 200MHz */
                                                /* SDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS200                (EXT_CSD_CARD_TYPE_HS200_1_8V | \
+                                        EXT_CSD_CARD_TYPE_HS200_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
--
Quoted 3 lines

1.7.0.4

Besides the minor stuff, looks good.

Kind regards
Ulf Hansson

#147 lore raw

Re: [PATCH v2 2/5] mmc: identify available device type to select

Quoted 91 lines · Seungwon Jeon
Quoted 82 lines · Ulf Hansson
Quoted 81 lines · Seungwon Jeon

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

---
Changes in v2:
Just rebased with latest one.

 drivers/mmc/core/mmc.c   |   77 ++++++++++++++++++++++++++-------------------
 include/linux/mmc/card.h |    6 ++-
 include/linux/mmc/host.h |    6 ---
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 56 insertions(+), 45 deletions(-)
drivers/mmc/core/mmc.c +29 -11
index db9655f..0abece0 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
        u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
        u32 caps = host->caps, caps2 = host->caps2;
        unsigned int hs_max_dtr = 0;
+       unsigned int avail_type = 0;
 
-       if (card_type & EXT_CSD_CARD_TYPE_26)
+       if (caps & MMC_CAP_MMC_HIGHSPEED &&
+           card_type & EXT_CSD_CARD_TYPE_HS_26) {
                hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+       }
 
        if (caps & MMC_CAP_MMC_HIGHSPEED &&
-                       card_type & EXT_CSD_CARD_TYPE_52)
+           card_type & EXT_CSD_CARD_TYPE_HS_52) {
                hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+       }
 
-       if ((caps & MMC_CAP_1_8V_DDR &&
-                       card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-           (caps & MMC_CAP_1_2V_DDR &&
-                       card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+       if (caps & MMC_CAP_1_8V_DDR &&
+           card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
                hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+       }
 
-       if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-                       card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-           (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-                       card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+       if (caps & MMC_CAP_1_2V_DDR &&
+           card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+               hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+       }
+
+       if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+           card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
                hs_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+       }
+
+       if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+           card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+               hs_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+       }
 
        card->ext_csd.hs_max_dtr = hs_max_dtr;
-       card->ext_csd.card_type = card_type;
+       card->mmc_avail_type = avail_type;
 }
 
 /*
@@ -708,6 +726,11 @@ static struct device_type mmc_type = {
        .groups = mmc_attr_groups,
 };
 
Quoted 8 lines

drivers/mmc/core/mmc.c static struct device_type mmc_type = { · line 733

Quoted 5 lines
drivers/mmc/core/mmc.c +5 -0
+static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
+{
+       return card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+}
+

Having a separate function for this seem a bit silly. Similar checks is performed all over the code. I suggest you remove this.

Quoted 5 lines

I understand your meaning.
Yes, actually similar checking card type is done.
But checking DDR type is required several times unlike other type case.
I considered for that. I think it's pretty useful in terms of avoiding duplication and enhancement of readability.

As we don't have functions that performs the similar check for "mmc_avail_type", I don't think we should have it for ddr either. I prefer the symmetry in the code, so please remove.

Kind regards
Ulf Hansson

Quoted 178 lines
Quoted 100 lines
Quoted 100 lines
drivers/mmc/core/mmc.c +10 -22
 /*
  * Select the PowerClass for the current bus width
  * If power class is defined for 4/8 bit bus in the
@@ -808,12 +831,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
        host = card->host;
 
-       if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-                       host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
                err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-       if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-                       host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+       if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
                err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
        /* If fails try again during next card power cycle */
@@ -1072,10 +1093,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
         */
        if (card->ext_csd.hs_max_dtr != 0) {
                err = 0;
-               if (card->ext_csd.hs_max_dtr > 52000000 &&
-                   host->caps2 & MMC_CAP2_HS200)
+               if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
                        err = mmc_select_hs200(card);
-               else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
+               else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
                        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                        EXT_CSD_HS_TIMING, 1,
                                        card->ext_csd.generic_cmd6_time,
@@ -1089,13 +1109,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                               mmc_hostname(card->host));
                        err = 0;
                } else {
-                       if (card->ext_csd.hs_max_dtr > 52000000 &&
-                           host->caps2 & MMC_CAP2_HS200) {
+                       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
                                mmc_set_timing(card->host,
                                               MMC_TIMING_MMC_HS200);
-                       } else {
+                       else
                                mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-                       }
                }
        }
 
@@ -1118,14 +1136,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        /*
         * Indicate DDR mode (if supported).
         */
-       if (mmc_card_hs(card)) {
-               if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
-                       && (host->caps & MMC_CAP_1_8V_DDR))
-                               ddr = MMC_1_8V_DDR_MODE;
-               else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
-                       && (host->caps & MMC_CAP_1_2V_DDR))
-                               ddr = MMC_1_2V_DDR_MODE;
-       }
+       if (mmc_card_hs(card))
+               ddr = mmc_snoop_ddr(card);
 
        /*
         * Indicate HS200 SDR mode (if supported).
@@ -1145,8 +1157,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                 * 3. set the clock to > 52Mhz <=200MHz and
                 * 4. execute tuning for HS200
                 */
-               if ((host->caps2 & MMC_CAP2_HS200) &&
-                   card->host->ops->execute_tuning) {
+               if (card->host->ops->execute_tuning) {
                        mmc_host_clk_hold(card->host);
                        err = card->host->ops->execute_tuning(card->host,
                                MMC_SEND_TUNING_BLOCK_HS200);
@@ -1255,7 +1266,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                         *
                         * WARNING: eMMC rules are NOT the same as SD DDR
                         */
-                       if (ddr == MMC_1_2V_DDR_MODE) {
+                       if (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) {
                                err = __mmc_set_signal_voltage(host,
                                        MMC_SIGNAL_VOLTAGE_120);
                                if (err)
include/linux/mmc/card.h +0 -1
index 5473133..c232b10 100644
@@ -68,7 +68,6 @@ struct mmc_ext_csd {
 #define MMC_HIGH_DDR_MAX_DTR   52000000
 #define MMC_HS200_MAX_DTR      200000000
        unsigned int            sectors;
-       unsigned int            card_type;
        unsigned int            hc_erase_size;          /* In sectors */
        unsigned int            hc_erase_timeout;       /* In milliseconds */
        unsigned int            sec_trim_mult;  /* Secure trim multiplier  */
@@ -297,7 +296,10 @@ struct mmc_card {
        const char              **info;         /* info strings */
        struct sdio_func_tuple  *tuples;        /* unknown common tuples */
 
Quoted 7 lines

include/linux/mmc/card.h struct mmc_card { · line 301

Quoted 4 lines
include/linux/mmc/card.h +3 -1
-       unsigned int            sd_bus_speed;   /* Bus Speed Mode set for the card */
+       union {
+               unsigned int            sd_bus_speed;   /* Bus Speed Mode set for the card */
+               unsigned int            mmc_avail_type; /* supported device type by both host and card */

Using a union here won't be that much of a gain since there are only few instances of the struct. Please remove.

Yes, you're right. It's not much in gain.
I intended to distinguish these two similar members respectively. It's used only in each specific type domain and not used at the same time. If no meaningful, I can remove as your suggestion.

Thanks,
Seungwon Jeon

Quoted 62 lines
Quoted 54 lines
include/linux/mmc/card.h +1 -0
+       };
 
        struct dentry           *debugfs_root;
        struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
include/linux/mmc/host.h +0 -6
index 2f263ae..1ee3c10 100644
@@ -62,12 +62,6 @@ struct mmc_ios {
 #define MMC_TIMING_MMC_DDR52   8
 #define MMC_TIMING_MMC_HS200   9
 
-#define MMC_SDR_MODE           0
-#define MMC_1_2V_DDR_MODE      1
-#define MMC_1_8V_DDR_MODE      2
-#define MMC_1_2V_SDR_MODE      3
-#define MMC_1_8V_SDR_MODE      4
-
        unsigned char   signal_voltage;         /* signalling voltage (1.8V or 3.3V) */
 
 #define MMC_SIGNAL_VOLTAGE_330 0
include/linux/mmc/mmc.h +8 -5
index 50bcde3..f734c0c 100644
@@ -354,18 +354,22 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE         (1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE       (1<<2)
 
-#define EXT_CSD_CARD_TYPE_26   (1<<0)  /* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52   (1<<1)  /* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_MASK 0x3F    /* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_HS_26        (1<<0)  /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_HS_52        (1<<1)  /* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_HS   (EXT_CSD_CARD_TYPE_HS_26 | \
+                                EXT_CSD_CARD_TYPE_HS_52)
 #define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
                                             /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
                                             /* DDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
                                        | EXT_CSD_CARD_TYPE_DDR_1_2V)
-#define EXT_CSD_CARD_TYPE_SDR_1_8V     (1<<4)  /* Card can run at 200MHz */
-#define EXT_CSD_CARD_TYPE_SDR_1_2V     (1<<5)  /* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_8V   (1<<4)  /* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V   (1<<5)  /* Card can run at 200MHz */
                                                /* SDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS200                (EXT_CSD_CARD_TYPE_HS200_1_8V | \
+                                        EXT_CSD_CARD_TYPE_HS200_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
--
Quoted 3 lines

1.7.0.4

Besides the minor stuff, looks good.

Kind regards
Ulf Hansson

#148 lore raw

RE: [PATCH v2 2/5] mmc: identify available device type to select

Quoted 96 lines · Ulf Hansson
Quoted 91 lines · Seungwon Jeon
Quoted 82 lines · Ulf Hansson
Quoted 81 lines · Seungwon Jeon

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

---
Changes in v2:
Just rebased with latest one.

 drivers/mmc/core/mmc.c   |   77 ++++++++++++++++++++++++++-------------------
 include/linux/mmc/card.h |    6 ++-
 include/linux/mmc/host.h |    6 ---
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 56 insertions(+), 45 deletions(-)
drivers/mmc/core/mmc.c +29 -11
index db9655f..0abece0 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
        u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
        u32 caps = host->caps, caps2 = host->caps2;
        unsigned int hs_max_dtr = 0;
+       unsigned int avail_type = 0;
 
-       if (card_type & EXT_CSD_CARD_TYPE_26)
+       if (caps & MMC_CAP_MMC_HIGHSPEED &&
+           card_type & EXT_CSD_CARD_TYPE_HS_26) {
                hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+       }
 
        if (caps & MMC_CAP_MMC_HIGHSPEED &&
-                       card_type & EXT_CSD_CARD_TYPE_52)
+           card_type & EXT_CSD_CARD_TYPE_HS_52) {
                hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+       }
 
-       if ((caps & MMC_CAP_1_8V_DDR &&
-                       card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-           (caps & MMC_CAP_1_2V_DDR &&
-                       card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+       if (caps & MMC_CAP_1_8V_DDR &&
+           card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
                hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+       }
 
-       if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-                       card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-           (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-                       card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+       if (caps & MMC_CAP_1_2V_DDR &&
+           card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+               hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+       }
+
+       if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+           card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
                hs_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+       }
+
+       if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+           card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+               hs_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+       }
 
        card->ext_csd.hs_max_dtr = hs_max_dtr;
-       card->ext_csd.card_type = card_type;
+       card->mmc_avail_type = avail_type;
 }
 
 /*
@@ -708,6 +726,11 @@ static struct device_type mmc_type = {
        .groups = mmc_attr_groups,
 };
 
Quoted 8 lines

drivers/mmc/core/mmc.c static struct device_type mmc_type = { · line 733

Quoted 5 lines
drivers/mmc/core/mmc.c +5 -0
+static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
+{
+       return card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+}
+

Having a separate function for this seem a bit silly. Similar checks is performed all over the code. I suggest you remove this.

Quoted 4 lines

I understand your meaning.
Yes, actually similar checking card type is done.
But checking DDR type is required several times unlike other type case.
I considered for that. I think it's pretty useful in terms of avoiding duplication and enhancement

Quoted 6 lines

of readability.

Quoted 1 line

As we don't have functions that performs the similar check for "mmc_avail_type", I don't think we should have it for ddr either. I prefer the symmetry in the code, so please remove.

OK. I'll try to adjust.

Thanks,
Seungwon Jeon

Quoted 187 lines

Kind regards
Ulf Hansson

Quoted 100 lines
Quoted 100 lines
Quoted 100 lines
drivers/mmc/core/mmc.c +10 -22
 /*
  * Select the PowerClass for the current bus width
  * If power class is defined for 4/8 bit bus in the
@@ -808,12 +831,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
        host = card->host;
 
-       if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-                       host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
                err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-       if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-                       host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+       if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
                err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
        /* If fails try again during next card power cycle */
@@ -1072,10 +1093,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
         */
        if (card->ext_csd.hs_max_dtr != 0) {
                err = 0;
-               if (card->ext_csd.hs_max_dtr > 52000000 &&
-                   host->caps2 & MMC_CAP2_HS200)
+               if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
                        err = mmc_select_hs200(card);
-               else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
+               else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
                        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                        EXT_CSD_HS_TIMING, 1,
                                        card->ext_csd.generic_cmd6_time,
@@ -1089,13 +1109,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                               mmc_hostname(card->host));
                        err = 0;
                } else {
-                       if (card->ext_csd.hs_max_dtr > 52000000 &&
-                           host->caps2 & MMC_CAP2_HS200) {
+                       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
                                mmc_set_timing(card->host,
                                               MMC_TIMING_MMC_HS200);
-                       } else {
+                       else
                                mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-                       }
                }
        }
 
@@ -1118,14 +1136,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        /*
         * Indicate DDR mode (if supported).
         */
-       if (mmc_card_hs(card)) {
-               if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
-                       && (host->caps & MMC_CAP_1_8V_DDR))
-                               ddr = MMC_1_8V_DDR_MODE;
-               else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
-                       && (host->caps & MMC_CAP_1_2V_DDR))
-                               ddr = MMC_1_2V_DDR_MODE;
-       }
+       if (mmc_card_hs(card))
+               ddr = mmc_snoop_ddr(card);
 
        /*
         * Indicate HS200 SDR mode (if supported).
@@ -1145,8 +1157,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                 * 3. set the clock to > 52Mhz <=200MHz and
                 * 4. execute tuning for HS200
                 */
-               if ((host->caps2 & MMC_CAP2_HS200) &&
-                   card->host->ops->execute_tuning) {
+               if (card->host->ops->execute_tuning) {
                        mmc_host_clk_hold(card->host);
                        err = card->host->ops->execute_tuning(card->host,
                                MMC_SEND_TUNING_BLOCK_HS200);
@@ -1255,7 +1266,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                         *
                         * WARNING: eMMC rules are NOT the same as SD DDR
                         */
-                       if (ddr == MMC_1_2V_DDR_MODE) {
+                       if (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) {
                                err = __mmc_set_signal_voltage(host,
                                        MMC_SIGNAL_VOLTAGE_120);
                                if (err)
include/linux/mmc/card.h +0 -1
index 5473133..c232b10 100644
@@ -68,7 +68,6 @@ struct mmc_ext_csd {
 #define MMC_HIGH_DDR_MAX_DTR   52000000
 #define MMC_HS200_MAX_DTR      200000000
        unsigned int            sectors;
-       unsigned int            card_type;
        unsigned int            hc_erase_size;          /* In sectors */
        unsigned int            hc_erase_timeout;       /* In milliseconds */
        unsigned int            sec_trim_mult;  /* Secure trim multiplier  */
@@ -297,7 +296,10 @@ struct mmc_card {
        const char              **info;         /* info strings */
        struct sdio_func_tuple  *tuples;        /* unknown common tuples */
 
Quoted 4 lines
Quoted 4 lines

include/linux/mmc/card.h struct mmc_card {

Quoted 4 lines
include/linux/mmc/card.h +3 -1
-       unsigned int            sd_bus_speed;   /* Bus Speed Mode set for the card */
+       union {
+               unsigned int            sd_bus_speed;   /* Bus Speed Mode set for the card */
+               unsigned int            mmc_avail_type; /* supported device type by both host and card

*/

Quoted 74 lines
Quoted 3 lines

Using a union here won't be that much of a gain since there are only few instances of the struct. Please remove.

Yes, you're right. It's not much in gain.
I intended to distinguish these two similar members respectively. It's used only in each specific type domain and not used at the same time. If no meaningful, I can remove as your suggestion.

Thanks,
Seungwon Jeon

Quoted 62 lines
Quoted 54 lines
include/linux/mmc/card.h +1 -0
+       };
 
        struct dentry           *debugfs_root;
        struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
include/linux/mmc/host.h +0 -6
index 2f263ae..1ee3c10 100644
@@ -62,12 +62,6 @@ struct mmc_ios {
 #define MMC_TIMING_MMC_DDR52   8
 #define MMC_TIMING_MMC_HS200   9
 
-#define MMC_SDR_MODE           0
-#define MMC_1_2V_DDR_MODE      1
-#define MMC_1_8V_DDR_MODE      2
-#define MMC_1_2V_SDR_MODE      3
-#define MMC_1_8V_SDR_MODE      4
-
        unsigned char   signal_voltage;         /* signalling voltage (1.8V or 3.3V) */
 
 #define MMC_SIGNAL_VOLTAGE_330 0
include/linux/mmc/mmc.h +8 -5
index 50bcde3..f734c0c 100644
@@ -354,18 +354,22 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE         (1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE       (1<<2)
 
-#define EXT_CSD_CARD_TYPE_26   (1<<0)  /* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52   (1<<1)  /* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_MASK 0x3F    /* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_HS_26        (1<<0)  /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_HS_52        (1<<1)  /* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_HS   (EXT_CSD_CARD_TYPE_HS_26 | \
+                                EXT_CSD_CARD_TYPE_HS_52)
 #define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
                                             /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
                                             /* DDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
                                        | EXT_CSD_CARD_TYPE_DDR_1_2V)
-#define EXT_CSD_CARD_TYPE_SDR_1_8V     (1<<4)  /* Card can run at 200MHz */
-#define EXT_CSD_CARD_TYPE_SDR_1_2V     (1<<5)  /* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_8V   (1<<4)  /* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V   (1<<5)  /* Card can run at 200MHz */
                                                /* SDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS200                (EXT_CSD_CARD_TYPE_HS200_1_8V | \
+                                        EXT_CSD_CARD_TYPE_HS200_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
--
Quoted 3 lines

1.7.0.4

Besides the minor stuff, looks good.

Kind regards
Ulf Hansson

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

#149 lore raw

Re: [PATCH v2 2/5] mmc: identify available device type to select

In reply to Seungwon Jeon
Quoted 203 lines · Seungwon Jeon
Quoted 82 lines · Ulf Hansson
Quoted 81 lines · Seungwon Jeon

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

---
Changes in v2:
Just rebased with latest one.

 drivers/mmc/core/mmc.c   |   77 ++++++++++++++++++++++++++-------------------
 include/linux/mmc/card.h |    6 ++-
 include/linux/mmc/host.h |    6 ---
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 56 insertions(+), 45 deletions(-)
drivers/mmc/core/mmc.c +29 -11
index db9655f..0abece0 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
        u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
        u32 caps = host->caps, caps2 = host->caps2;
        unsigned int hs_max_dtr = 0;
+       unsigned int avail_type = 0;
 
-       if (card_type & EXT_CSD_CARD_TYPE_26)
+       if (caps & MMC_CAP_MMC_HIGHSPEED &&
+           card_type & EXT_CSD_CARD_TYPE_HS_26) {
                hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+       }
 
        if (caps & MMC_CAP_MMC_HIGHSPEED &&
-                       card_type & EXT_CSD_CARD_TYPE_52)
+           card_type & EXT_CSD_CARD_TYPE_HS_52) {
                hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+       }
 
-       if ((caps & MMC_CAP_1_8V_DDR &&
-                       card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-           (caps & MMC_CAP_1_2V_DDR &&
-                       card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+       if (caps & MMC_CAP_1_8V_DDR &&
+           card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
                hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+       }
 
-       if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-                       card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-           (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-                       card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+       if (caps & MMC_CAP_1_2V_DDR &&
+           card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+               hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+       }
+
+       if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+           card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
                hs_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+       }
+
+       if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+           card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+               hs_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+       }
 
        card->ext_csd.hs_max_dtr = hs_max_dtr;
-       card->ext_csd.card_type = card_type;
+       card->mmc_avail_type = avail_type;
 }
 
 /*
@@ -708,6 +726,11 @@ static struct device_type mmc_type = {
        .groups = mmc_attr_groups,
 };
 
Quoted 8 lines

drivers/mmc/core/mmc.c static struct device_type mmc_type = { · line 733

Quoted 5 lines
drivers/mmc/core/mmc.c +5 -0
+static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
+{
+       return card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+}
+

Having a separate function for this seem a bit silly. Similar checks is performed all over the code. I suggest you remove this.

I understand your meaning.
Yes, actually similar checking card type is done.
But checking DDR type is required several times unlike other type case.
I considered for that. I think it's pretty useful in terms of avoiding duplication and enhancement of readability.

Quoted 100 lines
Quoted 100 lines
drivers/mmc/core/mmc.c +10 -22
 /*
  * Select the PowerClass for the current bus width
  * If power class is defined for 4/8 bit bus in the
@@ -808,12 +831,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
        host = card->host;
 
-       if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-                       host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
                err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-       if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-                       host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+       if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
                err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
        /* If fails try again during next card power cycle */
@@ -1072,10 +1093,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
         */
        if (card->ext_csd.hs_max_dtr != 0) {
                err = 0;
-               if (card->ext_csd.hs_max_dtr > 52000000 &&
-                   host->caps2 & MMC_CAP2_HS200)
+               if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
                        err = mmc_select_hs200(card);
-               else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
+               else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
                        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                        EXT_CSD_HS_TIMING, 1,
                                        card->ext_csd.generic_cmd6_time,
@@ -1089,13 +1109,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                               mmc_hostname(card->host));
                        err = 0;
                } else {
-                       if (card->ext_csd.hs_max_dtr > 52000000 &&
-                           host->caps2 & MMC_CAP2_HS200) {
+                       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
                                mmc_set_timing(card->host,
                                               MMC_TIMING_MMC_HS200);
-                       } else {
+                       else
                                mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-                       }
                }
        }
 
@@ -1118,14 +1136,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        /*
         * Indicate DDR mode (if supported).
         */
-       if (mmc_card_hs(card)) {
-               if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
-                       && (host->caps & MMC_CAP_1_8V_DDR))
-                               ddr = MMC_1_8V_DDR_MODE;
-               else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
-                       && (host->caps & MMC_CAP_1_2V_DDR))
-                               ddr = MMC_1_2V_DDR_MODE;
-       }
+       if (mmc_card_hs(card))
+               ddr = mmc_snoop_ddr(card);
 
        /*
         * Indicate HS200 SDR mode (if supported).
@@ -1145,8 +1157,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                 * 3. set the clock to > 52Mhz <=200MHz and
                 * 4. execute tuning for HS200
                 */
-               if ((host->caps2 & MMC_CAP2_HS200) &&
-                   card->host->ops->execute_tuning) {
+               if (card->host->ops->execute_tuning) {
                        mmc_host_clk_hold(card->host);
                        err = card->host->ops->execute_tuning(card->host,
                                MMC_SEND_TUNING_BLOCK_HS200);
@@ -1255,7 +1266,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                         *
                         * WARNING: eMMC rules are NOT the same as SD DDR
                         */
-                       if (ddr == MMC_1_2V_DDR_MODE) {
+                       if (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) {
                                err = __mmc_set_signal_voltage(host,
                                        MMC_SIGNAL_VOLTAGE_120);
                                if (err)
include/linux/mmc/card.h +0 -1
index 5473133..c232b10 100644
@@ -68,7 +68,6 @@ struct mmc_ext_csd {
 #define MMC_HIGH_DDR_MAX_DTR   52000000
 #define MMC_HS200_MAX_DTR      200000000
        unsigned int            sectors;
-       unsigned int            card_type;
        unsigned int            hc_erase_size;          /* In sectors */
        unsigned int            hc_erase_timeout;       /* In milliseconds */
        unsigned int            sec_trim_mult;  /* Secure trim multiplier  */
@@ -297,7 +296,10 @@ struct mmc_card {
        const char              **info;         /* info strings */
        struct sdio_func_tuple  *tuples;        /* unknown common tuples */
 
Quoted 7 lines

include/linux/mmc/card.h struct mmc_card { · line 301

Quoted 4 lines
include/linux/mmc/card.h +3 -1
-       unsigned int            sd_bus_speed;   /* Bus Speed Mode set for the card */
+       union {
+               unsigned int            sd_bus_speed;   /* Bus Speed Mode set for the card */
+               unsigned int            mmc_avail_type; /* supported device type by both host and card */

Using a union here won't be that much of a gain since there are only few instances of the struct. Please remove.

Quoted 4 lines

Yes, you're right. It's not much in gain.
I intended to distinguish these two similar members respectively. It's used only in each specific type domain and not used at the same time. If no meaningful, I can remove as your suggestion.

Hi Seungwon,

I noticed in your latest version if this patch the "union" declaration is still there. Could you please update and send a new version.

Kind regards
Ulf Hansson

Quoted 67 lines

Thanks,
Seungwon Jeon

Quoted 62 lines
Quoted 54 lines
include/linux/mmc/card.h +1 -0
+       };
 
        struct dentry           *debugfs_root;
        struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
include/linux/mmc/host.h +0 -6
index 2f263ae..1ee3c10 100644
@@ -62,12 +62,6 @@ struct mmc_ios {
 #define MMC_TIMING_MMC_DDR52   8
 #define MMC_TIMING_MMC_HS200   9
 
-#define MMC_SDR_MODE           0
-#define MMC_1_2V_DDR_MODE      1
-#define MMC_1_8V_DDR_MODE      2
-#define MMC_1_2V_SDR_MODE      3
-#define MMC_1_8V_SDR_MODE      4
-
        unsigned char   signal_voltage;         /* signalling voltage (1.8V or 3.3V) */
 
 #define MMC_SIGNAL_VOLTAGE_330 0
include/linux/mmc/mmc.h +8 -5
index 50bcde3..f734c0c 100644
@@ -354,18 +354,22 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE         (1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE       (1<<2)
 
-#define EXT_CSD_CARD_TYPE_26   (1<<0)  /* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52   (1<<1)  /* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_MASK 0x3F    /* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_HS_26        (1<<0)  /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_HS_52        (1<<1)  /* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_HS   (EXT_CSD_CARD_TYPE_HS_26 | \
+                                EXT_CSD_CARD_TYPE_HS_52)
 #define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
                                             /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
                                             /* DDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
                                        | EXT_CSD_CARD_TYPE_DDR_1_2V)
-#define EXT_CSD_CARD_TYPE_SDR_1_8V     (1<<4)  /* Card can run at 200MHz */
-#define EXT_CSD_CARD_TYPE_SDR_1_2V     (1<<5)  /* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_8V   (1<<4)  /* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V   (1<<5)  /* Card can run at 200MHz */
                                                /* SDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS200                (EXT_CSD_CARD_TYPE_HS200_1_8V | \
+                                        EXT_CSD_CARD_TYPE_HS200_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
--
Quoted 3 lines

1.7.0.4

Besides the minor stuff, looks good.

Kind regards
Ulf Hansson

#150 lore raw

RE: [PATCH v2 2/5] mmc: identify available device type to select

Quoted 211 lines · Ulf Hansson
Quoted 91 lines · Seungwon Jeon
Quoted 82 lines · Ulf Hansson
Quoted 81 lines · Seungwon Jeon

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

---
Changes in v2:
Just rebased with latest one.

 drivers/mmc/core/mmc.c   |   77 ++++++++++++++++++++++++++-------------------
 include/linux/mmc/card.h |    6 ++-
 include/linux/mmc/host.h |    6 ---
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 56 insertions(+), 45 deletions(-)
drivers/mmc/core/mmc.c +29 -11
index db9655f..0abece0 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
        u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
        u32 caps = host->caps, caps2 = host->caps2;
        unsigned int hs_max_dtr = 0;
+       unsigned int avail_type = 0;
 
-       if (card_type & EXT_CSD_CARD_TYPE_26)
+       if (caps & MMC_CAP_MMC_HIGHSPEED &&
+           card_type & EXT_CSD_CARD_TYPE_HS_26) {
                hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+       }
 
        if (caps & MMC_CAP_MMC_HIGHSPEED &&
-                       card_type & EXT_CSD_CARD_TYPE_52)
+           card_type & EXT_CSD_CARD_TYPE_HS_52) {
                hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+       }
 
-       if ((caps & MMC_CAP_1_8V_DDR &&
-                       card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-           (caps & MMC_CAP_1_2V_DDR &&
-                       card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+       if (caps & MMC_CAP_1_8V_DDR &&
+           card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
                hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+       }
 
-       if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-                       card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-           (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-                       card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+       if (caps & MMC_CAP_1_2V_DDR &&
+           card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+               hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+       }
+
+       if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+           card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
                hs_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+       }
+
+       if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+           card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+               hs_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+       }
 
        card->ext_csd.hs_max_dtr = hs_max_dtr;
-       card->ext_csd.card_type = card_type;
+       card->mmc_avail_type = avail_type;
 }
 
 /*
@@ -708,6 +726,11 @@ static struct device_type mmc_type = {
        .groups = mmc_attr_groups,
 };
 
Quoted 8 lines

drivers/mmc/core/mmc.c static struct device_type mmc_type = { · line 733

Quoted 5 lines
drivers/mmc/core/mmc.c +5 -0
+static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
+{
+       return card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+}
+

Having a separate function for this seem a bit silly. Similar checks is performed all over the code. I suggest you remove this.

Quoted 4 lines

I understand your meaning.
Yes, actually similar checking card type is done.
But checking DDR type is required several times unlike other type case.
I considered for that. I think it's pretty useful in terms of avoiding duplication and enhancement

of readability.

Quoted 101 lines
Quoted 101 lines
Quoted 101 lines
drivers/mmc/core/mmc.c +10 -22
 /*
  * Select the PowerClass for the current bus width
  * If power class is defined for 4/8 bit bus in the
@@ -808,12 +831,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
        host = card->host;
 
-       if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-                       host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
                err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-       if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-                       host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+       if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
                err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
        /* If fails try again during next card power cycle */
@@ -1072,10 +1093,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
         */
        if (card->ext_csd.hs_max_dtr != 0) {
                err = 0;
-               if (card->ext_csd.hs_max_dtr > 52000000 &&
-                   host->caps2 & MMC_CAP2_HS200)
+               if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
                        err = mmc_select_hs200(card);
-               else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
+               else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
                        err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                        EXT_CSD_HS_TIMING, 1,
                                        card->ext_csd.generic_cmd6_time,
@@ -1089,13 +1109,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                               mmc_hostname(card->host));
                        err = 0;
                } else {
-                       if (card->ext_csd.hs_max_dtr > 52000000 &&
-                           host->caps2 & MMC_CAP2_HS200) {
+                       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
                                mmc_set_timing(card->host,
                                               MMC_TIMING_MMC_HS200);
-                       } else {
+                       else
                                mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-                       }
                }
        }
 
@@ -1118,14 +1136,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        /*
         * Indicate DDR mode (if supported).
         */
-       if (mmc_card_hs(card)) {
-               if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
-                       && (host->caps & MMC_CAP_1_8V_DDR))
-                               ddr = MMC_1_8V_DDR_MODE;
-               else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
-                       && (host->caps & MMC_CAP_1_2V_DDR))
-                               ddr = MMC_1_2V_DDR_MODE;
-       }
+       if (mmc_card_hs(card))
+               ddr = mmc_snoop_ddr(card);
 
        /*
         * Indicate HS200 SDR mode (if supported).
@@ -1145,8 +1157,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                 * 3. set the clock to > 52Mhz <=200MHz and
                 * 4. execute tuning for HS200
                 */
-               if ((host->caps2 & MMC_CAP2_HS200) &&
-                   card->host->ops->execute_tuning) {
+               if (card->host->ops->execute_tuning) {
                        mmc_host_clk_hold(card->host);
                        err = card->host->ops->execute_tuning(card->host,
                                MMC_SEND_TUNING_BLOCK_HS200);
@@ -1255,7 +1266,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                         *
                         * WARNING: eMMC rules are NOT the same as SD DDR
                         */
-                       if (ddr == MMC_1_2V_DDR_MODE) {
+                       if (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) {
                                err = __mmc_set_signal_voltage(host,
                                        MMC_SIGNAL_VOLTAGE_120);
                                if (err)
include/linux/mmc/card.h +0 -1
index 5473133..c232b10 100644
@@ -68,7 +68,6 @@ struct mmc_ext_csd {
 #define MMC_HIGH_DDR_MAX_DTR   52000000
 #define MMC_HS200_MAX_DTR      200000000
        unsigned int            sectors;
-       unsigned int            card_type;
        unsigned int            hc_erase_size;          /* In sectors */
        unsigned int            hc_erase_timeout;       /* In milliseconds */
        unsigned int            sec_trim_mult;  /* Secure trim multiplier  */
@@ -297,7 +296,10 @@ struct mmc_card {
        const char              **info;         /* info strings */
        struct sdio_func_tuple  *tuples;        /* unknown common tuples */
 
Quoted 4 lines
Quoted 4 lines

include/linux/mmc/card.h struct mmc_card {

Quoted 4 lines
include/linux/mmc/card.h +3 -1
-       unsigned int            sd_bus_speed;   /* Bus Speed Mode set for the card */
+       union {
+               unsigned int            sd_bus_speed;   /* Bus Speed Mode set for the card */
+               unsigned int            mmc_avail_type; /* supported device type by both host and card

*/

Quoted 7 lines
Quoted 3 lines

Using a union here won't be that much of a gain since there are only few instances of the struct. Please remove.

Yes, you're right. It's not much in gain.
I intended to distinguish these two similar members respectively. It's used only in each specific type domain and not used at the same time. If no meaningful, I can remove as your suggestion.

Quoted 4 lines

Hi Seungwon,

I noticed in your latest version if this patch the "union" declaration is still there. Could you please update and send a new version.

Oh, I was waiting your reply for my extra opinion :) I don't like to hold this strongly.
I'll update next.

Thanks,
Seungwon Jeon

Quoted 75 lines

Kind regards
Ulf Hansson

Quoted 67 lines

Thanks,
Seungwon Jeon

Quoted 62 lines
Quoted 54 lines
include/linux/mmc/card.h +1 -0
+       };
 
        struct dentry           *debugfs_root;
        struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
include/linux/mmc/host.h +0 -6
index 2f263ae..1ee3c10 100644
@@ -62,12 +62,6 @@ struct mmc_ios {
 #define MMC_TIMING_MMC_DDR52   8
 #define MMC_TIMING_MMC_HS200   9
 
-#define MMC_SDR_MODE           0
-#define MMC_1_2V_DDR_MODE      1
-#define MMC_1_8V_DDR_MODE      2
-#define MMC_1_2V_SDR_MODE      3
-#define MMC_1_8V_SDR_MODE      4
-
        unsigned char   signal_voltage;         /* signalling voltage (1.8V or 3.3V) */
 
 #define MMC_SIGNAL_VOLTAGE_330 0
include/linux/mmc/mmc.h +8 -5
index 50bcde3..f734c0c 100644
@@ -354,18 +354,22 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE         (1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE       (1<<2)
 
-#define EXT_CSD_CARD_TYPE_26   (1<<0)  /* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52   (1<<1)  /* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_MASK 0x3F    /* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_HS_26        (1<<0)  /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_HS_52        (1<<1)  /* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_HS   (EXT_CSD_CARD_TYPE_HS_26 | \
+                                EXT_CSD_CARD_TYPE_HS_52)
 #define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
                                             /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
                                             /* DDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
                                        | EXT_CSD_CARD_TYPE_DDR_1_2V)
-#define EXT_CSD_CARD_TYPE_SDR_1_8V     (1<<4)  /* Card can run at 200MHz */
-#define EXT_CSD_CARD_TYPE_SDR_1_2V     (1<<5)  /* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_8V   (1<<4)  /* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V   (1<<5)  /* Card can run at 200MHz */
                                                /* SDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS200                (EXT_CSD_CARD_TYPE_HS200_1_8V | \
+                                        EXT_CSD_CARD_TYPE_HS200_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
--
Quoted 3 lines

1.7.0.4

Besides the minor stuff, looks good.

Kind regards
Ulf Hansson

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

#151 lore raw

PATCH v3 2/5 mmc: identify available device type to select

In reply to Seungwon Jeon

Device types which are supported by both host and device can be identified when EXT_CSD is read. There is no need to check host's capability anymore.

---
 drivers/mmc/core/mmc.c   |   72 +++++++++++++++++++++++++---------------------
 include/linux/mmc/card.h |    6 ++-
 include/linux/mmc/host.h |    6 ----
 include/linux/mmc/mmc.h  |   12 +++++--
 4 files changed, 51 insertions(+), 45 deletions(-)
drivers/mmc/core/mmc.c +39 -33
index db9655f..97f1912 100644
@@ -243,28 +243,46 @@ static void mmc_select_card_type(struct mmc_card *card)
 	u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
 	u32 caps = host->caps, caps2 = host->caps2;
 	unsigned int hs_max_dtr = 0;
+	unsigned int avail_type = 0;
 
-	if (card_type & EXT_CSD_CARD_TYPE_26)
+	if (caps & MMC_CAP_MMC_HIGHSPEED &&
+	    card_type & EXT_CSD_CARD_TYPE_HS_26) {
 		hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_26;
+	}
 
 	if (caps & MMC_CAP_MMC_HIGHSPEED &&
-			card_type & EXT_CSD_CARD_TYPE_52)
+	    card_type & EXT_CSD_CARD_TYPE_HS_52) {
 		hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS_52;
+	}
 
-	if ((caps & MMC_CAP_1_8V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
-	    (caps & MMC_CAP_1_2V_DDR &&
-			card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+	if (caps & MMC_CAP_1_8V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) {
 		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_8V;
+	}
+
+	if (caps & MMC_CAP_1_2V_DDR &&
+	    card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+		hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_DDR_1_2V;
+	}
 
-	if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
-	    (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
-			card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+	if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
 		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
+	}
+
+	if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+	    card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
+		hs_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
+	}
 
 	card->ext_csd.hs_max_dtr = hs_max_dtr;
-	card->ext_csd.card_type = card_type;
+	card->mmc_avail_type = avail_type;
 }
 
 /*
@@ -808,12 +826,10 @@ static int mmc_select_hs200(struct mmc_card *card)
 
 	host = card->host;
 
-	if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
-			host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
+	if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
 
-	if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
-			host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
+	if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
 
 	/* If fails try again during next card power cycle */
@@ -1072,10 +1088,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 */
 	if (card->ext_csd.hs_max_dtr != 0) {
 		err = 0;
-		if (card->ext_csd.hs_max_dtr > 52000000 &&
-		    host->caps2 & MMC_CAP2_HS200)
+		if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
 			err = mmc_select_hs200(card);
-		else if	(host->caps & MMC_CAP_MMC_HIGHSPEED)
+		else if	(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
 			err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 					EXT_CSD_HS_TIMING, 1,
 					card->ext_csd.generic_cmd6_time,
@@ -1089,13 +1104,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			       mmc_hostname(card->host));
 			err = 0;
 		} else {
-			if (card->ext_csd.hs_max_dtr > 52000000 &&
-			    host->caps2 & MMC_CAP2_HS200) {
+			if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
 				mmc_set_timing(card->host,
 					       MMC_TIMING_MMC_HS200);
-			} else {
+			else
 				mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-			}
 		}
 	}
 
@@ -1118,14 +1131,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	/*
 	 * Indicate DDR mode (if supported).
 	 */
-	if (mmc_card_hs(card)) {
-		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
-			&& (host->caps & MMC_CAP_1_8V_DDR))
-				ddr = MMC_1_8V_DDR_MODE;
-		else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
-			&& (host->caps & MMC_CAP_1_2V_DDR))
-				ddr = MMC_1_2V_DDR_MODE;
-	}
+	if (mmc_card_hs(card))
+		ddr = card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
 
 	/*
 	 * Indicate HS200 SDR mode (if supported).
@@ -1145,8 +1152,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		 * 3. set the clock to > 52Mhz <=200MHz and
 		 * 4. execute tuning for HS200
 		 */
-		if ((host->caps2 & MMC_CAP2_HS200) &&
-		    card->host->ops->execute_tuning) {
+		if (card->host->ops->execute_tuning) {
 			mmc_host_clk_hold(card->host);
 			err = card->host->ops->execute_tuning(card->host,
 				MMC_SEND_TUNING_BLOCK_HS200);
@@ -1255,7 +1261,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 			 *
 			 * WARNING: eMMC rules are NOT the same as SD DDR
 			 */
-			if (ddr == MMC_1_2V_DDR_MODE) {
+			if (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) {
 				err = __mmc_set_signal_voltage(host,
 					MMC_SIGNAL_VOLTAGE_120);
 				if (err)
include/linux/mmc/card.h +4 -2
index 5473133..c232b10 100644
@@ -68,7 +68,6 @@ struct mmc_ext_csd {
 #define MMC_HIGH_DDR_MAX_DTR	52000000
 #define MMC_HS200_MAX_DTR	200000000
 	unsigned int		sectors;
-	unsigned int		card_type;
 	unsigned int		hc_erase_size;		/* In sectors */
 	unsigned int		hc_erase_timeout;	/* In milliseconds */
 	unsigned int		sec_trim_mult;	/* Secure trim multiplier  */
@@ -297,7 +296,10 @@ struct mmc_card {
 	const char		**info;		/* info strings */
 	struct sdio_func_tuple	*tuples;	/* unknown common tuples */
 
-	unsigned int		sd_bus_speed;	/* Bus Speed Mode set for the card */
+	union {
+		unsigned int		sd_bus_speed;	/* Bus Speed Mode set for the card */
+		unsigned int		mmc_avail_type;	/* supported device type by both host and card */
+	};
 
 	struct dentry		*debugfs_root;
 	struct mmc_part	part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
include/linux/mmc/host.h +0 -6
index 2f263ae..1ee3c10 100644
@@ -62,12 +62,6 @@ struct mmc_ios {
 #define MMC_TIMING_MMC_DDR52	8
 #define MMC_TIMING_MMC_HS200	9
 
-#define MMC_SDR_MODE		0
-#define MMC_1_2V_DDR_MODE	1
-#define MMC_1_8V_DDR_MODE	2
-#define MMC_1_2V_SDR_MODE	3
-#define MMC_1_8V_SDR_MODE	4
-
 	unsigned char	signal_voltage;		/* signalling voltage (1.8V or 3.3V) */
 
 #define MMC_SIGNAL_VOLTAGE_330	0
include/linux/mmc/mmc.h +8 -4
index 50bcde3..f734c0c 100644
@@ -354,18 +354,22 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-#define EXT_CSD_CARD_TYPE_26	(1<<0)	/* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52	(1<<1)	/* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_MASK	0x3F	/* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
+				 EXT_CSD_CARD_TYPE_HS_52)
 #define EXT_CSD_CARD_TYPE_DDR_1_8V  (1<<2)   /* Card can run at 52MHz */
 					     /* DDR mode @1.8V or 3V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_1_2V  (1<<3)   /* Card can run at 52MHz */
 					     /* DDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_DDR_52       (EXT_CSD_CARD_TYPE_DDR_1_8V  \
 					| EXT_CSD_CARD_TYPE_DDR_1_2V)
-#define EXT_CSD_CARD_TYPE_SDR_1_8V	(1<<4)	/* Card can run at 200MHz */
-#define EXT_CSD_CARD_TYPE_SDR_1_2V	(1<<5)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_8V	(1<<4)	/* Card can run at 200MHz */
+#define EXT_CSD_CARD_TYPE_HS200_1_2V	(1<<5)	/* Card can run at 200MHz */
 						/* SDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
+					 EXT_CSD_CARD_TYPE_HS200_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
Signature · 1 line
1.7.0.4
#152 lore raw

PATCH RESEND 3/5 mmc: step power class after final selection of bus mode

In reply to Ulf Hansson

Power class is changed once only after selection of bus modes including speed and bus-width finishes finally.

---
 drivers/mmc/core/mmc.c |   77 +++++++++++++++++++++++++++++++----------------
 1 files changed, 51 insertions(+), 26 deletions(-)
drivers/mmc/core/mmc.c +51 -26
index 1ea155a..0d17395 100644
@@ -737,8 +737,8 @@ static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
  * 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, u8 *ext_csd)
 {
 	int err = 0;
 	unsigned int pwrclass_val = 0;
@@ -759,13 +759,13 @@ static int mmc_select_powerclass(struct mmc_card *card,
 
 	switch (1 << host->ios.vdd) {
 	case MMC_VDD_165_195:
-		if (host->ios.clock <= 26000000)
+		if (host->ios.clock <= MMC_HIGH_26_MAX_DTR)
 			pwrclass_val = card->ext_csd.raw_pwr_cl_26_195;
-		else if	(host->ios.clock <= 52000000)
+		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)
+		else if (host->ios.clock <= MMC_HS200_MAX_DTR)
 			pwrclass_val = card->ext_csd.raw_pwr_cl_200_195;
 		break;
 	case MMC_VDD_27_28:
@@ -777,13 +777,13 @@ 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)
+		if (host->ios.clock <= MMC_HIGH_26_MAX_DTR)
 			pwrclass_val = card->ext_csd.raw_pwr_cl_26_360;
-		else if	(host->ios.clock <= 52000000)
+		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)
+		else if (host->ios.clock <= MMC_HS200_MAX_DTR)
 			pwrclass_val = card->ext_csd.raw_pwr_cl_200_360;
 		break;
 	default:
@@ -810,6 +810,44 @@ static int mmc_select_powerclass(struct mmc_card *card,
 	return err;
 }
 
+static int mmc_select_powerclass(struct mmc_card *card, u8 *ext_csd)
+{
+	int err, ddr;
+	u32 bus_width, ext_csd_bits;
+	struct mmc_host *host;
+
+	BUG_ON(!card);
+
+	host = card->host;
+
+	if (!ext_csd)
+		return 0;
+
+	/* 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 = mmc_snoop_ddr(card);
+	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, ext_csd);
+	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
@@ -1168,11 +1206,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);
 	}
 
 	/*
@@ -1201,12 +1234,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,
@@ -1231,13 +1258,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],
@@ -1275,6 +1295,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	}
 
 	/*
+	 * Choose the power calss with selected bus interface
+	 */
+	mmc_select_powerclass(card, ext_csd);
+
+	/*
 	 * Enable HPI feature (if supported)
 	 */
 	if (card->ext_csd.hpi) {
Signature · 1 line
1.7.0.4
#153 lore raw

PATCH v2 3/5 mmc: step power class after final selection of bus mode

Power class is changed once only after selection of bus modes including speed and bus-width finishes finally.

---
Changes in v2:
Cleaned up some unnecessary codes.

 drivers/mmc/core/mmc.c |   94 +++++++++++++++++++++++++++--------------------
 1 files changed, 54 insertions(+), 40 deletions(-)
drivers/mmc/core/mmc.c +54 -40
index 0abece0..88ff217 100644
@@ -737,17 +737,13 @@ static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
  * 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;
 	unsigned int pwrclass_val = 0;
-	struct mmc_host *host;
-
-	BUG_ON(!card);
-
-	host = card->host;
-	BUG_ON(!host);
+	struct mmc_host *host = card->host;
+	struct mmc_ext_csd *ext_csd = &card->ext_csd;
 
 	/* Power class selection is supported for versions >= 4.0 */
 	if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
@@ -759,14 +755,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:
@@ -777,14 +773,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 "
@@ -810,6 +806,37 @@ static int mmc_select_powerclass(struct mmc_card *card,
 	return err;
 }
 
+static int mmc_select_powerclass(struct mmc_card *card)
+{
+	int err, ddr;
+	u32 bus_width, ext_csd_bits;
+	struct mmc_host *host = card->host;
+
+	/* 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 = mmc_snoop_ddr(card);
+	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
@@ -1171,11 +1198,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);
 	}
 
 	/*
@@ -1204,12 +1226,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,
@@ -1234,13 +1250,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],
@@ -1278,6 +1287,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	}
 
 	/*
+	 * Choose the power calss with selected bus interface
+	 */
+	mmc_select_powerclass(card);
+
+	/*
 	 * Enable HPI feature (if supported)
 	 */
 	if (card->ext_csd.hpi) {
Signature · 1 line
1.7.0.4
#154 lore raw

Re: [PATCH v2 3/5] mmc: step power class after final selection of bus mode

Quoted 159 lines · Seungwon Jeon

Power class is changed once only after selection of bus modes including speed and bus-width finishes finally.

---
Changes in v2:
Cleaned up some unnecessary codes.

 drivers/mmc/core/mmc.c |   94 +++++++++++++++++++++++++++--------------------
 1 files changed, 54 insertions(+), 40 deletions(-)
drivers/mmc/core/mmc.c +49 -40
index 0abece0..88ff217 100644
@@ -737,17 +737,13 @@ static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
  * 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;
        unsigned int pwrclass_val = 0;
-       struct mmc_host *host;
-
-       BUG_ON(!card);
-
-       host = card->host;
-       BUG_ON(!host);
+       struct mmc_host *host = card->host;
+       struct mmc_ext_csd *ext_csd = &card->ext_csd;
 
        /* Power class selection is supported for versions >= 4.0 */
        if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
@@ -759,14 +755,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:
@@ -777,14 +773,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 "
@@ -810,6 +806,37 @@ static int mmc_select_powerclass(struct mmc_card *card,
        return err;
 }
 
+static int mmc_select_powerclass(struct mmc_card *card)
+{
+       int err, ddr;
+       u32 bus_width, ext_csd_bits;
+       struct mmc_host *host = card->host;
+
+       /* 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 = mmc_snoop_ddr(card);
+       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
@@ -1171,11 +1198,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);
        }
 
        /*
@@ -1204,12 +1226,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,
@@ -1234,13 +1250,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],

drivers/mmc/core/mmc.c static int mmc_init_card(struct mmc_host *host, u32 ocr, · line 1290

Quoted 4 lines
drivers/mmc/core/mmc.c +1 -0
@@ -1278,6 +1287,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        }
 
        /*
+        * Choose the power calss with selected bus interface

One line of comment is enough.

"calss" -> "class".

Quoted 11 lines
drivers/mmc/core/mmc.c +4 -1
+        */
+       mmc_select_powerclass(card);
+
+       /*
         * Enable HPI feature (if supported)
         */
        if (card->ext_csd.hpi) {
--

1.7.0.4

You should run checkpatch as well.

Besides these minor things, looks good - nice clean up!

Kind regards
Ulf Hansson

#155 lore raw

RE: [PATCH v2 3/5] mmc: step power class after final selection of bus mode

Quoted 162 lines · Ulf Hansson
Quoted 161 lines · Seungwon Jeon

Power class is changed once only after selection of bus modes including speed and bus-width finishes finally.

---
Changes in v2:
Cleaned up some unnecessary codes.

 drivers/mmc/core/mmc.c |   94 +++++++++++++++++++++++++++--------------------
 1 files changed, 54 insertions(+), 40 deletions(-)
drivers/mmc/core/mmc.c +49 -40
index 0abece0..88ff217 100644
@@ -737,17 +737,13 @@ static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
  * 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;
        unsigned int pwrclass_val = 0;
-       struct mmc_host *host;
-
-       BUG_ON(!card);
-
-       host = card->host;
-       BUG_ON(!host);
+       struct mmc_host *host = card->host;
+       struct mmc_ext_csd *ext_csd = &card->ext_csd;
 
        /* Power class selection is supported for versions >= 4.0 */
        if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
@@ -759,14 +755,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:
@@ -777,14 +773,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 "
@@ -810,6 +806,37 @@ static int mmc_select_powerclass(struct mmc_card *card,
        return err;
 }
 
+static int mmc_select_powerclass(struct mmc_card *card)
+{
+       int err, ddr;
+       u32 bus_width, ext_csd_bits;
+       struct mmc_host *host = card->host;
+
+       /* 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 = mmc_snoop_ddr(card);
+       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
@@ -1171,11 +1198,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);
        }
 
        /*
@@ -1204,12 +1226,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,
@@ -1234,13 +1250,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],
@@ -1278,6 +1287,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        }
 
Quoted 6 lines

drivers/mmc/core/mmc.c static int mmc_init_card(struct mmc_host *host, u32 ocr, · line 1290

Quoted 2 lines
drivers/mmc/core/mmc.c +1 -0
        /*
+        * Choose the power calss with selected bus interface

One line of comment is enough.

"calss" -> "class".

OK.

Quoted 13 lines
Quoted 9 lines
drivers/mmc/core/mmc.c +4 -1
+        */
+       mmc_select_powerclass(card);
+
+       /*
         * Enable HPI feature (if supported)
         */
        if (card->ext_csd.hpi) {
--
Quoted 3 lines

1.7.0.4

Quoted 1 line

You should run checkpatch as well.

It think there was no warning & error in 3/5.
Ok. Let me check more.

Quoted 2 lines

Besides these minor things, looks good - nice clean up!

Thanks,
Seungwon Jeon

Quoted 3 lines

Kind regards
Ulf Hansson

#156 lore raw

Re: [PATCH v2 3/5] mmc: step power class after final selection of bus mode

Quoted 184 lines · Seungwon Jeon
Quoted 162 lines · Ulf Hansson
Quoted 161 lines · Seungwon Jeon

Power class is changed once only after selection of bus modes including speed and bus-width finishes finally.

---
Changes in v2:
Cleaned up some unnecessary codes.

 drivers/mmc/core/mmc.c |   94 +++++++++++++++++++++++++++--------------------
 1 files changed, 54 insertions(+), 40 deletions(-)
drivers/mmc/core/mmc.c +49 -40
index 0abece0..88ff217 100644
@@ -737,17 +737,13 @@ static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
  * 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;
        unsigned int pwrclass_val = 0;
-       struct mmc_host *host;
-
-       BUG_ON(!card);
-
-       host = card->host;
-       BUG_ON(!host);
+       struct mmc_host *host = card->host;
+       struct mmc_ext_csd *ext_csd = &card->ext_csd;
 
        /* Power class selection is supported for versions >= 4.0 */
        if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
@@ -759,14 +755,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:
@@ -777,14 +773,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 "
@@ -810,6 +806,37 @@ static int mmc_select_powerclass(struct mmc_card *card,
        return err;
 }
 
+static int mmc_select_powerclass(struct mmc_card *card)
+{
+       int err, ddr;
+       u32 bus_width, ext_csd_bits;
+       struct mmc_host *host = card->host;
+
+       /* 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 = mmc_snoop_ddr(card);
+       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
@@ -1171,11 +1198,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);
        }
 
        /*
@@ -1204,12 +1226,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,
@@ -1234,13 +1250,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],
@@ -1278,6 +1287,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        }
 
Quoted 6 lines

drivers/mmc/core/mmc.c static int mmc_init_card(struct mmc_host *host, u32 ocr, · line 1290

Quoted 2 lines
drivers/mmc/core/mmc.c +1 -0
        /*
+        * Choose the power calss with selected bus interface

One line of comment is enough.

"calss" -> "class".

OK.

Quoted 13 lines
Quoted 12 lines
drivers/mmc/core/mmc.c +4 -1
+        */
+       mmc_select_powerclass(card);
+
+       /*
         * Enable HPI feature (if supported)
         */
        if (card->ext_csd.hpi) {
--

1.7.0.4

Quoted 4 lines
Quoted 1 line

You should run checkpatch as well.

It think there was no warning & error in 3/5.
Ok. Let me check more.

You are right, this patch didn't have checkpatch warnings or errors, but some of the other in this patchset had. Sorry.

Kind regards
Ulf Hansson

Quoted 9 lines
Quoted 2 lines

Besides these minor things, looks good - nice clean up!

Thanks,
Seungwon Jeon

Quoted 3 lines

Kind regards
Ulf Hansson

#157 lore raw

PATCH v3 3/5 mmc: step power class after final selection of bus mode

In reply to Seungwon Jeon

Power class is changed once only after selection of bus modes including speed and bus-width finishes finally.

---
 drivers/mmc/core/mmc.c |   96 +++++++++++++++++++++++++++--------------------
 1 files changed, 55 insertions(+), 41 deletions(-)
drivers/mmc/core/mmc.c +55 -41
index 97f1912..480c100 100644
@@ -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) {
Signature · 1 line
1.7.0.4
#158 lore raw

PATCH RESEND 4/5 mmc: rework selection of bus speed mode

In reply to Ulf Hansson

Current implementation for bus speed mode selection is too complicated. This patch is to simplify the codes and remove some duplicate parts.

The following changes are including:
* Adds functions for each mode selection(HS, HS-DDR, HS200 and etc)
* Rearranged the mode selection sequence with supported device type
* Adds maximum speed for HS200 mode(hs200_max_dtr)
* Adds field definition for HS_TIMING of EXT_CSD

---
 drivers/mmc/core/debugfs.c |    2 +-
 drivers/mmc/core/mmc.c     |  443 +++++++++++++++++++++++++-------------------
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/mmc.h    |    4 +
 4 files changed, 257 insertions(+), 193 deletions(-)
drivers/mmc/core/debugfs.c +1 -1
index 509229b..1f730db 100644
@@ -139,7 +139,7 @@ static int mmc_ios_show(struct seq_file *s, void *data)
 		str = "mmc DDR52";
 		break;
 	case MMC_TIMING_MMC_HS200:
-		str = "mmc high-speed SDR200";
+		str = "mmc HS200";
 		break;
 	default:
 		str = "invalid";
drivers/mmc/core/mmc.c +251 -192

526 lines not on this page · raw message

include/linux/mmc/card.h +1 -0
index c1ded09..974da1e 100644
@@ -63,6 +63,7 @@ struct mmc_ext_csd {
 	unsigned int            power_off_longtime;     /* Units: ms */
 	u8			power_off_notification;	/* state */
 	unsigned int		hs_max_dtr;
+	unsigned int		hs200_max_dtr;
 #define MMC_HIGH_26_MAX_DTR	26000000
 #define MMC_HIGH_52_MAX_DTR	52000000
 #define MMC_HIGH_DDR_MAX_DTR	52000000
include/linux/mmc/mmc.h +4 -0
index f734c0c..f429f13 100644
@@ -377,6 +377,10 @@ struct _mmc_csd {
 #define EXT_CSD_DDR_BUS_WIDTH_4	5	/* Card is in 4 bit DDR mode */
 #define EXT_CSD_DDR_BUS_WIDTH_8	6	/* Card is in 8 bit DDR mode */
 
+#define EXT_CSD_TIMING_BC	0	/* Backwards compatility */
+#define EXT_CSD_TIMING_HS	1	/* High speed */
+#define EXT_CSD_TIMING_HS200	2	/* HS200 */
+
 #define EXT_CSD_SEC_ER_EN	BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN	BIT(2)
 #define EXT_CSD_SEC_GB_CL_EN	BIT(4)
Signature · 1 line
1.7.0.4
#159 lore raw

PATCH v2 4/5 mmc: rework selection of bus speed mode

Current implementation for bus speed mode selection is too complicated. This patch is to simplify the codes and remove some duplicate parts.

The following changes are including:
* Adds functions for each mode selection(HS, HS-DDR, HS200 and etc)
* Rearranged the mode selection sequence with supported device type
* Adds maximum speed for HS200 mode(hs200_max_dtr)
* Adds field definition for HS_TIMING of EXT_CSD

---
Changes in v2:
Cleaned up some unnecessary codes.

 drivers/mmc/core/debugfs.c |    2 +-
 drivers/mmc/core/mmc.c     |  432 ++++++++++++++++++++++++--------------------
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/mmc.h    |    4 +
 4 files changed, 239 insertions(+), 200 deletions(-)
drivers/mmc/core/debugfs.c +1 -1
index 509229b..1f730db 100644
@@ -139,7 +139,7 @@ static int mmc_ios_show(struct seq_file *s, void *data)
 		str = "mmc DDR52";
 		break;
 	case MMC_TIMING_MMC_HS200:
-		str = "mmc high-speed SDR200";
+		str = "mmc HS200";
 		break;
 	default:
 		str = "invalid";
drivers/mmc/core/mmc.c +233 -199

511 lines not on this page · raw message

include/linux/mmc/card.h +1 -0
index c232b10..def6814 100644
@@ -63,6 +63,7 @@ struct mmc_ext_csd {
 	unsigned int            power_off_longtime;     /* Units: ms */
 	u8			power_off_notification;	/* state */
 	unsigned int		hs_max_dtr;
+	unsigned int		hs200_max_dtr;
 #define MMC_HIGH_26_MAX_DTR	26000000
 #define MMC_HIGH_52_MAX_DTR	52000000
 #define MMC_HIGH_DDR_MAX_DTR	52000000
include/linux/mmc/mmc.h +4 -0
index f734c0c..f429f13 100644
@@ -377,6 +377,10 @@ struct _mmc_csd {
 #define EXT_CSD_DDR_BUS_WIDTH_4	5	/* Card is in 4 bit DDR mode */
 #define EXT_CSD_DDR_BUS_WIDTH_8	6	/* Card is in 8 bit DDR mode */
 
+#define EXT_CSD_TIMING_BC	0	/* Backwards compatility */
+#define EXT_CSD_TIMING_HS	1	/* High speed */
+#define EXT_CSD_TIMING_HS200	2	/* HS200 */
+
 #define EXT_CSD_SEC_ER_EN	BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN	BIT(2)
 #define EXT_CSD_SEC_GB_CL_EN	BIT(4)
Signature · 1 line
1.7.0.4
#160 lore raw

PATCH v3 4/5 mmc: rework selection of bus speed mode

In reply to Seungwon Jeon

Current implementation for bus speed mode selection is too complicated. This patch is to simplify the codes and remove some duplicate parts.

The following changes are including:
* Adds functions for each mode selection(HS, HS-DDR, HS200 and etc)
* Rearranged the mode selection sequence with supported device type
* Adds maximum speed for HS200 mode(hs200_max_dtr)
* Adds field definition for HS_TIMING of EXT_CSD

---
 drivers/mmc/core/debugfs.c |    2 +-
 drivers/mmc/core/mmc.c     |  431 ++++++++++++++++++++++++--------------------
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/mmc.h    |    4 +
 4 files changed, 238 insertions(+), 200 deletions(-)
drivers/mmc/core/debugfs.c +1 -1
index 509229b..1f730db 100644
@@ -139,7 +139,7 @@ static int mmc_ios_show(struct seq_file *s, void *data)
 		str = "mmc DDR52";
 		break;
 	case MMC_TIMING_MMC_HS200:
-		str = "mmc high-speed SDR200";
+		str = "mmc HS200";
 		break;
 	default:
 		str = "invalid";
drivers/mmc/core/mmc.c +232 -199

510 lines not on this page · raw message

include/linux/mmc/card.h +1 -0
index c232b10..def6814 100644
@@ -63,6 +63,7 @@ struct mmc_ext_csd {
 	unsigned int            power_off_longtime;     /* Units: ms */
 	u8			power_off_notification;	/* state */
 	unsigned int		hs_max_dtr;
+	unsigned int		hs200_max_dtr;
 #define MMC_HIGH_26_MAX_DTR	26000000
 #define MMC_HIGH_52_MAX_DTR	52000000
 #define MMC_HIGH_DDR_MAX_DTR	52000000
include/linux/mmc/mmc.h +4 -0
index f734c0c..f429f13 100644
@@ -377,6 +377,10 @@ struct _mmc_csd {
 #define EXT_CSD_DDR_BUS_WIDTH_4	5	/* Card is in 4 bit DDR mode */
 #define EXT_CSD_DDR_BUS_WIDTH_8	6	/* Card is in 8 bit DDR mode */
 
+#define EXT_CSD_TIMING_BC	0	/* Backwards compatility */
+#define EXT_CSD_TIMING_HS	1	/* High speed */
+#define EXT_CSD_TIMING_HS200	2	/* HS200 */
+
 #define EXT_CSD_SEC_ER_EN	BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN	BIT(2)
 #define EXT_CSD_SEC_GB_CL_EN	BIT(4)
Signature · 1 line
1.7.0.4
#161 lore raw

Re: [PATCH v3 4/5] mmc: rework selection of bus speed mode

Quoted 3 lines · Seungwon Jeon

Current implementation for bus speed mode selection is too complicated. This patch is to simplify the codes and remove some duplicate parts.

Really appreciate you taking on this task!

Quoted 66 lines

The following changes are including:
* Adds functions for each mode selection(HS, HS-DDR, HS200 and etc)
* Rearranged the mode selection sequence with supported device type
* Adds maximum speed for HS200 mode(hs200_max_dtr)
* Adds field definition for HS_TIMING of EXT_CSD

---
 drivers/mmc/core/debugfs.c |    2 +-
 drivers/mmc/core/mmc.c     |  431 ++++++++++++++++++++++++--------------------
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/mmc.h    |    4 +
 4 files changed, 238 insertions(+), 200 deletions(-)
drivers/mmc/core/debugfs.c +1 -1
index 509229b..1f730db 100644
@@ -139,7 +139,7 @@ static int mmc_ios_show(struct seq_file *s, void *data)
                str = "mmc DDR52";
                break;
        case MMC_TIMING_MMC_HS200:
-               str = "mmc high-speed SDR200";
+               str = "mmc HS200";
                break;
        default:
                str = "invalid";
drivers/mmc/core/mmc.c +4 -3
index 480c100..6dd68e6 100644
@@ -242,7 +242,7 @@ static void mmc_select_card_type(struct mmc_card *card)
        struct mmc_host *host = card->host;
        u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
        u32 caps = host->caps, caps2 = host->caps2;
-       unsigned int hs_max_dtr = 0;
+       unsigned int hs_max_dtr = 0, hs200_max_dtr = 0;
        unsigned int avail_type = 0;
 
        if (caps & MMC_CAP_MMC_HIGHSPEED &&
@@ -271,17 +271,18 @@ static void mmc_select_card_type(struct mmc_card *card)
 
        if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
            card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
-               hs_max_dtr = MMC_HS200_MAX_DTR;
+               hs200_max_dtr = MMC_HS200_MAX_DTR;
                avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
        }
 
        if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
            card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
-               hs_max_dtr = MMC_HS200_MAX_DTR;
+               hs200_max_dtr = MMC_HS200_MAX_DTR;
                avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
        }
 
        card->ext_csd.hs_max_dtr = hs_max_dtr;
+       card->ext_csd.hs200_max_dtr = hs200_max_dtr;
        card->mmc_avail_type = avail_type;
 }
 
@@ -833,37 +834,46 @@ static int mmc_select_powerclass(struct mmc_card *card)
 }

drivers/mmc/core/mmc.c static int mmc_select_powerclass(struct mmc_card *card) · line 841

Quoted 10 lines
drivers/mmc/core/mmc.c +4 -3
 
 /*
- * Selects the desired buswidth and switch to the HS200 mode
- * if bus width set without error
+ * Set the bus speed for the selected speed mode.
  */
-static int mmc_select_hs200(struct mmc_card *card)
+static void mmc_set_bus_speed(struct mmc_card *card)
+{
+       unsigned int max_dtr = (unsigned int)-1;

I guess this is to silence compile warnings? Why not just:
unsigned int max_dtr = 0;

Quoted 20 lines
drivers/mmc/core/mmc.c +17 -2
+
+       if (mmc_card_hs200(card) && max_dtr > card->ext_csd.hs200_max_dtr)
+               max_dtr = card->ext_csd.hs200_max_dtr;
+       else if (mmc_card_hs(card) && max_dtr > card->ext_csd.hs_max_dtr)
+               max_dtr = card->ext_csd.hs_max_dtr;
+       else if (max_dtr > card->csd.max_dtr)
+               max_dtr = card->csd.max_dtr;
+
+       mmc_set_clock(card->host, max_dtr);
+}
+
+/*
+ * Select the bus width amoung 4-bit and 8-bit(SDR).
+ * If the bus width is changed successfully, return the slected width value.
+ * Zero is returned instead of error value if the wide width is not supported.
+ */
+static int mmc_select_bus_width(struct mmc_card *card)
 {
-       int idx, err = -EINVAL;
-       struct mmc_host *host;

drivers/mmc/core/mmc.c static int mmc_select_powerclass(struct mmc_card *card) · line 867

Quoted 10 lines
drivers/mmc/core/mmc.c +2 -2
        static unsigned ext_csd_bits[] = {
-               EXT_CSD_BUS_WIDTH_4,
                EXT_CSD_BUS_WIDTH_8,
+               EXT_CSD_BUS_WIDTH_4,
        };
        static unsigned bus_widths[] = {
-               MMC_BUS_WIDTH_4,
                MMC_BUS_WIDTH_8,
+               MMC_BUS_WIDTH_4,
        };

Do we really need to keep these arrays? The only contain only two values.

Can't we just try with 8-bit, if supported, and if it fails try with 4-bit. Would that further simplify the code?

Quoted 473 lines
drivers/mmc/core/mmc.c +205 -189
+       struct mmc_host *host = card->host;
+       unsigned idx, bus_width = 0;
+       int err = 0;
 
-       BUG_ON(!card);
-
-       host = card->host;
-
-       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
-               err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
-
-       if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
-               err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
-
-       /* If fails try again during next card power cycle */
-       if (err)
-               goto err;
+       if ((card->csd.mmca_vsn < CSD_SPEC_VER_4) &&
+           !(host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)))
+               return 0;
 
-       idx = (host->caps & MMC_CAP_8_BIT_DATA) ? 1 : 0;
+       idx = (host->caps & MMC_CAP_8_BIT_DATA) ? 0 : 1;
 
        /*
         * Unlike SD, MMC cards dont have a configuration register to notify
@@ -871,8 +881,7 @@ static int mmc_select_hs200(struct mmc_card *card)
         * the supported bus width or compare the ext csd values of current
         * bus width and ext csd values of 1 bit mode read earlier.
         */
-       for (; idx >= 0; idx--) {
-
+       for (; idx < ARRAY_SIZE(bus_widths); idx++) {
                /*
                 * Host is capable of 8bit transfer, then switch
                 * the device to work in 8bit transfer mode. If the
@@ -887,27 +896,202 @@ static int mmc_select_hs200(struct mmc_card *card)
                if (err)
                        continue;
 
-               mmc_set_bus_width(card->host, bus_widths[idx]);
+               bus_width = bus_widths[idx];
+               mmc_set_bus_width(host, bus_width);
 
+               /*
+                * If controller can't handle bus width test,
+                * compare ext_csd previously read in 1 bit mode
+                * against ext_csd at new bus width
+                */
                if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
-                       err = mmc_compare_ext_csds(card, bus_widths[idx]);
+                       err = mmc_compare_ext_csds(card, bus_width);
                else
-                       err = mmc_bus_test(card, bus_widths[idx]);
-               if (!err)
+                       err = mmc_bus_test(card, bus_width);
+
+               if (!err) {
+                       err = bus_width;
                        break;
+               } else {
+                       pr_warn("%s: switch to bus width %d failed\n",
+                               mmc_hostname(host), ext_csd_bits[idx]);
+               }
        }
 
-       /* switch to HS200 mode if bus width set successfully */
+       return err;
+}
+
+/*
+ * Switch to the high-speed mode
+ */
+static int mmc_select_hs(struct mmc_card *card)
+{
+       int err;
+
+       err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                          EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
+                          card->ext_csd.generic_cmd6_time,
+                          true, true, true);
        if (!err)
+               mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+
+       return err;
+}
+
+/*
+ * Activate wide bus and DDR if supported.
+ */
+static int mmc_select_hs_ddr(struct mmc_card *card)
+{
+       struct mmc_host *host = card->host;
+       u32 bus_width, ext_csd_bits;
+       int err = 0;
+
+       if (!(card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52))
+               return 0;
+
+       bus_width = host->ios.bus_width;
+       if (bus_width == MMC_BUS_WIDTH_1)
+               return 0;
+
+       ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
+               EXT_CSD_DDR_BUS_WIDTH_8 : EXT_CSD_DDR_BUS_WIDTH_4;
+
+       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                       EXT_CSD_BUS_WIDTH,
+                       ext_csd_bits,
+                       card->ext_csd.generic_cmd6_time);
+       if (err) {
+               pr_warn("%s: switch to bus width %d ddr failed\n",
+                       mmc_hostname(host), 1 << bus_width);
+               return err;
+       }
+
+       /*
+        * eMMC cards can support 3.3V to 1.2V i/o (vccq)
+        * signaling.
+        *
+        * EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq.
+        *
+        * 1.8V vccq at 3.3V core voltage (vcc) is not required
+        * in the JEDEC spec for DDR.
+        *
+        * Do not force change in vccq since we are obviously
+        * working and no change to vccq is needed.
+        *
+        * WARNING: eMMC rules are NOT the same as SD DDR
+        */
+       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_1_2V) {
+               err = __mmc_set_signal_voltage(host,
+                               MMC_SIGNAL_VOLTAGE_120);
+               if (err)
+                       return err;
+       }
+
+       mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
+
+       return err;
+}
+
+/*
+ * For device supporting HS200 mode, the following sequence
+ * should be done before executing the tuning process.
+ * 1. set the desired bus width(4-bit or 8-bit, 1-bit is not supported)
+ * 2. switch to HS200 mode
+ * 3. set the clock to > 52Mhz and <=200MHz
+ */
+static int mmc_select_hs200(struct mmc_card *card)
+{
+       struct mmc_host *host = card->host;
+       int err = -EINVAL;
+
+       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_2V)
+               err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120);
+
+       if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
+               err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180);
+
+       /* If fails try again during next card power cycle */
+       if (err)
+               goto err;
+
+       /*
+        * Set the bus width(4 or 8) with host's support and
+        * switch to HS200 mode if bus width is set successfully.
+        */
+       err = mmc_select_bus_width(card);
+       if (!IS_ERR_VALUE(err)) {
                err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                               EXT_CSD_HS_TIMING, 2,
-                               card->ext_csd.generic_cmd6_time,
-                               true, true, true);
+                                  EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200,
+                                  card->ext_csd.generic_cmd6_time,
+                                  true, true, true);
+               if (!err)
+                       mmc_set_timing(host, MMC_TIMING_MMC_HS200);
+       }
 err:
        return err;
 }
 
 /*
+ * Activate High Speed or HS200 mode if supported.
+ */
+static int mmc_select_timing(struct mmc_card *card)
+{
+       int err = 0;
+
+       if ((card->csd.mmca_vsn < CSD_SPEC_VER_4 &&
+            card->ext_csd.hs_max_dtr == 0))
+               goto bus_speed;
+
+       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
+               err = mmc_select_hs200(card);
+       else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
+               err = mmc_select_hs(card);
+
+       if (err && err != -EBADMSG)
+               return err;
+
+       if (err) {
+               pr_warn("%s: switch to %s failed\n",
+                       mmc_card_hs(card) ? "high-speed" :
+                       (mmc_card_hs200(card) ? "hs200" : ""),
+                       mmc_hostname(card->host));
+               err = 0;
+       }
+
+bus_speed:
+       /*
+        * Set the bus speed to the selected bus timing.
+        * If timing is not selected, backward compatible is the default.
+        */
+       mmc_set_bus_speed(card);
+       return err;
+}
+
+/*
+ * Execute tuning sequence to seek the proper bus operating
+ * conditions for HS200, which sends CMD21 to the device.
+ */
+static int mmc_hs200_tuning(struct mmc_card *card)
+{
+       struct mmc_host *host = card->host;
+       int err = 0;
+
+       if (host->ops->execute_tuning) {
+               mmc_host_clk_hold(host);
+               err = host->ops->execute_tuning(host,
+                               MMC_SEND_TUNING_BLOCK_HS200);
+               mmc_host_clk_release(host);
+
+               if (err)
+                       pr_warn("%s: tuning execution failed\n",
+                               mmc_hostname(host));
+       }
+
+       return err;
+}
+
+/*
  * Handle the detection and initialisation of a card.
  *
  * In the case of a resume, "oldcard" will contain the card
@@ -917,9 +1101,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        struct mmc_card *oldcard)
 {
        struct mmc_card *card;
-       int err, ddr = 0;
+       int err;
        u32 cid[4];
-       unsigned int max_dtr;
        u32 rocr;
        u8 *ext_csd = NULL;
 
@@ -1111,173 +1294,23 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        }
 
        /*
-        * Activate high speed (if supported)
-        */
-       if (card->ext_csd.hs_max_dtr != 0) {
-               err = 0;
-               if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
-                       err = mmc_select_hs200(card);
-               else if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS)
-                       err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                                       EXT_CSD_HS_TIMING, 1,
-                                       card->ext_csd.generic_cmd6_time,
-                                       true, true, true);
-
-               if (err && err != -EBADMSG)
-                       goto free_card;
-
-               if (err) {
-                       pr_warning("%s: switch to highspeed failed\n",
-                              mmc_hostname(card->host));
-                       err = 0;
-               } else {
-                       if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
-                               mmc_set_timing(card->host,
-                                              MMC_TIMING_MMC_HS200);
-                       else
-                               mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-               }
-       }
-
-       /*
-        * Compute bus speed.
-        */
-       max_dtr = (unsigned int)-1;
-
-       if (mmc_card_hs(card) || mmc_card_hs200(card)) {
-               if (max_dtr > card->ext_csd.hs_max_dtr)
-                       max_dtr = card->ext_csd.hs_max_dtr;
-               if (mmc_card_hs(card) && (max_dtr > 52000000))
-                       max_dtr = 52000000;
-       } else if (max_dtr > card->csd.max_dtr) {
-               max_dtr = card->csd.max_dtr;
-       }
-
-       mmc_set_clock(host, max_dtr);
-
-       /*
-        * Indicate DDR mode (if supported).
+        * Select timing interface
         */
-       if (mmc_card_hs(card))
-               ddr = card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+       err = mmc_select_timing(card);
+       if (err)
+               goto free_card;
 
-       /*
-        * Indicate HS200 SDR mode (if supported).
-        */
        if (mmc_card_hs200(card)) {
-               u32 ext_csd_bits;
-               u32 bus_width = card->host->ios.bus_width;
-
-               /*
-                * For devices supporting HS200 mode, the bus width has
-                * to be set before executing the tuning function. If
-                * set before tuning, then device will respond with CRC
-                * errors for responses on CMD line. So for HS200 the
-                * sequence will be
-                * 1. set bus width 4bit / 8 bit (1 bit not supported)
-                * 2. switch to HS200 mode
-                * 3. set the clock to > 52Mhz <=200MHz and
-                * 4. execute tuning for HS200
-                */
-               if (card->host->ops->execute_tuning) {
-                       mmc_host_clk_hold(card->host);
-                       err = card->host->ops->execute_tuning(card->host,
-                               MMC_SEND_TUNING_BLOCK_HS200);
-                       mmc_host_clk_release(card->host);
-               }
-               if (err) {
-                       pr_warning("%s: tuning execution failed\n",
-                                  mmc_hostname(card->host));
+               err = mmc_hs200_tuning(card);
+               if (err)
                        goto err;
-               }
-
-               ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
-                               EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4;
-       }
-
-       /*
-        * Activate wide bus and DDR (if supported).
-        */
-       if (!mmc_card_hs200(card) &&
-           (card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
-           (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
-               static unsigned ext_csd_bits[][2] = {
-                       { EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
-                       { EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4 },
-                       { EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1 },
-               };
-               static unsigned bus_widths[] = {
-                       MMC_BUS_WIDTH_8,
-                       MMC_BUS_WIDTH_4,
-                       MMC_BUS_WIDTH_1
-               };
-               unsigned idx, bus_width = 0;
-
-               if (host->caps & MMC_CAP_8_BIT_DATA)
-                       idx = 0;
-               else
-                       idx = 1;
-               for (; idx < ARRAY_SIZE(bus_widths); idx++) {
-                       bus_width = bus_widths[idx];
-                       if (bus_width == MMC_BUS_WIDTH_1)
-                               ddr = 0; /* no DDR for 1-bit width */
-
-                       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                                        EXT_CSD_BUS_WIDTH,
-                                        ext_csd_bits[idx][0],
-                                        card->ext_csd.generic_cmd6_time);
-                       if (!err) {
-                               mmc_set_bus_width(card->host, bus_width);
-
-                               /*
-                                * If controller can't handle bus width test,
-                                * compare ext_csd previously read in 1 bit mode
-                                * against ext_csd at new bus width
-                                */
-                               if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
-                                       err = mmc_compare_ext_csds(card,
-                                               bus_width);
-                               else
-                                       err = mmc_bus_test(card, bus_width);
-                               if (!err)
-                                       break;
-                       }
-               }
-
-               if (!err && ddr) {
-                       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                                        EXT_CSD_BUS_WIDTH,
-                                        ext_csd_bits[idx][1],
-                                        card->ext_csd.generic_cmd6_time);
-               }
-               if (err) {
-                       pr_warning("%s: switch to bus width %d ddr %d "
-                               "failed\n", mmc_hostname(card->host),
-                               1 << bus_width, ddr);
-                       goto free_card;
-               } else if (ddr) {
-                       /*
-                        * eMMC cards can support 3.3V to 1.2V i/o (vccq)
-                        * signaling.
-                        *
-                        * EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq.
-                        *
-                        * 1.8V vccq at 3.3V core voltage (vcc) is not required
-                        * in the JEDEC spec for DDR.
-                        *
-                        * Do not force change in vccq since we are obviously
-                        * working and no change to vccq is needed.
-                        *
-                        * WARNING: eMMC rules are NOT the same as SD DDR
-                        */
-                       if (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) {
-                               err = __mmc_set_signal_voltage(host,
-                                       MMC_SIGNAL_VOLTAGE_120);
-                               if (err)
-                                       goto err;
-                       }
-                       mmc_set_timing(card->host, MMC_TIMING_MMC_DDR52);
-                       mmc_set_bus_width(card->host, bus_width);
+       } else if (mmc_card_hs(card)) {
+               /* Select the desired bus width optionally */
+               err = mmc_select_bus_width(card);
+               if (!IS_ERR_VALUE(err)) {
+                       err = mmc_select_hs_ddr(card);
+                       if (err)
+                               goto err;
                }
        }
 
include/linux/mmc/card.h +1 -0
index c232b10..def6814 100644
@@ -63,6 +63,7 @@ struct mmc_ext_csd {
        unsigned int            power_off_longtime;     /* Units: ms */
        u8                      power_off_notification; /* state */
        unsigned int            hs_max_dtr;
+       unsigned int            hs200_max_dtr;
 #define MMC_HIGH_26_MAX_DTR    26000000
 #define MMC_HIGH_52_MAX_DTR    52000000
 #define MMC_HIGH_DDR_MAX_DTR   52000000
include/linux/mmc/mmc.h +4 -1
index f734c0c..f429f13 100644
@@ -377,6 +377,10 @@ struct _mmc_csd {
 #define EXT_CSD_DDR_BUS_WIDTH_4        5       /* Card is in 4 bit DDR mode */
 #define EXT_CSD_DDR_BUS_WIDTH_8        6       /* Card is in 8 bit DDR mode */
 
+#define EXT_CSD_TIMING_BC      0       /* Backwards compatility */
+#define EXT_CSD_TIMING_HS      1       /* High speed */
+#define EXT_CSD_TIMING_HS200   2       /* HS200 */
+
 #define EXT_CSD_SEC_ER_EN      BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN  BIT(2)
 #define EXT_CSD_SEC_GB_CL_EN   BIT(4)
--
Quoted 3 lines

1.7.0.4

Overall looks good to me, besides the minor comments above.

Since this kind of touches quite old code, I would appreciate if it could go though some more testing in linux next, thus it's material for early queueing to 3.16.

But before we go on, I would like to know if you managed to test all the different variants of buswidth/speedmode and the bus width test? If there is any specific test would like to get help to run, just tell me.

Nice work!

Kind regards
Ulf Hansson

#162 lore raw

RE: [PATCH v3 4/5] mmc: rework selection of bus speed mode

Quoted 74 lines · Ulf Hansson
Quoted 3 lines · Seungwon Jeon

Current implementation for bus speed mode selection is too complicated. This patch is to simplify the codes and remove some duplicate parts.

Really appreciate you taking on this task!

Quoted 67 lines

The following changes are including:
* Adds functions for each mode selection(HS, HS-DDR, HS200 and etc)
* Rearranged the mode selection sequence with supported device type
* Adds maximum speed for HS200 mode(hs200_max_dtr)
* Adds field definition for HS_TIMING of EXT_CSD

---
 drivers/mmc/core/debugfs.c |    2 +-
 drivers/mmc/core/mmc.c     |  431 ++++++++++++++++++++++++--------------------
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/mmc.h    |    4 +
 4 files changed, 238 insertions(+), 200 deletions(-)
drivers/mmc/core/debugfs.c +1 -1
index 509229b..1f730db 100644
@@ -139,7 +139,7 @@ static int mmc_ios_show(struct seq_file *s, void *data)
                str = "mmc DDR52";
                break;
        case MMC_TIMING_MMC_HS200:
-               str = "mmc high-speed SDR200";
+               str = "mmc HS200";
                break;
        default:
                str = "invalid";
drivers/mmc/core/mmc.c +4 -3
index 480c100..6dd68e6 100644
@@ -242,7 +242,7 @@ static void mmc_select_card_type(struct mmc_card *card)
        struct mmc_host *host = card->host;
        u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
        u32 caps = host->caps, caps2 = host->caps2;
-       unsigned int hs_max_dtr = 0;
+       unsigned int hs_max_dtr = 0, hs200_max_dtr = 0;
        unsigned int avail_type = 0;
 
        if (caps & MMC_CAP_MMC_HIGHSPEED &&
@@ -271,17 +271,18 @@ static void mmc_select_card_type(struct mmc_card *card)
 
        if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
            card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
-               hs_max_dtr = MMC_HS200_MAX_DTR;
+               hs200_max_dtr = MMC_HS200_MAX_DTR;
                avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
        }
 
        if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
            card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
-               hs_max_dtr = MMC_HS200_MAX_DTR;
+               hs200_max_dtr = MMC_HS200_MAX_DTR;
                avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
        }
 
        card->ext_csd.hs_max_dtr = hs_max_dtr;
+       card->ext_csd.hs200_max_dtr = hs200_max_dtr;
        card->mmc_avail_type = avail_type;
 }
 
@@ -833,37 +834,46 @@ static int mmc_select_powerclass(struct mmc_card *card)
 }
 
Quoted 12 lines

drivers/mmc/core/mmc.c static int mmc_select_powerclass(struct mmc_card *card) · line 841

Quoted 9 lines
drivers/mmc/core/mmc.c +4 -3
 /*
- * Selects the desired buswidth and switch to the HS200 mode
- * if bus width set without error
+ * Set the bus speed for the selected speed mode.
  */
-static int mmc_select_hs200(struct mmc_card *card)
+static void mmc_set_bus_speed(struct mmc_card *card)
+{
+       unsigned int max_dtr = (unsigned int)-1;

I guess this is to silence compile warnings? Why not just:
unsigned int max_dtr = 0;

Basically, I made an effort to keep the previous codes if it's not a problem. If you found something wrong, please let me know.

Quoted 34 lines
Quoted 21 lines
drivers/mmc/core/mmc.c +17 -2
+
+       if (mmc_card_hs200(card) && max_dtr > card->ext_csd.hs200_max_dtr)
+               max_dtr = card->ext_csd.hs200_max_dtr;
+       else if (mmc_card_hs(card) && max_dtr > card->ext_csd.hs_max_dtr)
+               max_dtr = card->ext_csd.hs_max_dtr;
+       else if (max_dtr > card->csd.max_dtr)
+               max_dtr = card->csd.max_dtr;
+
+       mmc_set_clock(card->host, max_dtr);
+}
+
+/*
+ * Select the bus width amoung 4-bit and 8-bit(SDR).
+ * If the bus width is changed successfully, return the slected width value.
+ * Zero is returned instead of error value if the wide width is not supported.
+ */
+static int mmc_select_bus_width(struct mmc_card *card)
 {
-       int idx, err = -EINVAL;
-       struct mmc_host *host;

drivers/mmc/core/mmc.c static int mmc_select_powerclass(struct mmc_card *card) · line 867

Quoted 10 lines
drivers/mmc/core/mmc.c +2 -2
        static unsigned ext_csd_bits[] = {
-               EXT_CSD_BUS_WIDTH_4,
                EXT_CSD_BUS_WIDTH_8,
+               EXT_CSD_BUS_WIDTH_4,
        };
        static unsigned bus_widths[] = {
-               MMC_BUS_WIDTH_4,
                MMC_BUS_WIDTH_8,
+               MMC_BUS_WIDTH_4,
        };

Do we really need to keep these arrays? The only contain only two values.

Quoted 2 lines

Can't we just try with 8-bit, if supported, and if it fails try with 4-bit. Would that further simplify the code?

Yes, current implementation does that.
First, it tries with 8-bit if supported, and if failed, it will be tried with 4-bit. And I think using array can make simple retry coding if considering failure case. I intended to keep original way.

Quoted 7 lines

Overall looks good to me, besides the minor comments above.

Since this kind of touches quite old code, I would appreciate if it could go though some more testing in linux next, thus it's material for early queueing to 3.16.

Quoted 6 lines

But before we go on, I would like to know if you managed to test all the different variants of buswidth/speedmode and the bus width test? If there is any specific test would like to get help to run, just tell me.

Nice work!

It would be nice if it's picked for 3.15.
As I mentioned above, I basically kept the original flow and way.

This change applies only to eMMC type and participates only in card initialization's process. I tested on the following various mode and detection is performed successfully.

- HS400 w/ 8-bit
- HS400 w/ 4-bit : HS200 mode is selected(Because HS400 is possible with 8-bit)
- HS200 w/ 4-bit or 8-bit
- DDR52 w/ 4-bit or 8-bit
- High speed w/ 1-bit, 4-bit or 8-bit
- Backwards w/ 1-bit, 4-bit or 8-bit

I really appreciate your deep reviews.

Thanks,
Seungwon Jeon

author Acked-by
#163 lore raw

Re: [PATCH v3 4/5] mmc: rework selection of bus speed mode

Quoted 87 lines · Seungwon Jeon
Quoted 74 lines · Ulf Hansson
Quoted 3 lines · Seungwon Jeon

Current implementation for bus speed mode selection is too complicated. This patch is to simplify the codes and remove some duplicate parts.

Really appreciate you taking on this task!

Quoted 67 lines

The following changes are including:
* Adds functions for each mode selection(HS, HS-DDR, HS200 and etc)
* Rearranged the mode selection sequence with supported device type
* Adds maximum speed for HS200 mode(hs200_max_dtr)
* Adds field definition for HS_TIMING of EXT_CSD

---
 drivers/mmc/core/debugfs.c |    2 +-
 drivers/mmc/core/mmc.c     |  431 ++++++++++++++++++++++++--------------------
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/mmc.h    |    4 +
 4 files changed, 238 insertions(+), 200 deletions(-)
drivers/mmc/core/debugfs.c +1 -1
index 509229b..1f730db 100644
@@ -139,7 +139,7 @@ static int mmc_ios_show(struct seq_file *s, void *data)
                str = "mmc DDR52";
                break;
        case MMC_TIMING_MMC_HS200:
-               str = "mmc high-speed SDR200";
+               str = "mmc HS200";
                break;
        default:
                str = "invalid";
drivers/mmc/core/mmc.c +4 -3
index 480c100..6dd68e6 100644
@@ -242,7 +242,7 @@ static void mmc_select_card_type(struct mmc_card *card)
        struct mmc_host *host = card->host;
        u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
        u32 caps = host->caps, caps2 = host->caps2;
-       unsigned int hs_max_dtr = 0;
+       unsigned int hs_max_dtr = 0, hs200_max_dtr = 0;
        unsigned int avail_type = 0;
 
        if (caps & MMC_CAP_MMC_HIGHSPEED &&
@@ -271,17 +271,18 @@ static void mmc_select_card_type(struct mmc_card *card)
 
        if (caps2 & MMC_CAP2_HS200_1_8V_SDR &&
            card_type & EXT_CSD_CARD_TYPE_HS200_1_8V) {
-               hs_max_dtr = MMC_HS200_MAX_DTR;
+               hs200_max_dtr = MMC_HS200_MAX_DTR;
                avail_type |= EXT_CSD_CARD_TYPE_HS200_1_8V;
        }
 
        if (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
            card_type & EXT_CSD_CARD_TYPE_HS200_1_2V) {
-               hs_max_dtr = MMC_HS200_MAX_DTR;
+               hs200_max_dtr = MMC_HS200_MAX_DTR;
                avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
        }
 
        card->ext_csd.hs_max_dtr = hs_max_dtr;
+       card->ext_csd.hs200_max_dtr = hs200_max_dtr;
        card->mmc_avail_type = avail_type;
 }
 
@@ -833,37 +834,46 @@ static int mmc_select_powerclass(struct mmc_card *card)
 }
 
Quoted 12 lines

drivers/mmc/core/mmc.c static int mmc_select_powerclass(struct mmc_card *card) · line 841

Quoted 9 lines
drivers/mmc/core/mmc.c +4 -3
 /*
- * Selects the desired buswidth and switch to the HS200 mode
- * if bus width set without error
+ * Set the bus speed for the selected speed mode.
  */
-static int mmc_select_hs200(struct mmc_card *card)
+static void mmc_set_bus_speed(struct mmc_card *card)
+{
+       unsigned int max_dtr = (unsigned int)-1;

I guess this is to silence compile warnings? Why not just:
unsigned int max_dtr = 0;

Quoted 2 lines

Basically, I made an effort to keep the previous codes if it's not a problem. If you found something wrong, please let me know.

Got it, let's keep it as is then!

Quoted 35 lines
Quoted 35 lines
Quoted 22 lines
drivers/mmc/core/mmc.c +17 -2
+
+       if (mmc_card_hs200(card) && max_dtr > card->ext_csd.hs200_max_dtr)
+               max_dtr = card->ext_csd.hs200_max_dtr;
+       else if (mmc_card_hs(card) && max_dtr > card->ext_csd.hs_max_dtr)
+               max_dtr = card->ext_csd.hs_max_dtr;
+       else if (max_dtr > card->csd.max_dtr)
+               max_dtr = card->csd.max_dtr;
+
+       mmc_set_clock(card->host, max_dtr);
+}
+
+/*
+ * Select the bus width amoung 4-bit and 8-bit(SDR).
+ * If the bus width is changed successfully, return the slected width value.
+ * Zero is returned instead of error value if the wide width is not supported.
+ */
+static int mmc_select_bus_width(struct mmc_card *card)
 {
-       int idx, err = -EINVAL;
-       struct mmc_host *host;

drivers/mmc/core/mmc.c static int mmc_select_powerclass(struct mmc_card *card) · line 867

Quoted 10 lines
drivers/mmc/core/mmc.c +2 -2
        static unsigned ext_csd_bits[] = {
-               EXT_CSD_BUS_WIDTH_4,
                EXT_CSD_BUS_WIDTH_8,
+               EXT_CSD_BUS_WIDTH_4,
        };
        static unsigned bus_widths[] = {
-               MMC_BUS_WIDTH_4,
                MMC_BUS_WIDTH_8,
+               MMC_BUS_WIDTH_4,
        };

Do we really need to keep these arrays? The only contain only two values.

Quoted 6 lines
Quoted 2 lines

Can't we just try with 8-bit, if supported, and if it fails try with 4-bit. Would that further simplify the code?

Yes, current implementation does that.
First, it tries with 8-bit if supported, and if failed, it will be tried with 4-bit. And I think using array can make simple retry coding if considering failure case. I intended to keep original way.

I understand you want to make as small changes as possible, that's good. So let's keep this as is then.

If we want to change this, we can do that in a follow up patch instead.

Quoted 8 lines
Quoted 8 lines

Overall looks good to me, besides the minor comments above.

Since this kind of touches quite old code, I would appreciate if it could go though some more testing in linux next, thus it's material for early queueing to 3.16.

Quoted 8 lines
Quoted 6 lines

But before we go on, I would like to know if you managed to test all the different variants of buswidth/speedmode and the bus width test? If there is any specific test would like to get help to run, just tell me.

Nice work!

It would be nice if it's picked for 3.15.
As I mentioned above, I basically kept the original flow and way.

I leave the decision to Chris. Still I think some more testing in linux-next would be nice.

Quoted 16 lines

This change applies only to eMMC type and participates only in card initialization's process. I tested on the following various mode and detection is performed successfully.

- HS400 w/ 8-bit
- HS400 w/ 4-bit : HS200 mode is selected(Because HS400 is possible with 8-bit)
- HS200 w/ 4-bit or 8-bit
- DDR52 w/ 4-bit or 8-bit
- High speed w/ 1-bit, 4-bit or 8-bit
- Backwards w/ 1-bit, 4-bit or 8-bit

I really appreciate your deep reviews.

Thanks,
Seungwon Jeon

#164 lore raw

PATCH RESEND 5/5 mmc: add support for HS400 mode of eMMC5.0

In reply to Ulf Hansson

This patch adds HS400 mode support for eMMC5.0 device. HS400 mode is high speed DDR interface timing from HS200. Clock frequency is up to 200MHz and only 8-bit bus width is supported. In addition, tuning process of HS200 is required to synchronize the command response on the CMD line because CMD input timing for HS400 mode is the same as HS200 mode.

---
 drivers/mmc/core/bus.c     |    1 +
 drivers/mmc/core/debugfs.c |    3 +
 drivers/mmc/core/mmc.c     |  126 +++++++++++++++++++++++++++++++++++++++++---
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/host.h   |   15 +++++-
 include/linux/mmc/mmc.h    |    7 ++-
 6 files changed, 144 insertions(+), 9 deletions(-)
drivers/mmc/core/bus.c +1 -0
index e8a21fb..d28ecf1 100644
@@ -358,6 +358,7 @@ int mmc_add_card(struct mmc_card *card)
 			mmc_hostname(card->host),
 			mmc_card_uhs(card) ? "ultra high speed " :
 			(mmc_card_hs(card) ? "high speed " : ""),
+			mmc_card_hs400(card) ? "HS400 " :
 			(mmc_card_hs200(card) ? "HS200 " : ""),
 			mmc_card_ddr52(card) ? "DDR " : "",
 			uhs_bus_speed_mode, type, card->rca);
drivers/mmc/core/debugfs.c +3 -0
index 1f730db..91eb162 100644
@@ -141,6 +141,9 @@ static int mmc_ios_show(struct seq_file *s, void *data)
 	case MMC_TIMING_MMC_HS200:
 		str = "mmc HS200";
 		break;
+	case MMC_TIMING_MMC_HS400:
+		str = "mmc HS400";
+		break;
 	default:
 		str = "invalid";
 		break;
drivers/mmc/core/mmc.c +119 -7

198 lines not on this page · raw message

include/linux/mmc/card.h +1 -0
index 974da1e..30a81dc 100644
@@ -110,6 +110,7 @@ struct mmc_ext_csd {
 	u8			raw_pwr_cl_200_360;	/* 237 */
 	u8			raw_pwr_cl_ddr_52_195;	/* 238 */
 	u8			raw_pwr_cl_ddr_52_360;	/* 239 */
+	u8			raw_pwr_cl_ddr_200_360;	/* 253 */
 	u8			raw_bkops_status;	/* 246 */
 	u8			raw_sectors[4];		/* 212 - 4 bytes */
 
include/linux/mmc/host.h +14 -1
index 66e632c..7c0e277 100644
@@ -61,6 +61,8 @@ struct mmc_ios {
 #define MMC_TIMING_UHS_DDR50	7
 #define MMC_TIMING_MMC_DDR52	8
 #define MMC_TIMING_MMC_HS200	9
+#define MMC_TIMING_MMC_HS400	10
+#define MMC_TIMING_MMC_HS400_TUNING 11
 
 	unsigned char	signal_voltage;		/* signalling voltage (1.8V or 3.3V) */
 
@@ -278,6 +280,10 @@ struct mmc_host {
 				 MMC_CAP2_PACKED_WR)
 #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)	/* Don't power up before scan */
 #define MMC_CAP2_SANITIZE	(1 << 15)		/* Support Sanitize */
+#define MMC_CAP2_HS400_1_8V	(1 << 16)	/* Can support HS400 1.8V */
+#define MMC_CAP2_HS400_1_2V	(1 << 17)	/* Can support HS400 1.2V */
+#define MMC_CAP2_HS400		(MMC_CAP2_HS400_1_8V | \
+				 MMC_CAP2_HS400_1_2V)
 
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
 
@@ -495,11 +501,18 @@ static inline int mmc_card_uhs(struct mmc_card *card)
 
 static inline bool mmc_card_hs200(struct mmc_card *card)
 {
-	return card->ios->timing == MMC_TIMING_MMC_HS200;
+	return card->ios->timing == MMC_TIMING_MMC_HS200 ||
+		card->ios->timing == MMC_TIMING_MMC_HS400_TUNING;
 }
 
 static inline bool mmc_card_ddr52(struct mmc_card *card)
 {
 	return card->ios->timing == MMC_TIMING_MMC_DDR52;
 }
+
+static inline bool mmc_card_hs400(struct mmc_card *card)
+{
+	return card->ios->timing == MMC_TIMING_MMC_HS400;
+}
+
 #endif /* LINUX_MMC_HOST_H */
include/linux/mmc/mmc.h +6 -1
index f429f13..64ec963 100644
@@ -325,6 +325,7 @@ struct _mmc_csd {
 #define EXT_CSD_POWER_OFF_LONG_TIME	247	/* RO */
 #define EXT_CSD_GENERIC_CMD6_TIME	248	/* RO */
 #define EXT_CSD_CACHE_SIZE		249	/* RO, 4 bytes */
+#define EXT_CSD_PWR_CL_DDR_200_360	253	/* RO */
 #define EXT_CSD_TAG_UNIT_SIZE		498	/* RO */
 #define EXT_CSD_DATA_TAG_SUPPORT	499	/* RO */
 #define EXT_CSD_MAX_PACKED_WRITES	500	/* RO */
@@ -354,7 +355,6 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-#define EXT_CSD_CARD_TYPE_MASK	0x3F	/* Mask out reserved bits */
 #define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
 #define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
@@ -370,6 +370,10 @@ struct _mmc_csd {
 						/* SDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
 					 EXT_CSD_CARD_TYPE_HS200_1_2V)
+#define EXT_CSD_CARD_TYPE_HS400_1_8V	(1<<6)	/* Card can run at 200MHz DDR, 1.8V */
+#define EXT_CSD_CARD_TYPE_HS400_1_2V	(1<<7)	/* Card can run at 200MHz DDR, 1.2V */
+#define EXT_CSD_CARD_TYPE_HS400		(EXT_CSD_CARD_TYPE_HS400_1_8V | \
+					 EXT_CSD_CARD_TYPE_HS400_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
@@ -380,6 +384,7 @@ struct _mmc_csd {
 #define EXT_CSD_TIMING_BC	0	/* Backwards compatility */
 #define EXT_CSD_TIMING_HS	1	/* High speed */
 #define EXT_CSD_TIMING_HS200	2	/* HS200 */
+#define EXT_CSD_TIMING_HS400	3	/* HS400 */
 
 #define EXT_CSD_SEC_ER_EN	BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN	BIT(2)
Signature · 1 line
1.7.0.4
#165 lore raw

PATCH v2 5/5 mmc: add support for HS400 mode of eMMC5.0

This patch adds HS400 mode support for eMMC5.0 device. HS400 mode is high speed DDR interface timing from HS200. Clock frequency is up to 200MHz and only 8-bit bus width is supported. In addition, tuning process of HS200 is required to synchronize the command response on the CMD line because CMD input timing for HS400 mode is the same as HS200 mode.

---
Changes in v2:
Cleaned up some unnecessary codes.

 drivers/mmc/core/bus.c     |    1 +
 drivers/mmc/core/debugfs.c |    3 +
 drivers/mmc/core/mmc.c     |  120 +++++++++++++++++++++++++++++++++++++++++---
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/host.h   |   15 +++++-
 include/linux/mmc/mmc.h    |    7 ++-
 6 files changed, 138 insertions(+), 9 deletions(-)
drivers/mmc/core/bus.c +1 -0
index f37e9d6..d2dbf02 100644
@@ -349,6 +349,7 @@ int mmc_add_card(struct mmc_card *card)
 			mmc_hostname(card->host),
 			mmc_card_uhs(card) ? "ultra high speed " :
 			(mmc_card_hs(card) ? "high speed " : ""),
+			mmc_card_hs400(card) ? "HS400 " :
 			(mmc_card_hs200(card) ? "HS200 " : ""),
 			mmc_card_ddr52(card) ? "DDR " : "",
 			uhs_bus_speed_mode, type, card->rca);
drivers/mmc/core/debugfs.c +3 -0
index 1f730db..91eb162 100644
@@ -141,6 +141,9 @@ static int mmc_ios_show(struct seq_file *s, void *data)
 	case MMC_TIMING_MMC_HS200:
 		str = "mmc HS200";
 		break;
+	case MMC_TIMING_MMC_HS400:
+		str = "mmc HS400";
+		break;
 	default:
 		str = "invalid";
 		break;
drivers/mmc/core/mmc.c +113 -7

192 lines not on this page · raw message

include/linux/mmc/card.h +1 -0
index def6814..2b24c36 100644
@@ -110,6 +110,7 @@ struct mmc_ext_csd {
 	u8			raw_pwr_cl_200_360;	/* 237 */
 	u8			raw_pwr_cl_ddr_52_195;	/* 238 */
 	u8			raw_pwr_cl_ddr_52_360;	/* 239 */
+	u8			raw_pwr_cl_ddr_200_360;	/* 253 */
 	u8			raw_bkops_status;	/* 246 */
 	u8			raw_sectors[4];		/* 212 - 4 bytes */
 
include/linux/mmc/host.h +14 -1
index 1ee3c10..cc716e4 100644
@@ -61,6 +61,8 @@ struct mmc_ios {
 #define MMC_TIMING_UHS_DDR50	7
 #define MMC_TIMING_MMC_DDR52	8
 #define MMC_TIMING_MMC_HS200	9
+#define MMC_TIMING_MMC_HS400	10
+#define MMC_TIMING_MMC_HS400_TUNING 11
 
 	unsigned char	signal_voltage;		/* signalling voltage (1.8V or 3.3V) */
 
@@ -274,6 +276,10 @@ struct mmc_host {
 #define MMC_CAP2_PACKED_CMD	(MMC_CAP2_PACKED_RD | \
 				 MMC_CAP2_PACKED_WR)
 #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)	/* Don't power up before scan */
+#define MMC_CAP2_HS400_1_8V	(1 << 15)	/* Can support HS400 1.8V */
+#define MMC_CAP2_HS400_1_2V	(1 << 16)	/* Can support HS400 1.2V */
+#define MMC_CAP2_HS400		(MMC_CAP2_HS400_1_8V | \
+				 MMC_CAP2_HS400_1_2V)
 
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
 
@@ -486,11 +492,18 @@ static inline int mmc_card_uhs(struct mmc_card *card)
 
 static inline bool mmc_card_hs200(struct mmc_card *card)
 {
-	return card->host->ios.timing == MMC_TIMING_MMC_HS200;
+	return card->host->ios.timing == MMC_TIMING_MMC_HS200 ||
+		card->host->ios.timing == MMC_TIMING_MMC_HS400_TUNING;
 }
 
 static inline bool mmc_card_ddr52(struct mmc_card *card)
 {
 	return card->host->ios.timing == MMC_TIMING_MMC_DDR52;
 }
+
+static inline bool mmc_card_hs400(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_MMC_HS400;
+}
+
 #endif /* LINUX_MMC_HOST_H */
include/linux/mmc/mmc.h +6 -1
index f429f13..64ec963 100644
@@ -325,6 +325,7 @@ struct _mmc_csd {
 #define EXT_CSD_POWER_OFF_LONG_TIME	247	/* RO */
 #define EXT_CSD_GENERIC_CMD6_TIME	248	/* RO */
 #define EXT_CSD_CACHE_SIZE		249	/* RO, 4 bytes */
+#define EXT_CSD_PWR_CL_DDR_200_360	253	/* RO */
 #define EXT_CSD_TAG_UNIT_SIZE		498	/* RO */
 #define EXT_CSD_DATA_TAG_SUPPORT	499	/* RO */
 #define EXT_CSD_MAX_PACKED_WRITES	500	/* RO */
@@ -354,7 +355,6 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-#define EXT_CSD_CARD_TYPE_MASK	0x3F	/* Mask out reserved bits */
 #define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
 #define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
@@ -370,6 +370,10 @@ struct _mmc_csd {
 						/* SDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
 					 EXT_CSD_CARD_TYPE_HS200_1_2V)
+#define EXT_CSD_CARD_TYPE_HS400_1_8V	(1<<6)	/* Card can run at 200MHz DDR, 1.8V */
+#define EXT_CSD_CARD_TYPE_HS400_1_2V	(1<<7)	/* Card can run at 200MHz DDR, 1.2V */
+#define EXT_CSD_CARD_TYPE_HS400		(EXT_CSD_CARD_TYPE_HS400_1_8V | \
+					 EXT_CSD_CARD_TYPE_HS400_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
@@ -380,6 +384,7 @@ struct _mmc_csd {
 #define EXT_CSD_TIMING_BC	0	/* Backwards compatility */
 #define EXT_CSD_TIMING_HS	1	/* High speed */
 #define EXT_CSD_TIMING_HS200	2	/* HS200 */
+#define EXT_CSD_TIMING_HS400	3	/* HS400 */
 
 #define EXT_CSD_SEC_ER_EN	BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN	BIT(2)
Signature · 1 line
1.7.0.4
#166 lore raw

Re: [PATCH v2 5/5] mmc: add support for HS400 mode of eMMC5.0

Thanks,
Jackey

Quoted 358 lines · Seungwon Jeon

This patch adds HS400 mode support for eMMC5.0 device. HS400 mode is high speed DDR interface timing from HS200. Clock frequency is up to 200MHz and only 8-bit bus width is supported. In addition, tuning process of HS200 is required to synchronize the command response on the CMD line because CMD input timing for HS400 mode is the same as HS200 mode.

---
Changes in v2:
Cleaned up some unnecessary codes.

 drivers/mmc/core/bus.c     |    1 +
 drivers/mmc/core/debugfs.c |    3 +
 drivers/mmc/core/mmc.c     |  120 +++++++++++++++++++++++++++++++++++++++++---
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/host.h   |   15 +++++-
 include/linux/mmc/mmc.h    |    7 ++-
 6 files changed, 138 insertions(+), 9 deletions(-)
drivers/mmc/core/bus.c +1 -0
index f37e9d6..d2dbf02 100644
@@ -349,6 +349,7 @@ int mmc_add_card(struct mmc_card *card)
 			mmc_hostname(card->host),
 			mmc_card_uhs(card) ? "ultra high speed " :
 			(mmc_card_hs(card) ? "high speed " : ""),
+			mmc_card_hs400(card) ? "HS400 " :
 			(mmc_card_hs200(card) ? "HS200 " : ""),
 			mmc_card_ddr52(card) ? "DDR " : "",
 			uhs_bus_speed_mode, type, card->rca);
drivers/mmc/core/debugfs.c +3 -0
index 1f730db..91eb162 100644
@@ -141,6 +141,9 @@ static int mmc_ios_show(struct seq_file *s, void *data)
 	case MMC_TIMING_MMC_HS200:
 		str = "mmc HS200";
 		break;
+	case MMC_TIMING_MMC_HS400:
+		str = "mmc HS400";
+		break;
 	default:
 		str = "invalid";
 		break;
drivers/mmc/core/mmc.c +113 -7
index e356a54..998b0af 100644
@@ -240,7 +240,7 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
 static void mmc_select_card_type(struct mmc_card *card)
 {
 	struct mmc_host *host = card->host;
-	u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
+	u8 card_type = card->ext_csd.raw_card_type;
 	u32 caps = host->caps, caps2 = host->caps2;
 	unsigned int hs_max_dtr = 0, hs200_max_dtr = 0;
 	unsigned int avail_type = 0;
@@ -281,6 +281,18 @@ static void mmc_select_card_type(struct mmc_card *card)
 		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
 	}
 
+	if (caps2 & MMC_CAP2_HS400_1_8V &&
+	    card_type & EXT_CSD_CARD_TYPE_HS400_1_8V) {
+		hs200_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS400_1_8V;
+	}
+
+	if (caps2 & MMC_CAP2_HS400_1_2V &&
+	    card_type & EXT_CSD_CARD_TYPE_HS400_1_2V) {
+		hs200_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS400_1_2V;
+	}
+
 	card->ext_csd.hs_max_dtr = hs_max_dtr;
 	card->ext_csd.hs200_max_dtr = hs200_max_dtr;
 	card->mmc_avail_type = avail_type;
@@ -499,6 +511,8 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
 			ext_csd[EXT_CSD_PWR_CL_DDR_52_195];
 		card->ext_csd.raw_pwr_cl_ddr_52_360 =
 			ext_csd[EXT_CSD_PWR_CL_DDR_52_360];
+		card->ext_csd.raw_pwr_cl_ddr_200_360 =
+			ext_csd[EXT_CSD_PWR_CL_DDR_200_360];
 	}
 
 	if (card->ext_csd.rev >= 5) {
@@ -665,7 +679,10 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
 		(card->ext_csd.raw_pwr_cl_ddr_52_195 ==
 			bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_195]) &&
 		(card->ext_csd.raw_pwr_cl_ddr_52_360 ==
-			bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360]));
+			bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360]) &&
+		(card->ext_csd.raw_pwr_cl_ddr_200_360 ==
+			bw_ext_csd[EXT_CSD_PWR_CL_DDR_200_360]));
+
 	if (err)
 		err = -EINVAL;
 
@@ -729,7 +746,8 @@ static struct device_type mmc_type = {
 
 static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
 {
-	return card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+	return card->mmc_avail_type &
+		(EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_HS400);
 }
 
 /*
@@ -781,7 +799,9 @@ static int __mmc_select_powerclass(struct mmc_card *card,
 				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;
+			pwrclass_val = (bus_width == EXT_CSD_DDR_BUS_WIDTH_8) ?
+				ext_csd->raw_pwr_cl_ddr_200_360 :
+				ext_csd->raw_pwr_cl_200_360;
 		break;
 	default:
 		pr_warning("%s: Voltage range not supported "
@@ -845,7 +865,8 @@ static void mmc_set_bus_speed(struct mmc_card *card)
 {
 	unsigned int max_dtr = (unsigned int)-1;
 
-	if (mmc_card_hs200(card) && max_dtr > card->ext_csd.hs200_max_dtr)
+	if ((mmc_card_hs200(card) || mmc_card_hs400(card)) &&
+	     max_dtr > card->ext_csd.hs200_max_dtr)
 		max_dtr = card->ext_csd.hs200_max_dtr;
 	else if (mmc_card_hs(card) && max_dtr > card->ext_csd.hs_max_dtr)
 		max_dtr = card->ext_csd.hs_max_dtr;
@@ -944,6 +965,28 @@ static int mmc_select_hs(struct mmc_card *card)
 }
 
 /*
+ * Revert to the high-speed mode from above speed
+ */
+static int mmc_revert_to_hs(struct mmc_card *card)
+{
+	/*
+	 * CMD13, which is used to confirm the completion of timing
+	 * change, will be issued at higher speed timing condtion
+	 * rather than high-speed. If device has completed the change
+	 * to high-speed mode, it may not be proper timing to issue
+	 * command. Low speed supplies better timing margin than high
+	 * speed. Accordingly clock rate & timging should be chagned
+	 * ahead before actual switch.
+	 */
+	mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+	mmc_set_bus_speed(card);
+
+	return mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+			  EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
+			  card->ext_csd.generic_cmd6_time);
+}
+
+/*
  * Activate wide bus and DDR if supported.
  */
 static int mmc_select_hs_ddr(struct mmc_card *card)
@@ -999,6 +1042,56 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
 	return err;
 }
 
+static int mmc_select_hs400(struct mmc_card *card)
+{
+	struct mmc_host *host = card->host;
+	int err = 0, ddr;
+
+	ddr = mmc_snoop_ddr(card);
+
+	/*
+	 * The bus width is set to only 8 DDR in HS400 mode
+	 */
+	if (!(ddr & EXT_CSD_CARD_TYPE_HS400 &&
+	      host->ios.bus_width == MMC_BUS_WIDTH_8))
+		return 0;
+
+	/*
+	 * Before setting BUS_WIDTH for dual data rate operation,
+	 * HS_TIMING must be set to High Speed(0x1)
+	 */
+	err = mmc_revert_to_hs(card);
+	if (err) {
+		pr_warn("%s: switch to high-speed from hs200 failed, err:%d\n",
+			mmc_hostname(host), err);
+		return err;
+	}
+
+	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+			 EXT_CSD_BUS_WIDTH,
+			 EXT_CSD_DDR_BUS_WIDTH_8,
+			 card->ext_csd.generic_cmd6_time);
+	if (err) {
+		pr_warn("%s: switch to bus width for hs400 failed, err:%d\n",
+			mmc_hostname(host), err);
+		return err;
+	}
+
+	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+			 EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400,
+			 card->ext_csd.generic_cmd6_time);
+	if (err) {
+		pr_warn("%s: switch to hs400 failed, err:%d\n",
+			 mmc_hostname(host), err);
+		return err;
+	}
+
+	mmc_set_timing(host, MMC_TIMING_MMC_HS400);
+	mmc_set_bus_speed(card);
+
+	return 0;
+}
+
 /*
  * For device supporting HS200 mode, the following sequence
  * should be done before executing the tuning process.
@@ -1031,7 +1124,16 @@ static int mmc_select_hs200(struct mmc_card *card)
 				   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200,
 				   card->ext_csd.generic_cmd6_time,
 				   true, true, true);
-		if (!err)
+		if (err)
+			goto err;
+
+		if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400)
+			/*
+			 * Timing should be adjusted to the HS400 target
+			 * operation frequency for tuning process
+			 */
+			mmc_set_timing(host, MMC_TIMING_MMC_HS400_TUNING);
+		else
 			mmc_set_timing(host, MMC_TIMING_MMC_HS200);
 	}
 err:
@@ -1076,7 +1178,7 @@ bus_speed:
 
 /*
  * Execute tuning sequence to seek the proper bus operating
- * conditions for HS200, which sends CMD21 to the device.
+ * conditions for HS200 and HS400, which sends CMD21 to the device.
  */
 static int mmc_hs200_tuning(struct mmc_card *card)
 {
@@ -1310,6 +1412,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		err = mmc_hs200_tuning(card);
 		if (err)
 			goto err;
+
+		err = mmc_select_hs400(card);
+		if (err)
+			goto err;
 	} else if (mmc_card_hs(card)) {
 		/* Select the desired bus width optionally */
 		err = mmc_select_bus_width(card);
include/linux/mmc/card.h +1 -0
index def6814..2b24c36 100644
@@ -110,6 +110,7 @@ struct mmc_ext_csd {
 	u8			raw_pwr_cl_200_360;	/* 237 */
 	u8			raw_pwr_cl_ddr_52_195;	/* 238 */
 	u8			raw_pwr_cl_ddr_52_360;	/* 239 */
+	u8			raw_pwr_cl_ddr_200_360;	/* 253 */
 	u8			raw_bkops_status;	/* 246 */
 	u8			raw_sectors[4];		/* 212 - 4 bytes */
 
include/linux/mmc/host.h +14 -1
index 1ee3c10..cc716e4 100644
@@ -61,6 +61,8 @@ struct mmc_ios {
 #define MMC_TIMING_UHS_DDR50	7
 #define MMC_TIMING_MMC_DDR52	8
 #define MMC_TIMING_MMC_HS200	9
+#define MMC_TIMING_MMC_HS400	10
+#define MMC_TIMING_MMC_HS400_TUNING 11
 
 	unsigned char	signal_voltage;		/* signalling voltage (1.8V or 3.3V) */
 
@@ -274,6 +276,10 @@ struct mmc_host {
 #define MMC_CAP2_PACKED_CMD	(MMC_CAP2_PACKED_RD | \
 				 MMC_CAP2_PACKED_WR)
 #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)	/* Don't power up before scan */
+#define MMC_CAP2_HS400_1_8V	(1 << 15)	/* Can support HS400 1.8V */
+#define MMC_CAP2_HS400_1_2V	(1 << 16)	/* Can support HS400 1.2V */
+#define MMC_CAP2_HS400		(MMC_CAP2_HS400_1_8V | \
+				 MMC_CAP2_HS400_1_2V)
 
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
 
@@ -486,11 +492,18 @@ static inline int mmc_card_uhs(struct mmc_card *card)
 
 static inline bool mmc_card_hs200(struct mmc_card *card)
 {
-	return card->host->ios.timing == MMC_TIMING_MMC_HS200;
+	return card->host->ios.timing == MMC_TIMING_MMC_HS200 ||
+		card->host->ios.timing == MMC_TIMING_MMC_HS400_TUNING;
 }
 
 static inline bool mmc_card_ddr52(struct mmc_card *card)
 {
 	return card->host->ios.timing == MMC_TIMING_MMC_DDR52;
 }
+
+static inline bool mmc_card_hs400(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_MMC_HS400;
+}
+
 #endif /* LINUX_MMC_HOST_H */
include/linux/mmc/mmc.h +6 -1
index f429f13..64ec963 100644
@@ -325,6 +325,7 @@ struct _mmc_csd {
 #define EXT_CSD_POWER_OFF_LONG_TIME	247	/* RO */
 #define EXT_CSD_GENERIC_CMD6_TIME	248	/* RO */
 #define EXT_CSD_CACHE_SIZE		249	/* RO, 4 bytes */
+#define EXT_CSD_PWR_CL_DDR_200_360	253	/* RO */
 #define EXT_CSD_TAG_UNIT_SIZE		498	/* RO */
 #define EXT_CSD_DATA_TAG_SUPPORT	499	/* RO */
 #define EXT_CSD_MAX_PACKED_WRITES	500	/* RO */
@@ -354,7 +355,6 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-#define EXT_CSD_CARD_TYPE_MASK	0x3F	/* Mask out reserved bits */
 #define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
 #define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
@@ -370,6 +370,10 @@ struct _mmc_csd {
 						/* SDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
 					 EXT_CSD_CARD_TYPE_HS200_1_2V)
+#define EXT_CSD_CARD_TYPE_HS400_1_8V	(1<<6)	/* Card can run at 200MHz DDR, 1.8V */
+#define EXT_CSD_CARD_TYPE_HS400_1_2V	(1<<7)	/* Card can run at 200MHz DDR, 1.2V */
+#define EXT_CSD_CARD_TYPE_HS400		(EXT_CSD_CARD_TYPE_HS400_1_8V | \
+					 EXT_CSD_CARD_TYPE_HS400_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
@@ -380,6 +384,7 @@ struct _mmc_csd {
 #define EXT_CSD_TIMING_BC	0	/* Backwards compatility */
 #define EXT_CSD_TIMING_HS	1	/* High speed */
 #define EXT_CSD_TIMING_HS200	2	/* HS200 */
+#define EXT_CSD_TIMING_HS400	3	/* HS400 */
 
 #define EXT_CSD_SEC_ER_EN	BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN	BIT(2)
Signature · 7 lines
1.7.0.4


--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#167 lore raw

RE: [PATCH v2 5/5] mmc: add support for HS400 mode of eMMC5.0

Quoted 1 line · Jackey Shen

I'll send next version with adding your Reviewed-by.

Thanks,
Seungwon Jeon

Quoted 368 lines

Thanks,
Jackey

Quoted 353 lines · Seungwon Jeon

This patch adds HS400 mode support for eMMC5.0 device. HS400 mode is high speed DDR interface timing from HS200. Clock frequency is up to 200MHz and only 8-bit bus width is supported. In addition, tuning process of HS200 is required to synchronize the command response on the CMD line because CMD input timing for HS400 mode is the same as HS200 mode.

---
Changes in v2:
Cleaned up some unnecessary codes.

 drivers/mmc/core/bus.c     |    1 +
 drivers/mmc/core/debugfs.c |    3 +
 drivers/mmc/core/mmc.c     |  120 +++++++++++++++++++++++++++++++++++++++++---
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/host.h   |   15 +++++-
 include/linux/mmc/mmc.h    |    7 ++-
 6 files changed, 138 insertions(+), 9 deletions(-)
drivers/mmc/core/bus.c +1 -0
index f37e9d6..d2dbf02 100644
@@ -349,6 +349,7 @@ int mmc_add_card(struct mmc_card *card)
 			mmc_hostname(card->host),
 			mmc_card_uhs(card) ? "ultra high speed " :
 			(mmc_card_hs(card) ? "high speed " : ""),
+			mmc_card_hs400(card) ? "HS400 " :
 			(mmc_card_hs200(card) ? "HS200 " : ""),
 			mmc_card_ddr52(card) ? "DDR " : "",
 			uhs_bus_speed_mode, type, card->rca);
drivers/mmc/core/debugfs.c +3 -0
index 1f730db..91eb162 100644
@@ -141,6 +141,9 @@ static int mmc_ios_show(struct seq_file *s, void *data)
 	case MMC_TIMING_MMC_HS200:
 		str = "mmc HS200";
 		break;
+	case MMC_TIMING_MMC_HS400:
+		str = "mmc HS400";
+		break;
 	default:
 		str = "invalid";
 		break;
drivers/mmc/core/mmc.c +113 -7
index e356a54..998b0af 100644
@@ -240,7 +240,7 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
 static void mmc_select_card_type(struct mmc_card *card)
 {
 	struct mmc_host *host = card->host;
-	u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
+	u8 card_type = card->ext_csd.raw_card_type;
 	u32 caps = host->caps, caps2 = host->caps2;
 	unsigned int hs_max_dtr = 0, hs200_max_dtr = 0;
 	unsigned int avail_type = 0;
@@ -281,6 +281,18 @@ static void mmc_select_card_type(struct mmc_card *card)
 		avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
 	}
 
+	if (caps2 & MMC_CAP2_HS400_1_8V &&
+	    card_type & EXT_CSD_CARD_TYPE_HS400_1_8V) {
+		hs200_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS400_1_8V;
+	}
+
+	if (caps2 & MMC_CAP2_HS400_1_2V &&
+	    card_type & EXT_CSD_CARD_TYPE_HS400_1_2V) {
+		hs200_max_dtr = MMC_HS200_MAX_DTR;
+		avail_type |= EXT_CSD_CARD_TYPE_HS400_1_2V;
+	}
+
 	card->ext_csd.hs_max_dtr = hs_max_dtr;
 	card->ext_csd.hs200_max_dtr = hs200_max_dtr;
 	card->mmc_avail_type = avail_type;
@@ -499,6 +511,8 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
 			ext_csd[EXT_CSD_PWR_CL_DDR_52_195];
 		card->ext_csd.raw_pwr_cl_ddr_52_360 =
 			ext_csd[EXT_CSD_PWR_CL_DDR_52_360];
+		card->ext_csd.raw_pwr_cl_ddr_200_360 =
+			ext_csd[EXT_CSD_PWR_CL_DDR_200_360];
 	}
 
 	if (card->ext_csd.rev >= 5) {
@@ -665,7 +679,10 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
 		(card->ext_csd.raw_pwr_cl_ddr_52_195 ==
 			bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_195]) &&
 		(card->ext_csd.raw_pwr_cl_ddr_52_360 ==
-			bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360]));
+			bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360]) &&
+		(card->ext_csd.raw_pwr_cl_ddr_200_360 ==
+			bw_ext_csd[EXT_CSD_PWR_CL_DDR_200_360]));
+
 	if (err)
 		err = -EINVAL;
 
@@ -729,7 +746,8 @@ static struct device_type mmc_type = {
 
 static inline unsigned int mmc_snoop_ddr(struct mmc_card *card)
 {
-	return card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52;
+	return card->mmc_avail_type &
+		(EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_HS400);
 }
 
 /*
@@ -781,7 +799,9 @@ static int __mmc_select_powerclass(struct mmc_card *card,
 				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;
+			pwrclass_val = (bus_width == EXT_CSD_DDR_BUS_WIDTH_8) ?
+				ext_csd->raw_pwr_cl_ddr_200_360 :
+				ext_csd->raw_pwr_cl_200_360;
 		break;
 	default:
 		pr_warning("%s: Voltage range not supported "
@@ -845,7 +865,8 @@ static void mmc_set_bus_speed(struct mmc_card *card)
 {
 	unsigned int max_dtr = (unsigned int)-1;
 
-	if (mmc_card_hs200(card) && max_dtr > card->ext_csd.hs200_max_dtr)
+	if ((mmc_card_hs200(card) || mmc_card_hs400(card)) &&
+	     max_dtr > card->ext_csd.hs200_max_dtr)
 		max_dtr = card->ext_csd.hs200_max_dtr;
 	else if (mmc_card_hs(card) && max_dtr > card->ext_csd.hs_max_dtr)
 		max_dtr = card->ext_csd.hs_max_dtr;
@@ -944,6 +965,28 @@ static int mmc_select_hs(struct mmc_card *card)
 }
 
 /*
+ * Revert to the high-speed mode from above speed
+ */
+static int mmc_revert_to_hs(struct mmc_card *card)
+{
+	/*
+	 * CMD13, which is used to confirm the completion of timing
+	 * change, will be issued at higher speed timing condtion
+	 * rather than high-speed. If device has completed the change
+	 * to high-speed mode, it may not be proper timing to issue
+	 * command. Low speed supplies better timing margin than high
+	 * speed. Accordingly clock rate & timging should be chagned
+	 * ahead before actual switch.
+	 */
+	mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+	mmc_set_bus_speed(card);
+
+	return mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+			  EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
+			  card->ext_csd.generic_cmd6_time);
+}
+
+/*
  * Activate wide bus and DDR if supported.
  */
 static int mmc_select_hs_ddr(struct mmc_card *card)
@@ -999,6 +1042,56 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
 	return err;
 }
 
+static int mmc_select_hs400(struct mmc_card *card)
+{
+	struct mmc_host *host = card->host;
+	int err = 0, ddr;
+
+	ddr = mmc_snoop_ddr(card);
+
+	/*
+	 * The bus width is set to only 8 DDR in HS400 mode
+	 */
+	if (!(ddr & EXT_CSD_CARD_TYPE_HS400 &&
+	      host->ios.bus_width == MMC_BUS_WIDTH_8))
+		return 0;
+
+	/*
+	 * Before setting BUS_WIDTH for dual data rate operation,
+	 * HS_TIMING must be set to High Speed(0x1)
+	 */
+	err = mmc_revert_to_hs(card);
+	if (err) {
+		pr_warn("%s: switch to high-speed from hs200 failed, err:%d\n",
+			mmc_hostname(host), err);
+		return err;
+	}
+
+	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+			 EXT_CSD_BUS_WIDTH,
+			 EXT_CSD_DDR_BUS_WIDTH_8,
+			 card->ext_csd.generic_cmd6_time);
+	if (err) {
+		pr_warn("%s: switch to bus width for hs400 failed, err:%d\n",
+			mmc_hostname(host), err);
+		return err;
+	}
+
+	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+			 EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400,
+			 card->ext_csd.generic_cmd6_time);
+	if (err) {
+		pr_warn("%s: switch to hs400 failed, err:%d\n",
+			 mmc_hostname(host), err);
+		return err;
+	}
+
+	mmc_set_timing(host, MMC_TIMING_MMC_HS400);
+	mmc_set_bus_speed(card);
+
+	return 0;
+}
+
 /*
  * For device supporting HS200 mode, the following sequence
  * should be done before executing the tuning process.
@@ -1031,7 +1124,16 @@ static int mmc_select_hs200(struct mmc_card *card)
 				   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200,
 				   card->ext_csd.generic_cmd6_time,
 				   true, true, true);
-		if (!err)
+		if (err)
+			goto err;
+
+		if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400)
+			/*
+			 * Timing should be adjusted to the HS400 target
+			 * operation frequency for tuning process
+			 */
+			mmc_set_timing(host, MMC_TIMING_MMC_HS400_TUNING);
+		else
 			mmc_set_timing(host, MMC_TIMING_MMC_HS200);
 	}
 err:
@@ -1076,7 +1178,7 @@ bus_speed:
 
 /*
  * Execute tuning sequence to seek the proper bus operating
- * conditions for HS200, which sends CMD21 to the device.
+ * conditions for HS200 and HS400, which sends CMD21 to the device.
  */
 static int mmc_hs200_tuning(struct mmc_card *card)
 {
@@ -1310,6 +1412,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		err = mmc_hs200_tuning(card);
 		if (err)
 			goto err;
+
+		err = mmc_select_hs400(card);
+		if (err)
+			goto err;
 	} else if (mmc_card_hs(card)) {
 		/* Select the desired bus width optionally */
 		err = mmc_select_bus_width(card);
include/linux/mmc/card.h +1 -0
index def6814..2b24c36 100644
@@ -110,6 +110,7 @@ struct mmc_ext_csd {
 	u8			raw_pwr_cl_200_360;	/* 237 */
 	u8			raw_pwr_cl_ddr_52_195;	/* 238 */
 	u8			raw_pwr_cl_ddr_52_360;	/* 239 */
+	u8			raw_pwr_cl_ddr_200_360;	/* 253 */
 	u8			raw_bkops_status;	/* 246 */
 	u8			raw_sectors[4];		/* 212 - 4 bytes */
 
include/linux/mmc/host.h +14 -1
index 1ee3c10..cc716e4 100644
@@ -61,6 +61,8 @@ struct mmc_ios {
 #define MMC_TIMING_UHS_DDR50	7
 #define MMC_TIMING_MMC_DDR52	8
 #define MMC_TIMING_MMC_HS200	9
+#define MMC_TIMING_MMC_HS400	10
+#define MMC_TIMING_MMC_HS400_TUNING 11
 
 	unsigned char	signal_voltage;		/* signalling voltage (1.8V or 3.3V) */
 
@@ -274,6 +276,10 @@ struct mmc_host {
 #define MMC_CAP2_PACKED_CMD	(MMC_CAP2_PACKED_RD | \
 				 MMC_CAP2_PACKED_WR)
 #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)	/* Don't power up before scan */
+#define MMC_CAP2_HS400_1_8V	(1 << 15)	/* Can support HS400 1.8V */
+#define MMC_CAP2_HS400_1_2V	(1 << 16)	/* Can support HS400 1.2V */
+#define MMC_CAP2_HS400		(MMC_CAP2_HS400_1_8V | \
+				 MMC_CAP2_HS400_1_2V)
 
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
 
@@ -486,11 +492,18 @@ static inline int mmc_card_uhs(struct mmc_card *card)
 
 static inline bool mmc_card_hs200(struct mmc_card *card)
 {
-	return card->host->ios.timing == MMC_TIMING_MMC_HS200;
+	return card->host->ios.timing == MMC_TIMING_MMC_HS200 ||
+		card->host->ios.timing == MMC_TIMING_MMC_HS400_TUNING;
 }
 
 static inline bool mmc_card_ddr52(struct mmc_card *card)
 {
 	return card->host->ios.timing == MMC_TIMING_MMC_DDR52;
 }
+
+static inline bool mmc_card_hs400(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_MMC_HS400;
+}
+
 #endif /* LINUX_MMC_HOST_H */
include/linux/mmc/mmc.h +6 -2
index f429f13..64ec963 100644
@@ -325,6 +325,7 @@ struct _mmc_csd {
 #define EXT_CSD_POWER_OFF_LONG_TIME	247	/* RO */
 #define EXT_CSD_GENERIC_CMD6_TIME	248	/* RO */
 #define EXT_CSD_CACHE_SIZE		249	/* RO, 4 bytes */
+#define EXT_CSD_PWR_CL_DDR_200_360	253	/* RO */
 #define EXT_CSD_TAG_UNIT_SIZE		498	/* RO */
 #define EXT_CSD_DATA_TAG_SUPPORT	499	/* RO */
 #define EXT_CSD_MAX_PACKED_WRITES	500	/* RO */
@@ -354,7 +355,6 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-#define EXT_CSD_CARD_TYPE_MASK	0x3F	/* Mask out reserved bits */
 #define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
 #define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
@@ -370,6 +370,10 @@ struct _mmc_csd {
 						/* SDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
 					 EXT_CSD_CARD_TYPE_HS200_1_2V)
+#define EXT_CSD_CARD_TYPE_HS400_1_8V	(1<<6)	/* Card can run at 200MHz DDR, 1.8V */
+#define EXT_CSD_CARD_TYPE_HS400_1_2V	(1<<7)	/* Card can run at 200MHz DDR, 1.2V */
+#define EXT_CSD_CARD_TYPE_HS400		(EXT_CSD_CARD_TYPE_HS400_1_8V | \
+					 EXT_CSD_CARD_TYPE_HS400_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
@@ -380,6 +384,7 @@ struct _mmc_csd {
 #define EXT_CSD_TIMING_BC	0	/* Backwards compatility */
 #define EXT_CSD_TIMING_HS	1	/* High speed */
 #define EXT_CSD_TIMING_HS200	2	/* HS200 */
+#define EXT_CSD_TIMING_HS400	3	/* HS400 */
 
 #define EXT_CSD_SEC_ER_EN	BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN	BIT(2)
--

1.7.0.4

Quoted 5 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to [email protected]
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#168 lore raw

PATCH v3 5/5 mmc: add support for HS400 mode of eMMC5.0

In reply to Seungwon Jeon

This patch adds HS400 mode support for eMMC5.0 device. HS400 mode is high speed DDR interface timing from HS200. Clock frequency is up to 200MHz and only 8-bit bus width is supported. In addition, tuning process of HS200 is required to synchronize the command response on the CMD line because CMD input timing for HS400 mode is the same as HS200 mode.

---
 drivers/mmc/core/bus.c     |    1 +
 drivers/mmc/core/debugfs.c |    3 +
 drivers/mmc/core/mmc.c     |  115 +++++++++++++++++++++++++++++++++++++++++--
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/host.h   |   15 +++++-
 include/linux/mmc/mmc.h    |    7 ++-
 6 files changed, 134 insertions(+), 8 deletions(-)
drivers/mmc/core/bus.c +1 -0
index f37e9d6..d2dbf02 100644
@@ -349,6 +349,7 @@ int mmc_add_card(struct mmc_card *card)
 			mmc_hostname(card->host),
 			mmc_card_uhs(card) ? "ultra high speed " :
 			(mmc_card_hs(card) ? "high speed " : ""),
+			mmc_card_hs400(card) ? "HS400 " :
 			(mmc_card_hs200(card) ? "HS200 " : ""),
 			mmc_card_ddr52(card) ? "DDR " : "",
 			uhs_bus_speed_mode, type, card->rca);
drivers/mmc/core/debugfs.c +3 -0
index 1f730db..91eb162 100644
@@ -141,6 +141,9 @@ static int mmc_ios_show(struct seq_file *s, void *data)
 	case MMC_TIMING_MMC_HS200:
 		str = "mmc HS200";
 		break;
+	case MMC_TIMING_MMC_HS400:
+		str = "mmc HS400";
+		break;
 	default:
 		str = "invalid";
 		break;
drivers/mmc/core/mmc.c +109 -6

181 lines not on this page · raw message

include/linux/mmc/card.h +1 -0
index def6814..2b24c36 100644
@@ -110,6 +110,7 @@ struct mmc_ext_csd {
 	u8			raw_pwr_cl_200_360;	/* 237 */
 	u8			raw_pwr_cl_ddr_52_195;	/* 238 */
 	u8			raw_pwr_cl_ddr_52_360;	/* 239 */
+	u8			raw_pwr_cl_ddr_200_360;	/* 253 */
 	u8			raw_bkops_status;	/* 246 */
 	u8			raw_sectors[4];		/* 212 - 4 bytes */
 
include/linux/mmc/host.h +14 -1
index 1ee3c10..cc716e4 100644
@@ -61,6 +61,8 @@ struct mmc_ios {
 #define MMC_TIMING_UHS_DDR50	7
 #define MMC_TIMING_MMC_DDR52	8
 #define MMC_TIMING_MMC_HS200	9
+#define MMC_TIMING_MMC_HS400	10
+#define MMC_TIMING_MMC_HS400_TUNING 11
 
 	unsigned char	signal_voltage;		/* signalling voltage (1.8V or 3.3V) */
 
@@ -274,6 +276,10 @@ struct mmc_host {
 #define MMC_CAP2_PACKED_CMD	(MMC_CAP2_PACKED_RD | \
 				 MMC_CAP2_PACKED_WR)
 #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)	/* Don't power up before scan */
+#define MMC_CAP2_HS400_1_8V	(1 << 15)	/* Can support HS400 1.8V */
+#define MMC_CAP2_HS400_1_2V	(1 << 16)	/* Can support HS400 1.2V */
+#define MMC_CAP2_HS400		(MMC_CAP2_HS400_1_8V | \
+				 MMC_CAP2_HS400_1_2V)
 
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
 
@@ -486,11 +492,18 @@ static inline int mmc_card_uhs(struct mmc_card *card)
 
 static inline bool mmc_card_hs200(struct mmc_card *card)
 {
-	return card->host->ios.timing == MMC_TIMING_MMC_HS200;
+	return card->host->ios.timing == MMC_TIMING_MMC_HS200 ||
+		card->host->ios.timing == MMC_TIMING_MMC_HS400_TUNING;
 }
 
 static inline bool mmc_card_ddr52(struct mmc_card *card)
 {
 	return card->host->ios.timing == MMC_TIMING_MMC_DDR52;
 }
+
+static inline bool mmc_card_hs400(struct mmc_card *card)
+{
+	return card->host->ios.timing == MMC_TIMING_MMC_HS400;
+}
+
 #endif /* LINUX_MMC_HOST_H */
include/linux/mmc/mmc.h +6 -1
index f429f13..64ec963 100644
@@ -325,6 +325,7 @@ struct _mmc_csd {
 #define EXT_CSD_POWER_OFF_LONG_TIME	247	/* RO */
 #define EXT_CSD_GENERIC_CMD6_TIME	248	/* RO */
 #define EXT_CSD_CACHE_SIZE		249	/* RO, 4 bytes */
+#define EXT_CSD_PWR_CL_DDR_200_360	253	/* RO */
 #define EXT_CSD_TAG_UNIT_SIZE		498	/* RO */
 #define EXT_CSD_DATA_TAG_SUPPORT	499	/* RO */
 #define EXT_CSD_MAX_PACKED_WRITES	500	/* RO */
@@ -354,7 +355,6 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE		(1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE	(1<<2)
 
-#define EXT_CSD_CARD_TYPE_MASK	0x3F	/* Mask out reserved bits */
 #define EXT_CSD_CARD_TYPE_HS_26	(1<<0)	/* Card can run at 26MHz */
 #define EXT_CSD_CARD_TYPE_HS_52	(1<<1)	/* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_HS	(EXT_CSD_CARD_TYPE_HS_26 | \
@@ -370,6 +370,10 @@ struct _mmc_csd {
 						/* SDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_HS200		(EXT_CSD_CARD_TYPE_HS200_1_8V | \
 					 EXT_CSD_CARD_TYPE_HS200_1_2V)
+#define EXT_CSD_CARD_TYPE_HS400_1_8V	(1<<6)	/* Card can run at 200MHz DDR, 1.8V */
+#define EXT_CSD_CARD_TYPE_HS400_1_2V	(1<<7)	/* Card can run at 200MHz DDR, 1.2V */
+#define EXT_CSD_CARD_TYPE_HS400		(EXT_CSD_CARD_TYPE_HS400_1_8V | \
+					 EXT_CSD_CARD_TYPE_HS400_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1	0	/* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */
@@ -380,6 +384,7 @@ struct _mmc_csd {
 #define EXT_CSD_TIMING_BC	0	/* Backwards compatility */
 #define EXT_CSD_TIMING_HS	1	/* High speed */
 #define EXT_CSD_TIMING_HS200	2	/* HS200 */
+#define EXT_CSD_TIMING_HS400	3	/* HS400 */
 
 #define EXT_CSD_SEC_ER_EN	BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN	BIT(2)
Signature · 1 line
1.7.0.4
#169 lore raw

Re: [PATCH v3 5/5] mmc: add support for HS400 mode of eMMC5.0

Quoted 126 lines · Seungwon Jeon

This patch adds HS400 mode support for eMMC5.0 device. HS400 mode is high speed DDR interface timing from HS200. Clock frequency is up to 200MHz and only 8-bit bus width is supported. In addition, tuning process of HS200 is required to synchronize the command response on the CMD line because CMD input timing for HS400 mode is the same as HS200 mode.

---
 drivers/mmc/core/bus.c     |    1 +
 drivers/mmc/core/debugfs.c |    3 +
 drivers/mmc/core/mmc.c     |  115 +++++++++++++++++++++++++++++++++++++++++--
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/host.h   |   15 +++++-
 include/linux/mmc/mmc.h    |    7 ++-
 6 files changed, 134 insertions(+), 8 deletions(-)
drivers/mmc/core/bus.c +1 -0
index f37e9d6..d2dbf02 100644
@@ -349,6 +349,7 @@ int mmc_add_card(struct mmc_card *card)
                        mmc_hostname(card->host),
                        mmc_card_uhs(card) ? "ultra high speed " :
                        (mmc_card_hs(card) ? "high speed " : ""),
+                       mmc_card_hs400(card) ? "HS400 " :
                        (mmc_card_hs200(card) ? "HS200 " : ""),
                        mmc_card_ddr52(card) ? "DDR " : "",
                        uhs_bus_speed_mode, type, card->rca);
drivers/mmc/core/debugfs.c +3 -0
index 1f730db..91eb162 100644
@@ -141,6 +141,9 @@ static int mmc_ios_show(struct seq_file *s, void *data)
        case MMC_TIMING_MMC_HS200:
                str = "mmc HS200";
                break;
+       case MMC_TIMING_MMC_HS400:
+               str = "mmc HS400";
+               break;
        default:
                str = "invalid";
                break;
drivers/mmc/core/mmc.c +26 -4
index 6dd68e6..969d595 100644
@@ -240,7 +240,7 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
 static void mmc_select_card_type(struct mmc_card *card)
 {
        struct mmc_host *host = card->host;
-       u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
+       u8 card_type = card->ext_csd.raw_card_type;
        u32 caps = host->caps, caps2 = host->caps2;
        unsigned int hs_max_dtr = 0, hs200_max_dtr = 0;
        unsigned int avail_type = 0;
@@ -281,6 +281,18 @@ static void mmc_select_card_type(struct mmc_card *card)
                avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
        }
 
+       if (caps2 & MMC_CAP2_HS400_1_8V &&
+           card_type & EXT_CSD_CARD_TYPE_HS400_1_8V) {
+               hs200_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS400_1_8V;
+       }
+
+       if (caps2 & MMC_CAP2_HS400_1_2V &&
+           card_type & EXT_CSD_CARD_TYPE_HS400_1_2V) {
+               hs200_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS400_1_2V;
+       }
+
        card->ext_csd.hs_max_dtr = hs_max_dtr;
        card->ext_csd.hs200_max_dtr = hs200_max_dtr;
        card->mmc_avail_type = avail_type;
@@ -499,6 +511,8 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
                        ext_csd[EXT_CSD_PWR_CL_DDR_52_195];
                card->ext_csd.raw_pwr_cl_ddr_52_360 =
                        ext_csd[EXT_CSD_PWR_CL_DDR_52_360];
+               card->ext_csd.raw_pwr_cl_ddr_200_360 =
+                       ext_csd[EXT_CSD_PWR_CL_DDR_200_360];
        }
 
        if (card->ext_csd.rev >= 5) {
@@ -665,7 +679,10 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
                (card->ext_csd.raw_pwr_cl_ddr_52_195 ==
                        bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_195]) &&
                (card->ext_csd.raw_pwr_cl_ddr_52_360 ==
-                       bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360]));
+                       bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360]) &&
+               (card->ext_csd.raw_pwr_cl_ddr_200_360 ==
+                       bw_ext_csd[EXT_CSD_PWR_CL_DDR_200_360]));
+
        if (err)
                err = -EINVAL;
 
@@ -776,7 +793,9 @@ static int __mmc_select_powerclass(struct mmc_card *card,
                                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;
+                       pwrclass_val = (bus_width == EXT_CSD_DDR_BUS_WIDTH_8) ?
+                               ext_csd->raw_pwr_cl_ddr_200_360 :
+                               ext_csd->raw_pwr_cl_200_360;
                break;
        default:
                pr_warning("%s: Voltage range not supported "
@@ -840,7 +859,8 @@ static void mmc_set_bus_speed(struct mmc_card *card)
 {
        unsigned int max_dtr = (unsigned int)-1;
 
-       if (mmc_card_hs200(card) && max_dtr > card->ext_csd.hs200_max_dtr)
+       if ((mmc_card_hs200(card) || mmc_card_hs400(card)) &&
+            max_dtr > card->ext_csd.hs200_max_dtr)
                max_dtr = card->ext_csd.hs200_max_dtr;
        else if (mmc_card_hs(card) && max_dtr > card->ext_csd.hs_max_dtr)
                max_dtr = card->ext_csd.hs_max_dtr;
@@ -939,6 +959,28 @@ static int mmc_select_hs(struct mmc_card *card)
 }
 
 /*
+ * Revert to the high-speed mode from above speed
+ */

drivers/mmc/core/mmc.c static int mmc_select_hs(struct mmc_card *card) · line 973

Quoted 10 lines
drivers/mmc/core/mmc.c +10 -0
+static int mmc_revert_to_hs(struct mmc_card *card)
+{
+       /*
+        * CMD13, which is used to confirm the completion of timing
+        * change, will be issued at higher speed timing condtion
+        * rather than high-speed. If device has completed the change
+        * to high-speed mode, it may not be proper timing to issue
+        * command. Low speed supplies better timing margin than high
+        * speed. Accordingly clock rate & timging should be chagned
+        * ahead before actual switch.

I have some problem to understand this comment. I guess you are trying to provide the arguments to why it makes sense to perform the revert to lower speed mode!?

This makes me wonder if this is not part of the spec? Could you try to clarify?

Quoted 14 lines
drivers/mmc/core/mmc.c +10 -0
+        */
+       mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+       mmc_set_bus_speed(card);
+
+       return mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                         EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
+                         card->ext_csd.generic_cmd6_time);
+}
+
+/*
  * Activate wide bus and DDR if supported.
  */
 static int mmc_select_hs_ddr(struct mmc_card *card)

drivers/mmc/core/mmc.c static int mmc_select_hs_ddr(struct mmc_card *card) · line 1044

Quoted 10 lines
drivers/mmc/core/mmc.c +7 -0
@@ -993,6 +1035,54 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
        return err;
 }
 
+static int mmc_select_hs400(struct mmc_card *card)
+{
+       struct mmc_host *host = card->host;
+       int err = 0;
+
+       /*
+        * The bus width is set to only 8 DDR in HS400 mode

Please rephrase the comment to something like:
"HS400 mode requires 8-bit bus width."

drivers/mmc/core/mmc.c static int mmc_select_hs_ddr(struct mmc_card *card) · line 1053

Quoted 9 lines
drivers/mmc/core/mmc.c +9 -0
+        */
+       if (!(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 &&
+             host->ios.bus_width == MMC_BUS_WIDTH_8))
+               return 0;
+
+       /*
+        * Before setting BUS_WIDTH for dual data rate operation,
+        * HS_TIMING must be set to High Speed(0x1)
+        */

Please rephrase comment:

"Before switching to dual data rate operation for HS400, we need revert from HS200 timing to regular HS timing."

drivers/mmc/core/mmc.c static int mmc_select_hs_ddr(struct mmc_card *card) · line 1054

Quoted 1 line
drivers/mmc/core/mmc.c +1 -0
+       err = mmc_revert_to_hs(card);

I don't think we need a separate function to handle the revert. Please, just add the code here instead. While you do that, I suppose we should combine the comment in that function into one comment here.

Quoted 38 lines
drivers/mmc/core/mmc.c +31 -0
+       if (err) {
+               pr_warn("%s: switch to high-speed from hs200 failed, err:%d\n",
+                       mmc_hostname(host), err);
+               return err;
+       }
+
+       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                        EXT_CSD_BUS_WIDTH,
+                        EXT_CSD_DDR_BUS_WIDTH_8,
+                        card->ext_csd.generic_cmd6_time);
+       if (err) {
+               pr_warn("%s: switch to bus width for hs400 failed, err:%d\n",
+                       mmc_hostname(host), err);
+               return err;
+       }
+
+       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                        EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400,
+                        card->ext_csd.generic_cmd6_time);
+       if (err) {
+               pr_warn("%s: switch to hs400 failed, err:%d\n",
+                        mmc_hostname(host), err);
+               return err;
+       }
+
+       mmc_set_timing(host, MMC_TIMING_MMC_HS400);
+       mmc_set_bus_speed(card);
+
+       return 0;
+}
+
 /*
  * For device supporting HS200 mode, the following sequence
  * should be done before executing the tuning process.
@@ -1025,7 +1115,16 @@ static int mmc_select_hs200(struct mmc_card *card)
                                   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200,
                                   card->ext_csd.generic_cmd6_time,
                                   true, true, true);

drivers/mmc/core/mmc.c static int mmc_select_hs200(struct mmc_card *card) · line 1126

Quoted 10 lines
drivers/mmc/core/mmc.c +9 -1
-               if (!err)
+               if (err)
+                       goto err;
+
+               if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400)
+                       /*
+                        * Timing should be adjusted to the HS400 target
+                        * operation frequency for tuning process
+                        */
+                       mmc_set_timing(host, MMC_TIMING_MMC_HS400_TUNING);

This seems strange. Do we really need a separate
MMC_TIMING_MMC_HS400_TUNING value?

Quoted 41 lines
drivers/mmc/core/mmc.c +6 -1
+               else
                        mmc_set_timing(host, MMC_TIMING_MMC_HS200);
        }
 err:
@@ -1070,7 +1169,7 @@ bus_speed:
 
 /*
  * Execute tuning sequence to seek the proper bus operating
- * conditions for HS200, which sends CMD21 to the device.
+ * conditions for HS200 and HS400, which sends CMD21 to the device.
  */
 static int mmc_hs200_tuning(struct mmc_card *card)
 {
@@ -1304,6 +1403,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                err = mmc_hs200_tuning(card);
                if (err)
                        goto err;
+
+               err = mmc_select_hs400(card);
+               if (err)
+                       goto err;
        } else if (mmc_card_hs(card)) {
                /* Select the desired bus width optionally */
                err = mmc_select_bus_width(card);
include/linux/mmc/card.h +1 -0
index def6814..2b24c36 100644
@@ -110,6 +110,7 @@ struct mmc_ext_csd {
        u8                      raw_pwr_cl_200_360;     /* 237 */
        u8                      raw_pwr_cl_ddr_52_195;  /* 238 */
        u8                      raw_pwr_cl_ddr_52_360;  /* 239 */
+       u8                      raw_pwr_cl_ddr_200_360; /* 253 */
        u8                      raw_bkops_status;       /* 246 */
        u8                      raw_sectors[4];         /* 212 - 4 bytes */
 
include/linux/mmc/host.h +0 -0
index 1ee3c10..cc716e4 100644

include/linux/mmc/host.h struct mmc_ios { · line 65

Quoted 5 lines
include/linux/mmc/host.h +2 -0
@@ -61,6 +61,8 @@ struct mmc_ios {
 #define MMC_TIMING_UHS_DDR50   7
 #define MMC_TIMING_MMC_DDR52   8
 #define MMC_TIMING_MMC_HS200   9
+#define MMC_TIMING_MMC_HS400   10
+#define MMC_TIMING_MMC_HS400_TUNING 11

MMC_TIMING_MMC_HS400_TUNING ?

Quoted 15 lines
include/linux/mmc/host.h +4 -0
        unsigned char   signal_voltage;         /* signalling voltage (1.8V or 3.3V) */
 
@@ -274,6 +276,10 @@ struct mmc_host {
 #define MMC_CAP2_PACKED_CMD    (MMC_CAP2_PACKED_RD | \
                                 MMC_CAP2_PACKED_WR)
 #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)  /* Don't power up before scan */
+#define MMC_CAP2_HS400_1_8V    (1 << 15)       /* Can support HS400 1.8V */
+#define MMC_CAP2_HS400_1_2V    (1 << 16)       /* Can support HS400 1.2V */
+#define MMC_CAP2_HS400         (MMC_CAP2_HS400_1_8V | \
+                                MMC_CAP2_HS400_1_2V)
 
        mmc_pm_flag_t           pm_caps;        /* supported pm features */
 

include/linux/mmc/host.h static inline int mmc_card_uhs(struct mmc_card *card) · line 496

Quoted 6 lines
include/linux/mmc/host.h +2 -1
@@ -486,11 +492,18 @@ static inline int mmc_card_uhs(struct mmc_card *card)
 
 static inline bool mmc_card_hs200(struct mmc_card *card)
 {
-       return card->host->ios.timing == MMC_TIMING_MMC_HS200;
+       return card->host->ios.timing == MMC_TIMING_MMC_HS200 ||
+               card->host->ios.timing == MMC_TIMING_MMC_HS400_TUNING;

MMC_TIMING_MMC_HS400_TUNING ?

Quoted 53 lines
include/linux/mmc/host.h +6 -0
 }
 
 static inline bool mmc_card_ddr52(struct mmc_card *card)
 {
        return card->host->ios.timing == MMC_TIMING_MMC_DDR52;
 }
+
+static inline bool mmc_card_hs400(struct mmc_card *card)
+{
+       return card->host->ios.timing == MMC_TIMING_MMC_HS400;
+}
+
 #endif /* LINUX_MMC_HOST_H */
include/linux/mmc/mmc.h +6 -2
index f429f13..64ec963 100644
@@ -325,6 +325,7 @@ struct _mmc_csd {
 #define EXT_CSD_POWER_OFF_LONG_TIME    247     /* RO */
 #define EXT_CSD_GENERIC_CMD6_TIME      248     /* RO */
 #define EXT_CSD_CACHE_SIZE             249     /* RO, 4 bytes */
+#define EXT_CSD_PWR_CL_DDR_200_360     253     /* RO */
 #define EXT_CSD_TAG_UNIT_SIZE          498     /* RO */
 #define EXT_CSD_DATA_TAG_SUPPORT       499     /* RO */
 #define EXT_CSD_MAX_PACKED_WRITES      500     /* RO */
@@ -354,7 +355,6 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE         (1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE       (1<<2)
 
-#define EXT_CSD_CARD_TYPE_MASK 0x3F    /* Mask out reserved bits */
 #define EXT_CSD_CARD_TYPE_HS_26        (1<<0)  /* Card can run at 26MHz */
 #define EXT_CSD_CARD_TYPE_HS_52        (1<<1)  /* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_HS   (EXT_CSD_CARD_TYPE_HS_26 | \
@@ -370,6 +370,10 @@ struct _mmc_csd {
                                                /* SDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_HS200                (EXT_CSD_CARD_TYPE_HS200_1_8V | \
                                         EXT_CSD_CARD_TYPE_HS200_1_2V)
+#define EXT_CSD_CARD_TYPE_HS400_1_8V   (1<<6)  /* Card can run at 200MHz DDR, 1.8V */
+#define EXT_CSD_CARD_TYPE_HS400_1_2V   (1<<7)  /* Card can run at 200MHz DDR, 1.2V */
+#define EXT_CSD_CARD_TYPE_HS400                (EXT_CSD_CARD_TYPE_HS400_1_8V | \
+                                        EXT_CSD_CARD_TYPE_HS400_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
@@ -380,6 +384,7 @@ struct _mmc_csd {
 #define EXT_CSD_TIMING_BC      0       /* Backwards compatility */
 #define EXT_CSD_TIMING_HS      1       /* High speed */
 #define EXT_CSD_TIMING_HS200   2       /* HS200 */
+#define EXT_CSD_TIMING_HS400   3       /* HS400 */
 
 #define EXT_CSD_SEC_ER_EN      BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN  BIT(2)
--
Quoted 3 lines

1.7.0.4

Kind regards
Ulf Hansson

#170 lore raw

RE: [PATCH v3 5/5] mmc: add support for HS400 mode of eMMC5.0

Hi Ulf,

Quoted 142 lines · Ulf Hansson
Quoted 126 lines · Seungwon Jeon

This patch adds HS400 mode support for eMMC5.0 device. HS400 mode is high speed DDR interface timing from HS200. Clock frequency is up to 200MHz and only 8-bit bus width is supported. In addition, tuning process of HS200 is required to synchronize the command response on the CMD line because CMD input timing for HS400 mode is the same as HS200 mode.

---
 drivers/mmc/core/bus.c     |    1 +
 drivers/mmc/core/debugfs.c |    3 +
 drivers/mmc/core/mmc.c     |  115 +++++++++++++++++++++++++++++++++++++++++--
 include/linux/mmc/card.h   |    1 +
 include/linux/mmc/host.h   |   15 +++++-
 include/linux/mmc/mmc.h    |    7 ++-
 6 files changed, 134 insertions(+), 8 deletions(-)
drivers/mmc/core/bus.c +1 -0
index f37e9d6..d2dbf02 100644
@@ -349,6 +349,7 @@ int mmc_add_card(struct mmc_card *card)
                        mmc_hostname(card->host),
                        mmc_card_uhs(card) ? "ultra high speed " :
                        (mmc_card_hs(card) ? "high speed " : ""),
+                       mmc_card_hs400(card) ? "HS400 " :
                        (mmc_card_hs200(card) ? "HS200 " : ""),
                        mmc_card_ddr52(card) ? "DDR " : "",
                        uhs_bus_speed_mode, type, card->rca);
drivers/mmc/core/debugfs.c +3 -0
index 1f730db..91eb162 100644
@@ -141,6 +141,9 @@ static int mmc_ios_show(struct seq_file *s, void *data)
        case MMC_TIMING_MMC_HS200:
                str = "mmc HS200";
                break;
+       case MMC_TIMING_MMC_HS400:
+               str = "mmc HS400";
+               break;
        default:
                str = "invalid";
                break;
drivers/mmc/core/mmc.c +26 -4
index 6dd68e6..969d595 100644
@@ -240,7 +240,7 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
 static void mmc_select_card_type(struct mmc_card *card)
 {
        struct mmc_host *host = card->host;
-       u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
+       u8 card_type = card->ext_csd.raw_card_type;
        u32 caps = host->caps, caps2 = host->caps2;
        unsigned int hs_max_dtr = 0, hs200_max_dtr = 0;
        unsigned int avail_type = 0;
@@ -281,6 +281,18 @@ static void mmc_select_card_type(struct mmc_card *card)
                avail_type |= EXT_CSD_CARD_TYPE_HS200_1_2V;
        }
 
+       if (caps2 & MMC_CAP2_HS400_1_8V &&
+           card_type & EXT_CSD_CARD_TYPE_HS400_1_8V) {
+               hs200_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS400_1_8V;
+       }
+
+       if (caps2 & MMC_CAP2_HS400_1_2V &&
+           card_type & EXT_CSD_CARD_TYPE_HS400_1_2V) {
+               hs200_max_dtr = MMC_HS200_MAX_DTR;
+               avail_type |= EXT_CSD_CARD_TYPE_HS400_1_2V;
+       }
+
        card->ext_csd.hs_max_dtr = hs_max_dtr;
        card->ext_csd.hs200_max_dtr = hs200_max_dtr;
        card->mmc_avail_type = avail_type;
@@ -499,6 +511,8 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
                        ext_csd[EXT_CSD_PWR_CL_DDR_52_195];
                card->ext_csd.raw_pwr_cl_ddr_52_360 =
                        ext_csd[EXT_CSD_PWR_CL_DDR_52_360];
+               card->ext_csd.raw_pwr_cl_ddr_200_360 =
+                       ext_csd[EXT_CSD_PWR_CL_DDR_200_360];
        }
 
        if (card->ext_csd.rev >= 5) {
@@ -665,7 +679,10 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
                (card->ext_csd.raw_pwr_cl_ddr_52_195 ==
                        bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_195]) &&
                (card->ext_csd.raw_pwr_cl_ddr_52_360 ==
-                       bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360]));
+                       bw_ext_csd[EXT_CSD_PWR_CL_DDR_52_360]) &&
+               (card->ext_csd.raw_pwr_cl_ddr_200_360 ==
+                       bw_ext_csd[EXT_CSD_PWR_CL_DDR_200_360]));
+
        if (err)
                err = -EINVAL;
 
@@ -776,7 +793,9 @@ static int __mmc_select_powerclass(struct mmc_card *card,
                                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;
+                       pwrclass_val = (bus_width == EXT_CSD_DDR_BUS_WIDTH_8) ?
+                               ext_csd->raw_pwr_cl_ddr_200_360 :
+                               ext_csd->raw_pwr_cl_200_360;
                break;
        default:
                pr_warning("%s: Voltage range not supported "
@@ -840,7 +859,8 @@ static void mmc_set_bus_speed(struct mmc_card *card)
 {
        unsigned int max_dtr = (unsigned int)-1;
 
-       if (mmc_card_hs200(card) && max_dtr > card->ext_csd.hs200_max_dtr)
+       if ((mmc_card_hs200(card) || mmc_card_hs400(card)) &&
+            max_dtr > card->ext_csd.hs200_max_dtr)
                max_dtr = card->ext_csd.hs200_max_dtr;
        else if (mmc_card_hs(card) && max_dtr > card->ext_csd.hs_max_dtr)
                max_dtr = card->ext_csd.hs_max_dtr;
@@ -939,6 +959,28 @@ static int mmc_select_hs(struct mmc_card *card)
 }
 
 /*
+ * Revert to the high-speed mode from above speed
+ */

drivers/mmc/core/mmc.c static int mmc_select_hs(struct mmc_card *card) · line 973

Quoted 10 lines
drivers/mmc/core/mmc.c +10 -0
+static int mmc_revert_to_hs(struct mmc_card *card)
+{
+       /*
+        * CMD13, which is used to confirm the completion of timing
+        * change, will be issued at higher speed timing condtion
+        * rather than high-speed. If device has completed the change
+        * to high-speed mode, it may not be proper timing to issue
+        * command. Low speed supplies better timing margin than high
+        * speed. Accordingly clock rate & timging should be chagned
+        * ahead before actual switch.

I have some problem to understand this comment. I guess you are trying to provide the arguments to why it makes sense to perform the revert to lower speed mode!?

Quoted 1 line

This makes me wonder if this is not part of the spec? Could you try to clarify?

But specification says that "HS_TIMING must be set to “0x1” before setting BUS_WIDTH for dual data rate operation". I think this sequence is not graceful.
I also commented why speed mode should be changed to high-speed mode from HS200 mode in the function-called part. Because it is not possible to set 8-bit data bus for dual rate on HS200 mode, revert to high-speed from HS200 is needed. If the above-commented point makes it confused, it could be removed.
Please let me know your opinion.

Quoted 18 lines
Quoted 18 lines
drivers/mmc/core/mmc.c +10 -0
+        */
+       mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+       mmc_set_bus_speed(card);
+
+       return mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                         EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
+                         card->ext_csd.generic_cmd6_time);
+}
+
+/*
  * Activate wide bus and DDR if supported.
  */
 static int mmc_select_hs_ddr(struct mmc_card *card)
@@ -993,6 +1035,54 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
        return err;
 }
 
Quoted 10 lines

drivers/mmc/core/mmc.c static int mmc_select_hs_ddr(struct mmc_card *card) · line 1044

Quoted 7 lines
drivers/mmc/core/mmc.c +7 -0
+static int mmc_select_hs400(struct mmc_card *card)
+{
+       struct mmc_host *host = card->host;
+       int err = 0;
+
+       /*
+        * The bus width is set to only 8 DDR in HS400 mode

Please rephrase the comment to something like:
"HS400 mode requires 8-bit bus width."

As it is, it was from spec's description.
But I think yours would be more clearable.

Quoted 11 lines

drivers/mmc/core/mmc.c static int mmc_select_hs_ddr(struct mmc_card *card) · line 1053

Quoted 10 lines
drivers/mmc/core/mmc.c +9 -0
+        */
+       if (!(card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400 &&
+             host->ios.bus_width == MMC_BUS_WIDTH_8))
+               return 0;
+
+       /*
+        * Before setting BUS_WIDTH for dual data rate operation,
+        * HS_TIMING must be set to High Speed(0x1)
+        */
Quoted 4 lines

Please rephrase comment:

"Before switching to dual data rate operation for HS400, we need revert from HS200 timing to regular HS timing."

Ok.

Quoted 6 lines

drivers/mmc/core/mmc.c static int mmc_select_hs_ddr(struct mmc_card *card) · line 1054

Quoted 2 lines
drivers/mmc/core/mmc.c +1 -0
+       err = mmc_revert_to_hs(card);

I don't think we need a separate function to handle the revert. Please, just add the code here instead. While you do that, I suppose we should combine the comment in that function into one comment here.

OK, I don't oppose that.

Quoted 44 lines
Quoted 44 lines
drivers/mmc/core/mmc.c +35 -1
+       if (err) {
+               pr_warn("%s: switch to high-speed from hs200 failed, err:%d\n",
+                       mmc_hostname(host), err);
+               return err;
+       }
+
+       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                        EXT_CSD_BUS_WIDTH,
+                        EXT_CSD_DDR_BUS_WIDTH_8,
+                        card->ext_csd.generic_cmd6_time);
+       if (err) {
+               pr_warn("%s: switch to bus width for hs400 failed, err:%d\n",
+                       mmc_hostname(host), err);
+               return err;
+       }
+
+       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                        EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400,
+                        card->ext_csd.generic_cmd6_time);
+       if (err) {
+               pr_warn("%s: switch to hs400 failed, err:%d\n",
+                        mmc_hostname(host), err);
+               return err;
+       }
+
+       mmc_set_timing(host, MMC_TIMING_MMC_HS400);
+       mmc_set_bus_speed(card);
+
+       return 0;
+}
+
 /*
  * For device supporting HS200 mode, the following sequence
  * should be done before executing the tuning process.
@@ -1025,7 +1115,16 @@ static int mmc_select_hs200(struct mmc_card *card)
                                   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200,
                                   card->ext_csd.generic_cmd6_time,
                                   true, true, true);
-               if (!err)
+               if (err)
+                       goto err;
+
+               if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400)
Quoted 8 lines

drivers/mmc/core/mmc.c static int mmc_select_hs200(struct mmc_card *card) · line 1126

Quoted 5 lines
drivers/mmc/core/mmc.c +5 -0
+                       /*
+                        * Timing should be adjusted to the HS400 target
+                        * operation frequency for tuning process
+                        */
+                       mmc_set_timing(host, MMC_TIMING_MMC_HS400_TUNING);

This seems strange. Do we really need a separate
MMC_TIMING_MMC_HS400_TUNING value?

Spec. describes the HS400 selection sequence like below.
<Quot>
...
6) Perform the Tuning Process at the HS400 target operating frequency
(Note: tuning process in HS200 mode is required to synchronize the command response on the CMD line to CLK for HS400 operation).
...
</Quot>
That means target clock rate for tuning sequence can be different with HS200.
Considering for that, it needs to distinguish.

Quoted 66 lines
Quoted 42 lines
drivers/mmc/core/mmc.c +6 -1
+               else
                        mmc_set_timing(host, MMC_TIMING_MMC_HS200);
        }
 err:
@@ -1070,7 +1169,7 @@ bus_speed:
 
 /*
  * Execute tuning sequence to seek the proper bus operating
- * conditions for HS200, which sends CMD21 to the device.
+ * conditions for HS200 and HS400, which sends CMD21 to the device.
  */
 static int mmc_hs200_tuning(struct mmc_card *card)
 {
@@ -1304,6 +1403,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                err = mmc_hs200_tuning(card);
                if (err)
                        goto err;
+
+               err = mmc_select_hs400(card);
+               if (err)
+                       goto err;
        } else if (mmc_card_hs(card)) {
                /* Select the desired bus width optionally */
                err = mmc_select_bus_width(card);
include/linux/mmc/card.h +1 -0
index def6814..2b24c36 100644
@@ -110,6 +110,7 @@ struct mmc_ext_csd {
        u8                      raw_pwr_cl_200_360;     /* 237 */
        u8                      raw_pwr_cl_ddr_52_195;  /* 238 */
        u8                      raw_pwr_cl_ddr_52_360;  /* 239 */
+       u8                      raw_pwr_cl_ddr_200_360; /* 253 */
        u8                      raw_bkops_status;       /* 246 */
        u8                      raw_sectors[4];         /* 212 - 4 bytes */
 
include/linux/mmc/host.h +0 -0
index 1ee3c10..cc716e4 100644

include/linux/mmc/host.h struct mmc_ios { · line 65

Quoted 5 lines
include/linux/mmc/host.h +2 -0
@@ -61,6 +61,8 @@ struct mmc_ios {
 #define MMC_TIMING_UHS_DDR50   7
 #define MMC_TIMING_MMC_DDR52   8
 #define MMC_TIMING_MMC_HS200   9
+#define MMC_TIMING_MMC_HS400   10
+#define MMC_TIMING_MMC_HS400_TUNING 11

MMC_TIMING_MMC_HS400_TUNING ?

Quoted 16 lines
include/linux/mmc/host.h +4 -0
        unsigned char   signal_voltage;         /* signalling voltage (1.8V or 3.3V) */
 
@@ -274,6 +276,10 @@ struct mmc_host {
 #define MMC_CAP2_PACKED_CMD    (MMC_CAP2_PACKED_RD | \
                                 MMC_CAP2_PACKED_WR)
 #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)  /* Don't power up before scan */
+#define MMC_CAP2_HS400_1_8V    (1 << 15)       /* Can support HS400 1.8V */
+#define MMC_CAP2_HS400_1_2V    (1 << 16)       /* Can support HS400 1.2V */
+#define MMC_CAP2_HS400         (MMC_CAP2_HS400_1_8V | \
+                                MMC_CAP2_HS400_1_2V)
 
        mmc_pm_flag_t           pm_caps;        /* supported pm features */
 
@@ -486,11 +492,18 @@ static inline int mmc_card_uhs(struct mmc_card *card)
 
Quoted 7 lines

include/linux/mmc/host.h static inline int mmc_card_uhs(struct mmc_card *card) · line 496

Quoted 5 lines
include/linux/mmc/host.h +2 -1
 static inline bool mmc_card_hs200(struct mmc_card *card)
 {
-       return card->host->ios.timing == MMC_TIMING_MMC_HS200;
+       return card->host->ios.timing == MMC_TIMING_MMC_HS200 ||
+               card->host->ios.timing == MMC_TIMING_MMC_HS400_TUNING;

MMC_TIMING_MMC_HS400_TUNING ?

It also indicates that card is currently in HS200 mode with the result of setting HS_TIMING'.

Thanks,
Seungwon Jeon

Quoted 64 lines
Quoted 54 lines
include/linux/mmc/host.h +6 -0
 }
 
 static inline bool mmc_card_ddr52(struct mmc_card *card)
 {
        return card->host->ios.timing == MMC_TIMING_MMC_DDR52;
 }
+
+static inline bool mmc_card_hs400(struct mmc_card *card)
+{
+       return card->host->ios.timing == MMC_TIMING_MMC_HS400;
+}
+
 #endif /* LINUX_MMC_HOST_H */
include/linux/mmc/mmc.h +6 -2
index f429f13..64ec963 100644
@@ -325,6 +325,7 @@ struct _mmc_csd {
 #define EXT_CSD_POWER_OFF_LONG_TIME    247     /* RO */
 #define EXT_CSD_GENERIC_CMD6_TIME      248     /* RO */
 #define EXT_CSD_CACHE_SIZE             249     /* RO, 4 bytes */
+#define EXT_CSD_PWR_CL_DDR_200_360     253     /* RO */
 #define EXT_CSD_TAG_UNIT_SIZE          498     /* RO */
 #define EXT_CSD_DATA_TAG_SUPPORT       499     /* RO */
 #define EXT_CSD_MAX_PACKED_WRITES      500     /* RO */
@@ -354,7 +355,6 @@ struct _mmc_csd {
 #define EXT_CSD_CMD_SET_SECURE         (1<<1)
 #define EXT_CSD_CMD_SET_CPSECURE       (1<<2)
 
-#define EXT_CSD_CARD_TYPE_MASK 0x3F    /* Mask out reserved bits */
 #define EXT_CSD_CARD_TYPE_HS_26        (1<<0)  /* Card can run at 26MHz */
 #define EXT_CSD_CARD_TYPE_HS_52        (1<<1)  /* Card can run at 52MHz */
 #define EXT_CSD_CARD_TYPE_HS   (EXT_CSD_CARD_TYPE_HS_26 | \
@@ -370,6 +370,10 @@ struct _mmc_csd {
                                                /* SDR mode @1.2V I/O */
 #define EXT_CSD_CARD_TYPE_HS200                (EXT_CSD_CARD_TYPE_HS200_1_8V | \
                                         EXT_CSD_CARD_TYPE_HS200_1_2V)
+#define EXT_CSD_CARD_TYPE_HS400_1_8V   (1<<6)  /* Card can run at 200MHz DDR, 1.8V */
+#define EXT_CSD_CARD_TYPE_HS400_1_2V   (1<<7)  /* Card can run at 200MHz DDR, 1.2V */
+#define EXT_CSD_CARD_TYPE_HS400                (EXT_CSD_CARD_TYPE_HS400_1_8V | \
+                                        EXT_CSD_CARD_TYPE_HS400_1_2V)
 
 #define EXT_CSD_BUS_WIDTH_1    0       /* Card is in 1 bit mode */
 #define EXT_CSD_BUS_WIDTH_4    1       /* Card is in 4 bit mode */
@@ -380,6 +384,7 @@ struct _mmc_csd {
 #define EXT_CSD_TIMING_BC      0       /* Backwards compatility */
 #define EXT_CSD_TIMING_HS      1       /* High speed */
 #define EXT_CSD_TIMING_HS200   2       /* HS200 */
+#define EXT_CSD_TIMING_HS400   3       /* HS400 */
 
 #define EXT_CSD_SEC_ER_EN      BIT(0)
 #define EXT_CSD_SEC_BD_BLK_EN  BIT(2)
--
Quoted 3 lines

1.7.0.4

Kind regards
Ulf Hansson
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html