备注:
1. Kernel版本:5.4
2. 使用工具:Source Insight 4.0
3. 参考博客:
2. [mmc subsystem] mmc core数据结构和宏定义说明
Linux MMC framework(2)_host controller driver
struct mmc_host是mmc core由host controller抽象出来的结构体,用于代表一个mmc host控制器。
struct mmc_host {
struct device *parent; //对应的host controller的device
struct device class_dev; // mmc_host的device结构体,会挂在class/mmc_host下
int index; // 该host的索引号
const struct mmc_host_ops *ops; // 该host的操作集,由host controller设置
struct mmc_pwrseq *pwrseq; // 该host电源管理有关的操作函数集
unsigned int f_min; // 该host支持的最低频率
unsigned int f_max; // 该host支持的最大频率
unsigned int f_init; // 该host使用的初始化频率
/*
* OCR(Operating Conditions Register)
* 是MMC/SD/SDIO卡的一个32-bit的寄存器,
* 其中有些bit指明了该卡的操作电压。
* MMC host在驱动这些卡的时候,
* 需要和Host自身所支持的电压范围匹配之后,
* 才能正常操作,这就是ocr_avail的存在意义
*/
u32 ocr_avail; // 该host可支持的操作电压范围
/*
* 如果MMC host针对SDIO、SD、MMC等不同类型的卡,
* 所支持的电压范围不同的话,
* 需要通过这几个字段特别指定。
* 否则,不需要赋值(初始化为0)
*/
u32 ocr_avail_sdio; /* SDIO-specific OCR */
u32 ocr_avail_sd; /* SD-specific OCR */
u32 ocr_avail_mmc; /* MMC-specific OCR */
#ifdef CONFIG_PM_SLEEP
struct notifier_block pm_notify;// 用于支持power management有关的notify实现
#endif
u32 max_current_330; // 3.3V时的最大电流
u32 max_current_300; // 3.0V时的最大电流
u32 max_current_180; // 1.8V时的最大电流
#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */
#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
#define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */
#define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */
#define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */
#define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */
#define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */
#define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */
#define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */
#define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */
#define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */
#define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */
#define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */
#define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */
#define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */
#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */
#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */
// 指示该MMC host所支持的功能特性
u32 caps; /* Host capabilities */
#define MMC_CAP_4_BIT_DATA (1 << 0) /* Can the host do 4 bit transfers */
#define MMC_CAP_MMC_HIGHSPEED (1 << 1) /* Can do MMC high-speed timing */
#define MMC_CAP_SD_HIGHSPEED (1 << 2) /* Can do SD high-speed timing */
#define MMC_CAP_SDIO_IRQ (1 << 3) /* Can signal pending SDIO IRQs */
#define MMC_CAP_SPI (1 << 4) /* Talks only SPI protocols */
#define MMC_CAP_NEEDS_POLL (1 << 5) /* Needs polling for card-detection */
#define MMC_CAP_8_BIT_DATA (1 << 6) /* Can the host do 8 bit transfers */
#define MMC_CAP_AGGRESSIVE_PM (1 << 7) /* Suspend (e)MMC/SD at idle */
#define MMC_CAP_NONREMOVABLE (1 << 8) /* Nonremovable e.g. eMMC */
#define MMC_CAP_WAIT_WHILE_BUSY (1 << 9) /* Waits while card is busy */
#define MMC_CAP_ERASE (1 << 10) /* Allow erase/trim commands */
#define MMC_CAP_3_3V_DDR (1 << 11) /* Host supports eMMC DDR 3.3V */
#define MMC_CAP_1_8V_DDR (1 << 12) /* Host supports eMMC DDR 1.8V */
#define MMC_CAP_1_2V_DDR (1 << 13) /* Host supports eMMC DDR 1.2V */
#define MMC_CAP_POWER_OFF_CARD (1 << 14) /* Can power off after boot */
#define MMC_CAP_BUS_WIDTH_TEST (1 << 15) /* CMD14/CMD19 bus width ok */
#define MMC_CAP_UHS_SDR12 (1 << 16) /* Host supports UHS SDR12 mode */
#define MMC_CAP_UHS_SDR25 (1 << 17) /* Host supports UHS SDR25 mode */
#define MMC_CAP_UHS_SDR50 (1 << 18) /* Host supports UHS SDR50 mode */
#define MMC_CAP_UHS_SDR104 (1 << 19) /* Host supports UHS SDR104 mode */
#define MMC_CAP_UHS_DDR50 (1 << 20) /* Host supports UHS DDR50 mode */
#define MMC_CAP_UHS (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | \
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | \
MMC_CAP_UHS_DDR50)
#define MMC_CAP_SYNC_RUNTIME_PM (1 << 21) /* Synced runtime PM suspends. */
#define MMC_CAP_NEED_RSP_BUSY (1 << 22) /* Commands with R1B can't use R1. */
#define MMC_CAP_DRIVER_TYPE_A (1 << 23) /* Host supports Driver Type A */
#define MMC_CAP_DRIVER_TYPE_C (1 << 24) /* Host supports Driver Type C */
#define MMC_CAP_DRIVER_TYPE_D (1 << 25) /* Host supports Driver Type D */
#define MMC_CAP_DONE_COMPLETE (1 << 27) /* RW reqs can be completed within mmc_request_done() */
#define MMC_CAP_CD_WAKE (1 << 28) /* Enable card detect wake */
#define MMC_CAP_CMD_DURING_TFR (1 << 29) /* Commands during data transfer */
#define MMC_CAP_CMD23 (1 << 30) /* CMD23 supported. */
#define MMC_CAP_HW_RESET (1 << 31) /* Hardware reset */
// 指示该MMC host所支持的功能特性
u32 caps2; /* More host capabilities */
#define MMC_CAP2_BOOTPART_NOACC (1 << 0) /* Boot partition no access */
#define MMC_CAP2_FULL_PWR_CYCLE (1 << 2) /* Can do full power cycle */
#define MMC_CAP2_HS200_1_8V_SDR (1 << 5) /* can support */
#define MMC_CAP2_HS200_1_2V_SDR (1 << 6) /* can support */
#define MMC_CAP2_HS200 (MMC_CAP2_HS200_1_8V_SDR | \
MMC_CAP2_HS200_1_2V_SDR)
#define MMC_CAP2_CD_ACTIVE_HIGH (1 << 10) /* Card-detect signal active high */
#define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /* Write-protect signal active high */
#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)
#define MMC_CAP2_HSX00_1_8V (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS400_1_8V)
#define MMC_CAP2_HSX00_1_2V (MMC_CAP2_HS200_1_2V_SDR | MMC_CAP2_HS400_1_2V)
#define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17)
#define MMC_CAP2_NO_WRITE_PROTECT (1 << 18) /* No physical write protect pin, assume that card is always read-write */
#define MMC_CAP2_NO_SDIO (1 << 19) /* Do not send SDIO commands during initialization */
#define MMC_CAP2_HS400_ES (1 << 20) /* Host supports enhanced strobe */
#define MMC_CAP2_NO_SD (1 << 21) /* Do not send SD commands during initialization */
#define MMC_CAP2_NO_MMC (1 << 22) /* Do not send (e)MMC commands during initialization */
#define MMC_CAP2_CQE (1 << 23) /* Has eMMC command queue engine */
#define MMC_CAP2_CQE_DCMD (1 << 24) /* CQE can issue a direct command */
#define MMC_CAP2_AVOID_3_3V (1 << 25) /* Host must negotiate down from 3.3V */
#define MMC_CAP2_MERGE_CAPABLE (1 << 26) /* Host can merge a segment over the segment size */
int fixed_drv_type; /* fixed driver type for non-removable media */
// 该host所支持的电源管理特性
mmc_pm_flag_t pm_caps; /* supported pm features */
/* host specific block data */
unsigned int max_seg_size; /* see blk_queue_max_segment_size */
unsigned short max_segs; /* see blk_queue_max_segments */
unsigned short unused;
unsigned int max_req_size; /* maximum number of bytes in one req */
unsigned int max_blk_size; /* maximum size of one mmc block */
unsigned int max_blk_count; /* maximum number of blocks in one req */
unsigned int max_busy_timeout; /* max busy timeout in ms */
/* private data */
// 该host的bus使用的锁
spinlock_t lock; /* lock for claim and bus ops */
// 用于保存MMC bus的当前配置
struct mmc_ios ios; /* current io bus settings */
/* group bitfields together to minimize padding */
unsigned int use_spi_crc:1;
unsigned int claimed:1; /* host exclusively claimed */ // host是否已经被占用
unsigned int bus_dead:1; /* bus has been released */ // host的bus是否处于激活状态
unsigned int can_retune:1; /* re-tuning can be used */
unsigned int doing_retune:1; /* re-tuning in progress */
unsigned int retune_now:1; /* do re-tuning at next req */
unsigned int retune_paused:1; /* re-tuning is temporarily disabled */
unsigned int use_blk_mq:1; /* use blk-mq */
unsigned int retune_crc_disable:1; /* don't trigger retune upon crc */
unsigned int can_dma_map_merge:1; /* merging can be used */
int rescan_disable; /* disable card detection */ // 禁止rescan的标识,禁止搜索card
int rescan_entered; /* used with nonremovable devices */// 是否已经rescan过的标识,对应不可移除的设备只能rescan一次
int need_retune; /* re-tuning is needed */
int hold_retune; /* hold off re-tuning */
unsigned int retune_period; /* re-tuning period in secs */
struct timer_list retune_timer; /* for periodic re-tuning */
bool trigger_card_event; /* card_event necessary */
struct mmc_card *card; /* device attached to this host */// 和该host绑定在一起的card
wait_queue_head_t wq;
struct mmc_ctx *claimer; /* context that has host claimed */// 该host的占有者进程
int claim_cnt; /* "claim" nesting count */// 占有者进程对该host的占用计数
struct mmc_ctx default_ctx; /* default context */
struct delayed_work detect; // 检测卡槽变化的工作
int detect_change; /* card detect flag */// 需要检测卡槽变化的标识
struct mmc_slot slot; // 卡槽的结构体
const struct mmc_bus_ops *bus_ops; /* current bus driver */ // host的mmc总线的操作集
unsigned int bus_refs; /* reference counter */ // host的mmc总线的使用计数
unsigned int sdio_irqs;
struct task_struct *sdio_irq_thread;
struct delayed_work sdio_irq_work;
bool sdio_irq_pending;
atomic_t sdio_irq_thread_abort;
mmc_pm_flag_t pm_flags; /* requested pm features */
struct led_trigger *led; /* activity led */
#ifdef CONFIG_REGULATOR
bool regulator_enabled; /* regulator state */ // 代表regulator(LDO)的状态
#endif
struct mmc_supply supply;
struct dentry *debugfs_root; // 对应的debug目录结构体
/* Ongoing data transfer that allows commands during transfer */
struct mmc_request *ongoing_mrq;
#ifdef CONFIG_FAIL_MMC_REQUEST
struct fault_attr fail_mmc_request;
#endif
unsigned int actual_clock; /* Actual HC clock rate */
unsigned int slotno; /* used for sdio acpi binding */
int dsr_req; /* DSR value is valid */
u32 dsr; /* optional driver stage (DSR) value */
/* Command Queue Engine (CQE) support */
const struct mmc_cqe_ops *cqe_ops;
void *cqe_private;
int cqe_qdepth;
bool cqe_enabled;
bool cqe_on;
unsigned long private[0] ____cacheline_aligned;
};
mmc core将host需要提供的一些操作方法封装成struct mmc_host_ops。
mmc core主模块的很多接口都是基于这里面的操作方法来实现的,通过这些方法来操作host硬件达到对应的目的。
所以struct mmc_host_ops也是host controller driver需要实现的核心部分。
struct mmc_host_ops {
/*
* It is optional for the host to implement pre_req and post_req in
* order to support double buffering of requests (prepare one
* request while another request is active).
* pre_req() must always be followed by a post_req().
* To undo a call made to pre_req(), call post_req() with
* a nonzero err condition.
*/
// post_req和pre_req是为了实现异步请求处理而设置的,是非必需的,
// 异步请求处理就是指,当另外一个异步请求还没有处理完成的时候,
// 可以先准备另外一个异步请求而不必等待
void (*post_req)(struct mmc_host *host, struct mmc_request *req,
int err);
void (*pre_req)(struct mmc_host *host, struct mmc_request *req);
// host处理mmc请求的方法,在mmc_start_request中会调用
void (*request)(struct mmc_host *host, struct mmc_request *req);
/*
* Avoid calling the next three functions too often or in a "fast
* path", since underlaying controller might implement them in an
* expensive and/or slow way. Also note that these functions might
* sleep, so don't call them in the atomic contexts!
*/
/*
* Notes to the set_ios callback:
* ios->clock might be 0. For some controllers, setting 0Hz
* as any other frequency works. However, some controllers
* explicitly need to disable the clock. Otherwise e.g. voltage
* switching might fail because the SDCLK is not really quiet.
*/
// 设置host的总线的io setting
void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios);
/*
* Return values for the get_ro callback should be:
* 0 for a read/write card
* 1 for a read-only card
* -ENOSYS when not supported (equal to NULL callback)
* or a negative errno value when something bad happened
*/
int (*get_ro)(struct mmc_host *host); // 获取host上的card的读写属性
/*
* Return values for the get_cd callback should be:
* 0 for a absent card
* 1 for a present card
* -ENOSYS when not supported (equal to NULL callback)
* or a negative errno value when something bad happened
*/
int (*get_cd)(struct mmc_host *host); // 检测host的卡槽中card的插入状态
void (*enable_sdio_irq)(struct mmc_host *host, int enable);
/* Mandatory callback when using MMC_CAP2_SDIO_IRQ_NOTHREAD. */
void (*ack_sdio_irq)(struct mmc_host *host);
/* optional callback for HC quirks */ // 初始化card的方法
void (*init_card)(struct mmc_host *host, struct mmc_card *card);
int (*start_signal_voltage_switch)(struct mmc_host *host, struct mmc_ios *ios);
/* Check if the card is pulling dat[0:3] low */
int (*card_busy)(struct mmc_host *host); // 用于检测card是否处于busy状态
/* The tuning command opcode value is different for SD and eMMC cards */
// 执行tuning操作,为card选择一个合适的采样点
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);
/* Prepare switch to DDR during the HS400 init sequence */
int (*hs400_prepare_ddr)(struct mmc_host *host);
/* Prepare for switching from HS400 to HS200 */
void (*hs400_downgrade)(struct mmc_host *host);
/* Complete selection of HS400 */
void (*hs400_complete)(struct mmc_host *host);
/* Prepare enhanced strobe depending host driver */
void (*hs400_enhanced_strobe)(struct mmc_host *host,
struct mmc_ios *ios);
int (*select_drive_strength)(struct mmc_card *card,
unsigned int max_dtr, int host_drv,
int card_drv, int *drv_type);
void (*hw_reset)(struct mmc_host *host); // 硬件复位
void (*card_event)(struct mmc_host *host); // 硬件复位
/*
* Optional callback to support controllers with HW issues for multiple
* I/O. Returns the number of supported blocks for the request.
*/
int (*multi_io_quirk)(struct mmc_card *card,
unsigned int direction, int blk_size);
};
struct mmc_card是mmc core由mmc设备抽象出来的card设备的结构体,用于代表一个mmc设备。
/*
* MMC device
*/
struct mmc_card {
struct mmc_host *host; /* the host this device belongs to */ // 该mmc_card所属host
struct device dev; /* the device */ // 对应的device
u32 ocr; /* the current OCR setting */
unsigned int rca; /* relative card address of device */
unsigned int type; /* card type */ // card类型
#define MMC_TYPE_MMC 0 /* MMC card */
#define MMC_TYPE_SD 1 /* SD card */
#define MMC_TYPE_SDIO 2 /* SDIO card */
#define MMC_TYPE_SD_COMBO 3 /* SD combo (IO+mem) card */
unsigned int state; /* (our) card state */ // card的当前状态
unsigned int quirks; /* card quirks */ // 该card的一些特点
unsigned int quirk_max_rate; /* max rate set by 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 */
/* for byte mode */
#define MMC_QUIRK_NONSTD_SDIO (1<<2) /* non-standard SDIO card attached */
/* (missing CIA registers) */
#define MMC_QUIRK_NONSTD_FUNC_IF (1<<4) /* SDIO card has nonstd function interfaces */
#define MMC_QUIRK_DISABLE_CD (1<<5) /* disconnect CD/DAT[3] resistor */
#define MMC_QUIRK_INAND_CMD38 (1<<6) /* iNAND devices have broken CMD38 */
#define MMC_QUIRK_BLK_NO_CMD23 (1<<7) /* Avoid CMD23 for regular multiblock */
#define MMC_QUIRK_BROKEN_BYTE_MODE_512 (1<<8) /* Avoid sending 512 bytes in */
/* byte mode */
#define MMC_QUIRK_LONG_READ_TIME (1<<9) /* Data read time > CSD says */
#define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10) /* Skip secure for erase/trim */
#define MMC_QUIRK_BROKEN_IRQ_POLLING (1<<11) /* Polling SDIO_CCCR_INTx could create a fake interrupt */
#define MMC_QUIRK_TRIM_BROKEN (1<<12) /* Skip trim */
#define MMC_QUIRK_BROKEN_HPI (1<<13) /* Disable broken HPI support */
bool reenable_cmdq; /* Re-enable Command Queue */
unsigned int erase_size; /* erase size in sectors */
unsigned int erase_shift; /* if erase unit is power 2 */
unsigned int pref_erase; /* in sectors */
unsigned int eg_boundary; /* don't cross erase-group boundaries */
unsigned int erase_arg; /* erase / trim / discard */
u8 erased_byte; /* value of erased bytes */
u32 raw_cid[4]; /* raw card CID */ // 原始的cid寄存器的值
u32 raw_csd[4]; /* raw card CSD */ // 原始的csd寄存器的值
u32 raw_scr[2]; /* raw card SCR */ // 原始的scr寄存器的值
u32 raw_ssr[16]; /* raw card SSR */ // 原始的ssr寄存器的值
struct mmc_cid cid; /* card identification */ // 从cid寄存器的值解析出来的信息
struct mmc_csd csd; /* card specific */ // 从csd寄存器的值解析出来的信息
struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */ // 从ext_csd寄存器的值解析出来的信息
struct sd_scr scr; /* extra SD information */ // 外部sd card的信息
struct sd_ssr ssr; /* yet more SD information */ // 更多关于sd card的信息
struct sd_switch_caps sw_caps; /* switch (CMD6) caps */ // sd的切换属性
unsigned int sdio_funcs; /* number of SDIO functions */ // sdio funcs的数量
atomic_t sdio_funcs_probed; /* number of probed SDIO funcs */
struct sdio_cccr cccr; /* common card info */
struct sdio_cis cis; /* common tuple info */
struct sdio_func *sdio_func[SDIO_MAX_FUNCS]; /* SDIO functions (devices) */ //sdio func指针
struct sdio_func *sdio_single_irq; /* SDIO function when only one IRQ active */
unsigned num_info; /* number of info strings */
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 */
unsigned int mmc_avail_type; /* supported device type by both host and card */
unsigned int drive_strength; /* for UHS-I, HS200 or HS400 */
struct dentry *debugfs_root; // 对应debug目录的结构体
struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */ // 物理分区
unsigned int nr_parts; // 分区数量
unsigned int bouncesz; /* Bounce buffer size */
struct workqueue_struct *complete_wq; /* Private workqueue */
};
host的mmc总线的操作集,由host插入的card决定。
不同类型的card对mmc总线的操作有所不同。
struct mmc_bus_ops {
void (*remove)(struct mmc_host *); // 从软件上注销mmc总线上的card
void (*detect)(struct mmc_host *); // 检测mmc总线上的card是否被移除
int (*pre_suspend)(struct mmc_host *); // suspend前的准备工作
int (*suspend)(struct mmc_host *); // 对应mmc总线的suspend操作
int (*resume)(struct mmc_host *); // 对应mmc总线的resume操作
int (*runtime_suspend)(struct mmc_host *); // 对应mmc总线的runtime suspend操作
int (*runtime_resume)(struct mmc_host *); // 对应mmc总线的runtime resume操作
int (*alive)(struct mmc_host *); // 检测mmc总线上的card的激活状态
int (*shutdown)(struct mmc_host *);// 关闭mmc总线的操作
int (*hw_reset)(struct mmc_host *);// mmc总线上的HW 复位
int (*sw_reset)(struct mmc_host *);// mmc总线上的SW 复位
};
struct mmc_ios {
unsigned int clock; /* clock rate */ // 当前工作频率
unsigned short vdd; // 支持的电压表
unsigned int power_delay_ms; /* waiting for stable power */
/* vdd stores the bit number of the selected voltage range from below. */
unsigned char bus_mode; /* command output mode */ // 总线输出模式,包括开漏模式和上拉模式
#define MMC_BUSMODE_OPENDRAIN 1
#define MMC_BUSMODE_PUSHPULL 2
unsigned char chip_select; /* SPI chip select */ // spi片选
#define MMC_CS_DONTCARE 0
#define MMC_CS_HIGH 1
#define MMC_CS_LOW 2
unsigned char power_mode; /* power supply mode */ // 电源状态模式
#define MMC_POWER_OFF 0
#define MMC_POWER_UP 1
#define MMC_POWER_ON 2
#define MMC_POWER_UNDEFINED 3
unsigned char bus_width; /* data bus width */ // 总线宽度
#define MMC_BUS_WIDTH_1 0
#define MMC_BUS_WIDTH_4 2
#define MMC_BUS_WIDTH_8 3
unsigned char timing; /* timing specification used */ // 时序类型
#define MMC_TIMING_LEGACY 0
#define MMC_TIMING_MMC_HS 1
#define MMC_TIMING_SD_HS 2
#define MMC_TIMING_UHS_SDR12 3
#define MMC_TIMING_UHS_SDR25 4
#define MMC_TIMING_UHS_SDR50 5
#define MMC_TIMING_UHS_SDR104 6
#define MMC_TIMING_UHS_DDR50 7
#define MMC_TIMING_MMC_DDR52 8
#define MMC_TIMING_MMC_HS200 9
#define MMC_TIMING_MMC_HS400 10
unsigned char signal_voltage; /* signalling voltage (1.8V or 3.3V) */ // 信号的工作电压
#define MMC_SIGNAL_VOLTAGE_330 0
#define MMC_SIGNAL_VOLTAGE_180 1
#define MMC_SIGNAL_VOLTAGE_120 2
unsigned char drv_type; /* driver type (A, B, C, D) */ // 驱动类型
#define MMC_SET_DRIVER_TYPE_B 0
#define MMC_SET_DRIVER_TYPE_A 1
#define MMC_SET_DRIVER_TYPE_C 2
#define MMC_SET_DRIVER_TYPE_D 3
bool enhanced_strobe; /* hs400es selection */
};
struct mmc_command {
u32 opcode; // 命令的操作码,如MMC_GO_IDLE_STATE、MMC_SEND_OP_COND等等
u32 arg; // 命令的参数
#define MMC_CMD23_ARG_REL_WR (1 << 31)
#define MMC_CMD23_ARG_PACKED ((0 << 31) | (1 << 30))
#define MMC_CMD23_ARG_TAG_REQ (1 << 29)
u32 resp[4];
unsigned int flags; /* expected response type */
#define MMC_RSP_PRESENT (1 << 0)
#define MMC_RSP_136 (1 << 1) /* 136 bit response */
#define MMC_RSP_CRC (1 << 2) /* expect valid crc */
#define MMC_RSP_BUSY (1 << 3) /* card may send busy */
#define MMC_RSP_OPCODE (1 << 4) /* response contains opcode */
#define MMC_CMD_MASK (3 << 5) /* non-SPI command type */
#define MMC_CMD_AC (0 << 5)
#define MMC_CMD_ADTC (1 << 5)
#define MMC_CMD_BC (2 << 5)
#define MMC_CMD_BCR (3 << 5)
#define MMC_RSP_SPI_S1 (1 << 7) /* one status byte */
#define MMC_RSP_SPI_S2 (1 << 8) /* second byte */
#define MMC_RSP_SPI_B4 (1 << 9) /* four data bytes */
#define MMC_RSP_SPI_BUSY (1 << 10) /* card may send busy */
/*
* These are the native response types, and correspond to valid bit
* patterns of the above flags. One additional valid pattern
* is all zeros, which means we don't expect a response.
*/
#define MMC_RSP_NONE (0)
#define MMC_RSP_R1 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
#define MMC_RSP_R1B (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY)
#define MMC_RSP_R2 (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
#define MMC_RSP_R3 (MMC_RSP_PRESENT)
#define MMC_RSP_R4 (MMC_RSP_PRESENT)
#define MMC_RSP_R5 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
#define MMC_RSP_R6 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
#define MMC_RSP_R7 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
/* Can be used by core to poll after switch to MMC HS mode */
#define MMC_RSP_R1_NO_CRC (MMC_RSP_PRESENT|MMC_RSP_OPCODE)
#define mmc_resp_type(cmd) ((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))
/*
* These are the SPI response types for MMC, SD, and SDIO cards.
* Commands return R1, with maybe more info. Zero is an error type;
* callers must always provide the appropriate MMC_RSP_SPI_Rx flags.
*/
#define MMC_RSP_SPI_R1 (MMC_RSP_SPI_S1)
#define MMC_RSP_SPI_R1B (MMC_RSP_SPI_S1|MMC_RSP_SPI_BUSY)
#define MMC_RSP_SPI_R2 (MMC_RSP_SPI_S1|MMC_RSP_SPI_S2)
#define MMC_RSP_SPI_R3 (MMC_RSP_SPI_S1|MMC_RSP_SPI_B4)
#define MMC_RSP_SPI_R4 (MMC_RSP_SPI_S1|MMC_RSP_SPI_B4)
#define MMC_RSP_SPI_R5 (MMC_RSP_SPI_S1|MMC_RSP_SPI_S2)
#define MMC_RSP_SPI_R7 (MMC_RSP_SPI_S1|MMC_RSP_SPI_B4)
#define mmc_spi_resp_type(cmd) ((cmd)->flags & \
(MMC_RSP_SPI_S1|MMC_RSP_SPI_BUSY|MMC_RSP_SPI_S2|MMC_RSP_SPI_B4))
/*
* These are the command types.
*/
#define mmc_cmd_type(cmd) ((cmd)->flags & MMC_CMD_MASK)
unsigned int retries; /* max number of retries */ // 失败时的重复尝试次数
int error; /* command error */ // 命令的错误码
/*
* Standard errno values are used for errors, but some have specific
* meaning in the MMC layer:
*
* ETIMEDOUT Card took too long to respond
* EILSEQ Basic format problem with the received or sent data
* (e.g. CRC check failed, incorrect opcode in response
* or bad end bit)
* EINVAL Request cannot be performed because of restrictions
* in hardware and/or the driver
* ENOMEDIUM Host can determine that the slot is empty and is
* actively failing requests
*/
unsigned int busy_timeout; /* busy detect timeout in ms */
/* Set this flag only for blocking sanitize request */
bool sanitize_busy;
// 和该命令关联在一起的数据段
struct mmc_data *data; /* data segment associated with cmd */
// 该命令关联到哪个request
struct mmc_request *mrq; /* associated request */
};
mmc core用struct mmc_data来表示一个命令包。
struct mmc_data {
unsigned int timeout_ns; /* data timeout (in ns, max 80ms) */ // 超时时间,以ns为单位
unsigned int timeout_clks; /* data timeout (in clocks) */ // 超时时间,以clock为单位
unsigned int blksz; /* data block size */ // 块大小
unsigned int blocks; /* number of blocks */ // 块数量
unsigned int blk_addr; /* block address */ // card地址
int error; /* data error */
unsigned int flags; // 传输标识
#define MMC_DATA_WRITE BIT(8)
#define MMC_DATA_READ BIT(9)
/* Extra flags used by CQE */
#define MMC_DATA_QBR BIT(10) /* CQE queue barrier*/
#define MMC_DATA_PRIO BIT(11) /* CQE high priority */
#define MMC_DATA_REL_WR BIT(12) /* Reliable write */
#define MMC_DATA_DAT_TAG BIT(13) /* Tag request */
#define MMC_DATA_FORCED_PRG BIT(14) /* Forced programming */
unsigned int bytes_xfered;
struct mmc_command *stop; /* stop command */ // 结束传输的命令
struct mmc_request *mrq; /* associated request */// 该命令关联到哪个request
unsigned int sg_len; /* size of scatter list */ sg数组的size
int sg_count; /* mapped sg entries */ // 通过sg map出来的实际的entry的个
struct scatterlist *sg; /* I/O scatter list */ //一个struct scatterlist类型的数组
s32 host_cookie; /* host private data */ // host driver的私有数据
};
struct mmc_request是mmc core向host controller发起命令请求的处理单位。其包含了要传输的命令和数据。
struct mmc_request {
struct mmc_command *sbc; /* SET_BLOCK_COUNT for multiblock */ // 设置块数量的命令,怎么用的后续再补充
struct mmc_command *cmd; // 要传输的命令
struct mmc_data *data; // 要传输的数据
struct mmc_command *stop; // 要传输的stop命令
struct completion completion; // 完成量
struct completion cmd_completion;
// 传输结束后的回调函数
void (*done)(struct mmc_request *);/* completion function */
/*
* Notify uppers layers (e.g. mmc block driver) that recovery is needed
* due to an error associated with the mmc_request. Currently used only
* by CQE.
*/
void (*recovery_notifier)(struct mmc_request *);
struct mmc_host *host; // 所属host
/* Allow other commands during this ongoing data transfer or busy wait */
bool cap_cmd_during_tfr;
int tag;
};