USB PD 协议
一、模块定位与核心价值
1.1 模块概述
adapter_protocol_pd 是华为 MATE X5 快充系统中的 PD (USB Power Delivery) 协议适配层模块,作为 adapter_protocol 抽象层的协议实现之一,负责桥接 USB Type-C PD 协议栈与华为充电框架,实现 PD 快充功能。
1.2 核心功能
1.3 模块特点
极简设计: 仅 217 行代码,是所有协议实现中最精简的
桥接角色: 不直接操作硬件,委托给 USB Type-C 子系统
无寄存器操作: 通过 TCPM (Type-C Port Manager) 间接控制
标准 PD 协议: 遵循 USB-IF PD 3.0/2.0 规范
4 种芯片支持: SCHARGER_V600、FUSB3601、RT1711H、FUSB30X
二、系统架构设计
2.1 模块分层架构
┌─────────────────────────────────────────────────────────────┐
│ Charging Framework (Direct Charge) │
│ (调用 adapter_protocol 统一接口) │
└──────────────────────┬──────────────────────────────────────┘
│
┌──────────────────────▼──────────────────────────────────────┐
│ adapter_protocol.c (协议路由层) │
│ [根据 ADAPTER_PROTOCOL_PD 分发] │
└──────────────────────┬──────────────────────────────────────┘
│
┌─────────────┼─────────────┬───────────────┐
│ │ │ │
┌────▼───┐ ┌────▼───┐ ┌────▼───┐ ┌────▼───┐
│ PD │ │ SCP │ │ FCP │ ... │ UFCS │
└────┬───┘ └────────┘ └────────┘ └────────┘
│
┌────────▼──────────────────────────────────────────────────┐
│ adapter_protocol_pd.c (PD 协议适配层) │
│ ┌──────────────────────────────────────────────────┐ │
│ │ • 轻量级包装 (仅 4 个接口) │ │
│ │ • 状态维护 (电压缓存) │ │
│ │ • 委托转发给 USB Type-C 子系统 │ │
│ └──────────────────────────────────────────────────┘ │
└────────┬──────────────────────────────────────────────────┘
│ 调用
┌────────▼──────────────────────────────────────────────────┐
│ USB Type-C Subsystem (oem-typec-adapter.c) │
│ ┌──────────────────────────────────────────────────┐ │
│ │ • hisi_usb_typec_issue_hardreset() │ │
│ │ • hisi_usb_typec_set_pd_adapter_voltage() │ │
│ └──────────────────────────────────────────────────┘ │
└────────┬──────────────────────────────────────────────────┘
│
┌────────▼──────────────────────────────────────────────────┐
│ TCPM (Type-C Port Manager) │
│ • PD Policy Engine │
│ • Protocol Layer (Message Handling) │
│ • Physical Layer (TCPC Driver) │
└────────┬──────────────────────────────────────────────────┘
│
▼
USB Type-C Port (TCPC Hardware)
│
▼
PD Adapter (USB PD 充电器)
2.2 PD vs SCP/FCP 对比
| 特性 | PD | SCP | FCP |
|---|
| 协议标准 | USB-IF 标准 | 华为私有 | 华为私有 |
| 代码规模 | 217 行 | 2590 行 | 818 行 |
| 通信方式 | USB Type-C CC 线 | D+/D- 线 | D+/D- 线 |
| 电压调节 | PDO 协商 (离散) | 连续调节 (1mV) | 离散档位 (5V/9V/12V) |
| 功率范围 | 15W~240W | 25W~135W | 18W~36W |
| 复杂度 | 极简(委托) | 高(完整实现) | 中(完整实现) |
| 硬件依赖 | TCPM 子系统 | 直接寄存器操作 | 直接寄存器操作 |
| 认证机制 | USB 认证 | Hash 加密 | 无 |
2.3 数据流向
充电请求 (设置 9V)
│
├─→ adapter_set_output_voltage(ADAPTER_PROTOCOL_PD, 9000)
│
├─→ hwpd_set_output_voltage(9000)
│ ├─ 缓存电压: g_hwpd_dev->volt = 9000
│ └─ 调用 ops: p_ops->set_output_voltage(9000, dev_data)
│
├─→ hisi_usb_typec_set_pd_adapter_voltage(9000)
│ └─ 调用 TCPM API
│
├─→ TCPM Policy Engine
│ ├─ 构造 Request Message (9V PDO)
│ └─ 发送给 PD 适配器
│
└─→ PD Adapter
└─ 切换输出到 9V
Hard Reset 流程
│
├─→ adapter_hard_reset_master(ADAPTER_PROTOCOL_PD)
│
├─→ hwpd_hard_reset_master()
│ └─ 调用 ops: p_ops->hard_reset_master(dev_data)
│
├─→ hisi_usb_typec_issue_hardreset()
│ └─ 调用 TCPM API
│
├─→ TCPM Policy Engine
│ └─ 发送 Hard Reset 信号
│
└─→ PD Adapter
└─ 复位到默认 5V
三、核心数据结构
3.1 设备管理结构
struct hwpd_dev {
struct device *dev;
struct hwpd_ops *p_ops;
int volt;
int dev_id;
};
字段说明:
3.2 硬件操作接口
struct hwpd_ops {
const char *chip_name;
void *dev_data;
void (*hard_reset_master)(void *dev_data);
void (*set_output_voltage)(int volt, void *dev_data);
};
接口特点:
3.3 设备映射表
static const struct adapter_protocol_device_data g_hwpd_dev_data[] = {
{ PROTOCOL_DEVICE_ID_SCHARGER_V600, "scharger_v600" },
{ PROTOCOL_DEVICE_ID_FUSB3601, "fusb3601" },
{ PROTOCOL_DEVICE_ID_RT1711H, "rt1711h" },
{ PROTOCOL_DEVICE_ID_FUSB30X, "fusb30x" },
};
支持芯片:
SCHARGER_V600: 华为海思自研电源管理芯片
FUSB3601: ON Semiconductor USB PD 控制器
RT1711H: Richtek USB PD TCPC 芯片
FUSB30X: ON Semiconductor 旧版 PD 芯片
四、核心功能实现
4.1 电压控制
4.1.1 设置输出电压
static int hwpd_set_output_voltage(int volt)
{
struct hwpd_ops *l_ops = hwpd_get_ops();
if (!l_ops || !l_ops->set_output_voltage) {
hwlog_err("set_output_voltage is null\n");
return -EPERM;
}
hwlog_info("set output voltage: %d\n", volt);
g_hwpd_dev->volt = volt;
l_ops->set_output_voltage(volt, l_ops->dev_data);
return 0;
}
实现特点:
状态缓存: 保存电压到 g_hwpd_dev->volt
委托模式: 不直接操作硬件,调用 set_output_voltage 回调
无验证: 假设 USB Type-C 子系统会处理 PD 协商
4.1.2 获取输出电压
static int hwpd_get_output_voltage(int *volt)
{
struct hwpd_dev *l_dev = hwpd_get_dev();
if (!l_dev || !volt)
return -EPERM;
*volt = l_dev->volt;
return 0;
}
注意事项:
4.2 硬复位
static int hwpd_hard_reset_master(void)
{
struct hwpd_ops *l_ops = hwpd_get_ops();
if (!l_ops || !l_ops->hard_reset_master) {
hwlog_err("hard_reset_master is null\n");
return -EPERM;
}
l_ops->hard_reset_master(l_ops->dev_data);
return 0;
}
Hard Reset 作用:
4.3 注册与初始化
4.3.1 ops 注册
int hwpd_ops_register(struct hwpd_ops *ops)
{
int dev_id;
if (!g_hwpd_dev || !ops || !ops->chip_name) {
hwlog_err("g_hwpd_dev or ops or chip_name is null\n");
return -EPERM;
}
dev_id = hwpd_get_device_id(ops->chip_name);
if (dev_id < 0) {
hwlog_err("%s ops register fail\n", ops->chip_name);
return -EPERM;
}
g_hwpd_dev->p_ops = ops;
g_hwpd_dev->dev_id = dev_id;
hwlog_info("%d:%s ops register ok\n", dev_id, ops->chip_name);
return 0;
}
4.3.2 模块初始化
static int __init hwpd_init(void)
{
int ret;
struct hwpd_dev *l_dev;
l_dev = kzalloc(sizeof(*l_dev), GFP_KERNEL);
if (!l_dev)
return -ENOMEM;
g_hwpd_dev = l_dev;
l_dev->dev_id = PROTOCOL_DEVICE_ID_END;
l_dev->volt = ADAPTER_9V * POWER_MV_PER_V;
ret = adapter_protocol_ops_register(&adapter_protocol_hwpd_ops);
if (ret)
goto fail_register_ops;
return 0;
fail_register_ops:
kfree(l_dev);
g_hwpd_dev = NULL;
return ret;
}
初始化流程:
分配 hwpd_dev 结构体
设置默认电压为 9V
注册 4 个协议接口到 adapter_protocol
五、与 USB Type-C 子系统集成
5.1 USB Type-C 侧实现
#ifdef CONFIG_ADAPTER_PROTOCOL_PD
static struct hwpd_ops hisi_device_pd_protocol_ops = {
.chip_name = "scharger_v600",
.hard_reset_master = hisi_usb_typec_issue_hardreset,
.set_output_voltage = hisi_usb_typec_set_pd_adapter_voltage,
};
#endif
static int oem_typec_register_pd_dpm(void)
{
int ret;
void *data = (void *)&_oem_typec;
ret = pd_dpm_ops_register(&hisi_device_pd_dpm_ops, data);
if (ret)
return -EBUSY;
#ifdef CONFIG_ADAPTER_PROTOCOL_PD
hisi_device_pd_protocol_ops.dev_data = data;
ret = hwpd_ops_register(&hisi_device_pd_protocol_ops);
if (ret) {
I("pd protocol register failed\n");
return -EBUSY;
}
#endif
return 0;
}
5.2 实际功能实现
设置 PD 电压:
void hisi_usb_typec_set_pd_adapter_voltage(int volt, void *dev_data)
{
struct oem_typec *typec = (struct oem_typec *)dev_data;
hwlog_info("PD voltage set to %dmV\n", volt);
}
PD Hard Reset:
void hisi_usb_typec_issue_hardreset(void *dev_data)
{
struct oem_typec *typec = (struct oem_typec *)dev_data;
hwlog_info("PD Hard Reset issued\n");
}
六、典型使用场景
场景 1: PD 快充初始化
static int dc_init_pd_adapter(void)
{
int ret, mode;
ret = adapter_detect_support_mode(ADAPTER_PROTOCOL_PD, &mode);
if (ret == ADAPTER_DETECT_SUCC) {
hwlog_info("PD adapter detected\n");
}
ret = adapter_set_output_voltage(ADAPTER_PROTOCOL_PD, 9000);
hwlog_info("PD voltage set to 9V\n");
int volt;
adapter_get_output_voltage(ADAPTER_PROTOCOL_PD, &volt);
hwlog_info("Current PD voltage: %dmV\n", volt);
return 0;
}
场景 2: PD 电压切换
static void pd_voltage_switch_flow(void)
{
adapter_set_output_voltage(ADAPTER_PROTOCOL_PD, 9000);
msleep(500);
adapter_set_output_voltage(ADAPTER_PROTOCOL_PD, 12000);
msleep(500);
adapter_set_output_voltage(ADAPTER_PROTOCOL_PD, 20000);
msleep(500);
}
场景 3: PD Hard Reset
static int pd_recovery_by_hard_reset(void)
{
hwlog_info("PD negotiation failed, try hard reset\n");
adapter_hard_reset_master(ADAPTER_PROTOCOL_PD);
msleep(1000);
adapter_set_output_voltage(ADAPTER_PROTOCOL_PD, 9000);
msleep(500);
int vbus = get_charger_vbus();
if (abs(vbus - 9000) < 500) {
hwlog_info("PD recovery success\n");
return 0;
}
hwlog_err("PD recovery failed\n");
return -EPERM;
}
场景 4: PD 与 SCP 协同
static int select_best_protocol(void)
{
int mode, ret;
ret = adapter_detect_support_mode(ADAPTER_PROTOCOL_PD, &mode);
if (ret == ADAPTER_DETECT_SUCC) {
hwlog_info("Use PD protocol\n");
return ADAPTER_PROTOCOL_PD;
}
ret = adapter_detect_support_mode(ADAPTER_PROTOCOL_SCP, &mode);
if (ret == ADAPTER_DETECT_SUCC) {
hwlog_info("Use SCP protocol\n");
return ADAPTER_PROTOCOL_SCP;
}
hwlog_info("Use standard charging\n");
return ADAPTER_PROTOCOL_UNKNOWN;
}
场景 5: QTR 双口适配器处理
static bool is_qtr_pd_adapter(void)
{
int adapter_type;
adapter_get_adp_type(ADAPTER_PROTOCOL_PD, &adapter_type);
if (adapter_type == ADAPTER_TYPE_QTR_C_20V3A ||
adapter_type == ADAPTER_TYPE_QTR_C_10V4A) {
hwlog_info("QTR dual-port PD adapter detected\n");
return true;
}
return false;
}
七、调试方法
7.1 Kernel 日志分析
关键日志标签
adb shell dmesg | grep "pd_protocol"
adb shell dmesg | grep "hwpd"
adb shell dmesg | grep "adapter_protocol"
adb shell dmesg | grep "oem_typec"
adb shell dmesg | grep "TCPM"
adb shell dmesg | grep "PD_DPM"
典型日志输出
模块初始化:
[ 5.200] pd_protocol: 1:scharger_v600 ops register ok
电压设置:
[ 15.100] pd_protocol: set output voltage: 9000
[ 15.150] oem_typec: PD voltage set to 9000mV
[ 15.200] TCPM: Request 9V/3A PDO
[ 15.300] TCPM: PD negotiation success, switched to 9V
Hard Reset:
[ 20.000] pd_protocol: hard_reset_master
[ 20.010] oem_typec: PD Hard Reset issued
[ 20.100] TCPM: Hard Reset signal sent
[ 20.500] TCPM: Reset to vSafe5V
7.2 Sysfs 调试接口
cat /sys/class/hw_power/charger/adapter_detect
cat /sys/class/typec/port0/power_role
cat /sys/class/typec/port0/data_role
cat /sys/kernel/debug/tcpm/port0/pdos
7.3 常见问题诊断
| 现象 | 可能原因 | 检查方法 | 解决方案 |
|---|
| 电压设置无效 | PD 协商失败 | 检查 TCPM 日志 | 确认 PDO 支持目标电压 |
| 电压不稳定 | CC 线接触不良 | 检查 Type-C 连接 | 重新插拔线缆 |
| Hard Reset 失败 | TCPM 未响应 | 检查 TCPC 驱动 | 重启 USB Type-C 子系统 |
| 获取电压错误 | 缓存未更新 | 对比实际 VBUS | 读取实际充电器电压 |
| ops 注册失败 | chip_name 不匹配 | 检查设备映射表 | 确认芯片名称正确 |
7.4 调试示例
检查 PD 协商过程:
echo 1 > /sys/module/tcpm/parameters/debug
echo 9000 > /sys/class/hw_power/charger/adapter_voltage
dmesg -w | grep TCPM
八、性能与设计特点
8.1 极简设计优势
代码对比:
PD: 217 行 (100%)
FCP: 818 行 (377%)
SCP: 2590 行 (1193%)
优势:
维护成本低: 代码量少,逻辑简单
稳定性高: 委托给成熟的 TCPM 子系统
标准兼容: 遵循 USB-IF PD 规范
功能完整: 满足充电需求的核心功能
8.2 委托模式分析
设计模式:
┌─────────────────────────────────────────┐
│ adapter_protocol_pd.c │
│ (Wrapper/Adapter Pattern) │
│ │
│ • 不实现具体功能 │
│ • 仅提供统一接口 │
│ • 委托给专业子系统 │
└─────────────────┬───────────────────────┘
│ 委托
┌─────────────────▼───────────────────────┐
│ USB Type-C Subsystem │
│ (Real Implementation) │
│ │
│ • PD Policy Engine │
│ • Protocol Layer │
│ • TCPC Driver │
└─────────────────────────────────────────┘
优势:
8.3 状态缓存策略
优点:
响应快: 获取电压无延迟
无硬件访问: 减少 TCPM 调用
缺点:
可能不准: 协商失败时缓存与实际不符
无验证: 不检查实际适配器电压
九、最佳实践
9.1 电压设置
static int pd_set_voltage_safe(int target_volt)
{
int vbus;
adapter_set_output_voltage(ADAPTER_PROTOCOL_PD, target_volt);
msleep(500);
vbus = get_charger_vbus();
if (abs(vbus - target_volt) > 500) {
hwlog_err("PD voltage mismatch: target=%d, actual=%d\n",
target_volt, vbus);
return -EPERM;
}
return 0;
}
9.2 错误恢复
static int pd_recovery_strategy(void)
{
int retry;
for (retry = 0; retry < 3; retry++) {
adapter_hard_reset_master(ADAPTER_PROTOCOL_PD);
msleep(1000);
if (pd_set_voltage_safe(9000) == 0) {
hwlog_info("PD recovery success at retry %d\n", retry);
return 0;
}
}
hwlog_err("PD recovery failed after 3 retries\n");
return -EPERM;
}
9.3 与其他协议协同
static int select_optimal_protocol(void)
{
int pd_power, scp_power;
if (adapter_detect_support_mode(ADAPTER_PROTOCOL_PD, &mode) == 0) {
pd_power = get_pd_max_power();
if (adapter_detect_support_mode(ADAPTER_PROTOCOL_SCP, &mode) == 0) {
scp_power = get_scp_max_power();
if (scp_power > pd_power) {
hwlog_info("Choose SCP: %dW > PD: %dW\n",
scp_power/1000, pd_power/1000);
return ADAPTER_PROTOCOL_SCP;
}
}
return ADAPTER_PROTOCOL_PD;
}
return ADAPTER_PROTOCOL_UNKNOWN;
}
十、总结
10.1 核心特性总结
| 特性 | 描述 | 技术亮点 |
|---|
| 代码规模 | 217 行 | 所有协议中最精简 |
| 设计模式 | 委托模式 | 转发给 USB Type-C 子系统 |
| 协议标准 | USB PD 3.0/2.0 | 遵循 USB-IF 规范 |
| 功率范围 | 15W~240W | 取决于 PD 适配器 PDO |
| 接口数量 | 4 个 | 仅核心功能 |
| 硬件依赖 | TCPM 子系统 | 无直接寄存器操作 |
| 芯片支持 | 4 种 | TCPC 控制器 |
| 状态管理 | 电压缓存 | 快速查询 |
10.2 优势分析
相比私有协议 (SCP/FCP):
标准化: USB-IF 标准,兼容性好
简洁性: 代码量仅 8% (217/2590)
稳定性: 依赖成熟的 TCPM 子系统
维护性: 极少的代码,易于维护
相比完整 PD 实现:
复用性: 避免重复实现 PD 协议栈
专业性: TCPM 是 USB 官方参考实现
功能性: 满足充电场景的核心需求
10.3 设计理念
"Do One Thing Well"
adapter_protocol_pd 的核心设计理念:
1. 不重复造轮子 → 委托给 TCPM
2. 提供统一接口 → 适配充电框架
3. 保持极简设计 → 仅包装核心功能
4. 遵循标准协议 → USB PD 规范
10.4 适用场景
推荐使用 PD:
USB Type-C 接口设备
标准 PD 充电器
需要 USB 认证的产品
多协议兼容场景
推荐使用 SCP:
华为私有快充适配器
需要超高功率 (>100W)
需要精确电压控制
华为生态设备
推荐使用 FCP:
老旧华为快充适配器
简单快充需求 (18W~36W)
Micro-USB 接口设备
10.5 技术创新点
极简包装: 仅 217 行实现 PD 协议适配
委托模式: 充分利用现有 TCPM 子系统
零硬件操作: 通过 Type-C 框架间接控制
状态缓存: 电压值缓存提升查询性能
标准遵循: 严格遵循 USB PD 规范