mmc: tmio: Use modern PM ops
Subsystems (9)
Re: [PATCH v5 2/5] mmc: identify available device type to select
In reply to Seungwon JeonQuoted 7 lines · Seungwon Jeon
Device types which are supported by both host and device can be identified when
EXT_CSDis read. There is no need to check host's capability anymore.Signed-off-by Seungwon Jeon <[email protected]>Tested-by Jaehoon Chung <[email protected]>Acked-by Jaehoon Chung <[email protected]>
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@@ -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@@ -68,7 +68,6 @@ struct mmc_ext_csd {#define MMC_HIGH_DDR_MAX_DTR 52000000#define MMC_HS200_MAX_DTR 200000000unsigned 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@@ -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 0include/linux/mmc/mmc.h +8
-5@@ -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
PATCH v5 3/5 mmc: step power class after final selection of bus mode
In reply to Seungwon JeonPower 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
@@ -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
PATCH v5 4/5 mmc: rework selection of bus speed mode
In reply to Seungwon JeonCurrent 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
@@ -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
@@ -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
@@ -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
PATCH v5 5/5 mmc: add support for HS400 mode of eMMC5.0
In reply to Seungwon JeonThis 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
@@ -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
@@ -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
@@ -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
@@ -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 10unsigned 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
@@ -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
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.
Signed-off-by Seungwon Jeon <[email protected]>Tested-by Jaehoon Chung <[email protected]>Acked-by Jaehoon Chung <[email protected]>
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@@ -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@@ -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@@ -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@@ -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@@ -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 10unsigned 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@@ -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
v6 cover update selection of bus speed mode for eMMC
In reply to Seungwon JeonThis 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
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 ofprepare_hs400_tuningcallback(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 inmmc_select_hs400()using__mmc_switch().Changes in v3:
Removed the function to check DDRtype(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.2VDocumentation/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
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 andeMMC".
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 ofprepare_hs400_tuningcallback(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
PATCH v6 1/6 mmc: drop the speed mode of card's state
In reply to Seungwon JeonTiming 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v6 2/6 mmc: identify available device type to select
In reply to Seungwon JeonDevice 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
@@ -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
@@ -68,7 +68,6 @@ struct mmc_ext_csd {#define MMC_HIGH_DDR_MAX_DTR 52000000#define MMC_HS200_MAX_DTR 200000000unsigned 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
@@ -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
@@ -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
PATCH v6 3/6 mmc: step power class after final selection of bus mode
In reply to Seungwon JeonPower 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
@@ -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
PATCH v6 4/6 mmc: rework selection of bus speed mode
In reply to Seungwon JeonCurrent 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
@@ -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
@@ -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
@@ -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
PATCH v6 5/6 mmc: add support for HS400 mode of eMMC5.0
In reply to Seungwon JeonThis 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
@@ -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
@@ -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
@@ -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
@@ -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 10unsigned 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
@@ -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
PATCH v6 6/6 mmc: core: add DT bindings for eMMC HS400 1.8/1.2V
In reply to Seungwon JeonProvide 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
@@ -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
@@ -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
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.
Signed-off-by Seungwon Jeon <[email protected]>
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@@ -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@@ -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
cover update selection of bus speed mode for eMMC
In reply to Seungwon JeonThis 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
PATCH 1/6 mmc: drop the speed mode of card's state
In reply to Seungwon JeonTiming 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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.
Signed-off-by Seungwon Jeon <[email protected]>Tested-by Jaehoon Chung <[email protected]>Acked-by Jaehoon Chung <[email protected]>Signed-off-by Ulf Hansson <[email protected]>Signed-off-by Chris Ball <[email protected]>
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
PATCH 2/6 mmc: identify available device type to select
In reply to Seungwon JeonDevice 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
@@ -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
@@ -68,7 +68,6 @@ struct mmc_ext_csd {#define MMC_HIGH_DDR_MAX_DTR 52000000#define MMC_HS200_MAX_DTR 200000000unsigned 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
@@ -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
@@ -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
PATCH 3/6 mmc: step power class after final selection of bus mode
In reply to Seungwon JeonPower 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
@@ -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
PATCH 4/6 mmc: rework selection of bus speed mode
In reply to Seungwon JeonCurrent 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
@@ -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
@@ -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
@@ -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
PATCH 5/6 mmc: add support for HS400 mode of eMMC5.0
In reply to Seungwon JeonThis 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
@@ -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
@@ -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
@@ -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
@@ -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 10unsigned 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
@@ -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
PATCH 6/6 mmc: core: add DT bindings for eMMC HS400 1.8/1.2V
In reply to Seungwon JeonProvide 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
@@ -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
@@ -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
PATCH RESEND 1/5 mmc: drop the speed mode of card's state
In reply to Ulf HanssonTiming 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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.
Signed-off-by Seungwon Jeon <[email protected]>--- 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
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
-4device_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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -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
-17struct 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@@ -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
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.
Signed-off-by Seungwon Jeon <[email protected]>--- 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
-0drivers/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
-4device_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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -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
-6struct 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@@ -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
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.
Signed-off-by Seungwon Jeon <[email protected]>--- 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
-0drivers/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
-4device_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@@ -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@@ -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@@ -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@@ -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@@ -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@@ -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
-6struct 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@@ -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?
returncard->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 JeonQuoted 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
PATCH v2 1/5 mmc: drop the speed mode of card's state
In reply to Seungwon JeonTiming 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v3 1/5 mmc: drop the speed mode of card's state
In reply to Seungwon JeonTiming 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH RESEND 2/5 mmc: identify available device type to select
In reply to Ulf HanssonDevice 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
@@ -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
@@ -68,7 +68,6 @@ struct mmc_ext_csd {#define MMC_HIGH_DDR_MAX_DTR 52000000#define MMC_HS200_MAX_DTR 200000000unsigned 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
@@ -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
@@ -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
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
@@ -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
@@ -68,7 +68,6 @@ struct mmc_ext_csd {#define MMC_HIGH_DDR_MAX_DTR 52000000#define MMC_HS200_MAX_DTR 200000000unsigned 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
@@ -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
@@ -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
Jaehoon Chung
maintainerRe: [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_CSDis read. There is no need to check host's capability anymore.Signed-off-by Seungwon Jeon <[email protected]>---
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@@ -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
-1hs_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@@ -68,7 +68,6 @@ struct mmc_ext_csd {#define MMC_HIGH_DDR_MAX_DTR 52000000#define MMC_HS200_MAX_DTR 200000000unsigned 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@@ -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 0include/linux/mmc/mmc.h +8
-4@@ -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 */
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_CSDis read. There is no need to check host's capability anymore.Signed-off-by Seungwon Jeon <[email protected]>---
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@@ -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
-1if (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_HS200need 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@@ -68,7 +68,6 @@ struct mmc_ext_csd {#define MMC_HIGH_DDR_MAX_DTR 52000000#define MMC_HS200_MAX_DTR 200000000unsigned 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@@ -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 0include/linux/mmc/mmc.h +4
-2@@ -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
Jaehoon Chung
maintainerRe: [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_CSDis read. There is no need to check host's capability anymore.Signed-off-by Seungwon Jeon <[email protected]>---
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@@ -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
-1if (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_HS200need no more, doesn't?
Quoted 1 line
If you mean to remove '
MMC_CAP2_HS200' definition, it is currently used insdhci.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 JeonQuoted 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@@ -68,7 +68,6 @@ struct mmc_ext_csd {#define MMC_HIGH_DDR_MAX_DTR 52000000#define MMC_HS200_MAX_DTR 200000000unsigned 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@@ -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 0include/linux/mmc/mmc.h +8
-4@@ -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
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_CSDis read. There is no need to check host's capability anymore.Signed-off-by Seungwon Jeon <[email protected]>---
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@@ -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
-1if (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_HS200need no more, doesn't?
Quoted 5 lines
Quoted 1 line
If you mean to remove '
MMC_CAP2_HS200' definition, it is currently used insdhci.cI have also checked that it is used in
sdhci.c.
but I think that capability likeMMC_CAP2_HS200was defined to use for core, not controller. It can be changed other quirks instead ofMMC_CAP2_HS200intosdhci.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
Jaehoon Chung
maintainerRe: [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_CSDis read. There is no need to check host's capability anymore.Signed-off-by Seungwon Jeon <[email protected]>---
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@@ -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
-1if (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_HS200need 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 insdhci.cI have also checked that it is used in
sdhci.c.
but I think that capability likeMMC_CAP2_HS200was defined to use for core, not controller. It can be changed other quirks instead ofMMC_CAP2_HS200intosdhci.c
how about?Hmm.
I feel like current way is not bad insdhci.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
Re: [PATCH v2 2/5] mmc: identify available device type to select
In reply to Seungwon JeonQuoted 78 lines · Seungwon Jeon
Device types which are supported by both host and device can be identified when
EXT_CSDis read. There is no need to check host's capability anymore.Signed-off-by Seungwon Jeon <[email protected]>---
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@@ -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@@ -68,7 +68,6 @@ struct mmc_ext_csd {#define MMC_HIGH_DDR_MAX_DTR 52000000#define MMC_HS200_MAX_DTR 200000000unsigned 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@@ -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 0include/linux/mmc/mmc.h +8
-5@@ -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
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_CSDis read. There is no need to check host's capability anymore.Signed-off-by Seungwon Jeon <[email protected]>---
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@@ -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@@ -68,7 +68,6 @@ struct mmc_ext_csd {#define MMC_HIGH_DDR_MAX_DTR 52000000#define MMC_HS200_MAX_DTR 200000000unsigned 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@@ -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 0include/linux/mmc/mmc.h +8
-5@@ -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
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_CSDis read. There is no need to check host's capability anymore.Signed-off-by Seungwon Jeon <[email protected]>---
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@@ -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@@ -68,7 +68,6 @@ struct mmc_ext_csd {#define MMC_HIGH_DDR_MAX_DTR 52000000#define MMC_HS200_MAX_DTR 200000000unsigned 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 JeonQuoted 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@@ -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 0include/linux/mmc/mmc.h +8
-5@@ -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
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_CSDis read. There is no need to check host's capability anymore.Signed-off-by Seungwon Jeon <[email protected]>---
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@@ -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 HanssonQuoted 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@@ -68,7 +68,6 @@ struct mmc_ext_csd {#define MMC_HIGH_DDR_MAX_DTR 52000000#define MMC_HS200_MAX_DTR 200000000unsigned 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 JeonQuoted 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@@ -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 0include/linux/mmc/mmc.h +8
-5@@ -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
Re: [PATCH v2 2/5] mmc: identify available device type to select
In reply to Seungwon JeonQuoted 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_CSDis read. There is no need to check host's capability anymore.Signed-off-by Seungwon Jeon <[email protected]>---
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@@ -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@@ -68,7 +68,6 @@ struct mmc_ext_csd {#define MMC_HIGH_DDR_MAX_DTR 52000000#define MMC_HS200_MAX_DTR 200000000unsigned 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 JeonQuoted 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@@ -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 0include/linux/mmc/mmc.h +8
-5@@ -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
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_CSDis read. There is no need to check host's capability anymore.Signed-off-by Seungwon Jeon <[email protected]>---
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@@ -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 enhancementof 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@@ -68,7 +68,6 @@ struct mmc_ext_csd {#define MMC_HIGH_DDR_MAX_DTR 52000000#define MMC_HS200_MAX_DTR 200000000unsigned 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 HanssonQuoted 67 lines
Thanks,
Seungwon JeonQuoted 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@@ -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 0include/linux/mmc/mmc.h +8
-5@@ -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
PATCH v3 2/5 mmc: identify available device type to select
In reply to Seungwon JeonDevice 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
@@ -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
@@ -68,7 +68,6 @@ struct mmc_ext_csd {#define MMC_HIGH_DDR_MAX_DTR 52000000#define MMC_HS200_MAX_DTR 200000000unsigned 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
@@ -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
@@ -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
PATCH RESEND 3/5 mmc: step power class after final selection of bus mode
In reply to Ulf HanssonPower 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
@@ -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
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
@@ -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
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.
Signed-off-by Seungwon Jeon <[email protected]>---
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@@ -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
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.
Signed-off-by Seungwon Jeon <[email protected]>---
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@@ -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
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.
Signed-off-by Seungwon Jeon <[email protected]>---
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@@ -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 JeonQuoted 3 lines
Kind regards
Ulf Hansson
PATCH v3 3/5 mmc: step power class after final selection of bus mode
In reply to Seungwon JeonPower 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
@@ -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
PATCH RESEND 4/5 mmc: rework selection of bus speed mode
In reply to Ulf HanssonCurrent 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
@@ -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
@@ -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
@@ -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
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
@@ -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
@@ -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
@@ -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
PATCH v3 4/5 mmc: rework selection of bus speed mode
In reply to Seungwon JeonCurrent 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
@@ -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
@@ -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
@@ -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
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 modeselection(HS, HS-DDR, HS200 and etc)
* Rearranged the mode selection sequence with supported device type
* Adds maximum speed for HS200mode(hs200_max_dtr)
* Adds field definition forHS_TIMINGofEXT_CSDSigned-off-by Seungwon Jeon <[email protected]>Tested-by Jaehoon Chung <[email protected]>Acked-by Jaehoon Chung <[email protected]>--- 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@@ -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@@ -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
-2static 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@@ -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 52000000include/linux/mmc/mmc.h +4
-1@@ -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
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 modeselection(HS, HS-DDR, HS200 and etc)
* Rearranged the mode selection sequence with supported device type
* Adds maximum speed for HS200mode(hs200_max_dtr)
* Adds field definition forHS_TIMINGofEXT_CSDSigned-off-by Seungwon Jeon <[email protected]>Tested-by Jaehoon Chung <[email protected]>Acked-by Jaehoon Chung <[email protected]>--- 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@@ -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@@ -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 intmax_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
-2static 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
Ulf Hansson
Acked-byRe: [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 modeselection(HS, HS-DDR, HS200 and etc)
* Rearranged the mode selection sequence with supported device type
* Adds maximum speed for HS200mode(hs200_max_dtr)
* Adds field definition forHS_TIMINGofEXT_CSDSigned-off-by Seungwon Jeon <[email protected]>Tested-by Jaehoon Chung <[email protected]>Acked-by Jaehoon Chung <[email protected]>--- 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@@ -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@@ -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 intmax_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
-2static 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-bitI really appreciate your deep reviews.
Thanks,
Seungwon Jeon
PATCH RESEND 5/5 mmc: add support for HS400 mode of eMMC5.0
In reply to Ulf HanssonThis 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
@@ -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
@@ -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
@@ -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
@@ -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 11unsigned 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
@@ -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
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
@@ -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
@@ -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
@@ -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
@@ -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 11unsigned 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
@@ -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
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.
Signed-off-by Seungwon Jeon <[email protected]>---
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@@ -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@@ -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@@ -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@@ -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@@ -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 11unsigned 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@@ -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
RE: [PATCH v2 5/5] mmc: add support for HS400 mode of eMMC5.0
Quoted 1 line · Jackey Shen
Signed-off-by Jackey Shen <[email protected]>
I'll send next version with adding your Reviewed-by.
Thanks,
Seungwon Jeon
Quoted 368 lines
Thanks,
JackeyQuoted 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.
Signed-off-by Seungwon Jeon <[email protected]>---
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@@ -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@@ -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@@ -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@@ -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@@ -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 11unsigned 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@@ -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
PATCH v3 5/5 mmc: add support for HS400 mode of eMMC5.0
In reply to Seungwon JeonThis 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
@@ -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
@@ -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
@@ -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
@@ -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 11unsigned 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
@@ -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
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.
Signed-off-by Seungwon Jeon <[email protected]>Reviewed-by Jackey Shen <[email protected]>Tested-by Jaehoon Chung <[email protected]>Acked-by Jaehoon Chung <[email protected]>--- 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@@ -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@@ -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@@ -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 separateMMC_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@@ -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
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
-0unsigned 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@@ -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
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.
Signed-off-by Seungwon Jeon <[email protected]>Reviewed-by Jackey Shen <[email protected]>Tested-by Jaehoon Chung <[email protected]>Acked-by Jaehoon Chung <[email protected]>--- 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@@ -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@@ -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@@ -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_TUNINGvalue?
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@@ -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
-0include/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
-0unsigned 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
-1static 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@@ -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