linux 3.2 分析,块设备驱动3--sd卡驱动2(linux-3.2.36的host.h分析)

/*

* 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 */

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值