树莓派uboot的串口初始化(uboot驱动结构 2通用解析)

来源:互联网 发布:常见网络命令 编辑:程序博客网 时间:2024/05/22 00:22

先上一张看不清的图片 具体的下载资源里面的看 用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_UARTint (*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里面的函数。

点击打开链接  图片下载






0 0
原创粉丝点击