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()降低引用计数,也即它们必须成对使用。


第26~28行,设置block siz

### Linux SDIO 驱动开发指南 在Linux环境下,SDIO(Secure Digital Input Output)是一种用于嵌入式设备的标准接口协议。以下是关于如何开发SDIO驱动的一些关键点: #### 1. **理解SDIO架构** SDIO驱动程序的设计基于Linux内核中的`mmc_core`框架。该框架提供了管理MMC/SD卡以及SDIO功能的基础支持[^1]。开发者需要熟悉以下核心概念: - `struct mmc_host`: 表示主机控制器的结构体。 - `struct mmc_card`: 表示已识别的SD/MMC卡或SDIO设备。 - `struct sdio_func`: 描述单个SDIO函数的功能。 这些数据结构定义了SDIO设备及其操作方式,并通过标准API提供访问控制。 #### 2. **初始化过程** 当系统启动时,SDIO总线会扫描连接到系统的设备并分配相应的资源。对于特定平台的支持文件通常位于内核源码树下的路径`arch/arm/mach-(platform)/board-xxxx.c`中[^3]。在此过程中,需确保硬件初始化脚本正确配置GPIO、时钟以及其他必要的外设参数。 #### 3. **模块构建流程** 如果蓝牙或其他无线通信服务作为独立模块实现,则需要按照如下命令编译相关组件: ```bash make CROSS_COMPILE=arm-none-linux-gnueabi- ARCH=arm modules ``` 此步骤确保所有依赖项被正确链接至最终目标二进制文件中[^2]。 #### 4. **编写驱动代码** 下面是一个简单的例子展示如何注册一个新的SDIO驱动器: ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/sdio_func.h> static int my_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) { pr_info("My SDIO Driver Probed\n"); // Initialize your hardware here. return 0; } static void my_sdio_remove(struct sdio_func *func) { pr_info("My SDIO Driver Removed\n"); // Cleanup resources allocated during probe(). } // Match table used by the core to bind this driver with compatible devices. static const struct sdio_device_id my_sdio_ids[] = { { SDIO_DEVICE(0xaaaa, 0xbbbb) }, /* Vendor ID and Device ID */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(sdio, my_sdio_ids); static struct sdio_driver my_sdio_driver = { .probe = my_sdio_probe, .remove = my_sdio_remove, .name = "my_sdio", .id_table = my_sdio_ids, }; module_sdio_driver(my_sdio_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple example of an SDIO driver."); ``` 上述代码片段展示了基本的探针(`probe`)和移除(`remove`)回调机制,同时还包含了匹配表来指定哪些类型的SDIO设备可以由这个驱动处理。 #### 5. **调试技巧** 为了验证驱动行为是否正常工作,可以通过读取日志消息或者利用工具如`dmesg`查看输出信息。另外也可以借助专门设计用来测试SDIO交互的应用层应用程序来进行进一步分析。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值