/*
* linux/include/linux/mmc/host.h
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Host driver specific definitions.
*/
#ifndef LINUX_MMC_HOST_H
#define LINUX_MMC_HOST_H
#include
#include
#include
#include
#include
//struct mmc_ios主要是通过mmc_set_ios()调用host->ops->set_ios()
//set_ios()由驱动提供,所以这些结构由host驱动处理,core只管用
struct mmc_ios {
unsigned intclock;/* clock rate */ //时钟速度
unsigned shortvdd; //电压
/* vdd stores the bit number of the selected voltage range from below. */
unsigned charbus_mode;/* command output mode */
//这是io口的类型,对于我这个电气自动化学生还是懂点的,不过不细说了
#define MMC_BUSMODE_OPENDRAIN1 //开漏
#define MMC_BUSMODE_PUSHPULL2 //推挽
unsigned charchip_select;/* SPI chip select */
#define MMC_CS_DONTCARE0 //不关心
#define MMC_CS_HIGH1 //高速
#define MMC_CS_LOW2 //低速
/*
if (mmc_host_is_spi(host))
host->ios.chip_select = MMC_CS_HIGH;
else
host->ios.chip_select = MMC_CS_DONTCARE;
*/
unsigned charpower_mode;/* power supply mode */
#define MMC_POWER_OFF0//关
#define MMC_POWER_UP1//开
#define MMC_POWER_ON2//也是开,s3c2440处理和up一样
unsigned charbus_width;/* data bus width */ //数据总线宽度
#define MMC_BUS_WIDTH_10 //1位
#define MMC_BUS_WIDTH_42 //4位
#define MMC_BUS_WIDTH_83 //8位
unsigned chartiming;/* timing specification used */ //时序规范使用
#define MMC_TIMING_LEGACY0 //旧的
#define MMC_TIMING_MMC_HS1 //mmc
#define MMC_TIMING_SD_HS2 //sd
//UHS:超高速版。UHS-I: 超高速版1
//UHS是一种速度标准。
//下面是UHS-I的5种模式,在SDHCI标准中有个叫Host Control 2的寄存器
//它的第0~2位就是选择UHS的模式
#define MMC_TIMING_UHS_SDR12MMC_TIMING_LEGACY
#define MMC_TIMING_UHS_SDR25MMC_TIMING_SD_HS
#define MMC_TIMING_UHS_SDR503
#define MMC_TIMING_UHS_SDR1044
#define MMC_TIMING_UHS_DDR505
#define MMC_SDR_MODE0
#define MMC_1_2V_DDR_MODE1
#define MMC_1_8V_DDR_MODE2
unsigned charsignal_voltage;/* signalling voltage (1.8V or 3.3V) */
//上面说信号电压(1.8v 或 3.3v),没有提到1.2v
//我看了SDHCI,还是Host Control 2的第3位 1: 1.8v 0: 3.3v
//也没提到1.2v. 不过代码中提到eMMC卡可以支持1.2v或3.3v
//eMMC:(Embedded Multi Media Card),这东西的封装是:小型的
//BGA 封装。
#define MMC_SIGNAL_VOLTAGE_3300
#define MMC_SIGNAL_VOLTAGE_1801
#define MMC_SIGNAL_VOLTAGE_1202
unsigned chardrv_type;/* driver type (A, B, C, D) */
//还是Host Control 2寄存器的4~5位选择,默认是B
//UHS-I卡1.8v时才有效,3.3v无效
//还有Preset Value Enable = 0时可以被主机设置
//Preset Value Enable = 1时由Preset Value寄存器决定
/*
B:默认的驱动。50欧姆传输线阻抗。支持UHS104和UHS50卡。下面的都以B为参考。
A:x1.5驱动(是50/1.5 = 33欧姆)。支持208MHz
C:x0.75。支持208MHz的最弱驱动。
D:x0.5。这个主要是速度不是要紧的,重要是低noise,低EMI。最大频率由主机设计确定。
*/
#define MMC_SET_DRIVER_TYPE_B0
#define MMC_SET_DRIVER_TYPE_A1
#define MMC_SET_DRIVER_TYPE_C2
#define MMC_SET_DRIVER_TYPE_D3
};
//下面是写驱动要搞定的接口,如果你的硬件支持SDHCI。你可能看不到这个。
//已在sdhci.c统一实现。
struct mmc_host_ops {
/*
* Hosts that support power saving can use the 'enable' and 'disable'
* methods to exit and enter power saving states. 'enable' is called
* when the host is claimed and 'disable' is called (or scheduled with
* a delay) when the host is released. The 'disable' is scheduled if
* the disable delay set by 'mmc_set_disable_delay()' is non-zero,
* otherwise 'disable' is called immediately. 'disable' may be
* scheduled repeatedly, to permit ever greater power saving at the
* expense of ever greater latency to re-enable. Rescheduling is
* determined by the return value of the 'disable' method. A positive
* value gives the delay in milliseconds.
*
* In the case where a host function (like set_ios) may be called
* with or without the host claimed, enabling and disabling can be
* done directly and will nest correctly. Call 'mmc_host_enable()' and
* 'mmc_host_lazy_disable()' for this purpose, but note that these
* functions must be paired.
*
* Alternatively, 'mmc_host_enable()' may be paired with
* 'mmc_host_disable()' which calls 'disable' immediately. In this
* case the 'disable' method will be called with 'lazy' set to 0.
* This is mainly useful for error paths.
*
* Because lazy disable may be called from a work queue, the 'disable'
* method must claim the host when 'lazy' != 0, which will work
* correctly because recursion is detected and handled.
*/
/*
上面解释了一大堆,自己看看。我说一下调用过程。at91_mci.c sd卡
at91_mci_driver->at91_mci_suspend()->mmc_suspend_host()->host->bus_ops->suspend()(sd就是mmc_sd_suspend)-> /
__mmc_claim_host()->mmc_release_host()->mmc_host_lazy_disable()->mmc_host_do_disable()->host->ops->disable()
上面是disable的调用过程,enable从resume开始,不细说了!
*/
int (*enable)(struct mmc_host *host);
int (*disable)(struct mmc_host *host, int lazy);
/*
* 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.
*/
//为了双缓冲,一个准备,一个活动的,数据都是通过请求传输的
void(*post_req)(struct mmc_host *host, struct mmc_request *req,
int err);
void(*pre_req)(struct mmc_host *host, struct mmc_request *req,
bool is_first_req);
void(*request)(struct mmc_host *host, struct mmc_request *req);
/*
看看程序的调用,
先看request()
mmc_set_signal_vlotage()
主要send CMD11(切换电压)
cmd.opcode = SD_SWITCH_VOLTAGE;
cmd.arg = 0;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
err = mmc_wait_for_cmd(host, &cmd, 0);
if (err)
return err;
在mmc_wait_for_cmd()中
mrq.cmd = cmd;
cmd->data = NULL;
mmc_wait_for_req(host, &mrq);
mmc_wait_for_req()原型:
void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
{
__mmc_start_req(host, mrq);
*********************************************************************************
__mmc_start_req()原型:
static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
{
init_completion(&mrq->completion);//初始化完成量
mrq->done = mmc_wait_done;//函数指针done赋值(由mmc_request_done()调用)
mmc_start_request(host, mrq);//这个不贴了,最终调用host->ops->request(),就是这里的request()
}
*********************************************************************************
mmc_wait_for_req_done(host, mrq);//这个函数会等待一个完成量(由mmc_request_done()报告完成),
//如果出现错误,会再一次调用host->ops->request()
//mmc_request_done()一般在host->ops->request()中调用,
}
request()肯定是少不了寄存器操作,这正是写驱动要做的事。
post_req和pre_req实现它们的驱动比较少
在core.c中是用mmc_post_req()和mmc_pre_req()调用
struct mmc_async_req *mmc_start_req(struct mmc_host *host,
struct mmc_async_req *areq, int *error)
代码给出的解释是start a non_blocking request,上面说的mmc_wait_for_cmd,肯定是阻塞
在card/block调用了这个函数
struct mmc_async_req *mmc_start_req(struct mmc_host *host,
struct mmc_async_req *areq, int *error)
{
int err = 0;
struct mmc_async_req *data = host->areq;
if (areq)
mmc_pre_req(host, areq->mrq, !host->areq);
if (host->areq) {//当前有一个活动的异步req
mmc_wait_for_req_done(host, host->areq->mrq);
err = host->areq->err_check(host->card, host->areq);
if (err) {
mmc_post_req(host, host->areq->mrq, 0);
if (areq)
mmc_post_req(host, areq->mrq, -EINVAL);
host->areq = NULL;
goto out;
}
}
if (areq)
__mmc_start_req(host, areq->mrq);
if (host->areq)
mmc_post_req(host, host->areq->mrq, 0);
host->areq = areq;
out:
if (error)
*error = err;
return data;
}
上面的东西其实非常简单,我们先假设post_req pre_req没有。那么第一次调用时,host->areq为NULL,
会直接调用__mmc_start_req(),下一次调用,如果没有处理完再mmc_wait_for_req_done()等待,其实就
是把等待放到了下一次。
如果你加上post_req pre_req。多的逻辑就是不管当前有没有活动请求,先准备,当前没有当然直接运行,
如果有,等待完成。出错的话就mmc_post_req(host, areq->mrq, -EINVAL);取消新准备的req,因为它不能
运行直到错误接触。
*/
/*
* Avoid calling these 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! 可能睡眠,不能在原子上下文运行。
*
* Return values for the get_ro callback should be:
* 0 for a read/write card 0代表可读写
* 1 for a read-only card 1代表只读(写保护)
* -ENOSYS when not supported (equal to NULL callback)
* or a negative errno value when something bad happened
在SDCHI中有个寄存器Present State,它的第19位代表是否写保护
对应的硬件是WP脚
*
* 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
同样是寄存器Present State,它的第18位代表卡是否存在
对应的硬件是nCD脚,检测这个还有可能注意去抖动,但是
我看了s3cmci并没有这么做。直接读脚(因为它不支持SDCHI)。
*/
void(*set_ios)(struct mmc_host *host, struct mmc_ios *ios);
//看看上面的struct mmc_ios。你就知道可能要涉及哪些东西了。
int(*get_ro)(struct mmc_host *host);
int(*get_cd)(struct mmc_host *host);
void(*enable_sdio_irq)(struct mmc_host *host, int enable);
/* optional callback for HC quirks */
void(*init_card)(struct mmc_host *host, struct mmc_card *card);
int(*start_signal_voltage_switch)(struct mmc_host *host, struct mmc_ios *ios);//电压切换
int(*execute_tuning)(struct mmc_host *host);//执行调整,SDHCI就是发送CMD19
//曾经看到一个文章说:MMC支持CMD14和CMD19进行主线测试,从而选择合适总线进行通信。SD则不支持。
//但是SDHCI中说到了CMD19
void(*enable_preset_value)(struct mmc_host *host, bool enable);//SDCHI中的Host Control 2 Register
//第15位控制
int(*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv);
//整个host目录就没有发现这个应用,不过SDHCI有A B C D,不知道为什么没有实现这个接口
void(*hw_reset)(struct mmc_host *host);
};
struct mmc_card;
struct device;
struct mmc_async_req {
/* active mmc request */
struct mmc_request*mrq;
/*
* Check error status of completed mmc request.
* Returns 0 if success otherwise non zero.
*/
int (*err_check) (struct mmc_card *, struct mmc_async_req *);
//这个check,在card目录下的block.c和mmc_test.c实现,不需要驱动实现。
};
struct mmc_host {
struct device*parent;
struct deviceclass_dev;//上面是建立设备关系用的
intindex;
//dev_set_name(&host->class_dev, "mmc%d", host->index);
//看到上面这句,我想你应该知道index是干什么的了。
const struct mmc_host_ops *ops;
unsigned intf_min;
unsigned intf_max;
unsigned intf_init;
//上面的f_*是频率的最小值,最大值,初始值
u32ocr_avail;
u32ocr_avail_sdio;/* SDIO-specific OCR */
u32ocr_avail_sd;/* SD-specific OCR */
u32ocr_avail_mmc;/* MMC-specific OCR */
//上面是OCR寄存器值,记录了电压值,下面有宏定义
struct notifier_blockpm_notify;//通知链
//register_pm_notifier(&host->pm_notify);
//这个电源管理提供的通知链
#define MMC_VDD_165_1950x00000080/* VDD voltage 1.65 - 1.95 */
#define MMC_VDD_20_210x00000100/* VDD voltage 2.0 ~ 2.1 */
#define MMC_VDD_21_220x00000200/* VDD voltage 2.1 ~ 2.2 */
#define MMC_VDD_22_230x00000400/* VDD voltage 2.2 ~ 2.3 */
#define MMC_VDD_23_240x00000800/* VDD voltage 2.3 ~ 2.4 */
#define MMC_VDD_24_250x00001000/* VDD voltage 2.4 ~ 2.5 */
#define MMC_VDD_25_260x00002000/* VDD voltage 2.5 ~ 2.6 */
#define MMC_VDD_26_270x00004000/* VDD voltage 2.6 ~ 2.7 */
#define MMC_VDD_27_280x00008000/* VDD voltage 2.7 ~ 2.8 */
#define MMC_VDD_28_290x00010000/* VDD voltage 2.8 ~ 2.9 */
#define MMC_VDD_29_300x00020000/* VDD voltage 2.9 ~ 3.0 */
#define MMC_VDD_30_310x00040000/* VDD voltage 3.0 ~ 3.1 */
#define MMC_VDD_31_320x00080000/* VDD voltage 3.1 ~ 3.2 */
#define MMC_VDD_32_330x00100000/* VDD voltage 3.2 ~ 3.3 */
#define MMC_VDD_33_340x00200000/* VDD voltage 3.3 ~ 3.4 */
#define MMC_VDD_34_350x00400000/* VDD voltage 3.4 ~ 3.5 */
#define MMC_VDD_35_360x00800000/* VDD voltage 3.5 ~ 3.6 */
unsigned longcaps;/* 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 */ //轮询检测
/*
POLL其实是延时检测卡,当插入 SD卡之
后,SD 主控制器上的探测引脚会产生一个中断,之后调用中断函数里的工作队列,然后执
行工作队列里的 mmc_rescan 去扫描 SD 卡,为 SD 卡上电,发送地址,注册驱动等。考虑
到插入 SD 卡需要一个短时间的过程(有个弹簧卡槽固定住 SD 卡)
当然和SD主控制器的性能有关
*/
#define MMC_CAP_8_BIT_DATA(1 << 6)/* Can the host do 8 bit transfers */
#define MMC_CAP_DISABLE(1 << 7)/* Can the host be disabled */
#define MMC_CAP_NONREMOVABLE(1 << 8)/* Nonremovable e.g. eMMC *///不可移动,eMMC不可移动,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_1_8V_DDR(1 << 11)/* can support */
/* DDR mode at 1.8V */
#define MMC_CAP_1_2V_DDR(1 << 12)/* can support */
/* DDR mode at 1.2V */
#define MMC_CAP_POWER_OFF_CARD(1 << 13)/* Can power off after boot */
#define MMC_CAP_BUS_WIDTH_TEST(1 << 14)/* CMD14/CMD19 bus width ok *///mmc支持CMD14/CMD19
#define MMC_CAP_UHS_SDR12(1 << 15)/* Host supports UHS SDR12 mode */
#define MMC_CAP_UHS_SDR25(1 << 16)/* Host supports UHS SDR25 mode */
#define MMC_CAP_UHS_SDR50(1 << 17)/* Host supports UHS SDR50 mode */
#define MMC_CAP_UHS_SDR104(1 << 18)/* Host supports UHS SDR104 mode */
#define MMC_CAP_UHS_DDR50(1 << 19)/* Host supports UHS DDR50 mode */
#define MMC_CAP_SET_XPC_330(1 << 20)/* Host supports >150mA current at 3.3V */
#define MMC_CAP_SET_XPC_300(1 << 21)/* Host supports >150mA current at 3.0V */
#define MMC_CAP_SET_XPC_180(1 << 22)/* Host supports >150mA current at 1.8V */
#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_MAX_CURRENT_200(1 << 26)/* Host max current limit is 200mA */
#define MMC_CAP_MAX_CURRENT_400(1 << 27)/* Host max current limit is 400mA */
#define MMC_CAP_MAX_CURRENT_600(1 << 28)/* Host max current limit is 600mA */
#define MMC_CAP_MAX_CURRENT_800(1 << 29)/* Host max current limit is 800mA */
#define MMC_CAP_CMD23(1 << 30)/* CMD23 supported. */ //CMD23是为了停止多块读操作
#define MMC_CAP_HW_RESET(1 << 31)/* Hardware reset */
unsigned intcaps2;/* More host capabilities */
#define MMC_CAP2_BOOTPART_NOACC(1 << 0)/* Boot partition no access */ //引导分区不能访问
//eMMC有boot partition。SDHCI-PCI不能访问,不清楚为什么
#define MMC_CAP2_CACHE_CTRL(1 << 1)/* Allow cache control */ //允许c、ache控制, core.c中的cache操作会判断这个
#define MMC_CAP2_POWEROFF_NOTIFY (1 << 2)/* Notify poweroff supported */ //支持通知掉电
#define MMC_CAP2_NO_MULTI_READ(1 << 3)/* Multiblock reads don't work */ //多块读取不起作用
mmc_pm_flag_tpm_caps;/* supported pm features */
unsigned int power_notify_type;
#define MMC_HOST_PW_NOTIFY_NONE0
#define MMC_HOST_PW_NOTIFY_SHORT1
#define MMC_HOST_PW_NOTIFY_LONG2
//这上面short和long指的是时间,写EXT_CSD寄存器的等待时间
//secureMMC有EXT_CSD寄存器
/*
EXT_CSD:
Spec Ver 3.0
EXT_CSD的存在允许操作MMC的不同模式,一个特殊SWITCH命令被执行去切换不同的模式。然而当切换到不是标准的模式(Flash- or
ROM-MMC 模式),classes 1,3,5,6,7,8,9,10的命令码不能用。这些命令码被特殊命令占用。
这些特殊模式就是SecureMMC说的安全模式。
*/
#ifdef CONFIG_MMC_CLKGATE
intclk_requests;/* internal reference counter */ //函数mmc_host_clk_hold()即检查设置clk不是非零,切让此值加一,防止其他的clk操作。
unsigned intclk_delay;/* number of MCI clk hold cycles */
boolclk_gated;/* clock gated */ //时钟门控
struct work_structclk_gate_work; /* delayed clock gate */
unsigned intclk_old;/* old clock value cache */
spinlock_tclk_lock;/* lock for clk fields */
struct mutexclk_gate_mutex;/* mutex for clock gating */
#endif
/* host specific block data */
unsigned intmax_seg_size;/* see blk_queue_max_segment_size *///一个请求的段的最多有多少字节
unsigned shortmax_segs;/* see blk_queue_max_segments *///一个队列段数量的最大值
unsigned shortunused;
unsigned intmax_req_size;/* maximum number of bytes in one req *///一个请求的最大字节数
unsigned intmax_blk_size;/* maximum size of one mmc block *///一个mmc块的最大大小
unsigned intmax_blk_count;/* maximum number of blocks in one req *///一个请求中块的大小
unsigned intmax_discard_to;/* max. discard timeout in ms *///判断卡不能用的超时时间
/* private data */
spinlock_tlock;/* lock for claim and bus ops */
struct mmc_iosios;/* current io bus settings */
u32ocr;/* the current OCR setting */
/* group bitfields together to minimize padding */
unsigned intuse_spi_crc:1;
unsigned intclaimed:1;/* host exclusively claimed *///__mmc_claim_host()使用的
unsigned intbus_dead:1;/* bus has been released *///mmc_detach_bus()会使其为1
#ifdef CONFIG_MMC_DEBUG
unsigned intremoved:1;/* host is being removed */
#endif
/* Only used with MMC_CAP_DISABLE */
intenabled;/* host is enabled */
intrescan_disable;/* disable card detection *///在suspend时会使其为1,
intnesting_cnt;/* "enable" nesting count */ //主机被使能的计数,防止重复enable和disable
inten_dis_recurs;/* detect recursion *///在disable和enable之前都会把它赋值为1,结束为0。防止同事enable和disable
unsigned intdisable_delay;/* disable delay in msecs */
struct delayed_workdisable;/* disabling work */
//延时disable卡
struct mmc_card*card;/* device attached to this host */
wait_queue_head_twq;
struct task_struct*claimer;/* task that has host claimed */ //主机声明的任务
intclaim_cnt;/* "claim" nesting count */
struct delayed_workdetect;//延时检测的任务
const struct mmc_bus_ops *bus_ops;/* current bus driver */
/*
struct mmc_bus_ops {
int (*awake)(struct mmc_host *);//唤醒
int (*sleep)(struct mmc_host *);//睡眠
void (*remove)(struct mmc_host *);//sd卡拔出
void (*detect)(struct mmc_host *);//检测sd卡
int (*suspend)(struct mmc_host *);//挂起
int (*resume)(struct mmc_host *);//恢复
int (*power_save)(struct mmc_host *);//保存电源模式
int (*power_restore)(struct mmc_host *);//电源模式恢复
};
*/
unsigned intbus_refs;/* reference counter */ //总线操作计数
unsigned intsdio_irqs;//中断号
struct task_struct*sdio_irq_thread;//sdio.c中会建立一个线程用反复调用__mmc_claim_host直到成功。
atomic_tsdio_irq_thread_abort;
mmc_pm_flag_tpm_flags;/* requested pm features */
#ifdef CONFIG_LEDS_TRIGGERS
struct led_trigger*led;/* activity led */
#endif
#ifdef CONFIG_REGULATOR
boolregulator_enabled; /* regulator state */
#endif
struct dentry*debugfs_root;//debugfs使用
struct mmc_async_req*areq;/* active async req *///上面有说
#ifdef CONFIG_FAIL_MMC_REQUEST
struct fault_attrfail_mmc_request;
#endif
unsigned longprivate[0] ____cacheline_aligned;
};
//分配一个struct mmc_host的,extra是你的私有数据长度
//分配的大小是sizeof(struct mmc_host) + extra
extern struct mmc_host *mmc_alloc_host(int extra, struct device *);
//每一个struct mmc_host初始化之后要用mmc_add_host添加
extern int mmc_add_host(struct mmc_host *);
extern void mmc_remove_host(struct mmc_host *);
extern void mmc_free_host(struct mmc_host *);
//看上面的结构体,你可以看到private是放在最后的
//所以就是我们在mmc_alloc_host中对应的extra所申请的空间
static inline void *mmc_priv(struct mmc_host *host)
{
return (void *)host->private;
}
#define mmc_host_is_spi(host)((host)->caps & MMC_CAP_SPI)
#define mmc_dev(x)((x)->parent)
#define mmc_classdev(x)(&(x)->class_dev)
#define mmc_hostname(x)(dev_name(&(x)->class_dev))
//驱动的suspend和resume一定会调用这些
extern int mmc_suspend_host(struct mmc_host *);
extern int mmc_resume_host(struct mmc_host *);
/*
下面两个对应这个struct mmc_bus_ops中
int (*power_save)(struct mmc_host *);//保存电源模式
int (*power_restore)(struct mmc_host *);//电源模式恢复
*/
extern int mmc_power_save_host(struct mmc_host *host);
extern int mmc_power_restore_host(struct mmc_host *host);
//mmc_detect_change对应struct delayed_workdetect;检测为了防抖动,做延时
extern void mmc_detect_change(struct mmc_host *, unsigned long delay);
//request结束
extern void mmc_request_done(struct mmc_host *, struct mmc_request *);
//关闭或开启cache,会控制EXT_CSD寄存器
extern int mmc_cache_ctrl(struct mmc_host *, u8);
/*
sdio中断检测:
SDIO spec中的话
for SDIO, pin 8 is used for interrupt pin.
s3cmci.c中
if (gpio_get_value(S3C2410_GPE(8)) == 0) {
pr_debug("%s: signalling irq\n", __func__);
mmc_signal_sdio_irq(host->mmc);
}//直接判断gpio口
*/
static inline void mmc_signal_sdio_irq(struct mmc_host *host)
{
host->ops->enable_sdio_irq(host, 0);//这个驱动去实现
wake_up_process(host->sdio_irq_thread);
/*
唤醒的线程名叫ksdioirqd
对于不支持SDIO 中断的host,kerne会采用polling的方式来实现伪中断:
不断的唤醒ksdioirqd来检查SDIO的CCCR的中断标志位。
支持SDIO中断的host,则直接在SDIO中断产生的时候,
由host的驱动来负责通知mmc子系统唤醒ksdioirqd来检查中断。
*/
}
struct regulator;
//通过ocr寄存器调节电压
#ifdef CONFIG_REGULATOR
int mmc_regulator_get_ocrmask(struct regulator *supply);
int mmc_regulator_set_ocr(struct mmc_host *mmc,
struct regulator *supply,
unsigned short vdd_bit);
#else
static inline int mmc_regulator_get_ocrmask(struct regulator *supply)
{
return 0;
}
static inline int mmc_regulator_set_ocr(struct mmc_host *mmc,
struct regulator *supply,
unsigned short vdd_bit)
{
return 0;
}
#endif
//下面一些根据名字看看吧,不说了
int mmc_card_awake(struct mmc_host *host);
int mmc_card_sleep(struct mmc_host *host);
int mmc_card_can_sleep(struct mmc_host *host);
int mmc_host_enable(struct mmc_host *host);
int mmc_host_disable(struct mmc_host *host);
int mmc_host_lazy_disable(struct mmc_host *host);
int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *);
static inline void mmc_set_disable_delay(struct mmc_host *host,
unsigned int disable_delay)
{
host->disable_delay = disable_delay;
}
/* Module parameter */
extern int mmc_assume_removable;
static inline int mmc_card_is_removable(struct mmc_host *host)
{
return !(host->caps & MMC_CAP_NONREMOVABLE) && mmc_assume_removable;
}
static inline int mmc_card_keep_power(struct mmc_host *host)
{
return host->pm_flags & MMC_PM_KEEP_POWER;
}
static inline int mmc_card_wake_sdio_irq(struct mmc_host *host)
{
return host->pm_flags & MMC_PM_WAKE_SDIO_IRQ;
}
static inline int mmc_host_cmd23(struct mmc_host *host)
{
return host->caps & MMC_CAP_CMD23;
}
static inline int mmc_boot_partition_access(struct mmc_host *host)
{
return !(host->caps2 & MMC_CAP2_BOOTPART_NOACC);
}
#endif /* LINUX_MMC_HOST_H */