先上一张看不清的图片 具体的下载资源里面的看 用dia看
蓝色的部分是我们定义的部分
更加详细的部分看
http://blog.csdn.net/groundhappy/article/details/53256086
这里说通用的部分
uboot在初始化的时候会调用initf_dm->dm_init_and_scan->dm_scan_platdata(lists_bind_drivers)扫描所有的设备。
lists_bind_drivers对于所有的driver_info结构体产生一个设备。
我们定义了
U_BOOT_DEVICE(bcm2835_serials) = {
.name = "serial_pl01x",
.platdata = &serial_platdata,
};
U_BOOT_DEVICE宏就是定义driver_info结构的
我们定义了一个串口设备。这个设备是bcm2835_serials。设备所需要的驱动的名字是"serial_pl01x",而他私有的数据存放在serial_platdata里面。比如在开发板A上地址寄存器地址映射到了0X100000。在B开发板上是0X20000。这样的数据就可以放在serial_platdata里面。
首先要去寻找名字是serial_pl01x的驱动。通过lists_driver_lookup_name("serial_pl01x")我们找到了struct driver对象。
这个driver对象也定义了
U_BOOT_DRIVER(serial_pl01x) = {
.name = "serial_pl01x",
.id = UCLASS_SERIAL,
.of_match = of_match_ptr(pl01x_serial_id),
.ofdata_to_platdata = of_match_ptr(pl01x_serial_ofdata_to_platdata),
.platdata_auto_alloc_size = sizeof(struct pl01x_serial_platdata),
.probe = pl01x_serial_probe,
.ops = &pl01x_serial_ops,
.flags = DM_FLAG_PRE_RELOC,
.priv_auto_alloc_size = sizeof(struct pl01x_priv),
};
根据 U_BOOT_DEVICE(bcm2835_serials)里面的.name 首先我们找到了"serial_pl01x"这个驱动结构,然后根据driver里面的.id立马知道了这个设备是UCLASS_SERIAL设备。并且我们知道对于这个设备的操作是.ops=&pl01x_serial_ops。这个结构最后说。
接下来就是在gd->uclass_root里面找到管理UCLASS_SERIAL的结构。分配一个udevice设备放进去。
uclass_get(driv->id)也就是根据UCLASS_SERIAL,获取对应的uclass指针。首先在gd->uclass_root里面寻找对应的UCLASS节点
如果没有找到。调用uclass_add根据class_id 寻找对应的驱动。这里说明一下一个设备有不同层次的驱动。
第一层是uclass的类驱动。所有的设备都需要使用这一部分,也就是不管是串口还是I2C还是SPI还是其他设备,都有一部分通用的接口函数需要写。比如init destroy等等。
第二层是驱动同一类型但是不同型号的设备需,比如A B两种类型的串口可能寄存器位置等不一样,但是他们都属于串口。
找到了一个定义了UCLASS_DRIVER(serial)他的.id是UCLASS_SERIAL。因此根据这个驱动的结构体
calloc一个 uclass对象,并挂载到uclass_root里面。 这个uclass对象就保存ID为UCLASS_SERIAL的各类信息。
属于串口的类驱动,可以看到串口类驱动通用部分只提供了移除和插入的函数。
UCLASS_DRIVER(serial) = {
.id = UCLASS_SERIAL,
.name = "serial",
.flags = DM_UC_FLAG_SEQ_ALIAS,
.post_probe = serial_post_probe,
.pre_remove = serial_pre_remove,
.per_device_auto_alloc_size = sizeof(struct serial_dev_priv),
};
得到uclass结构指针之后就calloc了一个udevice结构。
接下来就是一系列的赋值并将这个udevice挂入uclass的链表里面。
最后就是driver当中的.ops成员。pl01x_serial_ops
struct dm_serial_ops {
int (*setbrg)(struct udevice *dev, int baudrate);
int (*getc)(struct udevice *dev);
int (*putc)(struct udevice *dev, const char ch);
int (*pending)(struct udevice *dev, bool input);
int (*clear)(struct udevice *dev);
#if CONFIG_POST & CONFIG_SYS_POST_UART
int (*loop)(struct udevice *dev, int on);
#endif
};
定义了这样的选项。
static const struct dm_serial_ops pl01x_serial_ops = {
.putc = pl01x_serial_putc,
.pending = pl01x_serial_pending,
.getc = pl01x_serial_getc,
.setbrg = pl01x_serial_setbrg,
};
。后续可以通过udevice->driver->ops来执行操作。其他的类型的串口也需要实现dm_serial_ops里面的函数。
点击打开链接 图片下载