linux mmc驱动

插曲:

因为使用的平台是telechips的tcc803x,其芯片用户手册描述寄存器都是四字节寻址的,但是在代码驱动中用的很可能是单字节寻址,咋一看,有可能有的地址在芯片手册上没有或者感觉写错了,其实不是,这个需要注意一下。

简单流程:

mmc host主控器注册完成之后,会分别生成一个底层硬件相关的主控制设备(struct)sdhci_host和通用抽象的主控制器设备(struct)mmc_host,当检测到有sd卡等mmc从设备插入时,mmc  host主控制器会向sd卡等mmc从设备发起会话,sd卡等从设备作出相应的应答。mmc host主控制建立会话的机制是先通过通用抽象的(struct)mmc_host主设备的通用操作集(struct)mmc_host_ops,再由通用操作集(struct)mmc_host_ops进一步调用底层硬件相关的操作集(struct)sdhci_ops实现主从设备的通信的。

转载:linux MMC framework(2) - sdhci host driver_Hacker_Albert的博客-CSDN博客

注册mmc主控制器:

static int sdhci_tcc_probe(struct platform_device *pdev)
{
    const struct of_device_id *match;
	const struct sdhci_tcc_soc_data *soc_data;
	struct sdhci_host *host;
	struct sdhci_pltfm_host *pltfm_host;
	struct sdhci_tcc *tcc = NULL;

    match = of_match_device(sdhci_tcc_of_match_table, &pdev->dev);

    soc_data = match->data;

    host = sdhci_pltfm_init(pdev, soc_data->pdata, sizeof(*tcc));

    pltfm_host = sdhci_priv(host);
	tcc = sdhci_pltfm_priv(pltfm_host);

    sdhci_add_host(host);

}

sdhci_tcc_of_match_table表:

static const struct of_device_id sdhci_tcc_of_match_table[] = {
	{ .compatible = "telechips,tcc803x-sdhci,module-only", .data = &soc_data_tcc803x},
	{}
};

表里的soc_data_tcc803x结构:

static const struct sdhci_tcc_soc_data soc_data_tcc803x = {
	.pdata = &sdhci_tcc803x_pdata,
	.parse_channel_configs = sdhci_tcc803x_parse_channel_configs,
	.set_channel_configs = sdhci_tcc803x_set_channel_configs,
	.set_core_clock = sdhci_tcc803x_set_core_clock,
	.sdhci_tcc_quirks = 0,
};

sdhci_tcc803x_pdata平台数据结构:

static const struct sdhci_pltfm_data sdhci_tcc803x_pdata = {
	.ops	= &sdhci_tcc803x_ops,
	.quirks	= SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
			SDHCI_QUIRK2_STOP_WITH_TC,
};

sdhci_tcc803x_ops操作集:

static const struct sdhci_ops sdhci_tcc803x_ops = {
	.get_max_clock = sdhci_tcc803x_clk_get_max_clock,
	.set_clock = sdhci_tcc_set_clock,
	.set_bus_width = sdhci_set_bus_width,
	.reset = sdhci_tcc_reset,
	.hw_reset = sdhci_tcc_hw_reset,
	.set_uhs_signaling = sdhci_set_uhs_signaling,
	.get_ro = sdhci_tcc_get_ro,

};

sdhci_ops与主控制硬件打交道,所以是再host主控制器驱动中实现的。

重新回到probe函数,看sdhci_pltfm_init函数:

struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
				    const struct sdhci_pltfm_data *pdata,
				    size_t priv_size)
{
    struct sdhci_host *host;

    //分配一个struct sdhci_host结构空间,附带分配一个struct sdhci_pltfm_host结构空间
    //和一个priv_size大小的空间
    host = sdhci_alloc_host(&pdev->dev,sizeof(struct sdhci_pltfm_host) + priv_size);

    if (pdata && pdata->ops)
		    host->ops = pdata->ops;  //对应上面定义的struct sdhci_ops sdhci_tcc803x_ops变量

    return host;
}

sdhci_alloc_host函数:

struct sdhci_host *sdhci_alloc_host(struct device *dev,
	size_t priv_size)
{
	struct mmc_host *mmc;
	struct sdhci_host *host;
    
    //本来是分配struct sdci_host结构体空间的,这里先分配struct mmc_host
    //结构体空间,附带分配着sdhci_host结构体空间,以及sdhci_host结构体附带
    //的其它空间大小
    mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev);

    host = mmc_priv(mmc);
	host->mmc = mmc;
	host->mmc_host_ops = sdhci_ops;
	mmc->ops = &host->mmc_host_ops;

    return host;
}

mmc_priv函数:

static inline void *mmc_priv(struct mmc_host *host)
{
	return (void *)host->private;
}

mmc_host结构体:

struct mmc_host {
	struct device		*parent;
	struct device		class_dev;
    const struct mmc_host_ops *ops;
    unsigned int		f_min;
	unsigned int		f_max;
	unsigned int		f_init;
    ......
    unsigned long		private[0] ____cacheline_aligned;
}

回到probe函数,看sdhci_priv函数:

static inline void *sdhci_priv(struct sdhci_host *host)
{
	return host->private;
}

sdhci_host结构:

struct sdhci_host {
	/* Data set by hardware interface driver */
	const char *hw_name;	/* Hardware bus name */
    const struct sdhci_ops *ops;	/* Low level hw interface */
	/* Internal data */
	struct mmc_host *mmc;	/* MMC structure */
	struct mmc_host_ops mmc_host_ops;	/* MMC host ops */
    ......
    unsigned long private[0] ____cacheline_aligned;
}

回到probe函数,看sdhci_add_host函数:

int sdhci_add_host(struct sdhci_host *host)
{
	sdhci_setup_host(host);
	__sdhci_add_host(host);
	return 0;
}

你可能感兴趣的:(linux,c语言,运维)