1、platform
平台总线模型就是把原来的驱动 C 文件给分成了两个, 一个是 device.c, 一个是 driver.c 。把稳定不变的放在 driver.c 里面, 需要变得就放在了 device.c 里面。平台总线模型将设备代码和驱动代码分离, 将和硬件设备相关的都放到 device.c 文件里面,驱动部分代码都放到 driver.c 文件里面。
2、platform_device
1)申请platform_device 结构体
struct platform_device {
const char *name; //platform 设备的名字, 用来和 platform 驱动相匹配。
int id; //ID 是用来区分如果设备名字相同的时候(通过在后面添加一个数字来代表不同的设备)
bool id_auto;
struct device dev; //内置的 device 结构体
u32 num_resources; //资源结构体数量
struct resource *resource; //指向一个资源结构体数组
const struct platform_device_id *id_entry;
char *driver_override; /* Driver name to force a match */
/* MFD cell pointer */
struct mfd_cell *mfd_cell;
/* arch specific additions */
struct pdev_archdata archdata;
};
platform 设备的名字, 用来和 platform 驱动相匹配。将会在/sys/bus 目录下生成以“name"命名的总线。
注:platform_device 结构体中的 struct device dev内容,必须填写release相关内容,否则会有警告。建议添加。
2)填充platform_device 中resource 结构体
resource 结构体内容如下:
struct resource {
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags;
struct resource *parent, *sibling, *child;
};
start 和 end 分别表示资源的起始和终止信息, 对于内存类的资源, 就表示内存起始和终止地址,
name表示资源名字,
flags 表示资源类型, 可选的资源类型都定义在了文件 include/linux/ioport.h 里面。
常用 flags 宏定义如下所示:
#define IORESOURCE_IO IO内存
#define IORESOURCE_MEM 一段物理内存
#define IORESOURCE_IRQ 中断
3)将设备信息注册到内核
然后使用platform_device_register 函数将设备信息注册到 Linux 内核中。
3、demo
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#define PHY_BASEADDR_GPIO 0x01C20800
struct resource led_res[]={
[0] = {
.start = PHY_BASEADDR_GPIO+0x0108,
.end = PHY_BASEADDR_GPIO+0x010B,
.flags = IORESOURCE_MEM ,
.name = "PH_Config_Reg",
},
[1] = {
.start = PHY_BASEADDR_GPIO+0x0114,
.end = PHY_BASEADDR_GPIO+0x0117,
.flags = IORESOURCE_MEM ,
.name = "PH_Mul_Reg ",
},
[2] = {
.start = PHY_BASEADDR_GPIO+0x010C,
.end = PHY_BASEADDR_GPIO+0x010F,
.flags = IORESOURCE_MEM ,
.name = "PH_Data_Reg",
}
};
void led_device_release(struct device *dev)
{
printk("led_device_release\n");
};
struct platform_device led_device={
.name = "my_led_device",
.id = -1,
.resource = led_res,
.num_resources = ARRAY_SIZE(led_res),
.dev = {
.release = &led_device_release
}
};
static int led_device_init(void)
{
int ret;
printk("platform device enter\n");
ret = platform_device_register(&led_device);
printk("ret = %d\n",ret);
return 0;
}
static void led_device_exit(void)
{
platform_device_unregister(&led_device);
printk("led_device_exit\n");
}
module_init(led_device_init);
module_exit(led_device_exit);
MODULE_LICENSE("GPL");
模块加载成功后可以在/sys/bus/platform/devices/ 路径下查看