SDIO驱动(5)sdio总线上的probe

本文详细介绍了SDIO驱动中probe过程的工作原理,涉及电源管理、资源同步、等待队列、中断锁以及block size的设置。在probe期间,通过禁止电源管理、独占式占用host、设置block size并与设备通信确认,确保了SDIO设备的正确连接和初始化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Linux 2.6.38

sdio总线上driver和设备的match成功只是软件之间的”切口“,好比《还钱》:

刘金山:明月几时有?

冯巩:抬头自己瞅。

但是冯巩并没有马上把请给他吧?这里硬件的连通性、能不能工作还不知道,所以要probe探测一下。

static int sdio_bus_probe(struct device *dev)
{
	struct sdio_driver *drv = to_sdio_driver(dev->driver);
	struct sdio_func *func = dev_to_sdio_func(dev);
	const struct sdio_device_id *id;
	int ret;

	id = sdio_match_device(func, drv);
	if (!id)
		return -ENODEV;

	/* Unbound SDIO functions are always suspended.
	 * During probe, the function is set active and the usage count
	 * is incremented.  If the driver supports runtime PM,
	 * it should call pm_runtime_put_noidle() in its probe routine and
	 * pm_runtime_get_noresume() in its remove routine.
	 */
	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
		ret = pm_runtime_get_sync(dev);
		if (ret < 0)
			goto out;
	}

	/* Set the default block size so the driver is sure it's something
	 * sensible. */
	sdio_claim_host(func);
	ret = sdio_set_block_size(func, 0);
	sdio_release_host(func);
	if (ret)
		goto disable_runtimepm;

	ret = drv->probe(func, id);
	if (ret)
		goto disable_runtimepm;

	return 0;

disable_runtimepm:
	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
		pm_runtime_put_noidle(dev);
out:
	return ret;
}
3、4行不用说了。

第8~10行,之前的match操作也调用的sdio_match_device,不过当时仅仅关心是不是匹配,其他一概不管。这里需要用到它的sdio_device_id返回值。


第12~22行,sdio host的caps成员记录其特性(capability),MMC_CAP_POWER_OFF_CARD是电源管理(Power Manager)方面的选项,设置了这个标志的host在suspend的时候将把card的电关掉。很显然,在probe的过程中不允许这种情况发生,解决方式就是禁止MMC子系统进入suspend模式。pm_runtime_get_sync()调用后将增加sdio device的引用计数,系统suspend过程中检测这个引用计数,发现其不为零就会退出suspend流程。相应的,pm_runtime_put_noidle()降低引用计数,也即它们必须成对使用。


第2

<think>嗯,用户想了解Linux SDIO驱动,我需要先理清楚SDIO的基本概念和它在Linux中的驱动结构。首先,SDIO是什么?SDIO全称是Secure Digital Input Output,它扩展了SD卡的标准,允许设备通过SD接口连接各种外设,比如Wi-Fi模块、蓝牙模块等。这点我记得没错吧? 接下来,用户可能想知道SDIO在Linux中的驱动架构。Linux的驱动模型通常分为主机控制器驱动、设备驱动和核心层。SDIO应该也是类似的架构。主机控制器驱动负责处理具体的硬件操作,比如SDHCI(Secure Digital Host Controller Interface)驱动,这个部分需要与硬件寄存器交互,处理DMA、中断等。对吗? 然后是SDIO核心层,这部分属于Linux内核的子系统,负责管理总线枚举、设备检测、电源管理等。核心层应该提供注册主机和设备驱动的API,以及处理通信协议。比如mmc core中的相关代码,可能需要提到struct mmc_host、struct mmc_card这些结构体。 设备驱动部分,针对具体的SDIO设备,比如Wi-Fi模块,每个设备会有自己的驱动,实现初始化、数据传输等功能。例如,bcmdhd驱动用于Broadcom的Wi-Fi芯片,这里可能需要举例说明设备驱动如何注册和操作。 用户可能还关心如何开发或调试SDIO驱动。开发方面,需要了解主机控制器的兼容性,设备驱动的注册流程,比如使用mmc_register_driver,以及如何处理中断和数据传输。调试的话,可能会用到mmc调试工具,比如mmc-utils,以及查看内核日志,使用示波器检查信号质量。 另外,需要注意SDIOSD存储卡的区别,虽然物理接口相同,但协议不同,SDIO支持更复杂的I/O操作。这可能也是用户容易混淆的地方,需要明确说明。 可能用户的实际需求是在开发或调试某个SDIO设备时遇到了问题,比如驱动无法识别设备,或者数据传输不稳定。这时候需要检查硬件连接、电源管理配置,以及驱动中的中断处理是否正确。例如,SDIO设备可能需要更高的电压或特定的初始化序列。 总结下来,回答的结构应该先介绍SDIO概念,再分层次讲解Linux中的驱动架构,包括主机驱动、核心层和设备驱动,然后给出开发调试的注意事项和工具,最后可能结合实际例子说明常见问题。确保使用正确的LaTeX格式,比如提到结构体时用$struct mmc_host$,独立公式用$$...$$,不过这部分可能用不上数学公式,但行内代码还是需要用反引号或者LaTeX的格式。</think>以下是对Linux SDIO驱动的结构化介绍,结合系统设计原理与实现细节: $$ \text{SDIO(Secure Digital Input Output)} $$ 是为扩展SD卡标准而制定的协议,允许通过SD接口连接Wi-Fi、蓝牙、GPS等外设。 ### 一、硬件层特性 1. **电气兼容性**:物理接口与SD卡相同(CLK/CMD/DAT[0-3]引脚) 2. **协议扩展**: - 支持CMD52(直接寄存器访问) - 支持CMD53(块数据传输) 3. **电压规范**:1.8V/3.3V双电压支持 ### 二、Linux驱动架构 ```text +-------------------+ | SDIO设备驱动 | (如bcmdhd、mwifiex) +-------------------+ ↓ +-------------------+ | MMC/SDIO核心层 | (drivers/mmc/core) +-------------------+ ↓ +-------------------+ | SDHCI主机控制器驱动 | (如s3c-sdhci、sdhci-pci) +-------------------+ ``` #### 1. 主机控制器驱动 - 关键结构体: ```c struct sdhci_host { // 描述主机控制器状态 struct mmc_host *mmc; // 关联的MMC主机对象 u32 quirks; // 硬件特性标记 const struct sdhci_ops *ops; // 操作函数集 }; ``` - 典型操作流程: ```c sdhci_request()sdhci_prepare_data()sdhci_set_transfer_mode() ``` #### 2. MMC/SDIO核心层 - 设备枚举过程: 1. 发送CMD5进行SDIO识别 2. 通过CMD52读取CIS(Card Information Structure) 3. 分配`struct mmc_card`并注册设备 #### 3. 设备驱动开发 注册示例: ```c static struct sdio_driver my_driver = { .probe = my_probe, .remove = my_remove, .name = "my_sdio_drv", .id_table = my_ids, // 匹配厂商/设备ID }; module_sdio_driver(my_driver); ``` ### 三、关键技术点 1. **中断处理**: - 使用CMD52设置中断使能位 - 通过`sdio_claim_irq()`注册中断处理函数 2. **数据传输**: ```c // 块模式传输 sdio_readsb(), sdio_writesb() // 字节模式传输 sdio_readb(), sdio_writeb() ``` 3. **电源管理**: - 通过SDIO_POWER_REG寄存器控制 - 调用`mmc_power_save_host()` ### 四、调试方法 1. 内核配置选项: ``` CONFIG_MMC_DEBUG=y CONFIG_MMC_TEST=m ``` 2. 调试工具: ```bash mmc-utils -d /dev/mmcblk0 inquiry dmesg | grep mmc ``` ### 五、典型问题排查 1. **设备未识别**: - 检查CMD5响应 - 验证CIS解析是否正确 2. **数据传输错误**: - 用示波器检查CLK信号质量 - 调整`sdhci_host->timeout_clk`值 $$ \text{SDIO时钟频率计算:} f_{oper} = \frac{f_{base}}{divider} $$ 建议开发时优先使用现有驱动框架(如`drivers/mmc`),重点关注设备特定配置和电源管理策略的实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值