平台总线模型
物理总线: I2C SPI
平台总线是Linux系统虚拟出来的总线
平台总线模型的使用
平台设备驱动
struct platform_device {
const char *name; // device.c 和 driver.c 下的名称要一致才能匹配成功
int id; // 设置成-1则不会生成后缀
bool id_auto;
struct device dev;
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;
};
// include/linux/device.h
struct device {
struct device *parent;
struct device_private *p;
struct kobject kobj;
const char *init_name; /* initial name of the device */
const struct device_type *type;
//...
void (*release)(struct device *dev);
//...
}
// include/linux/ioport.h
/*
* Resources are tree-like, allowing
* nesting etc..
*/
struct resource {
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags; // 资源类型
struct resource *parent, *sibling, *child;
};
ls /sys/bus/platform/devices/
注册总线成功后,会显示在此目录下
资源类型
include/linux/ioport.h
/*
* IO resources have these defined flags.
*/
#define IORESOURCE_BITS 0x000000ff /* Bus-specific bits */
#define IORESOURCE_TYPE_BITS 0x00001f00 /* Resource type */
#define IORESOURCE_IO 0x00000100 /* PCI/ISA I/O ports */
#define IORESOURCE_MEM 0x00000200
#define IORESOURCE_REG 0x00000300 /* Register offsets */
#define IORESOURCE_IRQ 0x00000400
#define IORESOURCE_DMA 0x00000800
#define IORESOURCE_BUS 0x00001000
#define IORESOURCE_PREFETCH 0x00002000 /* No side effects */
#define IORESOURCE_READONLY 0x00004000
#define IORESOURCE_CACHEABLE 0x00008000
#define IORESOURCE_RANGELENGTH 0x00010000
#define IORESOURCE_SHADOWABLE 0x00020000
#define IORESOURCE_SIZEALIGN 0x00040000 /* size indicates alignment */
#define IORESOURCE_STARTALIGN 0x00080000 /* start field is alignment */
#define IORESOURCE_MEM_64 0x00100000
#define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */
#define IORESOURCE_MUXED 0x00400000 /* Resource is software muxed */
#define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */
#define IORESOURCE_DISABLED 0x10000000
#define IORESOURCE_UNSET 0x20000000 /* No address assigned yet */
#define IORESOURCE_AUTO 0x40000000
#define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */
相关函数
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
static struct resource my_resource[] = {
[0] = {
.start = 0xFD660000,
.end = 0xFD660004,
.flags = IORESOURCE_MEM},
[1] = {.start = 13, .end = 13, .flags = IORESOURCE_IRQ},
};
void my_release(struct device *dev)
{
printk("my_release");
}
struct platform_device my_device
{
.name = "my_device",
.id = -1,
.resource = my_resource,
.num_resources = ARRAY_SIZE(my_resource),
.dev = {
.release = my_release,
}
};
static int dev_init(void)
{
platform_device_register(&my_device);
printk("hello init");
return 0;
}
static void dev_exit(void)
{
platform_device_unregister(&my_device);
printk("hello bye");
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("MCC");
MODULE_VERSION("V1.0");
软件驱动部分
// include/linux/platform_device.h
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
bool prevent_deferred_probe;
};
案例代码:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
int my_probe(struct platform_device *p)
{
printk("my_probe");
return 0;
}
int my_remove(struct platform_device *p)
{
printk("my_remove");
return 0;
}
struct platform_driver my_driver
{
.probe = my_probe,
.remove = my_remove,
.driver = {
.name = "my_device",
.owner = THIS_MODULE},
};
static int dev_init(void)
{
platform_driver_register(&my_driver);
printk("hello init");
return 0;
}
static void dev_exit(void)
{
platform_driver_unregister(&my_driver);
printk("hello bye");
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("MCC");
MODULE_VERSION("V1.0");
编写probe函数
int my_probe(struct platform_device *p)
{
struct resource *my = platform_get_resource(p, IORESOURCE_IRQ, 0);
printk("my_probe start=%ld\n", my->start);
return 0;
}