linux2.6中的platform和of

A platform机制platform_driver_register,什么时候调用PROBE函数 注册后如何找到驱动匹配的设备platform_driver_register(struct platform_driver *drv)注册后如何找到驱动匹配的设备

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 (*suspend_late)(struct platform_device *, pm_message_t state); int (*resume_early)(struct platform_device *); int (*resume)(struct platform_device *); struct device_driver driver;};

BUS首先初始化总线 do_basic_setup()->driver_init()->platform_bus_init()->…初始化platform_bus_type(虚拟总线)

DEVICE生成有2种方法

1 用函数platform_device_register()直接注册一个platform_device设备

设备向内核注册的时候platform_device_register()->platform_device_add()->…内核把设备挂在虚拟的platform bus下platform_device_register(&physmap_flash); /*这是一个flash驱动例子*/

2 从dts文件中读出来形成一个platform_device设备

用下面的函数_init gfar_of_init(void) 读取dts文件获得platform_device结构体 /*这是一个mac驱动的例子*/struct platform_device {const char* name;u32id;struct devicedev;u32num_resources;struct resource* resource;};

读取的是下面dts里面的结构ethernet@24000{#address-cells = <0x1>;#size-cells = <0x0>;device_type = "network";model = "eTSEC";compatible = "gianfar";reg = <0x24000 0x1000>;local-mac-address = [00 00 00 00 00 00];interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;interrupt-parent = <0x1>;phy-handle = <0x2>;phy-connection-type = "sgmii";};

DRIVER驱动注册的时候 platform_driver_register()->driver_register()->bus_add_driver()->driver_attach()->bus_for_each_dev() 对每个挂在虚拟的platform bus的设备作

__driver_attach()->driver_probe_device()->drv->bus->match() 就是下面的platform_match比较strncmp(pdev->name, drv->name, BUS_ID_SIZE),如果相符就调用platform_drv_probe()->driver->probe(),如果probe成功则绑定该设备到该驱动.

static int platform_match(struct device * dev, struct device_driver * drv){struct platform_device *pdev = container_of(dev, struct platform_device, dev);

return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);}

当最后匹配后就调用platform_drv_probe()->driver->probe() 进入驱动的probe()。

B of_platform机制

struct of_platform_driver{const char*name;const struct of_device_id*match_table;struct module*owner;

int(*probe)(struct of_device* dev, const struct of_device_id *match);int(*remove)(struct of_device* dev);

int(*suspend)(struct of_device* dev, pm_message_t state);int(*resume)(struct of_device* dev);int(*shutdown)(struct of_device* dev);

struct device_driverdriver;};

struct of_device_id{charname[32];chartype[32];charcompatible[128];#ifdef __KERNEL__void*data;#elsekernel_ulong_t data;#endif};

BUS首先初始化总线 do_basic_setup()->driver_init()->platform_bus_init()->…初始化of_platform_bus_type(虚拟总线)

DEVICE设备生成用下面的函数mpc8572_register_mtd(void)读取dts文件 获得device_node结构struct device_node {const char *name;const char *type;phandlenode;phandle linux_phandle;char*full_name;

structproperty *properties;struct property *deadprops; /* removed properties */structdevice_node *parent;structdevice_node *child;structdevice_node *sibling;structdevice_node *next;/* next device of same type */structdevice_node *allnext;/* next in list of all nodes */struct proc_dir_entry *pde;/* this node’s proc directory */struct kref kref;unsigned long _flags;void*data;};

读取的是下面dts里面的结构nor@ef800000{device_type = "rom";compatible = "direct-mapped";reg = <0xef800000 0x800000>;probe-type = "CFI";bank-width = <0x1>;partitions = <0x0 0x400000 0x400000 0x8001 0x408000 0x300001 0x708000 0x78001 0x780000 0x80001>;partition-names = "JFFS2(RW)", "DTB(RO)", "Linux Kernel(RO)", "Parameters(RO)", "U-BOOT(RO)";};

DRIVER驱动注册的时候 platform_driver_register()->driver_register()->bus_add_driver()->driver_attach()->bus_for_each_dev() 对每个挂在虚拟的platform bus的设备作 __driver_attach()->driver_probe_device()->drv->bus->match(), 就是下面的of_platform_bus_match,如果相符就调用 platform_drv_probe()->driver->probe()。

.最终比较的是of_platform_driver.match_table里面的那么,type,compatible与device_node里面的name,type,compatible

static int of_platform_bus_match(struct device *dev, struct device_driver *drv){struct of_device *of_dev = to_of_device(dev);struct of_platform_driver *of_drv = to_of_platform_driver(drv);const struct of_device_id *matches = of_drv->match_table;

if (!matches)return 0;

return of_match_device(matches, of_dev) != NULL;}

const struct of_device_id *of_match_device(const struct of_device_id *matches,const struct of_device *dev){if (!dev->node)return NULL;return of_match_node(matches, dev->node);}

const struct of_device_id *of_match_node(const struct of_device_id *matches, const struct device_node *node){while (matches->name[0] || matches->type[0] || matches->compatible[0]) {int match = 1;if (matches->name[0])match &= node->name&& !strcmp(matches->name, node->name);if (matches->type[0])match &= node->type&& !strcmp(matches->type, node->type);if (matches->compatible[0])match &= of_device_is_compatible(node,matches->compatible);if (match)return matches;matches++;}return NULL;}

当最后匹配后就调用platform_drv_probe()->driver->probe() 进入驱动的probe()。

或许人生就是一场旅行,在旅行中遇到的每一个人,

linux2.6中的platform和of

相关文章:

你感兴趣的文章:

标签云: