首页/目录/全部文章

全部文章

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

笔记列表

RFKill、休眠唤醒与 Wi-Fi 共存

RFKill、休眠唤醒与 Wi-Fi 共存

1. 标准RFKill

Bluetooth HCI设备注册rfkill,software block控制radio policy。rfkill list/block/unblock bluetooth不保证物理断电,具体取决于driver。

2. Rockchip平台实现

本厂商树另有:

  • net/rfkill/rfkill-bt.c
  • net/rfkill/rfkill-wlan.c
  • CONFIG_RFKILL_RK=y

它解析 compatible = "bluetooth-platdata"的旧式属性并控制power/reset/wake/RTS/clock。

3. Power sequence

rfkill_rk_set_power()协调:

-combo shared rail;
-BT reset/power GPIO;
-device wake;
-host wake IRQ;
-RTS pin state;
-external clock;
-与Wi-Fi当前power state。

因此HCI UART transport本身可能不知道真正电源状态。

4. Wake signals

  • BT,wake_gpio:host通知controller保持唤醒;
  • BT,wake_host_irq:controller唤醒host;
  • polarity由GPIO flags定义;
    -IRQ需配置wake;
    -suspend前切换sleep状态。

5. RTS GPIO

板型提供 uart_rts_gpios以及 default/rts_gpio pinctrl states。Suspend时把RTS从UART复用切到GPIO可防止模块误唤醒或实现厂商低功耗握手。

6. Shared power

Wi-Fi/BT combo可能共享VBAT/VIO/32k clock。单独重启BT时不可无条件关闭shared rail;rfkill-wlan.crfkill-bt.c通过全局状态协调。

7. 并发与限制

平台实现使用全局 g_rfkill,天然偏单实例;GPIO属性名称为厂商旧binding。它不同于标准UART Bluetooth child/serdev模型,迁移时不能同时让两套driver控制同一GPIO。

8. Suspend问题

常见失败:

-host wake polarity错;
-IRQ未标wake;
-wake GPIO过早拉低;
-RTS pinctrl错误;
-32k clock停;
-UART RX clock gated;
-Wi-Fi driver关闭shared rail;
-延迟work与suspend竞态。

9. 调试

1
2
3
4
rfkill list
cat /proc/interrupts | grep -i -E 'bt|gpio'
cat /sys/kernel/debug/gpio
cat /sys/kernel/debug/pinctrl/*/pinmux-pins

RK3588 蓝牙硬件与 Device Tree 集成

RK3588 蓝牙硬件与 Device Tree 集成

1. SoC事实

RK3588提供UART、USB、SDIO/PCIe和GPIO,但无内建Bluetooth radio。实际能力由板载/外接controller决定。

2. 本树板型

二十余个 rk3588*板级DTS包含 bluetooth-platdata节点。常见示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
wireless_bluetooth: wireless-bluetooth {
compatible = "bluetooth-platdata";
clocks = <&hym8563>;
clock-names = "ext_clock";
uart_rts_gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>;
pinctrl-names = "default", "rts_gpio";
pinctrl-0 = <&uart7m1_rtsn &bt_reset_gpio
&bt_wake_gpio &bt_irq_gpio>;
pinctrl-1 = <&uart7_gpios>;
BT,reset_gpio = <&gpio0 RK_PD4 GPIO_ACTIVE_HIGH>;
BT,wake_gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>;
BT,wake_host_irq = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>;
status = "okay";
};

这是tablet板示例,不是所有RK3588 PCB的固定引脚。

本树RK3588板型未使用标准brcm,*-bt、Realtek或Marvell UART child binding,也未发现板载USB/SDIO Bluetooth DT实例。平台节点只负责电源/唤醒,UART HCI通常还依赖用户态hciattach/厂商patchram流程;defconfig未显式启用BCM/RTL/QCA UART serdev协议。

3. UART

该示例使用UART7 M1 RTS pin。还必须在对应UART node启用TX/RX/CTS/RTS、设置正确pin group和状态。独立平台节点不会自动证明UART consumer已attach。

4. External clock

示例从HYM8563 RTC clock输出提供ext_clock。频率、常开/门控和上电顺序必须符合combo module要求,通常为32.768kHz。

5. GPIO

  • reset决定controller复位;
  • wake/device-wake决定低功耗;
  • host-wake是GPIO IRQ;
  • RTS在suspend切换。

Polarity取决于模块和电平转换,不能复制其它板型。

6. 模块类型

某些板型Wi-Fi节点标 ap6275p,提示AP6275P combo方案;其它EVB/vehicle/toybrick可能不同。应检查当前最终DTS、原理图、firmware和UART attach脚本。

7. USB dongle

外接USB Bluetooth不需要上述平台节点,由btusb枚举,但仍依赖USB host/PHY/VBUS和固件。

8. SDIO

SDIO Bluetooth driver虽已配置Marvell支持,不能据此判断板载BT走SDIO。Combo module常见结构是Wi-Fi走SDIO/PCIe、BT走UART。

9. 验证

1
2
3
dtc -I fs -O dts /sys/firmware/devicetree/base > running.dts
grep -n -E 'bluetooth|uart|serial' running.dts
dmesg | grep -Ei 'rfkill|Bluetooth|ttyS|serial'

最终DTB和运行枚举优先于源码中的其它板型。

并发、队列、缓冲与生命周期

并发、队列、缓冲与生命周期

1. 上下文

-USB completion在atomic/softirq语义下;
-UART receive callback不可长时间阻塞;
-firmware/setup可睡眠;
-workqueue执行重配置和恢复;
-HCI Core命令等待依赖RX事件推进。

2. SKB ownership

Transport queue持有TX skb;成功提交后completion释放或统计。RX parser分配skb并仅在完整frame后交HCI Core。错误路径必须重置partial state。

3. USB anchors

BTUSB按TX/RX/isoc/deferred anchor组织URB。Suspend/disconnect用kill/poison同步等待completion退出。

4. UART state bits

HCI_UART_SENDING序列化发送循环,HCI_UART_TX_WAKEUP记录发送期间的新数据。Protocol dequeue决定下一frame,并可能附加framing/escaping。

5. H5 timers

H5 link establishment、ack和retrans由timer/work推进。Close必须同步取消,防止访问已释放 hci_uart

6. SDIO

IRQ通知可读数据/可写credits;work或thread取包。Host claim范围必须短,避免阻塞Wi-Fi同host及PM。

7. Open/Close

状态转换需幂等处理:

-重复open避免重复提交RX;
-close先清running再kill I/O;
-disconnect先unregister阻止Core新请求;
-firmware work必须cancel;
-回调使用device reference。

8. Suspend

Suspend与TX竞态常用:

-suspending flag;
-busy counter;
-deferred queue;
-synchronized URB kill;
-resume后重提RX并flush deferred。

9. Statistics

HCI stat记录byte/packet/error;transport另有USB/SDIO/vendor日志。统计突增应结合btmon时间线,不只看最终值。

10. 内存压力

GFP_ATOMIC分配失败会丢RX frame。高吞吐下关注UART overrun、USB URB数量、SDIO block size、CPU调度和BlueZ消费速度。

Bluetooth 调试、性能、故障与安全

Bluetooth 调试、性能、故障与安全

1. 基础状态

1
2
3
4
5
6
rfkill list
btmgmt info
bluetoothctl show
hciconfig -a
ls /sys/class/bluetooth
dmesg | grep -Ei 'Bluetooth|btusb|hci_uart|rfkill|firmware'

2. 抓包

1
2
btmon
btmgmt power on

先启动btmon再复现,观察HCI command、status、event、disconnect reason。空中协议问题需独立sniffer。

3. UART

检查:

-controller和host baud一致;
-RTS/CTS pinmux;
-RX/TX是否交叉;
-reset/clock;
-host-wake;
-是否已运行hciattach或serdev已绑定;
-UART DMA/PIO overrun。

逻辑分析仪应按H4/H5 framing解码。

4. USB

1
2
3
lsusb -nn
lsusb -t
cat /sys/bus/usb/devices/*/power/control

测试关闭autosuspend只能用于定位,不应直接作为最终修复。

5. Firmware

从日志记录准确requested path、ROM/LMP/HCI revision。确认文件权限、大小、版本和下载后的boot event。

6. RK3588低功耗

逐项验证:

-rfkill unblock后的reset波形;
-32k clock;
-UART RTS/CTS;
-BT_WAKE;
-HOST_WAKE中断计数;
-suspend pinctrl;
-shared Wi-Fi/BT rail。

7. 性能

-提高UART baud前验证signal和flow control;
-USB避免错误hub拓扑和频繁autosuspend;
-SDIO优化block size/IRQ但兼顾Wi-Fi;
-检查CPU idle/wakeup latency;
-A2DP吞吐还受codec和BlueZ影响;
-HFP问题重点看USB isoc或UART时延。

8. 常见故障

现象 首要检查
无hci0 transport probe、attach、power
hci0 up timeout firmware、baud、reset
扫描正常连接失败 地址、firmware、加密事件
suspend后失联 wake GPIO/IRQ/clock
Wi-Fi开关影响BT shared rail/coexistence
音频卡顿 RF干扰、UART flow、USB isoc

9. 安全

-限制raw HCI、mgmt、VHCI权限;
-关闭不需要的legacy protocols和debug;
-使用受控firmware;
-及时修复Bluetooth stack/controller漏洞;
-关闭不需要的discoverable/pairable;
-采用Secure Connections并限制legacy pairing;
-devcoredump按敏感数据处理。

10. 产品证据

保留kernel config、最终DTB、firmware hash、controller revision、btmon复现、rfkill/GPIO dump和功耗波形,避免仅凭“hci0存在”判定集成完成。

Bluetooth HCI 驱动架构与源码总览

Bluetooth HCI 驱动架构与源码总览

1. 分层

1
2
3
4
5
6
7
bluetoothd / mgmt / AF_BLUETOOTH sockets

net/bluetooth HCI Core
│ struct hci_dev
drivers/bluetooth transport driver
│ USB / UART / SDIO / SMD / Virtio
Bluetooth controller firmware

本目录实现 HCI设备和主机之间的 transport,不实现 L2CAP、RFCOMM、SMP、BNEP等上层协议。

2. HCI driver contract

Transport分配 hci_dev并设置:

  • bus;
  • open/close/flush;
  • send;
  • setup/configure;
  • shutdown;
  • set_bdaddr/set_diag等可选回调;
  • quirks和 capabilities。

hci_register_dev()后HCI Core负责命令、事件、连接、mgmt和用户接口。

3. TX

1
2
3
4
HCI Core skb
-> hdev->send
-> transport queue/URB/serial write
-> controller

skb packet type区分 command、ACL、SCO、ISO、vendor diag。

4. RX

1
2
3
4
USB completion/UART parser/SDIO IRQ
-> assemble complete HCI frame
-> hci_recv_frame
-> HCI event/ACL/SCO/ISO dispatch

Framing错误、长度错误和USB status更新统计并触发重组/恢复。

5. Firmware

Intel/Broadcom/Realtek/QCA/MediaTek/Marvell helpers在 setup阶段识别芯片、下载 patch/config、设置地址和特性。固件路径及格式是厂商相关的。

6. RK3588

RK3588没有SoC内部 Bluetooth controller,常配 Wi-Fi/BT combo module:

-Bluetooth多走 UART;
-Wi-Fi多走 PCIe/SDIO;
-共享电源/32.768kHz clock;
-BT reset、host-wake、device-wake GPIO;
-RTS pin在休眠时可切GPIO。

厂商板型使用 bluetooth-platdata,并非标准 Broadcom/Realtek UART child binding。

7. 安全边界

Controller firmware、HCI raw socket、VHCI和debug接口均有高权限风险。量产应限制 CAP_NET_ADMIN/CAP_NET_RAW、固件来源和 /dev/vhci访问。

Linux 6.1 Bluetooth HCI 驱动文档索引

Linux 6.1 Bluetooth HCI 驱动文档索引

源码:rk3588/kernel-6.1/drivers/bluetooth/

文档 内容
Bluetooth驱动架构与源码总览.md HCI transport整体架构
源码目录与驱动索引.md 文件、Kconfig、构建状态
01-HCI设备注册与数据通路.md hci_dev、TX/RX和管理层
02-BTUSB探测固件与电源管理.md USB URB和quirks
03-HCI-UART-Ldisc与Serdev架构.md UART两种绑定方式
04-H4-H5-BCSP与低功耗协议.md UART framing/protocol
05-Broadcom-Realtek-Intel-QCA厂商支持.md firmware/config helpers
06-SDIO-MRVL-MTK与其它Transport.md SDIO、SMD、Virtio、VHCI
07-固件下载初始化与错误恢复.md firmware、安全和恢复
08-RFKill休眠唤醒与共存.md 标准HCI与Rockchip平台电源
09-RK3588蓝牙硬件与DTS集成.md UART模块、GPIO和时钟
10-并发队列缓冲与生命周期.md workqueue、URB、skb
11-调试性能故障与安全.md btmon、日志、吞吐和加固

本 defconfig内建 BT、BTUSB、HCI UART、ATH3K、BFUSB、VHCI和Marvell SDIO;但具体板载蓝牙常由厂商 bluetooth-platdata节点及 net/rfkill/rfkill-bt.c负责UART模块的电源与唤醒。

drivers/bluetooth 源码目录与驱动索引

drivers/bluetooth 源码目录与驱动索引

1. USB

  • btusb.c:主流USB HCI;
  • ath3k.c:Atheros firmware loader;
  • bcm203x.cbfusb.c:旧设备;
  • bpa10x.c:sniffer。

2. UART

  • hci_ldisc.c:TTY line discipline;
  • hci_serdev.c:serial device bus;
  • hci_uart.h:共同对象/API;
  • hci_h4.chci_h5.chci_bcsp.c:framing;
  • hci_bcm.chci_qca.chci_intel.c
  • hci_ll.chci_ath.chci_mrvl.chci_nokia.chci_ag6xx.c

本 Makefile没有 hci_rtl.c;Realtek UART逻辑由H5/serdev和 btrtl helper组合。

3. 厂商helpers

  • btintel.[ch]
  • btbcm.[ch]
  • btrtl.[ch]
  • btqca.[ch]
  • btmtk.[ch]

它们由多个 transport复用,不单独代表物理bus。

4. SDIO

  • btsdio.c:通用HCI SDIO;
  • btmrvl_main.cbtmrvl_sdio.c
  • btmtksdio.c

5. 其它

  • btmtkuart.c
  • btqcomsmd.c
  • btrsi.c
  • virtio_bt.c
  • hci_vhci.c
    -PCMCIA legacy drivers。

6. Defconfig

明确为 y

1
2
3
4
5
6
7
8
9
10
BT
BT_HCIBTUSB
BT_HCIUART
BT_HCIUART_ATH3K
BT_HCIBFUSB
BT_HCIVHCI
BT_MRVL
BT_MRVL_SDIO
RFKILL
RFKILL_RK

未显式启用H4/H5/BCM/QCA等选项时不能只因源码存在就宣称已编译。BT_HCIUART_ATH3K会 select H4。

7. 目录边界

  • HCI Core:net/bluetooth/
  • UAPI:include/uapi/linux/bluetooth.h及hci/mgmt headers;
  • Rockchip平台 rfkill:net/rfkill/rfkill-bt.crfkill-wlan.c
    -用户态:BlueZ,不在内核树本目录。

Simple PM Bus 与 OF 子设备枚举

Simple PM Bus 与 OF 子设备枚举

1. 用途

simple-pm-bus.c处理“本身几乎透明,但子设备访问前必须给父域上电”的DT容器。它不定义新的bus_type,children仍是platform devices。

2. Match表

1
2
3
4
5
simple-pm-bus   -> 真正执行PM与populate
simple-bus -> 仅保护性匹配
simple-mfd -> 仅保护性匹配
isa -> 仅保护性匹配
arm,amba-bus -> 仅保护性匹配

后四项带ONLY_BUS标记。它们通常已由OF Core自动populate;驱动只在自身compatible是节点最具体匹配时返回0,否则返回-ENODEV,避免抢占有专用driver的设备。

3. Probe

真正simple-pm-bus路径:

1
2
3
simple_pm_bus_probe
-> pm_runtime_enable(parent)
-> of_platform_populate(parent node, parent device)

可通过platform data传入of_dev_auxdata,给特定child补legacy name/data。

驱动不直接:

  • 获取clock;
  • 控制reset;
  • 调用runtime get;
  • 编程寄存器;
  • 建立独立地址转换。

电源资源由通用PM domain/clock等device links与父子关系协作。

4. Driver Override

如果用户通过driver_override强制绑定透明bus节点,probe立即返回0,不执行runtime PM或populate。这是调试逃生口,不能视为正常DT绑定方式。

5. Remove

remove只调用pm_runtime_disable()。OF创建的children通常由platform/OF生命周期处理;驱动本身没有显式of_platform_depopulate()

因此不适合被频繁动态unbind。若父driver解除而children仍存在,必须确保平台Core的设备移除顺序不会让child访问失去管理的父资源。

6. Runtime PM语义

pm_runtime_enable()仅启用框架,不等于立即上电或自动对每次child I/O计数。实际效果依赖:

  • 父节点是否挂genpd;
  • child和parent的runtime PM关系;
  • child driver是否正确get/put;
  • clock是否由runtime PM callback管理。

若只写compatible = "simple-pm-bus"但没有有效PM资源,驱动主要只承担child populate。

7. DT示意

1
2
3
4
5
6
7
8
9
10
11
12
domain-bus {
compatible = "vendor,specific-domain", "simple-pm-bus";
power-domains = <&pd X>;
#address-cells = <1>;
#size-cells = <1>;
ranges;

device@1000 {
compatible = "vendor,device";
reg = <0x1000 0x100>;
};
};

vendor,specific-domain有专用driver,simple-pm-bus不会越过更具体匹配抢占。

8. RK3588

在本树rk3588*.dts*中未发现simple-pm-bus compatible。大量普通simple-bus层次由OF平台枚举机制处理,并不意味着绑定了本驱动。

RK3588多数功能域通过rockchip,rk3588-power-controller及子设备power-domains引用管理,不依赖本文件建立总线。

9. 排障

1
2
3
ls /sys/bus/platform/drivers/simple-pm-bus
readlink /sys/bus/platform/devices/<node>/driver
cat /sys/bus/platform/devices/<node>/power/runtime_status

child未probe时先分辨:

  1. child platform device是否创建;
  2. compatible是否匹配child driver;
  3. 父genpd是否可用;
  4. 专用父driver是否抢占;
  5. 是否因父probe失败而未populate。

Linux 自定义 Bus Type 与设备模型

Linux 自定义 Bus Type 与设备模型

1. 何时需要自定义总线

platform bus适合固件已描述的MMIO设备。若设备由controller固件动态发现、使用非DT匹配规则,或需要专用modalias和I/O API,就会注册struct bus_type

本目录典型包括:

  • mhimhi_ep
  • fsl-mc
  • sunxi-rsb
  • moxtet
  • mips_cdmm

2. 基本组成

1
2
3
4
5
6
bus_register
-> controller discovery
-> device_initialize/device_add
-> bus.match
-> driver.probe
-> uevent/modalias

专用device通常内嵌struct device;专用driver内嵌struct device_driver。Core仍由drivers/base提供,bus driver只实现策略和协议。

3. Match

常见匹配键:

Bus 匹配对象
MHI Host channel name和mhi_device_id
MHI Endpoint endpoint channel/device name
FSL-MC vendor/object type/version
Sunxi RSB RSB device ID/compatible
MOXTET module type
MIPS CDMM device type和revision

Match必须稳定,因为它决定module autoload alias及哪个功能driver获得设备。

4. Controller与功能设备

通常存在两级device:

1
2
3
physical parent (PCI/platform)
-> controller device
-> function/channel/object devices

Controller负责:

  • transport寄存器和中断;
  • DMA/ring或command portal;
  • 发现/销毁children;
  • PM和错误恢复。

Function driver只使用导出的queue/command API,不直接接管底层硬件生命周期。

5. Uevent与模块加载

自定义bus实现uevent()生成:

1
MODALIAS=<bus>:<id>

用户空间udev据MODULE_DEVICE_TABLE加载功能driver。若modalias缺失或匹配表命名不同,device会存在于sysfs但没有driver。

6. Probe/Remove顺序

Controller删除前必须先删除所有child:

1
2
3
4
5
6
stop discovery/IRQ
-> block new I/O
-> device_unregister(children)
-> drain callbacks/work
-> free rings/resources
-> unregister controller

device_unregister()可能触发功能driver remove和异步引用释放,不能在child release前释放其parent私有内存。

7. 并发

自定义bus通常至少有:

  • bus/device model mutex;
  • controller状态锁;
  • channel/ring spinlock;
  • IRQ/tasklet/workqueue;
  • completion或waitqueue;
  • runtime PM引用。

Bus match/probe在可睡眠上下文,数据完成常在IRQ线程/tasklet;API必须明确callback上下文。

8. 安全边界

动态枚举ID来自硬件/固件。恶意或故障controller可能报告异常channel、object数、ring长度或DMA地址。Controller driver必须在创建设备和分配内存前验证:

  • ID范围;
  • 数量上限;
  • descriptor长度;
  • DMA窗口;
  • doorbell/ring索引;
  • 固件版本。

9. 与普通simple-bus区别

DT中的simple-bus只是地址层次和OF child枚举约定,不会注册名为simple-bus的Linux bus type。其children通常仍挂platform bus。

因此“DT bus node”和“struct bus_type”是两个不同概念。

MHI Host 控制器、通道与状态机

MHI Host 控制器、通道与状态机

1. 定位

MHI(Modem Host Interface)用于Host处理器通过PCIe等高速transport控制modem。drivers/bus/mhi/host实现协议Core,mhi_pci_generic提供常见PCI modem glue。

1
2
3
4
5
6
MHI function driver
-> mhi bus/channel API
-> transfer/event/command rings
-> MHI controller
-> PCIe/shared memory
-> modem

2. 对象

  • mhi_controller:transport callback、MMIO、DMA、IRQ、PM和ring集合;
  • mhi_device:controller或成对UL/DL channel设备;
  • mhi_driver:按channel name匹配的功能driver;
  • mhi_chan:方向、TRE ring、doorbell、状态;
  • mhi_event:完成和状态事件ring;
  • mhi_cmd:start/stop/reset channel等命令ring。

3. 注册

mhi_register_controller()

  1. 校验controller config;
  2. 分配channel/event/command对象;
  3. 初始化锁、workqueue、waitqueue和状态;
  4. 创建controller mhi_device
  5. 注册到mhi bus;
  6. 可选创建debugfs。

注册不自动给modem上电。Transport随后调用:

1
2
3
4
5
6
7
mhi_prepare_for_power_up
-> allocate DMA/context/rings
mhi_async_power_up or mhi_sync_power_up
-> RESET/READY
-> M0
-> mission mode
-> create channel devices

4. Ring

Host在一致性DMA内存中维护:

  • channel TRE ring;
  • event ring;
  • command ring;
  • channel/event/command context。

Queue传输:

1
2
3
4
5
6
mhi_queue_buf/mhi_queue_skb/mhi_queue_dma
-> map buffer
-> fill TRE
-> advance write pointer
-> memory barrier
-> ring channel doorbell

Modem写event ring并触发IRQ。Host解析completion code,回收TRE、unmap DMA并调用client callback。

5. Doorbell与并发

Doorbell可按burst mode配置,避免每个TRE都写MMIO。Ring更新需保证:

  1. descriptor和payload mapping对device可见;
  2. write pointer先更新;
  3. barrier之后再doorbell。

Channel/event各有锁;controller PM使用pm_lock和状态转换work。不能在持有spinlock时执行会睡眠的runtime PM或固件操作。

6. 状态机

MHI设备状态主要为RESET、READY、M0、M1、M2、M3、SYS_ERR:

  • M0:活动;
  • M1:进入低功耗的过渡;
  • M2:轻度低功耗,Host仍可唤醒;
  • M3:深度低功耗;
  • SYS_ERR:协议/设备错误,需要恢复。

Execution Environment包括PBL、SBL、AMSS、RDDM等,决定当前是boot、mission还是RAM dump。

mhi_queue_state_transition()把变化排入单线程state transition worker,按序执行READY、MISSION_MODE等复杂流程。

7. 固件和崩溃转储

boot.c实现BHI/BHIE:

  • 装载modem firmware;
  • 分段DMA传输;
  • 等待boot状态;
  • 进入mission mode;
  • RDDM时收集RAM dump。

固件名和超时来自controller profile。固件必须按产品信任链校验,不能仅依赖文件路径。

8. PCI Generic

mhi_pci_generic按PCI ID选择不同controller config,覆盖Qualcomm SDX、Quectel、Foxconn、Sierra、Telit等设备。

Probe:

1
2
3
4
5
6
7
pci_enable_device
-> request/map BAR
-> DMA mask
-> allocate MSI vectors
-> mhi_register_controller
-> prepare + sync power up
-> runtime PM/health timer

PCI AER、health check或SYS_ERR会调度recovery work,power down、reset PCI function、重新prepare/power up。

9. PM

功能driver使用mhi_device_get[_sync]()/mhi_device_put()维持device wake。Controller suspend要求channel可挂起并进入M3;resume重新进入M0。

计数不配对会导致modem无法休眠或I/O期间被挂起。

10. RK3588

MHI协议与SoC无关。受支持MHI PCI modem可以物理插到RK3588 PCIe,但还需要:

  • CONFIG_MHI_BUSCONFIG_MHI_BUS_PCI_GENERIC
  • 对应PCI ID;
  • PCIe、MSI和DMA正常;
  • firmware文件;
    -供电/reset/W_DISABLE等板级控制。

本树Rockchip defconfig未启用MHI,故不是默认数据路径。