Hi Ulf, On Tue, November 05, 2013, Ulf Hansson wrote: > Hi Seungwon, > > On 5 November 2013 14:27, Seungwon Jeon <tgih.jun@xxxxxxxxxxx> wrote: > > 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 > > * Power class is switched once only after bus modes(speed/width) > > are selected finally > > * Adds maximum speed for HS200 mode(hs200_max_dtr) > > * Adds available device type to be supported by both host and device > > * Adds field definition for HS_TIMING of EXT_CSD > > Very nice work you are doing here, this is certainly needed. > > Although, from a reviewing point of view it would be nice if you could > split up and do re-factoring in more minor pieces. Could that be done? Ok. I'll consider that. But I guess it would not be done nicely because a whole flow is organic. If you have any opinion, please let me know. Thanks, Seungwon Jeon > > Kind regards > Ulf Hansson > > > > > Signed-off-by: Seungwon Jeon <tgih.jun@xxxxxxxxxxx> > > --- > > drivers/mmc/core/mmc.c | 574 +++++++++++++++++++++++++++------------------- > > include/linux/mmc/card.h | 6 +- > > include/linux/mmc/host.h | 6 - > > include/linux/mmc/mmc.h | 4 + > > 4 files changed, 345 insertions(+), 245 deletions(-) > > > > diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c > > index f631f5a..f4f8991 100644 > > --- a/drivers/mmc/core/mmc.c > > +++ b/drivers/mmc/core/mmc.c > > @@ -242,29 +242,48 @@ 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 avail_type = 0; > > + unsigned int hs_max_dtr = 0, hs200_max_dtr = 0; > > > > - if (card_type & EXT_CSD_CARD_TYPE_26) > > + if (card_type & EXT_CSD_CARD_TYPE_26) { > > hs_max_dtr = MMC_HIGH_26_MAX_DTR; > > + avail_type |= EXT_CSD_CARD_TYPE_26; > > + } > > > > if (caps & MMC_CAP_MMC_HIGHSPEED && > > - card_type & EXT_CSD_CARD_TYPE_52) > > + card_type & EXT_CSD_CARD_TYPE_52) { > > hs_max_dtr = MMC_HIGH_52_MAX_DTR; > > + avail_type |= EXT_CSD_CARD_TYPE_52; > > + } > > + > > + 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_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_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) { > > + hs200_max_dtr = MMC_HS200_MAX_DTR; > > + avail_type |= EXT_CSD_CARD_TYPE_SDR_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)) > > - hs_max_dtr = MMC_HS200_MAX_DTR; > > + if (caps2 & MMC_CAP2_HS200_1_2V_SDR && > > + card_type & EXT_CSD_CARD_TYPE_SDR_1_2V) { > > + hs200_max_dtr = MMC_HS200_MAX_DTR; > > + avail_type |= EXT_CSD_CARD_TYPE_SDR_1_2V; > > + } > > > > card->ext_csd.hs_max_dtr = hs_max_dtr; > > + card->ext_csd.hs200_max_dtr = hs200_max_dtr; > > card->ext_csd.card_type = card_type; > > + card->mmc_avail_type = avail_type; > > } > > > > /* > > @@ -714,8 +733,8 @@ 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, u8 *ext_csd) > > { > > int err = 0; > > unsigned int pwrclass_val = 0; > > @@ -787,40 +806,99 @@ static int mmc_select_powerclass(struct mmc_card *card, > > return err; > > } > > > > +static inline unsigned int mmc_snoop_ddr(struct mmc_card *card) > > +{ > > + return card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52; > > +} > > + > > +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 > > + * 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; > > + > > + BUG_ON(!card); > > + > > + if (mmc_card_hs200(card)) { > > + if (max_dtr > card->ext_csd.hs200_max_dtr) > > + max_dtr = card->ext_csd.hs200_max_dtr; > > + } else if (mmc_card_highspeed(card)) { > > + if (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; > > 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, > > }; > > + struct mmc_host *host; > > + unsigned idx, bus_width = 0; > > + int err = 0; > > > > BUG_ON(!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) > > - 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) > > - 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 > > @@ -828,8 +906,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 > > @@ -844,25 +921,226 @@ 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(card->host), ext_csd_bits[idx]); > > + } > > } > > > > - /* switch to HS200 mode if bus width set successfully */ > > - if (!err) > > + return err; > > +} > > + > > +/* > > + * Switch to the high-speed mode > > + */ > > +static int mmc_select_hs(struct mmc_card *card) > > +{ > > + int err; > > + > > + BUG_ON(!card); > > + > > + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, > > + EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, > > + card->ext_csd.generic_cmd6_time); > > + if (!err) { > > + mmc_card_set_highspeed(card); > > + 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, u8 *ext_csd) > > +{ > > + struct mmc_host *host; > > + u32 bus_width, ext_csd_bits; > > + int err = 0, ddr; > > + > > + BUG_ON(!card); > > + > > + ddr = mmc_snoop_ddr(card); > > + if (!(ddr & EXT_CSD_CARD_TYPE_DDR_52)) > > + return 0; > > + > > + host = card->host; > > + 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 (ddr & EXT_CSD_CARD_TYPE_DDR_1_2V) { > > + err = __mmc_set_signal_voltage(host, > > + MMC_SIGNAL_VOLTAGE_120); > > + if (err) > > + return err; > > + } > > + > > + mmc_card_set_ddr_mode(card); > > + mmc_set_timing(host, MMC_TIMING_UHS_DDR50); > > + > > + 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) > > +{ > > + int err = -EINVAL; > > + struct mmc_host *host; > > + > > + BUG_ON(!card); > > + > > + host = card->host; > > + > > + if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_SDR_1_2V) > > + err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120); > > + > > + if (err && card->mmc_avail_type & EXT_CSD_CARD_TYPE_SDR_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, 0); > > + EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200, > > + card->ext_csd.generic_cmd6_time); > > + if (!err) { > > + mmc_card_set_hs200(card); > > + 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) > > +{ > > + struct mmc_host *host; > > + int err = 0; > > + > > + BUG_ON(!card); > > + > > + host = card->host; > > + > > + if ((card->csd.mmca_vsn < CSD_SPEC_VER_4 && > > + card->ext_csd.hs_max_dtr == 0)) > > + goto bus_speed; > > + > > + if (card->ext_csd.hs200_max_dtr > 52000000 && > > + host->caps2 & MMC_CAP2_HS200) > > + err = mmc_select_hs200(card); > > + else if (host->caps & MMC_CAP_MMC_HIGHSPEED) > > + err = mmc_select_hs(card); > > + > > + if (err && err != -EBADMSG) > > + return err; > > + > > + if (err) { > > + pr_warn("%s: switch to %s failed\n", > > + mmc_card_highspeed(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) > > +{ > > + int err = 0; > > + struct mmc_host *host; > > + > > + BUG_ON(!card); > > + > > + host = card->host; > > + > > + if (host->caps2 & MMC_CAP2_HS200 && > > + 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_warn("%s: tuning execution failed\n", > > + mmc_hostname(card->host)); > > + } > > + > > + return err; > > +} > > + > > +/* > > * Handle the detection and initialisation of a card. > > * > > * In the case of a resume, "oldcard" will contain the card > > @@ -872,9 +1150,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; > > > > @@ -1066,209 +1343,30 @@ 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->ext_csd.hs_max_dtr > 52000000 && > > - host->caps2 & MMC_CAP2_HS200) > > - err = mmc_select_hs200(card); > > - else if (host->caps & MMC_CAP_MMC_HIGHSPEED) > > - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, > > - EXT_CSD_HS_TIMING, 1, > > - card->ext_csd.generic_cmd6_time); > > - > > - 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->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); > > - } > > - } > > - } > > - > > - /* > > - * Compute bus speed. > > - */ > > - max_dtr = (unsigned int)-1; > > - > > - if (mmc_card_highspeed(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)) > > - 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_highspeed(card)) { > > - if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) > > - && ((host->caps & (MMC_CAP_1_8V_DDR | > > - MMC_CAP_UHS_DDR50)) > > - == (MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50))) > > - 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 | > > - MMC_CAP_UHS_DDR50)) > > - == (MMC_CAP_1_2V_DDR | MMC_CAP_UHS_DDR50))) > > - ddr = MMC_1_2V_DDR_MODE; > > - } > > + 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 ((host->caps2 & MMC_CAP2_HS200) && > > - 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; > > + } else if (mmc_card_highspeed(card)) { > > + /* Select the desired bus width optionally */ > > + err = mmc_select_bus_width(card); > > + if (!IS_ERR_VALUE(err)) { > > + err = mmc_select_hs_ddr(card, ext_csd); > > + if (err) > > + goto err; > > } > > - > > - 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); > > } > > > > /* > > - * Activate wide bus and DDR (if supported). > > + * Choose the power calss with selected bus interface > > */ > > - 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_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, > > - 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_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], > > - 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 == MMC_1_2V_DDR_MODE) { > > - err = __mmc_set_signal_voltage(host, > > - MMC_SIGNAL_VOLTAGE_120); > > - if (err) > > - goto err; > > - } > > - mmc_card_set_ddr_mode(card); > > - mmc_set_timing(card->host, MMC_TIMING_UHS_DDR50); > > - mmc_set_bus_width(card->host, bus_width); > > - } > > - } > > + mmc_select_powerclass(card, ext_csd); > > > > /* > > * Enable HPI feature (if supported) > > diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h > > index 176fdf8..c119735 100644 > > --- a/include/linux/mmc/card.h > > +++ b/include/linux/mmc/card.h > > @@ -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 > > @@ -299,7 +300,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 */ > > diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h > > index 99f5709..69d58b1 100644 > > --- a/include/linux/mmc/host.h > > +++ b/include/linux/mmc/host.h > > @@ -60,12 +60,6 @@ struct mmc_ios { > > #define MMC_TIMING_UHS_DDR50 7 > > #define MMC_TIMING_MMC_HS200 8 > > > > -#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 > > diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h > > index 50bcde3..87df508 100644 > > --- a/include/linux/mmc/mmc.h > > +++ b/include/linux/mmc/mmc.h > > @@ -373,6 +373,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) > > -- > > 1.7.0.4 > > > > > -- > To unsubscribe from this list: send the line "unsubscribe linux-mmc" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html