Linux MMC介绍
生活随笔
收集整理的這篇文章主要介紹了
Linux MMC介绍
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1. 介紹
Linux中,將包括MMC、SD、SDIO統稱為MMC子系統
MMC子系統從功能上可分為三個層次
- card層: Card驅動, 或稱client驅動 - core層: MMC的核心層, 完成不同協議和規范的實現, 為host層和設備驅動層提供接口函數 - host層: Host驅動, 針對不同主機端的SDHC、MMC控制器的驅動
2. 數據結構
MMC中包含的主要數據結構如下
- mmc_host 表示一個mmc host控制器 - mmc_card 表示一個mmc設備 - mmc_ios IO總線相關設置 - mmc_driver 表示一個card drive - mmc_bus_ops 總線操作函數集, 有mmc、sd、sdio三種 - mmc_host_ops Host Controller操作函數集 - mmc_command 表示一個mmc命令 - mmc_data 表示一個mmc數據 - mmc_request 表示一個mmc請求 - sdio_func 表示一個SDIO功能設備
mmc_host主要字段如下
struct mmc_host {
int index;
const struct mmc_host_ops *ops;
u32 ocr_avail;
u32 ocr_avail_sdio; /* SDIO-specific OCR */
u32 ocr_avail_sd; /* SD-specific OCR */
u32 ocr_avail_mmc; /* MMC-specific OCR */
u32 caps; /* Host能力標志*/
u32 caps2; /* Host更多能力標志*/
struct mmc_ios ios; /* current io bus settings */
int rescan_disable; /* disable card detection */
int rescan_entered; /* used with nonremovable devices */
struct mmc_card *card; /* device attached to this host */
struct delayed_work detect;
int detect_change; /* card檢測標志 */
struct mmc_slot slot;
const struct mmc_bus_ops *bus_ops; /* current bus driver */
struct mmc_supply supply;
unsigned int slotno; /* used for sdio acpi binding */
int dsr_req; /* DSR value is valid */
u32 dsr; /* optional driver stage (DSR) value */
unsigned long private[0];
};
mmc_card主要字段如下
struct mmc_card {
struct mmc_host *host; /* the host this device belongs to */
struct device dev; /* the device */
u32 ocr; /* the current OCR setting */
unsigned int rca; /* relative card address of device */
unsigned int type; /* Card類型: MMC、SD、SDIO、COMBO */
unsigned int state; /* (our) card state */
unsigned int quirks; /* card quirks */
struct mmc_cid cid; /* card identification */
struct mmc_csd csd; /* card specific */
struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */
struct sd_scr scr; /* extra SD information */
struct sd_ssr ssr; /* yet more SD information */
struct sd_switch_caps sw_caps; /* switch (CMD6) caps */
unsigned int sdio_funcs; /* number of SDIO functions */
struct sdio_cccr cccr; /* common card info */
struct sdio_cis cis; /* common tuple info */
struct sdio_func *sdio_func[7]; /* SDIO functions (devices) */
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 */
};
mmc_ios字段如下
struct mmc_ios {
unsigned int clock; /* 時鐘頻率 */
unsigned short vdd;
unsigned char bus_mode; /* 命令輸出模式: 開漏模式、上拉模式 */
unsigned char chip_select; /* SPI片選: DONTCARE、HIGH、LOW */
unsigned char power_mode; /* 電源供應狀態: UNDEFINED、OFF、UP、ON */
unsigned char bus_width; /* 數據總線寬度: 1、4、8 */
unsigned char timing; /* 總線速度模式: DS、HS、SDR12、SDR25... */
unsigned char signal_voltage; /* 信號電壓值: 3.3V、1.8V、1.2V */
unsigned char drv_type; /* 驅動類型: A, B, C, D */
bool enhanced_strobe; /* hs400es選擇 */
};
mmc_driver字段如下
struct mmc_driver {
struct device_driver drv;
int (*probe)(struct mmc_card *);
void (*remove)(struct mmc_card *);
void (*shutdown)(struct mmc_card *);
};
mmc_bus_ops字段如下
struct mmc_bus_ops {
void (*remove)(struct mmc_host *);
void (*detect)(struct mmc_host *);
int (*pre_suspend)(struct mmc_host *);
int (*suspend)(struct mmc_host *);
int (*resume)(struct mmc_host *);
int (*runtime_suspend)(struct mmc_host *);
int (*runtime_resume)(struct mmc_host *);
int (*power_save)(struct mmc_host *);
int (*power_restore)(struct mmc_host *);
int (*alive)(struct mmc_host *);
int (*shutdown)(struct mmc_host *);
int (*reset)(struct mmc_host *);
};
mmc_host_ops字段如下
struct mmc_host_ops {
void (*post_req)(struct mmc_host *, struct mmc_request *, int err);
void (*pre_req)(struct mmc_host *, struct mmc_request *, bool is_first_req);
void (*request)(struct mmc_host *host, struct mmc_request *req);
void (*set_ios)(struct mmc_host *, struct mmc_ios *);
int (*get_ro)(struct mmc_host *);
int (*get_cd)(struct mmc_host *);
void (*enable_sdio_irq)(struct mmc_host *, int enable);
void (*init_card)(struct mmc_host *, struct mmc_card *card);
int (*start_signal_voltage_switch)(struct mmc_host *, struct mmc_ios *);
int (*card_busy)(struct mmc_host *);
int (*execute_tuning)(struct mmc_host *, u32 opcode);
int (*prepare_hs400_tuning)(struct mmc_host *host, struct mmc_ios *ios);
void (*hs400_enhanced_strobe)(struct mmc_host *, struct mmc_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 *);
void (*card_event)(struct mmc_host *);
int (*multi_io_quirk)(struct mmc_card *, unsigned int direction, int blk_size);
};
3. MMC接口
3.1 Host API
Host相關接口, 供Host Controller使用
/* 設備樹解析 */ int mmc_of_parse(struct mmc_host *); /* 分配/釋放host結構體 */ struct mmc_host *mmc_alloc_host(int extra, struct device *); void mmc_free_host(struct mmc_host *); /* 添加/移除host設備 */ int mmc_add_host(struct mmc_host *); void mmc_remove_host(struct mmc_host *);
mmc_alloc_host主要流程如下
mmc_alloc_host kzalloc(sizeof(struct mmc_host) + extra) /* 分配mmc_host結構體 */ mmc_host::rescan_disable = 1 /* 禁用掃描*/ ida_pre_get ida_get_new /* ida相關 */ dev_set_name /* 設置設備名稱 */ device_initialize(mmc_host::class_dev) /* 初始化設備結構體 */ mmc_gpio_alloc /* 分配mmc_gpio結構體 */ init_waitqueue_head(mmc_host::wq) /* 初始化等待隊列 */ INIT_DELAYED_WORK(mmc_host::detect, mmc_rescan); /* 初始化工作隊列 */
mmc_add_host主要流程如下
mmc_add_host
device_add(mmc_host::class_dev)
/* 添加設備 */
mmc_start_host
/* 啟用該Host */
mmc_claim_host
/* 占用Host控制器 */
mmc_power_up
/* 給Host供電 */
mmc_host::mmc_ios::power_mode = MMC_POWER_UP
/* 設置power狀態為正在上電 */
mmc_set_initial_state
/* 設置初始化狀態 */
mmc_host::mmc_ios::bus_width = MMC_BUS_WIDTH_1
/* 設置總線寬帶為1bit */
mmc_host::mmc_ios::timing = MMC_TIMING_LEGACY
/* 設置總線速度模式為DS模式 */
mmc_set_ios
/* 將IO總線設置寫入Host驅動, 調用mmc_host::mmc_host_ops::set_ios */
__mmc_set_signal_voltage
/* 設置信號電壓, 依次嘗試3.3V、1.8V、1.2V */
mmc_host::mmc_ios::clock = mmc_host::f_init;
/* 設置時鐘頻率 */
mmc_host::mmc_ios::power_mode = MMC_POWER_ON
/* 設置power狀態為正常供電 */
mmc_set_ios
/* 將io相關設置寫入Host驅動 */
mmc_release_host
/* 釋放Host控制器 */
mmc_gpiod_request_cd_irq
/* 釋放Host控制器 */
_mmc_detect_change
/* Card掃描 */
mmc_host::detect_change = 1
/* 設置Card檢測標志 */
mmc_schedule_delayed_work(mmc_host::detect);
/* 調度工作隊列, 調度函數為mmc_rescan */
3.2 Card API
/* 注冊/注銷MMC Card驅動 */ int mmc_register_driver(struct mmc_driver *); void mmc_unregister_driver(struct mmc_driver *); /* 注冊/注銷SDIO Card驅動 */ int sdio_register_driver(struct sdio_driver *); void sdio_unregister_driver(struct sdio_driver *);
3.3 General API
/* Card檢測 */ void mmc_detect_change(struct mmc_host *host, unsigned long delay);
3.4 Command API
cmd0 - mmc_go_idle cmd1 - mmc_send_op_cond cmd2 - mmc_all_send_cid
4. MMC啟動
MMC在啟動時會進行相應的初始化
mmc_init
mmc_register_bus
bus_register /* 注冊了mmc總線 */
mmc_register_host_class
class_register /* 注冊'mmc_host'設備類 */
sdio_register_bus
bus_register /* 注冊了sdio總線 */
mmc_blk_init
register_blkdev /* 注冊mmc塊設備 */
mmc_register_driver
driver_register /* 注冊mmc card驅動 */
5. MMC掃描
MMC設備的發現通過mmc_rescan函數來實現,通過_mmc_detect_change/mmc_detect_change來觸發
mmc_rescan主要流程如下
mmc_rescan
mmc_host::mmc_host_ops::card_event
mmc_host::mmc_bus_ops::detect
mmc_host::mmc_host_ops::get_cd
mmc_rescan_try_freq
/* 使用不同時鐘頻率進行初始化 */
mmc_power_up
/* 設備供電 */
mmc_hw_reset_for_init
/* 針對部分eMMC(VCCQ一直為高) */
mmc_host::mmc_host_ops::hw_reset
sdio_reset
/* 僅針對SDIO設備 */
mmc_go_idle
/* 發送CMD0命令 */
mmc_send_if_cond
/* 僅針對SD設備 */
mmc_attach_sdio
/* SDIO設備初始化 */
mmc_attach_sd
/* SD設備初始化 */
mmc_attach_mmc
/* MMC設備初始化 */
mmc_power_off
/* 當上述設備都不是則停止供電 */
其中SDIO、SD、MMC的初始化流程各不相同
mmc_attach_sdio主要流程如下
/* SDIO Card初始化 */
mmc_attach_sdio
mmc_send_io_op_cond
/* 發送SD_IO_SEND_OP_COND, 獲????? */
mmc_attach_bus(mmc_sdio_ops)
/* 將SDIO總線操作集分配給Host */
host->ocr_avail = host->ocr_avail_sdio;
/* 設置SDIO的OCR */
mmc_select_voltage
/* 選擇合適的電壓值 */
mmc_sdio_init_card
/* 識別和初始化SDIO Card */
......
pm_runtime_set_active
/* 設置Card運行時PM狀態為活躍, 僅針對支持MMC_CAP_POWER_OFF_CARD特性的Host */
pm_runtime_enable
/* 使能Card運行時PM, 僅針對支持MMC_CAP_POWER_OFF_CARD特性的Host */
...... /* sdio functions related */
mmc_add_card(mmc_host::mmc_card)
/* 注冊SDIO Card */
sdio_add_func(mmc_host::mmc_card::sdio_func)
/* 注冊SDIO function */
mmc_attach_sd主要流程如下
/* SD Card初始化 */
mmc_attach_sd
mmc_send_app_op_cond
/* 發送SD_APP_OP_COND, 獲????? */
mmc_attach_bus(mmc_sd_ops)
/* 將SD總線操作集分配給Host */
host->ocr_avail = host->ocr_avail_sd;
/* 設置SD的OCR */
mmc_host_is_spi
->
mmc_go_idle
/* 發送CMD0 */
mmc_spi_read_ocr
/* 發送MMC_SPI_READ_OCR, 讀取??? */
mmc_select_voltage
/* 選擇合適的電壓值 */
mmc_sd_init_card
/* 識別和初始化SD Card */
......
mmc_add_card(mmc_host::mmc_card)
/* 注冊SD Card */
mmc_attach_mmc主要流程如下
/* MMC Card初始化 */
mmc_attach_mmc
mmc_send_op_cond
/* 發送MMC_SEND_OP_COND, 獲????? */
mmc_attach_bus(mmc_ops)
/* 將MMC總線操作集分配給Host */
host->ocr_avail = host->ocr_avail_mmc;
/* 設置MMC的OCR */
mmc_host_is_spi
->
mmc_spi_read_ocr
/* 發送MMC_SPI_READ_OCR, 讀取??? */
mmc_select_voltage
/* 選擇合適的電壓值 */
mmc_init_card
/* 識別和初始化MMC Card */
......
mmc_add_card(mmc_host::mmc_card)
/* 注冊MMC Card */
6. Host驅動
Host驅動的編寫主要步驟如下:
1. 通過mmc_alloc_host分配一個mmc_host結構體 2. 定義實現mmc_host_ops數據結構, 并賦值給上面的mmc_host::mmc_host_ops成員變量 3. 給mmc_host成員變量賦值, 如ocr_avail、caps等成員變量 4. 調用mmc_add_host注冊該Host
7. Card驅動
對于Memory Card,內核實現了塊設備驅動; 對于SDIO設備(比如WiFi), 則需要廠商實現(比如BCM的bcmdhd)
參考:
<ooonebook mmc>
<WF111 Datasheet>
<BCM4330 Datasheet>
<MMC/SD卡驅動實例開發講解>
<SDIO Simplified Specification>
總結
以上是生活随笔為你收集整理的Linux MMC介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GenericUDF使用流程记载(转载+
- 下一篇: 常见的那些模糊不清的计算机相关概念(长期