首页/目录/全部文章

全部文章

八个专题的源码、算法与协议笔记都在这里。

笔记列表

MHI Endpoint 设备侧实现

MHI Endpoint 设备侧实现

1. 角色

MHI_BUS_EP实现MHI链路的设备侧,典型是带PCIe Endpoint的modem SoC。它与Host MHI共用协议概念,但注册独立的mhi_ep bus type和endpoint API。

RK3588作为普通Linux Host时不使用该模块;只有把系统设计成MHI endpoint并提供底层controller glue时才相关。

2. 文件

  • main.c:controller、bus、device/driver、channel和IRQ work;
  • mmio.c:MHI寄存器、中断状态及host context读写;
  • ring.c:读取Host ring元素、offset推进;
  • sm.c:RESET/READY/M0/M3/SYS_ERR转换;
  • internal.h:channel、ring和事件内部对象。

3. 注册

底层endpoint controller driver构造mhi_ep_cntrl并调用:

1
2
3
4
5
mhi_ep_register_controller(config)
-> validate callbacks/config
-> allocate channel/event objects
-> create workqueue
-> register controller mhi_ep_device

Host写入配置后,mhi_ep_power_up()缓存host contexts、初始化ring并进入协议状态机。

4. Bus设备

Endpoint按照配置中的UL/DL channel创建mhi_ep_devicemhi_ep_drivermhi_device_id匹配,并在probe时获得成对channel。

方向以endpoint视角定义,使用时需特别核对DMA_TO_DEVICEDMA_FROM_DEVICE对应Host的UL/DL,避免反向理解。

5. Ring

Host拥有TRE ring内存;Endpoint通过controller callback访问Host地址空间:

1
2
3
4
5
6
7
read host context
-> cache rp/wp
-> fetch TRE
-> transfer payload
-> generate completion event
-> update context
-> ring host interrupt/doorbell

ring.c维护本地read/write offset并处理wrap。Host地址、元素数和长度必须由transport映射到受限PCIe窗口。

6. 数据API

Endpoint功能driver可:

  • mhi_ep_queue_skb()向Host发送;
  • 查询queue是否为空;
  • 接收Host数据callback;
  • 在channel start/stop时建立或清理资源。

当Host未提供TRE时发送返回-ENOSPC,client应做背压而不是忙循环。

7. 中断与Workqueue

MMIO IRQ读取control、command和channel doorbell状态。较重处理排入controller workqueue:

  • state change;
  • command ring;
  • channel ring;
  • reset/error。

中断路径只清状态、记录bitmap和排work,避免在hardirq执行Host内存访问和client callback。

8. 状态机

Endpoint响应Host控制寄存器变化:

1
2
3
4
RESET
-> READY
-> M0
-> M3

协议错误进入SYS_ERR,停止channel并通知Host。Power down必须先flush work、销毁channel devices,再释放ring/context。

9. 与Gadget/PCI Endpoint区别

MHI Endpoint不是USB Gadget,也不是通用PCI endpoint function。它依赖外层transport提供:

  • Host地址空间读写;
  • IRQ触发;
  • MMIO寄存器暴露;
  • DMA能力;
  • link状态。

这些底层能力不由drivers/bus/mhi/ep创建。

10. 安全

Host控制ring地址和TRE内容,endpoint必须视其为不可信输入:

  • 验证地址落在允许window;
  • 验证长度和channel ID;
  • 防止offset/元素数溢出;
  • reset时取消所有异步DMA;
  • 不在释放channel后继续回调client。

11. 限制

源码仍标记部分TD分片处理为TODO。设计endpoint产品前应结合目标controller glue、Host版本和实际大包/异常reset测试,不应只依据基本loopback成功判断完备性。

FSL-MC / DPAA2 对象总线

FSL-MC / DPAA2 对象总线

1. 定位

NXP DPAA2硬件由Management Complex(MC)固件管理。Linux不直接扫描固定MMIO外设,而是通过MC command portal发现DPRC container中的对象并创建fsl-mc设备。

1
2
3
4
5
Linux fsl-mc bus
-> MC portal command
-> Management Complex firmware
-> DPRC object container
-> DPNI/DPBP/DPCON/DPMCP等对象

2. Kconfig

FSL_MC_BUS依赖OF及Layerscape平台,select generic MSI IRQ domain。FSL_MC_UAPI_SUPPORT可额外允许用户空间通过MC portal发命令。

RK3588不满足Layerscape平台依赖,默认不会构建。

3. Bus注册

fsl_mc_bus_driver_init()

  1. 注册fsl-mc bus type;
  2. 初始化resource pools;
  3. 注册root MC platform driver;
  4. 注册platform bus notifier处理相关设备;
  5. 建立MSI domain支持。

Root probe映射MC portal,查询DPRC属性并扫描对象。

4. 对象模型

  • fsl_mc_bus:一个DPRC container;
  • fsl_mc_device:MC object;
  • fsl_mc_driver:按vendor/object type匹配;
  • fsl_mc_io:一个command portal;
  • resource pool:DPMCP、DPBP、DPCON等可分配对象;
  • MSI descriptor:对象中断。

对象ID由MC固件分配,不等同于DT unit address。

5. Command Portal

mc_send_command()通过portal MMIO发送固定command:

1
2
3
4
5
encode header/token/command ID
-> write params
-> write command header
-> poll completion
-> decode status/response

Portal访问必须序列化;命令有超时,固件错误需转换为Linux errno。不能在atomic上下文执行可能长时间轮询的MC命令。

6. DPRC扫描

dprc-driver.c查询container内对象列表:

1
2
3
4
5
get object count
-> get object descriptor
-> compare existing children
-> add new fsl_mc_device
-> remove vanished object

这支持运行时对象创建/销毁。Rescan与driver probe/remove必须避免并发引用已删除对象。

7. 资源分配

fsl-mc-allocator.c维护按type分类的resource pool。Function driver请求DPMCP/DPBP/DPCON时从pool取得对象并在remove时归还。

资源对象本身也是MC device,生命周期和所有权不能只用裸ID管理。

8. MSI

fsl-mc-msi.c为MC objects建立MSI domain,把固件描述的IRQ index映射到Linux virq。配置包括:

  • 分配MSI descriptors;
  • 写对象IRQ地址/data;
  • mask/unmask和affinity;
  • remove时释放domain资源。

9. UAPI

启用FSL_MC_UAPI_SUPPORT后,字符接口允许用户态向portal提交MC command。它扩大了固件控制面:

  • 权限必须严格限制;
  • command buffer需验证;
  • 不应让普通应用任意创建/销毁网络加速对象;
  • 容器隔离不自动等于硬件对象隔离。

10. 错误恢复

MC固件异常可能导致所有对象命令超时。恢复通常不是单一child reset,而是portal/DPRC甚至MC firmware级重建。Driver remove顺序必须先停止DPAA2网络/加速功能,再删除对象和portal。

11. RK3588结论

本模块仅作为目录完整性分析。RK3588没有FSL Management Complex、DPRC DT节点或相关defconfig,不参与该平台启动。

外部并行总线与板级扩展

外部并行总线与板级扩展

1. 共性

WEIM、EBI2、GMI、MBUS、UniPhier System Bus和IXP4xx Expansion Bus连接NOR、SRAM、FPGA、LCD、网卡等板级器件。核心任务是把CPU地址窗口映射到chip select,并配置时序。

1
2
3
4
5
CPU address
-> interconnect window
-> chip select
-> address/data/control pins
-> external device

2. i.MX WEIM

imx-weim.c

  • 从DT child读取fsl,weim-cs-timing
  • 根据SoC寄存器布局写每个CS timing;
  • 处理burst clock;
  • 调用of_platform_populate()创建外设。

时序数组长度必须与SoC data一致,错误值可能造成总线锁死或外部器件损坏。

3. Qualcomm EBI2

qcom-ebi2.c配置CS mode和设备timing,支持NAND、SRAM等。Parent完成寄存器配置后populate child。

EBI2 pinctrl、电压域和外部总线宽度必须与板级原理图一致。

4. Tegra GMI

tegra-gmi.c管理clock、reset、chip select、bus width和timing。Runtime/system PM需要确保外设操作期间GMI clock保持。

5. Marvell MBUS

mvebu-mbus.c管理地址decode windows:

  • target/attribute;
  • base/size;
  • remap;
  • DRAM window;
  • PCIe等master可见范围。

Window必须按硬件粒度对齐且不可重叠。错误窗口可能让DMA访问错误外设或越过内存边界。

6. UniPhier System Bus

uniphier-system-bus.c解析每个bank的地址、宽度和timing,将纳秒转换为时钟周期并写控制器,然后populate child。

若目标timing超过字段范围,driver应报错而不是截断。

7. IXP4xx Expansion Bus

intel-ixp4xx-eb.c通过syscon配置CS,支持flash及板级扩展器件。它必须先于child discovery完成,防止child driver以bootloader遗留时序访问。

8. HiSilicon LPC

hisi_lpc.c不同于memory-mapped并行总线:它为ARM64提供ISA I/O port到LPC transaction的间接PIO映射,处理I/O cycle和错误。

使用者调用inb/outb风格接口,底层并非普通MMIO load/store。

9. MOXTET与TS-NBUS

  • MOXTET通过SPI串行探测Turris MOX模块链,注册自定义module devices并控制GPIO/IRQ;
  • TS-NBUS通过GPIO和PWM产生FPGA NBUS时序。

它们是特定板级产品总线,不是通用SPI/GPIO替代层。

10. Device Tree要点

外部总线parent通常提供:

  • reg和clock/reset;
  • #address-cells/#size-cells
  • ranges
  • chip-select timing;
  • bus width;
  • pinctrl;
  • child device compatible。

DT地址转换错误时,child虽然probe成功,也可能访问错误物理地址。

11. 安全与可靠性

  • 不允许用户态随意修改timing/syscon;
  • 外部FPGA/NOR窗口不应映射到非特权进程;
  • DMA-capable child需IOMMU或受限DMA mask;
  • suspend前停止child I/O;
  • reset后必须恢复timing再恢复children。

12. RK3588

RK3588没有使用这些控制器。其外部存储、PCIe和低速外设由专用drivers目录负责;不能选择一个“类似AXI/并行总线”驱动来替代Rockchip控制器。

SoC 互连、错误监控与 QoS

SoC 互连、错误监控与 QoS

1. 两类互连驱动

本目录互连代码主要做:

  1. cache coherency/port管理;
  2. timeout、target abort、decode error和master定位。

它们通常不提供drivers/interconnect中的带宽投票API。

2. ARM CCI

arm-cci.c支持ARM CCI-400/500/550 coherent interconnect:

  • 解析CPU/ACE/ACE-Lite port;
  • 保存port控制寄存器;
  • CPU PM/低级电源转换时enable/disable snoop和DVM;
  • 提供CCI PMU相关基础。

CCI端口在CPU缓存仍活动时错误关闭会破坏一致性,所以低级操作与CPU suspend顺序严格绑定。

RK3588采用Cortex-A55/A76与DSU体系,DTS未声明CCI compatible,本驱动不匹配。

3. OMAP L3

omap_l3_smx.comap_l3_noc.c处理中断:

1
2
3
4
5
L3 error IRQ
-> read error source/register
-> decode target/master/opcode
-> clear latch
-> report fatal/custom error

错误可能来自访问断电模块、非法地址、timeout或权限。Handler必须先保存寄存器再清状态,否则会丢失诊断。

4. Broadcom GISB

brcmstb_gisb.c管理GISB arbiter timeout/target abort:

  • 读取错误地址和master;
  • 根据SoC master mask打印来源;
  • 清错误;
  • 可在external abort hook中辅助诊断。

它是错误观测器,不会自动修复造成timeout的外设。

5. Baikal-T1 AXI/APB

bt1-axi.cbt1-apb.c读取error handler block,记录总线错误地址/类型,并通过sysfs暴露错误计数和部分timeout参数。

修改timeout过小会制造误报,过大则让CPU长时间等待故障slave。

6. DA8xx Master Priority

da8xx-mstpri.c允许调整多个master优先级。这是静态仲裁配置,不是动态interconnect带宽框架。

优先级提高某master会牺牲其它master延迟,需结合DDR和实时业务整体评估。

7. TI SYSC

ti-sysc.c是OMAP interconnect target module通用driver:

  • 识别SYSC/SYSS/REV寄存器布局;
  • clock/reset/idle/wakeup;
  • legacy hwmod兼容;
  • runtime PM;
  • populate child。

其代码很大是因为需要支持多代TI寄存器quirk,不是通用SoC syscon driver。

8. QCOM SSC、Tegra ACONNECT、Sun50i DE2

这些driver主要打开特定功能域:

  • SSC block bus连接Sensor Core内部外设;
  • ACONNECT连接Tegra Audio Processing Engine;
  • DE2 bus申请SRAM并使显示engine可访问。

它们都是平台电源/访问前置条件,children仍由其它功能driver管理。

9. 错误处理原则

总线错误日志至少应包含:

  • fault address;
  • read/write及opcode;
  • master/initiator;
  • target/slave;
  • security/privilege;
  • timeout或decode;
  • power/clock状态。

只打印“bus error”而不保存首个fault寄存器,后续中断风暴会覆盖根因。

10. RK3588边界

RK3588的NoC QoS、PM domain、DDR/devfreq和system monitor位于Rockchip专用目录及firmware/DT配置,不由上述驱动实现。即使协议同样称AXI/APB,也不能复用Baikal、OMAP或Broadcom寄存器驱动。

资源、时钟、复位、PM 与子节点生命周期

资源、时钟、复位、PM 与子节点生命周期

1. Parent-first原则

Bus controller通常是children访问硬件的前提。Probe必须先完成parent资源,再创建child:

1
2
3
4
5
6
regulator/genpd
-> clocks
-> reset
-> MMIO/timing/windows
-> IRQ/error masks
-> register/populate children

of_platform_populate()不是无条件的第一步。

2. Managed资源

devm_*适合MMIO、clock引用和普通分配,但不能自动表达所有硬件停机顺序。例如:

  • devm释放IRQ前仍可能有DMA;
  • devm关clock前child仍可能访问;
  • bus type上的device引用可能晚于parent remove;
  • workqueue/timer必须显式cancel/flush。

3. Clock

外部总线timing通常由clock频率换算。若clock rate在runtime变化:

  • timing寄存器可能需要重新计算;
  • divider字段必须检查上下限;
  • clock notifier与I/O需串行;
  • resume后先恢复clock再恢复register。

只在probe计算一次不一定适合动态DVFS。

4. Reset

安全顺序通常为:

1
2
3
4
5
assert reset
-> enable clock/power
-> deassert reset
-> wait ready
-> program controller

具体硬件可能要求先clock后reset。必须按binding/TRM,而不是机械套模板。

Remove/suspend前若assert parent reset,需先停止所有children和DMA。

5. Runtime PM

Bus parent runtime suspend条件:

  • child均已suspend;
  • 无pending command/ring;
  • 无wake transaction;
  • IRQ已处理或设为wake;
  • register context已保存。

Child runtime get通过parent-child PM依赖或device link向上传播。若自定义bus没有正确父子关系,parent可能过早断电。

6. Child Populate

OF容器常用:

1
of_platform_populate(np, NULL, lookup, &pdev->dev);

关键参数:

  • root node;
  • match table;
  • auxdata;
  • parent device。

Parent参数决定sysfs层次和PM依赖。传错或设NULL可能破坏runtime PM排序。

7. 动态枚举

MHI/FSL-MC不依赖静态OF child,而由hardware/firmware状态创建device。它们必须处理:

  • late appearance;
  • reset后重新枚举;
  • object/channel消失;
  • driver正在probe时controller错误;
  • userspace持有设备节点。

8. Deferred Probe

Bus driver可能等待:

  • clock/reset/regulator;
  • syscon;
  • genpd;
  • firmware;
  • IOMMU/MSI domain。

返回-EPROBE_DEFER前不得populate不可用的children。否则children反复probe并访问未准备好的parent。

9. Remove

建议逆序:

1
2
3
4
5
6
7
block new child creation
-> unregister/depopulate children
-> flush work/timers
-> disable IRQ
-> stop DMA/rings
-> assert reset
-> disable clocks/power

simple-pm-bus源码remove仅disable runtime PM,是透明OF容器的简化实现,不应推广到有硬件状态的controller。

10. System Sleep

系统suspend与runtime suspend不完全相同:

  • console/wakeup bus可能保持;
  • firmware-managed bus可能需要handshake;
  • MHI需进入M3;
  • 外部总线可能丢失timing context;
  • abort/error monitor可能要保持捕获wake fault。

Resume需在children之前恢复parent寄存器。

11. 常见错误

  • clock enable后probe失败未disable;
  • deassert reset后未等待ready;
  • children先创建、timing后写;
  • remove未depopulate;
  • suspend未停DMA;
  • error IRQ清除顺序错误;
  • runtime PM引用不配对;
  • 动态clock后timing未更新。

并发、锁、中断、DMA 与错误恢复

并发、锁、中断、DMA 与错误恢复

1. 并发来源

Bus driver并发通常来自:

  • child driver的I/O;
  • controller IRQ;
  • runtime/system PM;
  • sysfs/debugfs;
  • hotplug或firmware rescan;
  • reset/recovery work;
  • DMA completion;
  • device remove。

仅用一个mutex不能覆盖hardirq和ring更新,也不应让spinlock包围可睡眠路径。

2. 锁分层

典型规则:

  • mutex:probe/remove、配置、枚举、sysfs;
  • spinlock:IRQ状态、短ring指针、doorbell;
  • rwlock/RCU:读多写少状态或device查找;
  • completion/waitqueue:命令及状态转换;
  • refcount/device reference:异步对象生命周期;
  • workqueue:从IRQ转到可睡眠恢复。

必须规定锁顺序,例如controller state → channel → ring,避免recovery与I/O形成ABBA。

3. 中断

错误IRQ:

  1. 读取并保存全部latch;
  2. mask或ack;
  3. 最小化格式化日志;
  4. 重处理放thread/work;
  5. 根据严重度决定继续、reset或panic。

若先清后读会丢fault;若不mask持续level IRQ会形成风暴。

MHI event IRQ还需确保ring element在读取前已通过DMA barrier可见。

4. DMA

MHI/FSL-MC及bus children可能DMA。关键点:

  • 使用DMA API,不直接假定物理地址;
  • 检查dma mask;
  • coherent ring仍需遵守producer/consumer顺序;
  • streaming buffer必须map/unmap和sync;
  • reset前停止device DMA;
  • IOMMU domain必须先于设备启动;
  • controller释放前等待completion不再访问ring。

5. Ring一致性

Producer顺序:

1
2
3
4
write descriptor/payload metadata
-> dma_wmb
-> update write pointer
-> doorbell

Consumer:

1
2
3
4
5
observe producer pointer/event
-> dma_rmb
-> read descriptor
-> process
-> update read pointer

普通spin_lock不自动替代所有设备DMA barrier。

6. 错误分级

级别 处理
可重试命令失败 返回errno,不重置全总线
单channel错误 stop/reset channel
timeout/target abort 保存现场,隔离故障child
controller SYS_ERR 阻止I/O,重建controller
DMA越界/不可恢复一致性错误 禁用设备,必要时系统级恢复

错误恢复不能在旧I/O仍可能completion时直接重新分配同一ring。

7. Recovery状态机

1
2
3
4
5
6
RUNNING
-> QUIESCING
-> RESETTING
-> REINITIALIZING
-> REENUMERATING
-> RUNNING

所有提交API先检查状态。只有一个worker负责主恢复;重复错误合并,避免并发reset。

8. Hot Remove

MHI PCI设备拔出或FSL-MC object消失时:

  • 从匹配表阻止新probe;
  • 标记device offline;
  • 取消client callbacks;
  • 完成pending I/O为-ENODEV
  • device_unregister()
  • 等release后释放parent对象。

功能driver不能缓存未持引用的channel/object指针。

9. Sysfs/Debugfs

写timeout、priority或状态触发器必须和I/O串行。Debugfs默认不是稳定ABI,不能让生产守护进程依赖其格式。

显示register时要避免:

  • 读取会clear的状态;
  • 访问已断电域;
  • 暴露物理地址或敏感DMA内容;
  • 在锁内生成超长输出。

10. Fault Injection

建议测试:

  • clock/reset失败;
  • IRQ丢失/风暴;
  • ring满和wrap;
  • DMA map失败;
  • firmware超时;
  • suspend与I/O竞争;
  • remove与completion竞争;
  • malformed descriptor;
  • recovery中再次SYS_ERR。

成功probe和正常传输不足以证明生命周期正确。

RK3588 适用性、DTS 与配置核对

RK3588 适用性、DTS 与配置核对

1. 直接结论

drivers/bus没有Rockchip专用源文件。本树rk3588*.dts*未发现以下compatible:

  • simple-pm-bus
  • ARM CCI;
  • FSL-MC;
  • MHI platform controller;
  • OMAP/TI SYSC;
  • Tegra/Sunxi/QCOM/Broadcom等本目录bus controller。

Rockchip defconfig也未显式启用MHI、FSL-MC或本目录其它平台bus选项。

2. 为什么仍会编译部分代码

Makefile规定:

1
2
obj-$(CONFIG_OF) += simple-pm-bus.o
obj-y += mhi/

第一行表示启用OF时编译simple-pm-bus对象,不代表RK3588存在匹配设备。第二行只是进入MHI子目录,其内部对象仍由CONFIG_MHI_BUS/MHI_BUS_EP决定。

“进入链接/模块目录”“driver注册”“匹配设备”是三个不同阶段。

3. 普通Simple Bus

RK3588 DTS包含大量SoC地址层次和simple-bus语义。它们主要由OF Core创建platform devices。

simple-pm-bus.csimple-bus使用ONLY_BUS保护逻辑,不会把所有普通SoC节点都接管成power-managed bus。

因此不能通过:

1
lsmod | grep simple

判断RK3588子设备枚举是否正常。

4. RK3588内部互连

RK3588使用AXI/AHB/APB/NoC,但协议名称不等于驱动兼容。相关实现分散在:

  • drivers/soc/rockchip:PM domain、QoS、system monitor等;
  • drivers/clk/rockchip:总线clock;
  • drivers/devfreq及DDR驱动:频率/带宽;
  • drivers/interconnect:若厂商树提供带宽provider;
  • firmware/PMU:部分电源与安全配置;
  • 各功能driver自身。

本目录Baikal AXI/APB、OMAP L3或Broadcom GISB的寄存器完全不同,不能用于RK3588。

本树RK3588 DTS约有50个qos@... syscon节点,power-domain通过pm_qos phandle引用;drivers/soc/rockchip/pm_domains.c解析这些regmap并在域切换时管理QoS。它们不是独立的drivers/bus设备。

另外:

  • drivers/devfreq/rockchip_bus.c虽然包含rockchip,rk3588-bus匹配且defconfig启用,但当前rk3588*.dts*没有对应节点;
  • drivers/devfreq/event/rockchip-nocp.c及配置存在,但match表没有RK3588且RK3588 DTS无NOCP节点。

故不能只凭Kconfig已启用就宣称RK3588正在运行bus devfreq或NoC monitor。

5. Cache Coherency

RK3588 CPU cluster使用DSU,不通过DTS中的CCI-400/500/550节点。本目录arm-cci.c不参与CPU coherency初始化。

PCIe/设备DMA一致性由arm64 DMA coherency属性、SMMU/IOMMU和设备driver共同决定。

RK3588的PL330 DMA以arm,primecell设备存在,由drivers/amba/bus.c和OF Core创建AMBA device,再绑定drivers/dma/pl330.c;AMBA总线本体不在drivers/bus

6. MHI扩展可能

如果RK3588产品通过PCIe连接受支持的5G modem,MHI Host可能成为实际路径:

1
2
3
4
5
RK3588 PCIe RC
-> PCI modem
-> mhi_pci_generic
-> mhi bus
-> WWAN/QMI/MBIM功能driver

需要额外启用:

1
2
CONFIG_MHI_BUS=m
CONFIG_MHI_BUS_PCI_GENERIC=m

并确认PCI ID、MSI、DMA、firmware、供电、reset和WWAN client驱动。仅打开MHI Kconfig不会自动让任意PCIe modem工作。

7. Endpoint MHI

MHI_BUS_EP针对modem/endpoint设备侧。RK3588作为PCIe Root Complex时不需要;若使用RK3588 PCIe endpoint mode,还需专门MHI endpoint controller glue,本目录没有Rockchip实现。

8. DTS验证

1
2
grep -R "simple-pm-bus\|arm,cci\|fsl,mc\|mhi" \
arch/arm64/boot/dts/rockchip/rk3588*

最终仍应反编译运行DTB验证,因为板级overlay和构建选择可能改变源DTS结果。

9. 运行时验证

1
2
3
4
5
cat /proc/config.gz | grep -E 'MHI|FSL_MC|ARM_CCI|TI_SYSC'
ls /sys/bus | grep -E 'mhi|fsl'
find /sys/bus/platform/drivers -maxdepth 1 -name '*bus*'
lspci -nn
dmesg | grep -Ei 'mhi|bus error|interconnect|noc'

不要仅凭驱动目录存在或模块文件存在断言硬件启用。

10. RK3588调优边界

若目标是RK3588总线性能,应优先分析:

  • DDR devfreq和DMC;
  • Rockchip QoS节点/驱动;
  • NOC monitor;
  • CPU/DSU/CCI之外的互连clock;
  • PCIe Max Link Speed/Width;
  • IOMMU/TLB;
  • IRQ affinity;
  • 功能模块devfreq。

这些并非本目录大多数源文件的职责。

调试、故障排查与安全边界

调试、故障排查与安全边界

1. 先识别驱动类型

排障前先确定:

  • platform容器;
  • 自定义bus type;
  • 外部地址窗口;
  • 错误监控器;
  • MHI/FSL-MC动态对象;
  • 目标平台是否实际匹配。

错误分类不清容易把child probe失败误判为物理bus fault。

2. 基础信息

1
2
3
4
5
cat /proc/config.gz
ls /sys/bus
ls /sys/bus/platform/drivers
cat /sys/kernel/debug/devices_deferred
dmesg -w

检查device:

1
2
3
readlink /sys/bus/platform/devices/<dev>/driver
cat /sys/bus/platform/devices/<dev>/modalias
cat /sys/bus/platform/devices/<dev>/power/runtime_status

3. DT

1
dtc -I fs -O dts /sys/firmware/devicetree/base

重点核对:

  • compatible顺序;
  • status
  • reg/ranges;
  • clocks/resets/power-domains;
  • child unit address;
  • interrupt;
  • IOMMU/MSI;
  • timing和bus-width。

运行DTB比源码DTS更有证据力。

4. Child未出现

按顺序检查:

  1. parent platform device是否创建;
  2. parent driver是否probe;
  3. 是否返回defer/error;
  4. parent是否调用populate;
  5. child compatible是否正确;
  6. address translation是否成功;
  7. child依赖是否就绪。

5. 总线错误

遇到timeout/abort:

  • 保存首条完整日志;
  • 查fault address对应DT reg/ranges;
  • 查initiator/master;
  • 确认target power/clock/reset;
  • 检查访问宽度和alignment;
  • 检查secure/non-secure权限;
  • 避免反复读故障地址制造中断风暴。

不要直接增大timeout掩盖断电或错误地址。

6. MHI

1
2
3
4
lspci -nnk
ls /sys/bus/mhi/devices
ls /sys/kernel/debug/mhi 2>/dev/null
dmesg | grep -i mhi

排障层次:

  1. PCIe枚举和BAR/MSI;
  2. controller注册;
  3. firmware/BHI;
  4. execution environment;
  5. M0/mission mode;
  6. channel devices;
  7. client driver;
  8. SYS_ERR/RDDM。

直接重载client driver不能修复controller未进入mission mode。

7. PM

1
2
cat /sys/bus/platform/devices/<parent>/power/runtime_status
cat /sys/bus/platform/devices/<parent>/power/runtime_usage

若关闭autosuspend后故障消失,继续定位缺失PM引用、clock恢复、register context或parent-child依赖,不应永久用power/control=on掩盖。

8. Dynamic Debug和Trace

1
2
echo 'file drivers/bus/* +p' > /sys/kernel/debug/dynamic_debug/control
echo 'file drivers/bus/mhi/* +p' > /sys/kernel/debug/dynamic_debug/control

只在受控环境开启,MHI debugfs可能允许修改controller状态或暴露ring信息。

9. 安全边界

高风险面:

  • 外部bus window映射;
  • 用户态MC portal;
  • MHI firmware和DMA;
  • debugfs register写;
  • sysfs timing/priority;
  • 错误handler泄露物理地址;
  • 恶意PCIe endpoint;
  • 固件动态报告大量对象/channel。

加固:

  • 关闭未用bus选项;
  • 限制debugfs;
  • 固件签名与版本控制;
  • IOMMU隔离DMA;
  • 最小化MC UAPI权限;
  • 验证所有长度、ID和ring指针;
  • error storm限速;
  • 禁止用户态直接/dev/mem改总线寄存器。

10. 性能

性能问题先区分:

  • 互连/DDR带宽;
  • 外部总线timing;
  • MHI ring/IRQ;
  • PCIe链路;
  • CPU调度;
  • runtime PM唤醒。

本目录不存在统一“bus frequency”参数,也没有可对所有驱动通用的调优sysfs。

11. 修改验证

修改bus driver至少测试:

  • cold boot/warm reboot;
  • probe defer;
  • child bind/unbind;
  • runtime/system suspend;
  • I/O压力;
  • error IRQ;
  • controller reset;
  • hot remove;
  • DMA/IOMMU fault;
  • module unload(若允许)。

基础总线错误可能影响存储、console或电源管理,必须保留可恢复启动路径。

RSB、MOXTET 与 MIPS CDMM 专用总线

RSB、MOXTET 与 MIPS CDMM 专用总线

1. 共性与差异

三者都注册自定义bus_type,但传输和枚举来源完全不同:

Bus 底层 枚举
Sunxi RSB 专用串行控制器 DT child
MOXTET SPI连接的模块链 读取模块拓扑
MIPS CDMM CPU内部memory map 每CPU扫描

它们的client driver不能改注册为platform driver,因为match、modalias和I/O API均属于专用bus。

2. Sunxi RSB初始化

1
2
3
4
5
6
7
8
9
10
sunxi_rsb_init
-> bus_register(sunxi_rsb_bus)
-> platform_driver_register
sunxi_rsb_probe
-> map MMIO/request IRQ
-> clocks/reset
-> controller soft reset/divider
-> runtime PM autosuspend
-> parse DT children
-> sunxi_rsb_device_create

RSB常连接Allwinner PMIC和音频器件。Client通过RSB regmap访问,不直接操作controller寄存器。

3. RSB传输

一次传输由mutex串行:

1
2
3
4
program runtime address/register/data
-> start transfer
-> wait completion
-> IRQ读取status并complete

超时会发ABORT并返回错误;NACK、data error、busy需要区分。Runtime PM负责clock,system sleep执行更完整的hardware exit/init。

Controller设置pm_suspend_ignore_children(true),意味着children不会自动阻止父设备系统挂起,client必须遵守总线suspend约束。

4. MOXTET

MOXTET用于Turris MOX可堆叠模块:

1
2
3
4
5
6
7
moxtet_init
-> bus_register(moxtet)
-> spi_register_driver
moxtet_probe
-> SPI读取模块链
-> 按slot/type创建设备
-> 专用driver匹配

模块顺序决定拓扑。Driver导出device read/write、IRQ/GPIO相关接口。热插并非普通PCI/USB级动态发现,需按硬件支持评估。

moxtet_device的parent是SPI host对应对象,但function driver绑定在moxtet bus。

5. MIPS CDMM

CDMM是MIPS CPU内紧耦合device memory map,设备可能是Fast Debug Channel等。

1
2
3
4
5
subsys_initcall
-> bus_register(mips_cdmm)
-> register CPU hotplug callbacks
-> each CPU scan ACSR/CDMM region
-> register mips_cdmm_device

它是per-CPU总线。CPU online/offline会影响设备可达性,driver不能假设固定boot CPU永久在线。

6. Match与Modalias

  • RSB按sunxi_rsb_device_id/compatible;
  • MOXTET按module type;
  • CDMM按device type/revision。

各自uevent生成专用modalias供模块自动加载。

7. 生命周期

自定义bus退出顺序必须:

  1. 停止controller和新枚举;
  2. unregister所有child;
  3. unregister host driver;
  4. bus_unregister()

若先注销bus type,仍注册的device/driver会留下无效引用。

8. 错误处理

  • RSB事务错误可按单次传输返回errno;
  • MOXTET拓扑读取失败通常使整条模块链不可用;
  • CDMM扫描或CPU offline属于设备生命周期变化。

三者都不适合套用MHI的重型ring recovery,也不能用simple-pm-bus代替。

9. RK3588

RK3588不具备Sunxi RSB、MOXTET模块链或MIPS CDMM,Kconfig和DTS均不匹配。这些实现用于理解Linux自定义bus type,而非RK3588运行路径。

TI SYSC 模块电源与 Idle 管理

TI SYSC 模块电源与 Idle 管理

1. 定位

ti-sysc.c约3500行,是TI OMAP/AM/DRA interconnect target module驱动。它统一管理目标模块的:

  • revision/SYSC/SYSS寄存器;
  • functional/interface/optional clocks;
  • reset;
  • smart/force/no-idle;
  • wakeup;
  • runtime PM;
  • child platform devices;
  • 大量代际quirk。

它不是通用syscon驱动,也不适用于Rockchip。

2. 初始化

1
2
3
module_init(sysc_init)
-> platform bus notifier
-> register sysc platform driver

Notifier用于给legacy children补clock和PM关系。

3. Probe流程

1
2
3
4
5
6
7
8
9
10
11
parse ranges/module address
-> select SoC/module data
-> map/check REV/SYSC/SYSS
-> parse idle modes and quirks
-> acquire fck/ick/optional clocks
-> acquire shared reset
-> enable clocks/deassert reset
-> read revision
-> soft reset/init sysconfig
-> enable runtime PM
-> of_platform_populate(simple-bus children)

对于early console、timer或legacy hwmod,部分模块需要延迟idle或跳过普通populate。

4. 数据描述

struct sysc保存:

  • register offsets和width;
  • physical module range;
  • clock/reset;
  • sysc mask和regbits;
  • capabilities;
  • quirk flags;
  • saved context;
  • child/legacy信息;
  • delayed work和list节点。

ti_sysc_module_data等platform data允许架构侧补充legacy callback。

5. Idle模式

SYSC寄存器可控制SIDLE/MSTANDBY:

  • force idle;
  • no idle;
  • smart idle;
  • smart idle wakeup。

选择取决于DT声明、硬件能力和quirk。错误配置会导致:

  • 模块永不休眠;
  • 事务进行中被idle;
  • wake事件丢失;
  • interconnect timeout。

6. Runtime PM

Resume大致:

1
2
3
4
5
enable clocks
-> deassert reset
-> restore/reinit sysconfig
-> enable module
-> allow interconnect access

Suspend逆序关闭module和clock,并可能assert reset。Clock domain deny/allow与runtime PM配合,防止寄存器访问时域被关。

7. Soft Reset

Driver写SOFTRESET并轮询RESETDONE/SYSS。部分硬件reset bit自清、部分需特殊顺序;timeout可能只warn,因为老平台存在不可靠状态位。

不能把一次soft reset成功视为child DMA已停止,child driver仍需先quiesce。

8. Context Lost

支持REINIT_ON_CTX_LOST的模块在cluster PM或域掉电后:

  • 比较关键sysconfig与saved value;
  • 识别context丢失;
  • 重新执行module初始化;
  • 必要时soft reset;
  • 恢复idle/wakeup。

CPU cluster PM notifier在exit时处理登记模块。

9. Child PM

Platform bus notifier处理child add:

  • 查找parent sysc;
  • 给child提供legacy clocks;
  • 可挂专用child PM domain;
  • 让child runtime suspend/resume联动parent。

该机制用于兼容旧hwmod设备树,不应复制到新平台替代标准genpd/device link。

10. Remove

1
2
3
4
5
6
cancel delayed idle work
-> runtime resume/get
-> of_platform_depopulate
-> runtime put/disable
-> assert reset
-> unprepare clocks

相比simple-pm-bus,TI SYSC拥有真实寄存器和资源,必须显式depopulate及逆序回滚。

11. 并发

并发来源包括:

  • runtime PM;
  • delayed idle work;
  • platform notifier;
  • CPU PM notifier;
  • child I/O;
  • remove。

Disabled/restored module全局list由锁保护。复杂操作尽量由PM和work上下文串行,而不是在hardirq执行。

12. RK3588边界

Kconfig要求ARCH_OMAP2PLUS,compatible及寄存器布局均为TI。RK3588相似功能由Rockchip genpd、clock/reset、syscon和功能driver分担,不能使用ti-sysc替换。