备注:
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; };