Linux中用platform_device结构体来描述

本文介绍了Linux系统中平台设备的概念及其结构体定义,并通过RTC平台设备为例详细讲解了平台设备如何被添加到系统中及其实现驱动的方法。

二、相关概念

1、平台设备:
通常在Linux中,把SoC系统中集成的独立外设单元(如:I2C、IIS、RTC、看门狗等)都被当作平台设备来处理。在Linux中用platform_device结构体来描述一个平台设备,在2.6.30.4内核中定义在:include/linux/platform_device.h中,如下:

struct platform_device {
const char * name; //设备名称
int id;
struct device dev;
u32 num_resources; //设备使用各类资源的数量
struct resource * resource; //设备使用的资源

struct platform_device_id *id_entry;
};

现在你不必深入理解这个结构体,只要知道在Linux中是用这个结构体来定义一些平台设备的。比如在:arch/arm/plat-s3c24xx/devs.c中就定义了很多平台设备,下面我就只贴出RTC这一种的:

* RTC */
static struct resource s3c_rtc_resource[] = { //定义了RTC平台设备使用的资源,这些资源在驱动中都会用到
[0] = { //IO端口资源范围
.start = S3C24XX_PA_RTC,
.end = S3C24XX_PA_RTC + 0xff,
.flags = IORESOURCE_MEM,
},
[1] = { //RTC报警中断资源
.start = IRQ_RTC,
.end = IRQ_RTC,
.flags = IORESOURCE_IRQ,
},
[2] = { //TICK节拍时间中断资源
.start = IRQ_TICK,
.end = IRQ_TICK,
.flags = IORESOURCE_IRQ
}
};

struct platform_device s3c_device_rtc = { //定义了RTC平台设备
.name = "s3c2410-rtc", //设备名称
.id = -1,
.num_resources = ARRAY_SIZE(s3c_rtc_resource), //资源数量
.resource = s3c_rtc_resource, //引用上面定义的资源
};

EXPORT_SYMBOL(s3c_device_rtc);

好了,定义了平台设备,那系统是怎么来使用他的呢?我们打开:arch/arm/mach-s3c2440/mach-smdk2440.c这个ARM 2440平台的系统入口文件,可以看到在系统初始化函数smdk2440_machine_init中是使用platform_add_devices这个函数将一些平台设备添加到系统中的,如下:(至于系统是如何实现添加平台设备的,这里我们不必研究,这些Linux系统都已经做好了的,我们要研究的是后面平台设备的驱动是如何实现的)

static struct platform_device *smdk2440_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c0,
&s3c_device_iis,
DE>

&s3c_device_rtc, //这里我们添加上RTC平台设备,默认是没添加的
}; //平台设备列表,也就是说我们要使用一个新的平台设备要先在上面定义,然后加到这个列表中,最后到驱动层去实现该设备的驱动

static void __init smdk2440_machine_init(void)
{
s3c24xx_fb_set_platdata(&smdk2440_fb_info);
s3c_i2c0_set_platdata(NULL);
//将上面列表中的平台设备添加到系统总线中
platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));
smdk_machine_init();
}

2、平台设备驱动:
这里所讲的平台设备驱动是指具体的某种平台设备的驱动,比如上面讲的RTC平台设备,这里就是指RTC平台设备驱动。在Linux中,系统还为平台设备定义了平台驱动结构体platform_driver,就好比系统为字符设备定义了file_operations一样,但不要把平台设备跟字符设备、块设备、网络设备搞成了并列的概念,因平台设备也可以是字符设备等其他设备。注意:在被定义为平台设备的字符设备的驱动中,除了要实现字符设备驱动中file_operations的open、release、read、write等接口函数外,还要实现平台设备驱动中platform_driver的probe、remove、suspend、resume等接口函数。好了,在我们搞明白上面这些后,下面我们就来具体详细分析讲解RTC平台设备的驱动现实。

在实时操作系统(RTOS)中使用 `sunxi_mmc_host` 的配置和实现涉及多个关键步骤,包括设备树配置、驱动适配、GPIO设置以及MMC子系统的初始化等。以下是一个详细的指南: ### ### 设备树配置 在使用 `sunxi_mmc_host` 之前,需要确保设备树(Device Tree)中正确配置了MMC控制器的相关信息。设备树节点通常包含控制器寄存器地址、中断号、DMA通道、支持的时钟频率等信息。 示例设备树配置如下: ```dts mmc0: mmc@1c0f000 { compatible = "allwinner,sun7i-a20-mmc"; reg = <0x01c0f000 0x1000>; interrupts = <0x51 0x4>; dma-coherent; status = "okay"; slot@0 { reg = <0>; bus-width = <4>; cd-gpios = <&pio 7 12 1>; // PA12 作为卡检测引脚 wp-gpios = <&pio 7 13 1>; // PA13 作为写保护引脚 }; }; ``` ### ### GPIO配置 `sunxi_mmc_host` 依赖于特定的GPIO引脚用于数据线、时钟线、卡检测和写保护等功能。需要根据SoC的GPIO数据手册配置正确的引脚复用功能。 例如,对于UART调试接口 `uart_debug_port=0`,对应的TX和RX引脚为 `PA04` 和 `PA05`。类似地,MMC控制器的引脚也需要在GPIO控制器中进行配置,确保它们被设置为MMC功能模式[^2]。 ### ### 驱动实现与初始化 在RTOS中,`sunxi_mmc_host` 驱动通常需要实现 `mmc_host_ops` 结构体中的操作函数,包括 `request`、`set_ios`、`get_ro`、`get_cd` 等。这些函数负责处理MMC核心层下发的请求,并控制硬件行为。 以下是一个简化的驱动初始化示例: ```c static const struct mmc_host_ops sunxi_mmc_ops = { .request = sunxi_mmc_request, .set_ios = sunxi_mmc_set_ios, .get_ro = sunxi_mmc_get_ro, .get_cd = sunxi_mmc_get_cd, }; struct mmc_host *sunxi_mmc_host_init(void) { struct mmc_host *host; host = mmc_alloc_host(sizeof(struct sunxi_mmc_host), &pdev->dev); if (!host) return ERR_PTR(-ENOMEM); host->ops = &sunxi_mmc_ops; host->f_min = 400000; host->f_max = 50000000; host->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; host->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; return host; } ``` ### ### MMC子系统集成 在RTOS中,MMC子系统需要与块设备层集成。通常通过 `mmc_add_host` 接口将 `mmc_host` 注册到系统中,并创建相应的块设备节点。 ```c int sunxi_mmc_probe(struct platform_device *pdev) { struct mmc_host *host; int ret; host = sunxi_mmc_host_init(); if (IS_ERR(host)) return PTR_ERR(host); ret = mmc_add_host(host); if (ret) goto err_free_host; return 0; err_free_host: mmc_free_host(host); return ret; } ``` ### ### 内核参数与挂载配置 在引导阶段,确保内核参数中包含 `rootwait`,以保证MMC设备在挂载前已准备好。例如: ``` bootargs=root=/dev/mmcblk0p8 rootwait ``` 这可以防止内核在MMC设备未准备好时尝试挂载根文件系统而导致的 `unknown-block(0,0)` 错误[^3]。 ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值