一、说明
1、设置总线时需要设置的内容
- 时钟频率
host需要提供给emmc对应的时钟。如上述所说,不同的总线速度模式对应不同的最大时钟频率。
只需要设置host侧即可。 - 总线速度模式的设置
这是host和emmc card通讯的一种时序规范,因此,host和emmc的总线速度模式必须匹配起来才能正常通讯。
需要设置host侧和emmc侧。 - 总线宽度模式的设置
host和emmc通讯的DATA脚数量的定义,同样会影响他们之间的通讯。因此,双方也必须规定一个固定的宽度来进行后续的数据传输。
需要设置host侧和emmc侧。 - 信号电压的设置
也就是IO电压。对于sd card来说,card侧需要知道host提供的信号电压(3.3V或者1.8V)。但是emmc并不需要。
只需要设置host侧即可。
2、emmc支持的总线速度模式
信号电压、时钟频率、总线宽度很大程度上都取决于总线速度模式。以下来看一下他们的关系。
从《emmc 5.1》协议上看,有如下几种总线速度模式
- 总线速度模式说明
- legacy mode
单边采样(SDR),支持3V/1.8V/1.2V的信号电压,总线宽度支持1、4、8bit模式。
最大频率支持到26Mhz。
对应kernel中host的MMC_TIMING_LEGACY时序。 - HS mode
单边采样(SDR),支持3V/1.8V/1.2V的信号电压,总线宽度支持1、4、8bit模式。
最大频率支持到52Mhz
对应kernel中host的MMC_TIMING_MMC_HS时序。 - HSDDR mode
双边采样(DDR),支持3V/1.8V/1.2V的信号电压,总线宽度支持4、8bit模式。
最大频率支持到52Mhz
对应kernel中host的MMC_TIMING_UHS_DDR50时序。 - HS200 mode
单边采样(SDR),支持1.8V/1.2V的信号电压,总线宽度支持4、8bit模式。
最大频率支持到200Mhz
对应kernel中host的MMC_TIMING_MMC_HS200时序。 - HS400 mode
双边采样(DDR),支持1.8V/1.2V的信号电压,总线宽度支持8bit模式。
最大频率支持到200Mhz。
对应kernel中host的MMC_TIMING_MMC_HS400时序。
- legacy mode
二、总线参数设置方法
1、时钟频率的设置
- 各个总线速度模式下的最大时钟频率在协议中已经是固定的了。
在代码中定义如下
#define MMC_HIGH_26_MAX_DTR 26000000
#define MMC_HIGH_52_MAX_DTR 52000000
#define MMC_HIGH_DDR_MAX_DTR 52000000
#define MMC_HS200_MAX_DTR 200000000
#define MMC_HS400_MAX_DTR 200000000
- 设置时钟频率方法
mmc core已经提供了接口,mmc_set_clock,直接调用即可。
示例如下
mmc_set_clock(host, MMC_HIGH_52_MAX_DTR);
2、总线速度模式的设置
- 如何获取emmc支持的总线速度模式?
从ext_csd中获取:
kernel中定义如下
#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 0xFF /* Mask out reserved bits */
#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 */ /* SDR mode @1.2V I/O */
#define EXT_CSD_CARD_TYPE_HS200 (EXT_CSD_CARD_TYPE_SDR_1_8V | EXT_CSD_CARD_TYPE_SDR_1_2V)
#define EXT_CSD_CARD_TYPE_HS400_1_8V (1<<6) /* Card can run at 200MHz */ /* DDR mode @1.8V I/O */
#define EXT_CSD_CARD_TYPE_HS400_1_2V (1<<7) /* Card can run at 200MHz */ /* DDR mode @1.2V I/O */
#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V | EXT_CSD_CARD_TYPE_HS400_1_2V)
使用示例:
card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V
- 如何设置emmc的总线速度模式
主要是设置ext_csd的HS_TIMINIG寄存器
使用示例
//HS SDR(mmc_select_hs):
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,EXT_CSD_HS_TIMING, 1,card->ext_csd.generic_cmd6_time);
//HS DDR(mmc_select_hsddr->mmc_select_hs):
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,EXT_CSD_HS_TIMING, 1,card->ext_csd.generic_cmd6_time);
其ddr和总线宽度模式一起设置。
//HS 200(mmc_select_hs200)
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 2, 0);
//HS 400(mmc_select_hs400)
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 3, 0);
- 如何获取host支持的总线速度模式
根据mmc_host的caps属性和caps2属性进行判断。
#define MMC_CAP2_HS400_1_8V (1 << 22) /* can support */
#define MMC_CAP2_HS400_1_2V (1 << 23) /* can support */
#define MMC_CAP2_HS400 (MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V)
#define MMC_CAP2_HS200_1_8V_SDR (1 << 5) /* can support */
#define MMC_CAP2_HS200_1_2V_SDR (1 << 6)