块设备驱动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 <linux/leds.h>
#include <linux/sched.h>
#include <linux/fault-inject.h>

#include <linux/mmc/core.h>
#include <linux/mmc/pm.h>

//struct mmc_ios主要是通过mmc_set_ios()调用host->ops->set_ios()
//set_ios()由驱动提供,所以这些结构由host驱动处理,core只管用
struct mmc_ios {
	unsigned int	clock;			/* clock rate */ //时钟速度
	unsigned short	vdd; //电压

/* vdd stores the bit number of the selected voltage range from below. */

	unsigned char	bus_mode;		/* command output mode */
//这是io口的类型,对于我这个电气自动化学生还是懂点的,不过不细说了
#define MMC_BUSMODE_OPENDRAIN	1 //开漏
#define MMC_BUSMODE_PUSHPULL	2 //推挽

	unsigned char	chip_select;		/* SPI chip select */

#define MMC_CS_DONTCARE		0 //不关心
#define MMC_CS_HIGH		1 //高速
#define MMC_CS_LOW		2 //低速
/*
        if (mmc_host_is_spi(host))
                host->ios.chip_select = MMC_CS_HIGH;
        else
                host->ios.chip_select = MMC_CS_DONTCARE;
*/

	unsigned char	power_mode;		/* power supply mode */

#define MMC_POWER_OFF		0//关
#define MMC_POWER_UP		1//开
#define MMC_POWER_ON		2//也是开,s3c2440处理和up一样

	unsigned char	bus_width;		/* data bus width */ //数据总线宽度

#define MMC_BUS_WIDTH_1		0 //1位
#define MMC_BUS_WIDTH_4		2 //4位
#define MMC_BUS_WIDTH_8		3 //8位

	unsigned char	timing;			/* timing specification used */ //时序规范使用

#define MMC_TIMING_LEGACY	0 //旧的
#define MMC_TIMING_MMC_HS	1 //mmc
#define MMC_TIMING_SD_HS	2 //sd
//UHS:超高速版。UHS-I: 超高速版1
//UHS是一种速度标准。
//下面是UHS-I的5种模式,在SDHCI标准中有个叫Host Control 2的寄存器
//它的第0~2位就是选择UHS的模式
#define MMC_TIMING_UHS_SDR12	MMC_TIMING_LEGACY
#define MMC_TIMING_UHS_SDR25	MMC_TIMING_SD_HS
#define MMC_TIMING_UHS_SDR50	3
#define MMC_TIMING_UHS_SDR104	4
#define MMC_TIMING_UHS_DDR50	5

#define MMC_SDR_MODE		0
#define MMC_1_2V_DDR_MODE	1
#define MMC_1_8V_DDR_MODE	2

	unsigned char	signal_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_330	0
#define MMC_SIGNAL_VOLTAGE_180	1
#define MMC_SIGNAL_VOLTAGE_120	2

	unsigned char	drv_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_B	0
#define MMC_SET_DRIVER_TYPE_A	1
#define MMC_SET_DRIVER_TYPE_C	2
#define MMC_SET_DRIVER_TYPE_D	3
};

//下面是写驱动要搞定的接口,如果你的硬件支持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 device		class_dev;//上面是建立设备关系用的
	int			index;
	//dev_set_name(&host->class_dev, "mmc%d", host->index);
	//看到上面这句,我想你应该知道index是干什么的了。
	const struct mmc_host_ops *ops;
	unsigned int		f_min;
	unsigned int		f_max;
	unsigned int		f_init;
	//上面的f_*是频率的最小值,最大值,初始值
	u32			ocr_avail;
	u32			ocr_avail_sdio;	/* SDIO-specific OCR */
	u32			ocr_avail_sd;	/* SD-specific OCR */
	u32			ocr_avail_mmc;	/* MMC-specific OCR */
	//上面是OCR寄存器值,记录了电压值,下面有宏定义
	struct notifier_block	pm_notify;//通知链
	//register_pm_notifier(&host->pm_notify);
	//这个电源管理提供的通知链

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

	unsigned long		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 */ //轮询检测
/*
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 int		caps2;		/* 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_t		pm_caps;	/* supported pm features */
	unsigned int        power_notify_type;
#define MMC_HOST_PW_NOTIFY_NONE		0
#define MMC_HOST_PW_NOTIFY_SHORT	1
#define MMC_HOST_PW_NOTIFY_LONG		2
//这上面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
	int			clk_requests;	/* internal reference counter */ //函数mmc_host_clk_hold()即检查设置clk不是非零,切让此值加一,防止其他的clk操作。
	unsigned int		clk_delay;	/* number of MCI clk hold cycles */
	bool			clk_gated;	/* clock gated */ //时钟门控
	struct work_struct	clk_gate_work; /* delayed clock gate */
	unsigned int		clk_old;	/* old clock value cache */
	spinlock_t		clk_lock;	/* lock for clk fields */
	struct mutex		clk_gate_mutex;	/* mutex for clock gating */
#endif

	/* 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 *///一个mmc块的最大大小
	unsigned int		max_blk_count;	/* maximum number of blocks in one req *///一个请求中块的大小
	unsigned int		max_discard_to;	/* max. discard timeout in ms *///判断卡不能用的超时时间

	/* private data */
	spinlock_t		lock;		/* lock for claim and bus ops */

	struct mmc_ios		ios;		/* current io bus settings */
	u32			ocr;		/* the current OCR setting */

	/* group bitfields together to minimize padding */
	unsigned int		use_spi_crc:1;
	unsigned int		claimed:1;	/* host exclusively claimed *///__mmc_claim_host()使用的
	unsigned int		bus_dead:1;	/* bus has been released *///mmc_detach_bus()会使其为1
#ifdef CONFIG_MMC_DEBUG
	unsigned int		removed:1;	/* host is being removed */
#endif

	/* Only used with MMC_CAP_DISABLE */
	int			enabled;	/* host is enabled */
	int			rescan_disable;	/* disable card detection *///在suspend时会使其为1,
	int			nesting_cnt;	/* "enable" nesting count */ //主机被使能的计数,防止重复enable和disable
	int			en_dis_recurs;	/* detect recursion *///在disable和enable之前都会把它赋值为1,结束为0。防止同事enable和disable
	unsigned int		disable_delay;	/* disable delay in msecs */
	struct delayed_work	disable;	/* disabling work */
    //延时disable卡

	struct mmc_card		*card;		/* device attached to this host */

	wait_queue_head_t	wq;
	struct task_struct	*claimer;	/* task that has host claimed */ //主机声明的任务
	int			claim_cnt;	/* "claim" nesting count */

	struct delayed_work	detect;//延时检测的任务

	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 int		bus_refs;	/* reference counter */ //总线操作计数

	unsigned int		sdio_irqs;//中断号
	struct task_struct	*sdio_irq_thread;//sdio.c中会建立一个线程用反复调用__mmc_claim_host直到成功。
	atomic_t		sdio_irq_thread_abort;

	mmc_pm_flag_t		pm_flags;	/* requested pm features */

#ifdef CONFIG_LEDS_TRIGGERS
	struct led_trigger	*led;		/* activity led */
#endif

#ifdef CONFIG_REGULATOR
	bool			regulator_enabled; /* regulator state */
#endif

	struct dentry		*debugfs_root;//debugfs使用

	struct mmc_async_req	*areq;		/* active async req *///上面有说

#ifdef CONFIG_FAIL_MMC_REQUEST
	struct fault_attr	fail_mmc_request;
#endif

	unsigned long		private[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_work	detect;检测为了防抖动,做延时
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 */

你可能感兴趣的:(linux,移动,内核,ARM,linux内核)