Linux MMC介绍
1. 介紹
Linux中,將包括MMC、SD、SDIO統(tǒng)稱為MMC子系統(tǒng)
MMC子系統(tǒng)從功能上可分為三個(gè)層次
- card層: Card驅(qū)動(dòng), 或稱client驅(qū)動(dòng) - core層: MMC的核心層, 完成不同協(xié)議和規(guī)范的實(shí)現(xiàn), 為host層和設(shè)備驅(qū)動(dòng)層提供接口函數(shù) - host層: Host驅(qū)動(dòng), 針對(duì)不同主機(jī)端的SDHC、MMC控制器的驅(qū)動(dòng)
2. 數(shù)據(jù)結(jié)構(gòu)
MMC中包含的主要數(shù)據(jù)結(jié)構(gòu)如下
- mmc_host 表示一個(gè)mmc host控制器 - mmc_card 表示一個(gè)mmc設(shè)備 - mmc_ios IO總線相關(guān)設(shè)置 - mmc_driver 表示一個(gè)card drive - mmc_bus_ops 總線操作函數(shù)集, 有mmc、sd、sdio三種 - mmc_host_ops Host Controller操作函數(shù)集 - mmc_command 表示一個(gè)mmc命令 - mmc_data 表示一個(gè)mmc數(shù)據(jù) - mmc_request 表示一個(gè)mmc請(qǐng)求 - sdio_func 表示一個(gè)SDIO功能設(shè)備
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能力標(biāo)志*/
u32 caps2; /* Host更多能力標(biāo)志*/
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檢測(cè)標(biāo)志 */
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; /* 時(shí)鐘頻率 */
unsigned short vdd;
unsigned char bus_mode; /* 命令輸出模式: 開(kāi)漏模式、上拉模式 */
unsigned char chip_select; /* SPI片選: DONTCARE、HIGH、LOW */
unsigned char power_mode; /* 電源供應(yīng)狀態(tài): UNDEFINED、OFF、UP、ON */
unsigned char bus_width; /* 數(shù)據(jù)總線寬度: 1、4、8 */
unsigned char timing; /* 總線速度模式: DS、HS、SDR12、SDR25... */
unsigned char signal_voltage; /* 信號(hào)電壓值: 3.3V、1.8V、1.2V */
unsigned char drv_type; /* 驅(qū)動(dòng)類型: 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相關(guān)接口, 供Host Controller使用
/* 設(shè)備樹解析 */ int mmc_of_parse(struct mmc_host *); /* 分配/釋放host結(jié)構(gòu)體 */ struct mmc_host *mmc_alloc_host(int extra, struct device *); void mmc_free_host(struct mmc_host *); /* 添加/移除host設(shè)備 */ 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結(jié)構(gòu)體 */ mmc_host::rescan_disable = 1 /* 禁用掃描*/ ida_pre_get ida_get_new /* ida相關(guān) */ dev_set_name /* 設(shè)置設(shè)備名稱 */ device_initialize(mmc_host::class_dev) /* 初始化設(shè)備結(jié)構(gòu)體 */ mmc_gpio_alloc /* 分配mmc_gpio結(jié)構(gòu)體 */ init_waitqueue_head(mmc_host::wq) /* 初始化等待隊(duì)列 */ INIT_DELAYED_WORK(mmc_host::detect, mmc_rescan); /* 初始化工作隊(duì)列 */
mmc_add_host主要流程如下
mmc_add_host
device_add(mmc_host::class_dev)
/* 添加設(shè)備 */
mmc_start_host
/* 啟用該Host */
mmc_claim_host
/* 占用Host控制器 */
mmc_power_up
/* 給Host供電 */
mmc_host::mmc_ios::power_mode = MMC_POWER_UP
/* 設(shè)置power狀態(tài)為正在上電 */
mmc_set_initial_state
/* 設(shè)置初始化狀態(tài) */
mmc_host::mmc_ios::bus_width = MMC_BUS_WIDTH_1
/* 設(shè)置總線寬帶為1bit */
mmc_host::mmc_ios::timing = MMC_TIMING_LEGACY
/* 設(shè)置總線速度模式為DS模式 */
mmc_set_ios
/* 將IO總線設(shè)置寫入Host驅(qū)動(dòng), 調(diào)用mmc_host::mmc_host_ops::set_ios */
__mmc_set_signal_voltage
/* 設(shè)置信號(hào)電壓, 依次嘗試3.3V、1.8V、1.2V */
mmc_host::mmc_ios::clock = mmc_host::f_init;
/* 設(shè)置時(shí)鐘頻率 */
mmc_host::mmc_ios::power_mode = MMC_POWER_ON
/* 設(shè)置power狀態(tài)為正常供電 */
mmc_set_ios
/* 將io相關(guān)設(shè)置寫入Host驅(qū)動(dòng) */
mmc_release_host
/* 釋放Host控制器 */
mmc_gpiod_request_cd_irq
/* 釋放Host控制器 */
_mmc_detect_change
/* Card掃描 */
mmc_host::detect_change = 1
/* 設(shè)置Card檢測(cè)標(biāo)志 */
mmc_schedule_delayed_work(mmc_host::detect);
/* 調(diào)度工作隊(duì)列, 調(diào)度函數(shù)為mmc_rescan */
3.2 Card API
/* 注冊(cè)/注銷MMC Card驅(qū)動(dòng) */ int mmc_register_driver(struct mmc_driver *); void mmc_unregister_driver(struct mmc_driver *); /* 注冊(cè)/注銷SDIO Card驅(qū)動(dòng) */ int sdio_register_driver(struct sdio_driver *); void sdio_unregister_driver(struct sdio_driver *);
3.3 General API
/* Card檢測(cè) */ 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啟動(dòng)
MMC在啟動(dòng)時(shí)會(huì)進(jìn)行相應(yīng)的初始化
mmc_init
mmc_register_bus
bus_register /* 注冊(cè)了mmc總線 */
mmc_register_host_class
class_register /* 注冊(cè)'mmc_host'設(shè)備類 */
sdio_register_bus
bus_register /* 注冊(cè)了sdio總線 */
mmc_blk_init
register_blkdev /* 注冊(cè)mmc塊設(shè)備 */
mmc_register_driver
driver_register /* 注冊(cè)mmc card驅(qū)動(dòng) */
5. MMC掃描
MMC設(shè)備的發(fā)現(xiàn)通過(guò)mmc_rescan函數(shù)來(lái)實(shí)現(xiàn),通過(guò)_mmc_detect_change/mmc_detect_change來(lái)觸發(fā)
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
/* 使用不同時(shí)鐘頻率進(jìn)行初始化 */
mmc_power_up
/* 設(shè)備供電 */
mmc_hw_reset_for_init
/* 針對(duì)部分eMMC(VCCQ一直為高) */
mmc_host::mmc_host_ops::hw_reset
sdio_reset
/* 僅針對(duì)SDIO設(shè)備 */
mmc_go_idle
/* 發(fā)送CMD0命令 */
mmc_send_if_cond
/* 僅針對(duì)SD設(shè)備 */
mmc_attach_sdio
/* SDIO設(shè)備初始化 */
mmc_attach_sd
/* SD設(shè)備初始化 */
mmc_attach_mmc
/* MMC設(shè)備初始化 */
mmc_power_off
/* 當(dāng)上述設(shè)備都不是則停止供電 */
其中SDIO、SD、MMC的初始化流程各不相同
mmc_attach_sdio主要流程如下
/* SDIO Card初始化 */
mmc_attach_sdio
mmc_send_io_op_cond
/* 發(fā)送SD_IO_SEND_OP_COND, 獲取??? */
mmc_attach_bus(mmc_sdio_ops)
/* 將SDIO總線操作集分配給Host */
host->ocr_avail = host->ocr_avail_sdio;
/* 設(shè)置SDIO的OCR */
mmc_select_voltage
/* 選擇合適的電壓值 */
mmc_sdio_init_card
/* 識(shí)別和初始化SDIO Card */
......
pm_runtime_set_active
/* 設(shè)置Card運(yùn)行時(shí)PM狀態(tài)為活躍, 僅針對(duì)支持MMC_CAP_POWER_OFF_CARD特性的Host */
pm_runtime_enable
/* 使能Card運(yùn)行時(shí)PM, 僅針對(duì)支持MMC_CAP_POWER_OFF_CARD特性的Host */
...... /* sdio functions related */
mmc_add_card(mmc_host::mmc_card)
/* 注冊(cè)SDIO Card */
sdio_add_func(mmc_host::mmc_card::sdio_func)
/* 注冊(cè)SDIO function */
mmc_attach_sd主要流程如下
/* SD Card初始化 */
mmc_attach_sd
mmc_send_app_op_cond
/* 發(fā)送SD_APP_OP_COND, 獲取??? */
mmc_attach_bus(mmc_sd_ops)
/* 將SD總線操作集分配給Host */
host->ocr_avail = host->ocr_avail_sd;
/* 設(shè)置SD的OCR */
mmc_host_is_spi
->
mmc_go_idle
/* 發(fā)送CMD0 */
mmc_spi_read_ocr
/* 發(fā)送MMC_SPI_READ_OCR, 讀取??? */
mmc_select_voltage
/* 選擇合適的電壓值 */
mmc_sd_init_card
/* 識(shí)別和初始化SD Card */
......
mmc_add_card(mmc_host::mmc_card)
/* 注冊(cè)SD Card */
mmc_attach_mmc主要流程如下
/* MMC Card初始化 */
mmc_attach_mmc
mmc_send_op_cond
/* 發(fā)送MMC_SEND_OP_COND, 獲取??? */
mmc_attach_bus(mmc_ops)
/* 將MMC總線操作集分配給Host */
host->ocr_avail = host->ocr_avail_mmc;
/* 設(shè)置MMC的OCR */
mmc_host_is_spi
->
mmc_spi_read_ocr
/* 發(fā)送MMC_SPI_READ_OCR, 讀取??? */
mmc_select_voltage
/* 選擇合適的電壓值 */
mmc_init_card
/* 識(shí)別和初始化MMC Card */
......
mmc_add_card(mmc_host::mmc_card)
/* 注冊(cè)MMC Card */
6. Host驅(qū)動(dòng)
Host驅(qū)動(dòng)的編寫主要步驟如下:
1. 通過(guò)mmc_alloc_host分配一個(gè)mmc_host結(jié)構(gòu)體 2. 定義實(shí)現(xiàn)mmc_host_ops數(shù)據(jù)結(jié)構(gòu), 并賦值給上面的mmc_host::mmc_host_ops成員變量 3. 給mmc_host成員變量賦值, 如ocr_avail、caps等成員變量 4. 調(diào)用mmc_add_host注冊(cè)該Host
7. Card驅(qū)動(dòng)
對(duì)于Memory Card,內(nèi)核實(shí)現(xiàn)了塊設(shè)備驅(qū)動(dòng); 對(duì)于SDIO設(shè)備(比如WiFi), 則需要廠商實(shí)現(xiàn)(比如BCM的bcmdhd)
參考:
<ooonebook mmc>
<WF111 Datasheet>
<BCM4330 Datasheet>
<MMC/SD卡驅(qū)動(dòng)實(shí)例開(kāi)發(fā)講解>
<SDIO Simplified Specification>
總結(jié)
以上是生活随笔為你收集整理的Linux MMC介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: GenericUDF使用流程记载(转载+
- 下一篇: hive中操作struct与map三例