专栏首页HackforFunU-Boot 驱动模型

U-Boot 驱动模型

最近拿了一块 Firefly 的开发板,主控是 RK3308,发现上面用的 U-Boot 是 2017 年的,于是想移植一个最新的版本上去,调试驱动的时候,总结了这些经验。

U-Boot DM 三要素

DM 是 U-Boot 中的驱动框架,全称 Driver Mode。像 Linux Kernel 中的驱动三要素 device 、bus 、driver 一样,DM 也有自己的三要素:udevice、uclass、driver。

udevice 描述具体的某一个硬件设备。

driver 是与这个设备匹配的驱动。

uclass 是同一类设备的抽象,提供管理同一类设备的抽象接口。

  • udevice

通过三种途径生成:

  • dts 设备节点
  • UBOOTDEVICE(__name) 宏申明
  • 主动调用 device_bind_xxx 系列 API 根据当前 U-Boot 的编程哲学,基本大部分设备都是通过 dts 来描述,还有少部分设备因为特殊原因,可以通过 U_BOOT_DEVICE(_name) 宏申明。 在UBoot DM 初始化阶段(initfdm 和 initrdm),通过调用 dm_init_and_scan(boolpre_reloc_only) 根据名称 (UBOOT_DEVICE 中和 driver 的 name,或者 dts 和 driver 的 compatible) 匹配到对应的 driver,然后调用 device_bind_common 函数生成 udevice,udevice 会和 driver 绑定,并根据 driver 中的uclass id 找到对应的 uclass driver,并生成相应的 uclass, 并把该设备挂到 uclass 的设备节点之下。最后调用 driver 的 bind 函数。 还有部分特殊的驱动,他们并不存在实际意义上的设备,比如 MMC 子系统中的 mmcblk 驱动,该驱动主要是把所有的 mmc 设备注册到更上一层的 blk 子系统中,向 blk 层提供操作 mmc 设备的 blkops,向下通过mmc uclass 提供的统一接口控制 mmc 设备。显然,这个驱动位于抽象层,它不和具体的硬件设备直接交互,并不适合用一个 dts(dts 是用来描述具体的硬件信息的) 节点或者 UBOOTDEVICE(_name) 宏来为这个驱动显示的申明设备。这种情形下一般通过主动调用 device_bind_xxx 系列 API 来完成驱动和设备已经更上一层 uclass 之间的 bind。

A:生成 udevice。 B:绑定 udevice 和 driver。 C:把设备挂到 uclass 的dev_head 链表下。 D:调用设备驱动的 bind 接口。

  • uclass

这里主要的成员是 uclassdriver 和 devhead 链表。 dev_head 是一个链表头, 用来链接该类下的所有设备。可以通过 uclass_foreach_dev(dev,uc) 遍历该class 下的所有设备。 uclass_driver 是针对某一类设备提供的通用操作接口,然后通过 udevice->driver->ops 操作到具体的硬件设备。 uclassdriver 通过 UCLASSDRIVER(name) 宏申明, 在 device_bind_common 中根据 设备对应的驱动 driver 中的 uclass id 找到 uclassdriver,并生成相应的 uclass, 并把设备挂到该 uclass 的设备节点 dev_head 下。 以 pwm backlight 为例:

通过 UBOOTDRIVER 的 id 可以看出,该设备(pwm backlight)驱动属于 UCLASSPANELBACKLIGHT 类。

这里定义了 backlight 的 UCLASS_DRIVER。该 uclass driver 提供了 backlight_enable(structudevice*dev)backlight_set_brightness(structudevice*dev,intpercent) 两个通用的 API 供应用调用,可以看到他们都需要传递对应设备的 udevice ,然后通过 backlight_get_ops(dev) 拿到对该设备的操作接口。

  1. #define backlight_get_ops(dev) ((struct backlight_ops *)(dev)->driver->ops)

  • driver

通过 UBOOTDRIVER(__name) 宏声明。如果 driver 实现了 bind 接口,该bind 将在 device_bind_common 中 device 和 driver 匹配上后被调用, 而且在 device_bind_common 中会完成 udevice 和 driver 的绑定。

driver 一般都有对应的 probe 接口,通过 device_probe(structudevice*dev) 调用,需要注意的是driver 的 bind 接口调用的比 probe 接口早, 大部分在 dm_init_and_scan 中就被调用了。

driver 一般会提供 ops 操作接口,供上一层调用。

需要说明的是,driver 一般都不需要把自己注册到 uclass 中,而是在 device_bind _common 阶段实现driver 、uclass、device 三者的对接,然后 uclass 层通过 udevice->driver->ops 获取对应 driver 的操作接口。

设备驱动的使用

一般应用层的代码要使用某个设备的时候,首先需要通过 uclass_get_device_xxx 系列 API 拿到该设备的 udevice, 然后通过该设备的 uclass 提供的 API 操作该设备。

uclass_get_device_xxx 拿到该设备的 udevice 后会调用该设备的 probe 接口。

以前面提到的 pwm backlight 为例:

/**
 * drivers/video/simple_panel.c
 */
struct udevice *bldev;
uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, "backlight", &bldev);
backlight_enable(bldev);
backlight_set_brightness(bldev, percent);

本文分享自微信公众号 - HackforFun(gh_c8e36f389b90)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-10-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Hibernate常用API

    爱撒谎的男孩
  • 通过替代文本描述使LinkedIn媒体更具包容性

    原文 https://engineering.linkedin.com/blog/2019/alternative-text-descriptions

    LiveVideoStack
  • 如何更优雅地对接第三方API

    本文所有示例完整代码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/reposito...

    用户1148394
  • 聊聊rocketmq的SlaveSynchronize

    rocketmq-all-4.6.0-source-release/broker/src/main/java/org/apache/rocketmq/broke...

    codecraft
  • ElasticSearch AggregationBuilders java api常用聚会查询

    以球员信息为例,player索引的player type包含5个字段,姓名,年龄,薪水,球队,场上位置。 index的mapping为:

    小勇DW3
  • Netty简单概述

      本文开始给大家介绍Netty相关的内容,本篇主要介绍的是Netty概念性相关的内容

    用户4919348
  • 动图学 JavaScript 之:事件循环(Event Loop)

    今天该学习 Event Loop 啦,其实之前我写过一篇 Event Loop 的文章:

    savokiss
  • 【前端】:async、defer、onload、DOMContentLoaded

    The HTML <script> element is used to embed or reference executable code; this is...

    WEBJ2EE
  • 关于C#异步编程你应该了解的几点建议

    前段时间写了一篇关于C#异步编程入门的文章,你可以点击《C#异步编程入门看这篇就够了》查看。这篇文章我们来讨论下关于C#异步编程几个不成文的建议,希望对你写出高...

    依乐祝
  • JS:XML 解析

    WEBJ2EE

扫码关注云+社区

领取腾讯云代金券