2012-09-02 10:57:50
分类: LINUX
下面来看看内核时怎么注册platform总线的过程
点击(此处)折叠或打开
- int __init
platform_bus_init(void)
- {
-
int error; -
early_platform_cleanup();
-
error = device_register(&platform_bus);//注册了platform的设备 -
if (error) -
return error; -
error = bus_register(&platform_bus_type);//注册了platform总线 -
if (error) -
device_unregister(&platform_bus);
-
return error; - }
点击(此处)折叠或打开
- struct device platform_bus = {
-
.init_name = "platform", - };
点击(此处)折叠或打开
- struct bus_type platform_bus_type = {
-
.name = "platform", -
.dev_attrs = platform_dev_attrs, -
.match = platform_match, -
.uevent = platform_uevent, -
.pm = &platform_dev_pm_ops, - };
1、定义一个platform_device,并注册
2、定义一个platform_driver,并注册
定义platform_device过程
点击(此处)折叠或打开
- struct platform_device *platform_device_alloc(const
char *name, int
id)
- {
-
struct platform_object *pa; -
pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL); -
if (pa) { -
strcpy(pa->name, name); -
pa->pdev.name = pa->name; -
pa->pdev.id = id; -
device_initialize(&pa->pdev.dev);
-
pa->pdev.dev.release = platform_device_release; -
arch_setup_pdev_archdata(&pa->pdev);
-
}
-
return pa ? &pa->pdev : NULL; - }
下面首先来看看platform_device的注册过程
点击(此处)折叠或打开
- struct platform_device {
-
const char * name; //设备名 -
int id; //设备ID -
struct device dev;
-
u32 num_resources; //设备使用的资源的数目 -
struct resource * resource; //设备使用的资源 -
const struct platform_device_id *id_entry;
-
/* MFD cell pointer */ -
struct mfd_cell *mfd_cell; -
/* arch specific additions */ -
struct pdev_archdata archdata;
- };
点击(此处)折叠或打开
- struct resource {
-
resource_size_t start; -
resource_size_t end; -
const char *name; -
unsigned long flags; -
struct resource *parent, *sibling, *child; - };
点击(此处)折叠或打开
- int
platform_device_register(struct
platform_device *pdev)
- {
-
device_initialize(&pdev->dev);//dev初始化
-
arch_setup_pdev_archdata(pdev);
-
return platform_device_add(pdev);//加入到dev链表 - }
点击(此处)折叠或打开
- int
platform_device_add(struct
platform_device *pdev)
- {
-
int i, ret = 0; -
if (!pdev) -
return -EINVAL; -
if (!pdev->dev.parent) -
pdev->dev.parent = &platform_bus;//父设备设置为platform_bus -
pdev->dev.bus = &platform_bus_type;//设备挂载在platforrm总线上 -
if (pdev->id != -1) -
dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); -
else
-
dev_set_name(&pdev->dev, "%s", pdev->name); -
for (i = 0; i <</span> pdev->num_resources; i++) { //完成资源的初始化 -
struct resource *p, *r = &pdev->resource[i]; -
if (r->name == NULL) -
r->name = dev_name(&pdev->dev); -
p = r->parent; -
if (!p) { -
if (resource_type(r) == IORESOURCE_MEM) -
p = &iomem_resource; -
else if (resource_type(r) == IORESOURCE_IO) -
p = &ioport_resource; -
}
-
if (p && insert_resource(p, r)) { -
printk(KERN_ERR
-
"%s: failed to claim resource %d\n", -
dev_name(&pdev->dev), i); -
ret = -EBUSY; -
goto failed; -
}
-
}
-
pr_debug("Registering platform device '%s'. Parent at %s\n", -
dev_name(&pdev->dev), dev_name(pdev->dev.parent)); -
ret = device_add(&pdev->dev); -
if (ret == 0) -
return ret; -
failed: -
while (--i >= 0) { -
struct resource *r = &pdev->resource[i]; -
unsigned long type = resource_type(r); -
if (type == IORESOURCE_MEM || type == IORESOURCE_IO) -
release_resource(r);
-
}
-
return ret; - }
点击(此处)折叠或打开
- 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; - };
点击(此处)折叠或打开
- int
platform_driver_register(struct
platform_driver *drv)
- {
-
drv->driver.bus = &platform_bus_type;//注册到总线上,drv与dev匹配通过platform_bus_type注册的platform_match完成
-
if (drv->probe) -
drv->driver.probe = platform_drv_probe; -
if (drv->remove) -
drv->driver.remove = platform_drv_remove; -
if (drv->shutdown) -
drv->driver.shutdown = platform_drv_shutdown; -
return driver_register(&drv->driver); - }
点击(此处)折叠或打开
- int
driver_register(struct
device_driver *drv)
- {
-
int ret; -
struct device_driver *other;
-
BUG_ON(!drv->bus->p);
-
if ((drv->bus->probe && drv->probe) || -
(drv->bus->remove && drv->remove) || -
(drv->bus->shutdown && drv->shutdown)) -
printk(KERN_WARNING "Driver '%s' needs updating - please use " -
"bus_type methods\n", drv->name); -
other = driver_find(drv->name, drv->bus); -
if (other) { -
put_driver(other);
-
printk(KERN_ERR "Error: Driver '%s' is already registered, " -
"aborting...\n", drv->name); -
return -EBUSY; -
}
-
ret = bus_add_driver(drv); -
if (ret) -
return ret; -
ret = driver_add_groups(drv, drv->groups); -
if (ret) -
bus_remove_driver(drv);
-
return ret; - }
下面看看看驱动和设备的匹配过程,由以前可以看出,主要是调用bus的match函数来完成匹配。
点击(此处)折叠或打开
- static int
platform_match(struct device
*dev, struct device_driver *drv)
- {
-
struct platform_device *pdev = to_platform_device(dev);
-
struct platform_driver *pdrv = to_platform_driver(drv);
-
/* Attempt an OF style match first */ -
if (of_driver_match_device(dev, drv)) -
return 1; -
/* Then try to match against the id table */ -
if (pdrv->id_table) -
return platform_match_id(pdrv->id_table, pdev) != NULL; -
/* fall-back to driver name match */ -
return (strcmp(pdev->name, drv->name) == 0); - }
1、在bsp版文件中实现定义,在文件中将platform_device被化为一个数组,最后通过platform_add_devices函数注册。对于2440来说位于arch\arm\mach-s3c2440\mach-smdk2440.c中定义
点击(此处)折叠或打开
- static struct platform_device *smdk2440_devices[]
__initdata = {
-
&s3c_device_usb,
-
&s3c_device_lcd,
-
&s3c_device_wdt,
-
&s3c_device_i2c,
-
&s3c_device_iis,
- };
2、第二种方法只需要单独编写一个内核模块加载到内核中。
例子:
device文件:platform_dev.c
点击(此处)折叠或打开
- struct platform_device *my_led_dev;
-
- static int __init
platform_dev_init(void)
- {
-
int ret; -
-
//分配一个 platform_device结构体 -
my_led_dev = platform_device_alloc("platform_led", -1); -
-
ret = platform_device_add(my_led_dev);//将自定义的设备添加到内核设备架构中 -
-
if(ret)
-
platform_device_put(my_led_dev);//销毁platform设备结构
-
-
return ret; - }
-
- static void __exit platform_dev_exit(void)
- {
-
platform_device_unregister(my_led_dev);//注销platform_device
- }
-
- module_init(platform_dev_init);
- module_exit(platform_dev_exit);
-
- MODULE_AUTHOR("Sola");
- MODULE_LICENSE("GPL");
点击(此处)折叠或打开
- static int
s3c6410_led_open(struct inode
*inode, struct file *file)
- {
-
unsigned tmp; -
tmp = readl(S3C64XX_GPMCON); -
tmp = (tmp & ~(0xFFFF))|(0x1111U); -
writel(tmp, S3C64XX_GPMCON); -
-
return 0; - }
-
-
- static int
s3c6410_led_close(struct inode
*inode, struct file *file)
- {
-
return 0; - }
-
-
- static int
s3c6410_led_read(struct file
*filp, char __user *buff,
size_t count, loff_t
*offp)
- {
-
printk("#########read######\n");
-
return count; - }
- static int
s3c6410_led_write (struct file
*filp, const
char __user *buf, size_t count,loff_t *f_pos)
- {
-
char wbuf[10]; -
unsigned tmp; -
copy_from_user(wbuf,buf,count);
-
if(wbuf[0]==1)//1号灯亮 -
switch(wbuf[1])
-
{
-
case 0: //off -
tmp = readl(S3C64XX_GPMDAT); -
tmp |= (0x1U); -
writel(tmp, S3C64XX_GPMDAT); -
break;
-
case 1: //on -
tmp = readl(S3C64XX_GPMDAT); -
tmp &= ~(0x1U); -
writel(tmp, S3C64XX_GPMDAT); -
break;
-
default : -
break;
-
}
-
-
if(wbuf[0]==2)//2号灯亮 -
switch(wbuf[1])
-
{
-
case 0: //off -
tmp = readl(S3C64XX_GPMDAT); -
tmp |= (0x2U); -
writel(tmp, S3C64XX_GPMDAT); -
break;
-
case 1: //on -
tmp = readl(S3C64XX_GPMDAT); -
tmp &= ~(0x2U); -
writel(tmp, S3C64XX_GPMDAT); -
break;
-
default : -
break;
-
}
-
-
if(wbuf[0]==3)//3号灯亮 -
switch(wbuf[1])
-
{
-
case 0: //off -
tmp = readl(S3C64XX_GPMDAT); -
tmp |= (0x4U); -
writel(tmp, S3C64XX_GPMDAT); -
break;
-
case 1: //on -
tmp = readl(S3C64XX_GPMDAT); -
tmp &= ~(0x4U); -
writel(tmp, S3C64XX_GPMDAT); -
break;
-
default : -
break;
-
}
-
-
if(wbuf[0]==4)//4号灯亮 -
switch(wbuf[1])
-
{
-
case 0: //off -
tmp = readl(S3C64XX_GPMDAT); -
tmp |= (0x8U); -
writel(tmp, S3C64XX_GPMDAT); -
break;
-
case 1: //on -
tmp = readl(S3C64XX_GPMDAT); -
tmp &= ~(0x8U); -
writel(tmp, S3C64XX_GPMDAT); -
break;
-
default : -
break;
-
}
-
return count; - }
-
-
- static struct file_operations led_fops = {
-
.owner = THIS_MODULE, -
.open = s3c6410_led_open, -
.release = s3c6410_led_close, -
.read = s3c6410_led_read, -
.write = s3c6410_led_write, - };
-
-
- static int
my_plat_probe(struct
platform_device *dev)
- {
-
int rc; -
printk("Test platform_led dev\n"); -
//注册设备 -
rc = register_chrdev(LED_MAJOR,"platform_led",&led_fops); -
if (rc <</span>0) -
{
-
printk ("register %s char dev error\n","led"); -
return -1; -
}
-
printk ("ok!\n"); -
return 0; - }
-
- static int
my_plat_remove(struct
platform_device *dev)
- {
-
printk("my platfrom device has removed.\n"); -
return 0; - }
-
- struct platform_driver my_led_drv = {
-
.probe = my_plat_probe, -
.remove = my_plat_remove, -
.driver = { -
.owner = THIS_MODULE, -
.name = "platform_led", -
},
- };
-
- static int __init
platform_drv_init(void)
- {
-
int ret; -
-
ret = platform_driver_register(&my_led_drv); -
-
return ret; - }
-
- static void __exit platform_drv_exit(void)
- {
-
platform_driver_unregister(&my_led_drv);
- }
-
- module_init(platform_drv_init);
- module_exit(platform_drv_exit);
-
- MODULE_LICENSE("GPL");