当前位置:   article > 正文

RK3399 探索之旅 / 设备树速读 / Soc 基础设施

rockchip-efuse0

哈喽,老吴又来分享学习心得啦。目前,我已经从 hardware enable 工程师升级为 dts 工程师了。

1. 简介

思考一下,bringup 一款 Soc 的最小操作包括哪些?

  • 添加 Soc 层次的 Device Tree (arch/arm64/boot/dts/);

  • 添加 Timer driver (drviers/clksource/);

  • 添加 Interrupt controller driver (drivers/irqchip);

  • 添加 Serial port driver (drivers/tty/serial);

完成上面 4 个步骤后,就有机会启动系统进入命令行终端了。

接下来需要完善什么?

  • 添加 Pin muxing control driver (drivers/pintrl);

  • 添加 Clocks driver (drivers/clk/);

  • 添加 GPIO driver (drivers/gpio/);

  • 添加 SMP 的支持;

  • 添加 Network driver;

  • 添加各种 controller driver;

  • 添加各种 device driver;

本文会顺着上述思路,快速地浏览一下 NanoPC-T4 这块单板的设备树里 Soc 基础设施。

2. 查看 Soc 框图

点击查看大图

rk3399 大致包括 7 个部分:

  • ARM Processor

  • System Peripheral

  • Multi-Media Processor

  • Connectivity

  • Multi-Media Interface

  • External Memory Interface

  • Embedded Memory

阅读设备树时,Soc 框图可以协助我们确定好每个节点的定位和功能。

3. 确定 dts 文件关系

dts 文件关系图:

点击查看大图

rk3399-nanopi4-rev00.dts 和 rk3399-nanopi4-common.dtsi 用于描述板级信息;

rk3399.dtsi 等剩下的文件用于描述 Soc 信息;

4. 汇总完整的 dts 节点

完整的 dts 节点图:

点击查看大图

5. 查看 Soc 基础设施

5.1 cpus 节点

  1. cpus {
  2. #address-cells = <2>;
  3. #size-cells = <0>;
  4. cpu-map {
  5. cluster0 {
  6. core0 {
  7. cpu = <&cpu_l0>;
  8. };
  9. ...
  10. core3 {
  11. cpu = <&cpu_l3>;
  12. };
  13. };
  14. cluster1 {
  15. core0 {
  16. cpu = <&cpu_b0>;
  17. };
  18. core1 {
  19. cpu = <&cpu_b1>;
  20. };
  21. };
  22. };
  23. cpu_l0: cpu@0 {
  24. device_type = "cpu";
  25. compatible = "arm,cortex-a53", "arm,armv8";
  26. ...
  27. };
  28. ...
  29. cpu_b0: cpu@100 {
  30. device_type = "cpu";
  31. compatible = "arm,cortex-a72", "arm,armv8";
  32. };
  33. ...
  34. }

简单说明:

  • rk3399 有 4 个 a53 小核和 2 个 a72 大核。在 ARM 架构中,cpus 节点用于描述 cpu 核心的布局,cpus 节点下的每一个 cpu 节点代表一个 cpu 核心,上述设备树描述了。

  • cpu-map 节点用于描述 ARM cpu 的拓扑结构,SMP 处理器才需要这个节点。

  • cpu-map 可包含 3 种类型的实体:cluster(集群) / core / thread,cluster 里可以包含 1 个或多个 cluster/core。

相关代码:

  • 暂不关心,待定;

相关文档:

  • Documentation/devicetree/bindings/arm/cpus.txt

  • Documentation/devicetree/bindings/arm/topology.txt

相关接口:

  • /sys/devices/system/cpu,所有 cpu 相关的信息和支持的操作都在这个目录下。

5.2 clock controller 节点

  1. /arch/arm64/boot/dts/rockchip/rk3399.dtsi
  2. cru: clock-controller@ff760000 {
  3. compatible = "rockchip,rk3399-cru";
  4. reg = <0x0 0xff760000 0x0 0x1000>;
  5. #clock-cells = <1>;
  6. #reset-cells = <1>;
  7. assigned-clocks = ...;
  8. assigned-clock-rates = ...;
  9. };
  1. /arch/arm64/boot/dts/rockchip/rk3399.dtsi
  2. pmucru: pmu-clock-controller@ff750000 {
  3. compatible = "rockchip,rk3399-pmucru";
  4. reg = <0x0 0xff750000 0x0 0x1000>;
  5. #clock-cells = <1>;
  6. #reset-cells = <1>;
  7. assigned-clocks = ...;
  8. assigned-clock-rates = ...;
  9. };

简单说明:

  • rk3399 的 clock controller 包括 cru 和 pmucru 2部分,cru 是 clock & reset unit 的缩写,pmu 是 power management unit 的缩写。

  • clock controller 负责生成时钟并将其提供给 SoC 中的各种控制器,并且还为 SoC 外设实现了reset controller。

  • cru 和 pmucru 都是 clock provider, #clock-cells 表明clock consumer 需要用多少个单元才能引用 cru/pmucru 提供的 clock。

  • 通过 assigned-clocks 和 assigned-clock-rates 指定了一些 clock 的初始频率,包括 PLL、总线、VOP、GPU等。

相关文档:

  • Documentation/devicetree/bindings/clock/arm-integrator.txt

  • Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.txt

相关代码:

  • drivers/clk/rockchip/clk-rk3399.c

相关接口:

  • /sys/kernel/debug/clk/clk_summary,用于查看时钟树

5.3 interrupt controller 节点

  1. gic: interrupt-controller@fee00000 {
  2. compatible = "arm,gic-v3";
  3. ...
  4. its: interrupt-controller@fee20000 {
  5. compatible = "arm,gic-v3-its";
  6. #interrupt-cells = <4>;
  7. ...
  8. interrupt-controller;
  9. ...
  10. };
  11. ppi-partitions {
  12. ppi_cluster0: interrupt-partition-0 {
  13. affinity = <&cpu_l0 &cpu_l1 &cpu_l2 &cpu_l3>;
  14. };
  15. ppi_cluster1: interrupt-partition-1 {
  16. affinity = <&cpu_b0 &cpu_b1>;
  17. };
  18. };
  19. };

简单说明:

  • rk3399 使用中断控制器是 gic-v3。

  • gic-v3 是 ARM Generic Interrupt Controller, version 3 的缩写,是一款 ARM 出品的通用中断控制器。

  • AArch64 SMP 内核通常与 GICv3 搭配使用,GICv3 提供了专用外设中断(PPI),共享外设中断(SPI),软件生成的中断(SGI)和特定于区域的外设中断(LPI)。

  • interrupt-controller 属性用于标志一个中断控制器节点,#interrupt-cells = <4> 表明 Interrupt client devices 需要用 4 个单元才能确定引用的中断,例如 interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW 0>。

相关代码:

  • drivers/irqchip/irq-gic-v3.c

相关文档:

  • Documentation/devicetree/bindings/interrupt-controller/interrupts.txt

  • Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt

  • Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt

相关接口:

  • /sys/kernel/irq

5.4 pin controller 节点

  1. pinctrl: pinctrl {
  2. compatible = "rockchip,rk3399-pinctrl";
  3. ...
  4. // 4 x gpio controller
  5. gpio0: gpio0@ff720000 {
  6. compatible = "rockchip,gpio-bank";
  7. ...
  8. };
  9. ...
  10. // lots of pin configuration nodes
  11. ...
  12. i2c0 {
  13. i2c0_xfer: i2c0-xfer {
  14. rockchip,pins =
  15. <1 15 RK_FUNC_2 &pcfg_pull_none>,
  16. <1 16 RK_FUNC_2 &pcfg_pull_none>;
  17. };
  18. };
  19. ...
  20. }

简单说明:

  • rk3399 的 pin controller 包括 2 个部分:4 个 gpio controller 节点 + 一堆的引脚配置子节点。

  • pin controller 负责提供配置引脚复用,驱动强度,上下拉的功能。

  • Soc 里的其他 controllers 或者 device drivers 通过引用 pin controller 里的引脚配置子节点来配置引脚,它们被称为 pinctrl client devices。

  • 引脚配置子节点有 2 种类型:pin multiplexing(引脚复用) 和 pin configuration(引脚驱动强度、上下拉)。

  • rk3399 的 4.4 内核里 pinctrl 的 pin multiplexing 节点格式是 rockhip原厂 自己定义的: rockchip,pins,在更高版本的内核里应该会被修改为更通用的方式:pins。

相关代码:

  • drivers/pinctrl/pinctrl-rockchip.c

相关文档:

  • Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt

  • Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt

相关接口:

  1. $ tree /sys/kernel/debug/pinctrl
  2. /sys/kernel/debug/pinctrl
  3. ├── pinctrl-devices
  4. ├── pinctrl-handles
  5. ├── pinctrl-maps
  6. └── pinctrl-rockchip-pinctrl
  7.     ├── gpio-ranges
  8.     ├── pinconf-config
  9.     ├── pinconf-groups
  10.     ├── pinconf-pins
  11.     ├── pingroups
  12.     ├── pinmux-functions
  13.     ├── pinmux-pins
  14.     └── pins

5.5 gpio controller 节点

  1. gpio0: gpio0@ff720000 {
  2. compatible = "rockchip,gpio-bank";
  3. reg = <0x0 0xff720000 0x0 0x100>;
  4. clocks = <&pmucru PCLK_GPIO0_PMU>;
  5. interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH 0>;
  6. gpio-controller;
  7. #gpio-cells = <0x2>;
  8. interrupt-controller;
  9. #interrupt-cells = <0x2>;
  10. };
  11. ...
  12. gpio4: gpio4@ff790000 {
  13. compatible = "rockchip,gpio-bank";
  14. ...
  15. };

简单说明:

  • rk3399 共有 5 个 gpio controller,122 个 gpio,所有的 gpio 都可以产生中断,上电后默认都是 input 状态。

  • gpio-controller 属性表明这个一是 gpio 控制器节点,#gpio-cells = <2> 表明 gpio client devices 需要用 2 个单元才能确定引用的引脚。

  • interrupt-controller 属性表明 rk3399 的 gpio controller 也有中断控制器的功能,#interrupt-cells = <0x2> 表明需要 2 个单元来确定引用的中断,例如:interrupt-parent = <&gpio1>; interrupts = <20 IRQ_TYPE_EDGE_FALLING>。

  • 在rk3399 设备树里引用 gpio 的方式是:gpio = <&gpio0 1 GPIO_ACTIVE_HIGH>,如果需要引用多个 gpio,则使用 gpios 属性。

相关代码:

  • drivers/pinctrl/pinctrl-rockchip.c,和 pin controller 的驱动是同一个,说明 pinctrl 和 gpio 关联是很紧密的。

相关文档:

  • Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt

  • Documentation//devicetree/bindings/gpio/gpio.txt

相关接口:

  • /sys/class/gpio,传统的接口。

  • /dev/gpiochip0,比较推荐的接口。

  • libgpiod,推荐使用该库。

5.6 efuse 节点

  1. efuse0: efuse@ff690000 {
  2. compatible = "rockchip,rk3399-efuse";
  3. ...
  4. /* Data cells */
  5. specification_serial_number: specification-serial-number@6 {
  6. reg = <0x06 0x1>;
  7. bits = <0 5>;
  8. };
  9. cpu_id: cpu-id@7 {
  10. reg = <0x07 0x10>;
  11. };
  12. ...
  13. };

简单说明:

  • efuse 是一次性可编程存储器。

  • Data cells 子节点提供了rk3399 efuse 内部的数据布局;

相关代码:

  • driver/nvmem/rockchip-efuse.c

相关文档:

  • Documentation/devicetree/bindings/nvmem/nvmem.txt

相关接口:

  • sys/devices/platform/ff690000.efuse/rockchip-efuse0/nvmem

5.7 cpuinfo 节点

  1. cpuinfo {
  2. compatible = "rockchip,cpuinfo";
  3. nvmem-cells = <&cpu_id>;
  4. nvmem-cell-names = "id";
  5. };

简单说明:

  • rockchip 自家的东西,用于提供 cpu id;

  • NVMEM 是 Non Volatile Memory 的缩写,用于驱动芯片内的 efuse / eeprom。在 efuse 中一般会保存着例如 cpu id 之类的芯片相关的硬件信息,参考前面的 efuse. 节点;

  • cpuinfo 是 NVMEM 的 data consumer;

  • nvmem-cells 引用的是 cpu_id 数据,启动时会打印 cpu id,对应的 log 是: rockchip-cpuinfo cpuinfo: xxx;

相关代码:

  • driver/soc/rockchip/rockchip-cpuinfo.c

相关文档:

  • Documentation/devicetree/bindings/soc/rockchip/rockchip-cpuinfo.txt

6. 相关参考

  • Rockchip_RK3399TRM_V1.4_Part1-20170408.pdf

  • Rockchip RK3399 Datasheet V2.1-20200323.pdf

  • GICv3_v4_overview.pdf

思考技术,也思考人生

要学习技术,更要学习如何生活

你和我各有一个苹果,如果我们交换苹果的话,我们还是只有一个苹果。但当你和我各有一个想法,我们交换想法的话,我们就都有两个想法了。

嵌入式系统 (Linux、RTOS、OpenWrt、Android) 和 开源软件 感兴趣,关注公众号:嵌入式Hacker

觉得文章对你有价值,不妨点个 在看和赞

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/717752
推荐阅读
相关标签
  

闽ICP备14008679号