【安卓bsp个人笔记-AI生成文档】私有快充协议简单调试基于sprd平台,使用SD76930充电IC
AI总结的在SPRD平台实现私有快充协议代码及流程分析的个人笔记(偷懒不自己写文档了)
·
1. 原始充电、快充调用逻辑分析
1.1 系统架构
以上的电流都可以通过dts设置,如dts未设置才使用默认电流
1.2 核心文件分析
1.2.1 sprd_fchg_extcon.c - 快充扩展控制
主要功能
- 管理多种快充协议(SFCP、PD、Customized FCHG)
- 提供统一的快充接口和状态标志位
- 处理快充协议间的优先级和切换
关键函数
// 快充类型检测和切换
static void sprd_fchg_work(struct work_struct *data)
{
// 检测当前快充类型并设置相应的使能状
if (info->pd_extcon && (val.intval == POWER_SUPPLY_USB_TYPE_PD)) {
info->pd_enable = true;
info->fchg_type = POWER_SUPPLY_CHARGE_TYPE_FAST;
} else if (info->sfcp_extcon && val.intval == POWER_SUPPLY_CHARGE_TYPE_FAST) {
info->sfcp_enable = true;
info->fchg_type = POWER_SUPPLY_CHARGE_TYPE_FAST;
} else if (info->customized_fchg_extcon && val.intval == POWER_SUPPLY_CHARGE_TYPE_FAST) {
info->customized_fchg_enable = true;
info->fchg_type = POWER_SUPPLY_CHARGE_TYPE_FAST;
}
}
快充检测流程图
1.2.2 sd76930-charger.c - 充电器驱
主要功能
- 硬件充电器控制(SD76930芯片)
- 充电电流/电压调节
- 充电状态监
- 支持CUSTOM快充模式(硬件表现为可以设置DP/DM的pin脚电压)
关键函数
// CUSTOM快充模式设置
static int sd76930_charger_set_custom_chg(struct sd76930_charger_info *info, u32 vol)
{
if (vol < 7000) {
// 退出CUSTOM模式,恢复DCP
reg_val = 0x0;
ret = sd76930_update_bits(info, SD76930_REG_4,
SD76930_REG_DPVOL_MASK | SD76930_REG_DMVOL_MASK,
reg_val);
} else {
// 进入CUSTOM模式:DP=0V, DM=0V -> DP=3.3V, DM=0V
reg_val = SD76930_REG_DPVOL_0V | SD76930_REG_DMVOL_0V;
ret = sd76930_update_bits(info, SD76930_REG_4,
SD76930_REG_DPVOL_MASK | SD76930_REG_DMVOL_MASK,
reg_val);
msleep(10);
reg_val = SD76930_REG_DPVOL_3V3 | SD76930_REG_DMVOL_0V;
ret = sd76930_update_bits(info, SD76930_REG_4,
SD76930_REG_DPVOL_MASK | SD76930_REG_DMVOL_MASK,
reg_val);
}
}
1.2.3 charger-manager.c - 充电管理
主要功能
- 统一管理所有充电相关功
- 处理快充事件和状态切
- 提供
custom_fchg_dpdm_set接口供外部调
关键函数
// 快充事件处理
static void fast_charge_handler(struct charger_manager *cm)
{
// 检查是否满足快充条
if (cm_is_reach_fchg_threshold(cm)) {
// 启用固定快充
cm_fixed_fchg_enable(cm);
}
}
// CUSTOM快充DP/DM设置接口
int custom_fchg_dpdm_set(bool enable)
{
// 设置充电限制电流00mA
if (enable) {
val.intval = 500000; // 500mA
power_supply_set_property(psy, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val);
}
// 设置CUSTOM_CHG属
val.intval = enable ? 7500 : 0; // 7.5V或退
power_supply_set_property(psy, POWER_SUPPLY_PROP_CHARGE_TYPE, &val);
// 检查电压是否达V以上
if (enable) {
for (j = 0; j < 3; j++) {
msleep(600);
ret = get_charger_voltage(cm_public, &vbus);
if (ret == 0 && vbus > 7000000) {
voltage_ok = true;
break;
}
}
}
}
2. 协议内容
2.1 CUSTOM 18W快充协议规范
CUSTOM 18W快充协议是一种基于DP/DM电平检测的简单快充协议,具体规范如下
协议触发条件
- 当DP引脚.3V,DM引脚V
- 充电器检测到此电平组合后,自动切换到快充模式
- 输出7.5V电压,最大电.4A
- 总功率:7.5V × 2.4A = 18W
电平时序要求
- 初始状态:DP=0V, DM=0V(DCP模式
- 握手阶段:DP=0V, DM=0V 延时10ms DP=3.3V, DM=0V
- 检测阶段:维持DP=3.3V, DM=0V状态至00ms
- 电压检测:充电器输出电压应达到7V以上
- 确认阶段:连次检测电压均超过7V阈
协议优势
- 实现简单,无需复杂的通信协议
- 硬件成本低,兼容性好
- 检测速度快,响应时间
3. 快充识别流程
6.1 整体识别流程
6.2 详细识别步骤
步骤1:充电器类型检
// 在charger-manager.c中的检测逻辑
static int cm_get_bc1p2_type(struct charger_manager *cm, int *type)
{
// 1. 检测VBUS是否插入
if (!cm_is_ext_pwr_online(cm)) {
*type = CM_CHARGER_TYPE_NONE;
return 0;
}
// 2. 读取充电器类型寄存器
ret = regmap_read(cm->desc->charger_detect, ®_val);
// 3. 根据寄存器值判断类
switch (reg_val & CHARGER_TYPE_MASK) {
case SDP_TYPE:
*type = CM_CHARGER_TYPE_SDP;
break;
case DCP_TYPE:
*type = CM_CHARGER_TYPE_DCP;
break;
case CDP_TYPE:
*type = CM_CHARGER_TYPE_CDP;
break;
default:
*type = CM_CHARGER_TYPE_UNKNOWN;
break;
}
}
步骤2:快充协议优先级检
// 在sprd_fchg_extcon.c中的检测逻辑
static void sprd_fchg_work(struct work_struct *data)
{
// 1. 首先检测PD协议
if (info->pd_extcon && (val.intval == POWER_SUPPLY_USB_TYPE_PD)) {
info->pd_enable = true;
info->fchg_type = POWER_SUPPLY_CHARGE_TYPE_FAST;
goto notify;
}
// 2. 检测SFCP协议
if (info->sfcp_extcon && val.intval == POWER_SUPPLY_CHARGE_TYPE_FAST) {
info->sfcp_enable = true;
info->fchg_type = POWER_SUPPLY_CHARGE_TYPE_FAST;
goto notify;
}
// 3. 检测Customized FCHG协议
if (info->customized_fchg_extcon && val.intval == POWER_SUPPLY_CHARGE_TYPE_FAST) {
info->customized_fchg_enable = true;
info->fchg_type = POWER_SUPPLY_CHARGE_TYPE_FAST;
goto notify;
}
notify:
// 4. 通知充电管理
cm_notify_event(info->psy, CM_EVENT_FAST_CHARGE, NULL);
}
7. 快充检
7.1 CUSTOM协议检测详细流
7.1.1 检测工作函数部分
static void custom_18w_detect_only_work(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
struct custom_18w_info *info = container_of(dwork, struct custom_18w_info, detect_work);
int ret;
dev_info(info->dev, "[debug] custom_fchg Starting 18W fast charge detection only");
// 步骤1:关闭DCP模式,释放DP/DM准备进入检测模
// 这里通过设置寄存器位来禁用BC1.2检测功
ret = custom_dcp_switch_en(info, false);
if (ret) {
dev_err(info->dev, "Failed to disable DCP mode: %d\n", ret);
return;
}
// 步骤2:设置DP/DM电平进行协议握手
// 调用charger-manager.c中的custom_fchg_dpdm_set函数
ret = custom_fchg_dpdm_set(true);
if (ret) {
// 检测失败的处理逻辑
dev_info(info->dev, "[debug] custom_fchg 18W fast charge not supported, fallback to DCP mode");
// 恢复DCP模式
custom_dcp_switch_en(info, true);
custom_fchg_dpdm_set(false);
info->is_fast_charge_susport = false;
} else {
// 检测成功的处理逻辑
dev_info(info->dev, "[debug] custom_fchg 18W fast charge detection successful, but closing fast charge");
info->is_fast_charge_susport = true;
// 检测完成后立即关闭快充,只做检测不做启
custom_fchg_dpdm_set(false);
custom_dcp_switch_en(info, true);
// 通知Power Supply属性变
power_supply_changed(info->psy);
}
info->is_detecting = false;
}
函数逻辑分析
- DCP模式关闭:通过
custom_dcp_switch_en(info, false)禁用BC1.2检测,避免与快充检测冲 - 协议握手:调用
custom_fchg_dpdm_set(true)设置DP=3.3V, DM=0V进行协议握手 - 结果判断:根据返回值判断是否支18W快充
- 状态恢:无论成功与否,都恢复到DCP模式,只做检测不做启
- 属性通知:通过
power_supply_changed通知上层属性变
7.1.2 DCP模式切换函数分析
static int custom_dcp_switch_en(struct custom_18w_info *info, bool enable)
{
int ret;
dev_info(info->dev, "[debug] custom_fchg %s: enable = %d\n", __func__, enable);
// 通过regmap操作PMIC寄存
// BIT_DP_DM_BC_ENB_MASK控制BC1.2检测功能的使能
ret = regmap_update_bits(info->pmic, info->det_offset,
BIT_DP_DM_BC_ENB_MASK,
enable << BIT_DP_DM_BC_ENB_SHIFT);
if (ret)
dev_err(info->dev, "[debug] custom_fchg failed to switch dcp detect\n");
return ret;
}
函数逻辑分析
- 寄存器操:通过
regmap_update_bits操作PMIC寄存 - 位控:
BIT_DP_DM_BC_ENB_MASK控制BC1.2检测功能的使能/禁用 - 参数传:
enable参数决定是启用还是禁用DCP检 - 错误处理:如果寄存器操作失败,记录错误日志并返回错误
7.1.3 DP/DM设置函数分析
// 在charger-manager.c中的实现
int custom_fchg_dpdm_set(bool enable)
{
struct power_supply *psy;
union power_supply_propval val;
int ret = 0;
int i, vbus, j;
unsigned int back_limit_cur = 0;
bool voltage_ok = false;
dev_info(cm_public->dev, "[debug] custom_fchg: enable=%d\n", enable);
// 遍历所有充电器Power Supply
for (i = 0; cm_public->desc->psy_charger_stat[i]; i++) {
psy = power_supply_get_by_name(cm_public->desc->psy_charger_stat[i]);
if (!psy) {
dev_err(cm_public->dev, "Cannot find power supply \"%s\"\n",
cm_public->desc->psy_charger_stat[i]);
continue;
}
// 步骤1:保存并设置充电限制电流500mA
if (enable) {
// 获取当前电流限制
ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val);
if (ret) {
dev_err(cm_public->dev, "failed to get current limit: %d\n", ret);
power_supply_put(psy);
continue;
}
back_limit_cur = val.intval;
// 如果当前限制电流大于500mA,则设置500mA
if (back_limit_cur > 500000) {
val.intval = 500000; // 500mA
ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val);
if (ret) {
dev_err(cm_public->dev, "failed to set current limit: %d\n", ret);
}
}
}
// 步骤2:设置CUSTOM_CHG属性
// 7500mV = 7.5V表示启用CUSTOM快充表示退出为0
val.intval = enable ? 7500 : 0;
power_supply_set_property(psy, POWER_SUPPLY_PROP_CHARGE_TYPE, &val);
// 步骤3:如果启用,检查电压是否达V以上
if (enable) {
voltage_ok = false;
for (j = 0; j < 3; j++) {
msleep(600); // 等待600ms让充电器响应
ret = get_charger_voltage(cm_public, &vbus);
dev_info(cm_public->dev, "[debug] custom_fchg: vbus=%d ret=%d\n", vbus, ret);
if (ret == 0 && vbus > 7000000) { // 7V阈值
voltage_ok = true;
break;
}
}
if (!voltage_ok) {
dev_err(cm_public->dev, "[debug] custom_fchg: voltage check failed\n");
ret = -EINVAL;
}
}
power_supply_put(psy);
}
dev_info(cm_public->dev, "[debug]custom_fchg: result=%d, voltage_ok=%d\n", ret, voltage_ok);
return ret;
}
函数逻辑分析
- 电流限制:在启用快充前,将充电电流限制为500mA,避免电流过大,导致压降太大检测失败
- 协议触发:通过设置
POWER_SUPPLY_PROP_CHARGE_TYPE(GKI限制不能添加属性,故使用该属性)500mV来触发CUSTOM协议 - 电压检:连次检测充电器输出电压,必须超7V阈值
- 时序控制:每次检测间00ms,给充电器足够的响应时间
- 错误处理:如果电压检测失败,返回错误
7.1.4 硬件层DP/DM控制分析
// 在sd76930-charger.c中的实现
static int sd76930_charger_set_custom_chg(struct sd76930_charger_info *info, u32 vol)
{
u8 reg_val;
int ret;
dev_info(info->dev, "sd76930_charger_set_custom_chg: vol=%d\n", vol);
if (vol < 7000) {
// 退出CUSTOM模式,恢复DCP
reg_val = 0x0;
ret = sd76930_update_bits(info, SD76930_REG_4,
SD76930_REG_DPVOL_MASK | SD76930_REG_DMVOL_MASK,
reg_val);
if (ret) {
dev_err(info->dev, "failed to exit custom charge mode: %d\n", ret);
return ret;
}
dev_info(info->dev, "exited custom charge mode\n");
} else {
// 进入CUSTOM模式:DP=0V, DM=0V
reg_val = SD76930_REG_DPVOL_0V | SD76930_REG_DMVOL_0V;
ret = sd76930_update_bits(info, SD76930_REG_4,
SD76930_REG_DPVOL_MASK | SD76930_REG_DMVOL_MASK,
reg_val);
if (ret) {
dev_err(info->dev, "failed to set DP=0V, DM=0V: %d\n", ret);
return ret;
}
msleep(10); // 等待10ms
// 然后设置DP=3.3V, DM=0V
reg_val = SD76930_REG_DPVOL_3V3 | SD76930_REG_DMVOL_0V;
ret = sd76930_update_bits(info, SD76930_REG_4,
SD76930_REG_DPVOL_MASK | SD76930_REG_DMVOL_MASK,
reg_val);
if (ret) {
dev_err(info->dev, "failed to set DP=3.3V, DM=0V: %d\n", ret);
return ret;
}
// 等待确保DP电平稳定.3V
msleep(10);
dev_info(info->dev, "entered custom charge mode\n");
}
// 验证寄存器设置是否成
ret = sd76930_read(info, SD76930_REG_4, ®_val);
if (ret) {
dev_err(info->dev, "failed to read register after setting: %d\n", ret);
return ret;
}
dev_info(info->dev, "sd76930_charger_set_custom_chg: vol=%d, reg_val=0x%x, ret=%d\n",
vol, reg_val, ret);
return ret;
}
函数逻辑分析
- 两阶段设:先设置DP=0V, DM=0V,延10ms后再设置DP=3.3V, DM=0V
- 时序控制:通过
msleep(10)确保电平切换的时序 - 寄存器操作:使用
sd76930_update_bits更新SD76930芯片的寄存器 - 状态较验:通过
sd76930_read读取寄存器值验证设置是否成 - 错误处理:每个步骤都有详细的错误检查和日志记录
7.2 使能工作函数分析
static void custom_18w_enable_work(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
struct custom_18w_info *info = container_of(dwork, struct custom_18w_info, enable_work);
int ret;
dev_info(info->dev, "[debug] custom_fchg Starting 18W fast charge enable");
// 步骤1:关闭DCP模式,释放DP/DM
ret = custom_dcp_switch_en(info, false);
if (ret) {
dev_err(info->dev, "Failed to disable DCP mode: %d\n", ret);
return;
}
// 步骤2:启用快充
ret = custom_fchg_dpdm_set(true);
if (ret) {
// 启用失败,回退到DCP模式
dev_info(info->dev, "[debug] custom_fchg 18W fast charge not supported, fallback to DCP mode");
custom_dcp_switch_en(info, true);
custom_fchg_dpdm_set(false);
info->is_fast_charge = false;
} else {
// 启用成功
dev_info(info->dev, "[debug] custom_fchg 18W fast charge enable successful");
info->is_fast_charge = true;
// 通知Power Supply属性变
power_supply_changed(info->psy);
// 通知sprd_fchg_extcon快充状态变
if (info->fchg_info && info->fchg_info->psy) {
dev_info(info->dev, "[debug] custom_fchg Notifying CM_EVENT_FAST_CHARGE\n");
cm_notify_event(info->fchg_info->psy, CM_EVENT_FAST_CHARGE, NULL);
} else {
dev_err(info->dev, "[debug] custom_fchg fchg_info or psy is null, cannot notify fast charge\n");
}
}
info->is_detecting = false;
}
*函数逻辑分析
- 与检测函数的区别:使能函数会真正启用快充,而检测函数只做检
- 状态管理:设置
is_fast_charge = true表示快充已启 - 事件通知:通过
cm_notify_event通知充电管理器快充状态变化 - 错误处理:如果启用失败,立即回退到DCP模式
- 属性通知:通过
power_supply_changed同步Power Supply属
5. 新加文件调用逻辑分析
5.1 custom_18w_max_fchg.c 架构
5.2 Power Supply属性处理详细分
5.2.1 属性设置函数分析
static int custom_set_prop(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
{
struct custom_18w_info *info = power_supply_get_drvdata(psy);
switch (psp) {
case POWER_SUPPLY_PROP_ONLINE:
if (val->intval == 1) {
dev_info(info->dev, "[debug] custom_fchg ONLINE=1: Starting fast charge detection only, delay 2 seconds");
// 取消之前的检测工作,避免重复执行
cancel_delayed_work_sync(&info->detect_work);
// 设置检测状态并延时2秒后开始检
info->is_detecting = true;
schedule_delayed_work(&info->detect_work, msecs_to_jiffies(2000));
} else {
dev_info(info->dev, "[debug] custom_fchg ONLINE=0: Immediately stop detection");
// 立即停止检测,回到DCP模式
cancel_delayed_work_sync(&info->detect_work);
info->is_detecting = false;
info->is_fast_charge = false;
// 通知Power Supply属性变
power_supply_changed(info->psy);
// 恢复硬件状
custom_fchg_dpdm_set(false);
custom_dcp_switch_en(info, true);
}
break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
dev_info(info->dev, "[debug] custom_fchg set voltage_max: %d uV\n", val->intval);
// 判断传入的电压是否与输出的POWER_SUPPLY_PROP_VOLTAGE_MAX相同
if (val->intval == 7500000) { // 7.5V
dev_info(info->dev, "[debug] custom_fchg voltage_max matches, starting fast charge enable");
// 取消之前的使能工
cancel_delayed_work_sync(&info->enable_work);
// 延时2秒后开始快充使
info->is_detecting = true;
schedule_delayed_work(&info->enable_work, msecs_to_jiffies(2000));
} else {
dev_info(info->dev, "[debug] custom_fchg voltage_max not match, disabling fast charge");
// 电压不匹配,停止快充
cancel_delayed_work_sync(&info->enable_work);
info->is_detecting = false;
info->is_fast_charge = false;
// 通知Power Supply属性变
power_supply_changed(info->psy);
// 恢复硬件状
custom_fchg_dpdm_set(false);
custom_dcp_switch_en(info, true);
}
break;
}
return 0;
}
函数逻辑分析
-
ONLINE属性处
ONLINE=1:启动检测工作,延时2秒执行,避免与BC1.2检测冲ONLINE=0:立即停止所有工作,恢复到DCP模式- 使用
cancel_delayed_work_sync确保工作队列不会重复执行
-
VOLTAGE_MAX属性处
- 只有电压.5V时才启用快充,其他电压值都会禁用快
- 延时2秒执行使能工作,给检测工作足够的时间完成
- 通过电压值作为启用快充的触发条件
-
状态管理
is_detecting标志防止重复执行检使能工作is_fast_charge标志表示快充是否已启- 通过
power_supply_changed通知属性变
5.2.2 属性获取函数分析
static int custom_get_prop(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
struct custom_18w_info *info = power_supply_get_drvdata(psy);
switch (psp) {
case POWER_SUPPLY_PROP_ONLINE:
val->intval = info->is_fast_charge ? 1 : 0;
dev_info(info->dev, "[debug] custom_fchg is_fast_charge: %d\n", val->intval);
break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
val->intval = 7500000; // 7.5V
break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
val->intval = 2400000; // 2.4A
break;
case POWER_SUPPLY_PROP_CHARGE_TYPE:
val->intval = info->is_fast_charge_susport ? POWER_SUPPLY_CHARGE_TYPE_FAST : POWER_SUPPLY_CHARGE_TYPE_NONE;
dev_info(info->dev, "[debug] custom_fchg is_fast_charge_susport: %d\n", val->intval);
break;
}
return 0;
}
*函数逻辑分析
- ONLINE属性:返回当前快充是否启用的状
- VOLTAGE_MAX属性:固定返7500000,表示支持的最大电压为7.5V
- CURRENT_MAX属性:固定返2400000,表示支持的最大电2.4A
- CHARGE_TYPE属性:根据是否支持快充返回相应的充电类型
5.2.3 属性可写性检查函数分析
static int custom_prop_writeable(struct power_supply *psy,
enum power_supply_property psp)
{
return (psp == POWER_SUPPLY_PROP_ONLINE || psp == POWER_SUPPLY_PROP_VOLTAGE_MAX);
}
函数逻辑分析
- 只有
ONLINE和VOLTAGE_MAX属性是可写 - 其他属性(
CURRENT_MAX、CHARGE_TYPE)是只读 - 这确保了外部只能通过特定属性来控制快充行为
5.3 驱动初始化流程分
5.3.1 Probe函数详细分析
static int custom_18w_probe(struct platform_device *pdev)
{
struct custom_18w_info *info;
struct device_node *sys_np;
struct power_supply_config cfg = {};
struct platform_device *regmap_pdev;
int ret;
// 步骤1:分配内存并初始化基本信
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
info->dev = &pdev->dev;
info->det_offset = CUSTOM_CHARGER_DET_OFFSET;
info->is_detecting = false;
info->is_fast_charge = false;
// 步骤2:初始化工作队列
INIT_DELAYED_WORK(&info->detect_work, custom_18w_detect_only_work);
INIT_DELAYED_WORK(&info->enable_work, custom_18w_enable_work);
// 步骤3:查找syscon节点
sys_np = of_find_compatible_node(NULL, NULL, "sprd,sc27xx-syscon");
if (!sys_np)
return -ENODEV;
// 步骤4:判断芯片类型并设置offset
if (of_device_is_compatible(sys_np->parent, "sprd,sc2730"))
info->det_offset = CUSTOM_CHARGER_DETECT_MASK_SC2730;
else if (of_device_is_compatible(sys_np->parent, "sprd,sc2721"))
info->det_offset = CUSTOM_CHARGER_DETECT_MASK_SC2721;
else {
of_node_put(sys_np);
return -ENODEV;
}
// 步骤5:获取regmap
regmap_pdev = of_find_device_by_node(sys_np);
of_node_put(sys_np);
info->pmic = dev_get_regmap(regmap_pdev->dev.parent, NULL);
if (IS_ERR(info->pmic)) {
dev_err(info->dev, "failed to get regmap (%ld)\n", PTR_ERR(info->pmic));
return PTR_ERR(info->pmic);
}
// 步骤6:注册Power Supply
cfg.drv_data = info;
info->psy = devm_power_supply_register(&pdev->dev, &custom_desc, &cfg);
if (IS_ERR(info->psy)) {
dev_err(info->dev, "failed to register power supply (%ld)\n", PTR_ERR(info->psy));
return PTR_ERR(info->psy);
}
// 步骤7:注册到sprd_fchg_extcon系统
info->fchg_info = sprd_fchg_info_register(&pdev->dev);
if (IS_ERR(info->fchg_info)) {
dev_err(info->dev, "failed to register with sprd_fchg_extcon\n");
return PTR_ERR(info->fchg_info);
}
// 步骤8:初始化sprd_fchg_extcon
ret = info->fchg_info->ops->extcon_init(info->fchg_info, info->psy);
if (ret) {
dev_err(info->dev, "failed to init sprd_fchg_extcon\n");
if (info->fchg_info) {
info->fchg_info->ops->remove(info->fchg_info);
}
return ret;
}
platform_set_drvdata(pdev, info);
dev_info(info->dev, "%s: probe OK, integrated customized_fchg_psy\n", __func__);
return 0;
}
函数逻辑分析
- 内存分配:使用
devm_kzalloc分配内存,自动管理生命周 - 工作队列初始化:初始化检测和使能两个工作队列
- 设备树解:查找syscon节点并判断芯片类
- 寄存器映射:获取PMIC的regmap用于寄存器操作DP/DM切换
- Power Supply注册:注册到Linux Power Supply子系统
- 系统集成:注册到sprd_fchg_extcon系统,实现与现有快充框架的集成
- 错误处理:每个步骤都有完善的错误处理和资源清理
5.3.2 设备树匹配分析
static const struct of_device_id custom_18w_of_match[] = {
{ .compatible = "sprd,customized-fchg-psy" },
{ }
};
设备树配置示例:
custom_18w_max_fchg: custom_18w_max_fchg {
compatible = "sprd,customized-fchg-psy";
phys = <&hsphy>;
extcon = <&pmic_typec>, <&pmic_pd>;
};
5.4 驱动清理流程分析
static int custom_18w_remove(struct platform_device *pdev)
{
struct custom_18w_info *info = platform_get_drvdata(pdev);
// 取消工作队列
cancel_delayed_work_sync(&info->detect_work);
cancel_delayed_work_sync(&info->enable_work);
// 停止检
custom_fchg_dpdm_set(false);
custom_dcp_switch_en(info, true);
// 清理sprd_fchg_extcon
if (info->fchg_info) {
info->fchg_info->ops->remove(info->fchg_info);
}
dev_info(info->dev, "%s: removed\n", __func__);
return 0;
}
函数逻辑分析
- 工作队列清理:取消所有待执行的工作队
- 硬件状态恢:恢复到DCP模式,停止快充
- 系统集成清理:从sprd_fchg_extcon系统中注销
- 资源释放:由于使用了
devm_*函数,资源会自动释放
6. 自定义psy_customized_fchg快充方案推荐(AI给的建议)
6.1 方案架构设计
6.2 实现步骤
步骤1:创建驱动框
// 1. 定义设备树兼容
static const struct of_device_id custom_fchg_of_match[] = {
{ .compatible = "vendor,custom-fchg-psy" },
{ }
};
// 2. 定义Power Supply属
static enum power_supply_property custom_fchg_props[] = {
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_CHARGE_TYPE,
};
// 3. 定义Power Supply描述
static const struct power_supply_desc custom_fchg_desc = {
.name = "custom_fchg",
.type = POWER_SUPPLY_TYPE_UNKNOWN,
.properties = custom_fchg_props,
.num_properties = ARRAY_SIZE(custom_fchg_props),
.get_property = custom_fchg_get_prop,
.set_property = custom_fchg_set_prop,
.property_is_writeable = custom_fchg_prop_writeable,
};
步骤2:实现硬件控制接口
// 硬件控制函数
static int custom_fchg_hw_init(struct custom_fchg_info *info)
{
// 初始化硬件寄存器
// 设置默认参数
// 配置中断
}
static int custom_fchg_set_dpdm(struct custom_fchg_info *info, bool enable)
{
if (enable) {
// 设置DP=3.3V, DM=0V进行快充握手
regmap_update_bits(info->pmic, info->dpdm_reg,
DP_MASK | DM_MASK,
DP_3V3 | DM_0V);
} else {
// 恢复DCP模式
regmap_update_bits(info->pmic, info->dpdm_reg,
DP_MASK | DM_MASK,
DP_HIZ | DM_HIZ);
}
}
static int custom_fchg_detect_protocol(struct custom_fchg_info *info)
{
// 实现协议检测逻辑
// 检查电压、电流变化
// 判断是否支持快充
}
步骤3:实现Power Supply接口
static int custom_fchg_set_prop(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
{
struct custom_fchg_info *info = power_supply_get_drvdata(psy);
switch (psp) {
case POWER_SUPPLY_PROP_ONLINE:
if (val->intval == 1) {
// 启动快充检
schedule_delayed_work(&info->detect_work,
msecs_to_jiffies(2000));
} else {
// 停止快充
cancel_delayed_work_sync(&info->detect_work);
custom_fchg_set_dpdm(info, false);
info->is_fast_charge = false;
}
break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
if (val->intval == 9000000) { // 9V
// 启用快充
schedule_delayed_work(&info->enable_work,
msecs_to_jiffies(2000));
} else {
// 禁用快充
cancel_delayed_work_sync(&info->enable_work);
custom_fchg_set_dpdm(info, false);
info->is_fast_charge = false;
}
break;
}
return 0;
}
步骤4:集成到sprd_fchg_extcon系统
static int custom_fchg_probe(struct platform_device *pdev)
{
// 1. 注册Power Supply
info->psy = devm_power_supply_register(&pdev->dev,
&custom_fchg_desc, &cfg);
// 2. 注册到sprd_fchg_extcon系统
info->fchg_info = sprd_fchg_info_register(&pdev->dev);
// 3. 初始化sprd_fchg_extcon
ret = info->fchg_info->ops->extcon_init(info->fchg_info, info->psy);
// 4. 初始化工作队
INIT_DELAYED_WORK(&info->detect_work, custom_fchg_detect_work);
INIT_DELAYED_WORK(&info->enable_work, custom_fchg_enable_work);
}
6.3 设备树配置示
custom_fchg: custom-fchg {
compatible = "vendor,custom-fchg-psy";
reg = <0x1b9c 0x4>;
interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "fchg";
// 硬件相关配置
dpdm-reg = <0x1b9c>;
voltage-reg = <0x1ba0>;
current-reg = <0x1ba4>;
// 快充参数
fchg-voltage-max = <9000000>; // 9V
fchg-current-max = <2000000>; // 2A
fchg-power-max = <18000000>; // 18W
// 检测参
detect-delay-ms = <2000>;
enable-delay-ms = <2000>;
voltage-threshold = <7000000>; // 7V
};
6.4 测试和验
测试用例
-
基本功能测试
- Power Supply属性读
- 硬件控制接口
- 协议检测功
-
集成测试
- 与sprd_fchg_extcon集成
- 与charger-manager交互
- 事件通知机制
-
异常处理测试
- 硬件错误处理
- 超时处理
- 回退机制
调试方法
// 添加调试日志
#define DEBUG_CUSTOM_FCHG 1
#if DEBUG_CUSTOM_FCHG
#define custom_fchg_dbg(fmt, ...) \
dev_info(info->dev, "[custom_fchg] " fmt, ##__VA_ARGS__)
#else
#define custom_fchg_dbg(fmt, ...)
#endif
// 状态监
static void custom_fchg_monitor_status(struct custom_fchg_info *info)
{
custom_fchg_dbg("Status: online=%d, fchg=%d, voltage=%d, current=%d",
info->is_online, info->is_fast_charge,
info->voltage, info->current);
}
7. 方案问题与限制分析(AI给的修改建议)
7.1 技术问题
7.1.1 协议兼容性问题
问题描述:
- CUSTOM 18W协议是专有协议,与标准快充协议(QC、PD、SFCP)不兼容
- 充电器必须支持CUSTOM协议才能实现18W快充,通用性较差
影响分析:
// 在custom_fchg_dpdm_set函数中的兼容性检查
if (ret == 0 && vbus > 7000000) { // 7V阈值
voltage_ok = true;
break;
} else {
// 不支持CUSTOM协议的充电器无法触发快充
dev_err(cm_public->dev, "[debug] custom_fchg: voltage check failed\n");
ret = -EINVAL;
}
解决方案:
- 实现多协议检测机制,优先检测标准协议
- 提供协议降级机制,不支持CUSTOM时回退到DCP模式
7.1.2 时序控制问题
问题描述:
- DP/DM电平切换时序要求严格,时序错误会导致协议握手失败
- 硬件响应时间不确定,可能导致检测失败
代码分析:
// 在sd76930_charger_set_custom_chg中的时序控制
msleep(10); // 等待10ms - 固定延时可能不够精确
reg_val = SD76930_REG_DPVOL_3V3 | SD76930_REG_DMVOL_0V;
ret = sd76930_update_bits(info, SD76930_REG_4,
SD76930_REG_DPVOL_MASK | SD76930_REG_DMVOL_MASK,
reg_val);
msleep(10); // 再次等待10ms
潜在问题:
- 固定延时可能在某些硬件上不够或过多
- 没有动态调整机制
- 时序错误可能导致充电器无法正确识别协议
7.1.3 电压检测可靠性问题
问题描述:
- 电压检测只进行3次,可能因为瞬时干扰导致误判
- 7V阈值固定,没有考虑充电器电压波动
代码分析:
// 在custom_fchg_dpdm_set中的电压检测
for (j = 0; j < 3; j++) {
msleep(600); // 等待600ms
ret = get_charger_voltage(cm_public, &vbus);
if (ret == 0 && vbus > 7000000) { // 7V阈值
voltage_ok = true;
break;
}
}
改进建议:
- 增加检测次数和容错机制
- 实现动态阈值调整
- 添加电压稳定性检查
7.2 系统集成问题
7.2.1 工作队列管理问题
问题描述:
- 检测和使能工作队列可能存在竞态条件
- 延时工作队列在系统休眠时可能被延迟执行
代码分析:
// 在custom_set_prop中的工作队列管理
if (val->intval == 1) {
cancel_delayed_work_sync(&info->detect_work);
info->is_detecting = true;
schedule_delayed_work(&info->detect_work, msecs_to_jiffies(2000));
}
潜在问题:
is_detecting标志可能被多个工作队列同时修改- 2秒延时在系统负载高时可能不够
- 没有考虑系统休眠/唤醒对工作队列的影响
7.2.2 状态同步问题
问题描述:
- Power Supply属性状态与实际硬件状态可能不同步
- 多个模块同时修改状态可能导致不一致
代码分析:
// 状态管理分散在多个函数中
info->is_fast_charge = true; // 在enable_work中设置
info->is_fast_charge_susport = true; // 在detect_work中设置
power_supply_changed(info->psy); // 通知属性变化
改进建议:
- 实现统一的状态管理机制
- 添加状态一致性检查
- 使用原子操作保护状态变量
7.3 硬件限制问题
7.3.1 寄存器操作风险
问题描述:
- 直接操作PMIC寄存器可能影响其他功能
- 寄存器位操作错误可能导致系统不稳定
代码分析:
// 在custom_dcp_switch_en中的寄存器操作
ret = regmap_update_bits(info->pmic, info->det_offset,
BIT_DP_DM_BC_ENB_MASK,
enable << BIT_DP_DM_BC_ENB_SHIFT);
风险分析:
- 如果
det_offset错误,可能操作错误的寄存器 - 位操作可能影响其他功能模块
- 没有寄存器操作的互斥保护
7.3.2 电流限制问题
问题描述:
- 检测期间将电流限制为500mA,可能影响充电效率
- 没有考虑电池电量对电流限制的影响
代码分析:
// 在custom_fchg_dpdm_set中的电流限制
if (back_limit_cur > 500000) {
val.intval = 500000; // 固定500mA
ret = power_supply_set_property(psy, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val);
}
7.4 调试和维护问题
7.4.1 调试信息不足
问题描述:
- 调试信息分散,难以追踪完整的执行流程
- 缺少性能监控和统计信息
当前调试信息:
dev_info(info->dev, "[debug] custom_fchg Starting 18W fast charge detection only");
dev_info(info->dev, "[debug] custom_fchg 18W fast charge detection successful");
改进建议:
- 添加执行时间统计
- 实现状态机日志
- 提供性能指标监控
7.4.2 错误处理不完善
问题描述:
- 某些错误情况下没有完整的恢复机制
- 错误码不够详细,难以定位问题
代码分析:
if (ret) {
dev_err(info->dev, "Failed to disable DCP mode: %d\n", ret);
return; // 直接返回,没有清理已分配的资源
}
7.5 性能问题
7.5.1 检测延迟问题
问题描述:
- 检测过程需要多次延时,总耗时较长
- 2秒的检测延时可能影响用户体验
时间分析:
检测总时间 = 2秒(启动延时) + 3×600ms(电压检测) + 硬件响应时间
≈ 3.8秒 + 硬件响应时间
7.5.2 功耗问题
问题描述:
- 检测期间需要维持DP=3.3V电平,增加功耗
- 频繁的寄存器操作可能影响系统功耗
7.6 改进建议
7.6.1 技术改进
-
增强协议兼容性
// 建议实现多协议检测 static int detect_fast_charge_protocol(struct custom_18w_info *info) { // 1. 检测QC协议 if (detect_qc_protocol(info) == 0) return QC_PROTOCOL; // 2. 检测PD协议 if (detect_pd_protocol(info) == 0) return PD_PROTOCOL; // 3. 检测CUSTOM协议 if (detect_custom_protocol(info) == 0) return CUSTOM_PROTOCOL; return NO_PROTOCOL; } -
优化时序控制
// 建议实现动态时序调整 static int set_dpdm_with_retry(struct custom_18w_info *info, bool enable) { int retry_count = 0; int max_retries = 5; while (retry_count < max_retries) { ret = set_dpdm_levels(info, enable); if (ret == 0) break; msleep(10 * (retry_count + 1)); // 递增延时 retry_count++; } return ret; } -
增强状态管理
// 建议使用状态机管理 enum fchg_state { FCHG_STATE_IDLE, FCHG_STATE_DETECTING, FCHG_STATE_ENABLING, FCHG_STATE_ACTIVE, FCHG_STATE_ERROR }; static void fchg_state_machine(struct custom_18w_info *info, enum fchg_event event) { // 状态机逻辑 }
7.6.2 系统改进
-
添加配置选项
// 建议添加可配置参数 struct custom_18w_config { u32 detect_delay_ms; u32 voltage_threshold_uv; u32 max_retry_count; bool enable_debug; }; -
增强错误处理
// 建议实现完整的错误恢复 static int custom_fchg_error_recovery(struct custom_18w_info *info) { // 1. 停止所有工作队列 // 2. 恢复硬件状态 // 3. 重置软件状态 // 4. 记录错误信息 // 5. 通知上层系统 } -
添加性能监控
// 建议添加性能统计 struct custom_18w_stats { u32 detect_count; u32 success_count; u32 fail_count; u32 total_detect_time_ms; u32 avg_detect_time_ms; };
7.7 问题总结
CUSTOM 18W快充方案虽然实现了基本的快充功能,但在协议兼容性、时序控制、状态管理、错误处理等方面还存在一些问题。通过上述分析和改进建议,可以显著提升方案的稳定性、可靠性和用户体验。
关键改进点:
- 增强协议兼容性和降级机制
- 优化时序控制和重试机制
- 完善状态管理和错误处理
- 添加性能监控和调试支持
- 提高代码的可维护性和可扩展性
这些改进将使快充方案更加健壮和实用。
8. 总结
7.1 关键要点
- 模块化设:将快充功能分解为检测、使能、控制等独立模块
- 状态管理:使用工作队列管理异步操作,避免阻塞
- 错误处理:实现完善的回退机制和错误恢
- 系统集成:通过sprd_fchg_extcon与现有系统无缝集
7.2 最佳实现
- 硬件抽象:将硬件相关操作封装为独立接
- 状态同步:确保Power Supply状态与实际硬件状态
- 资源管理:正确管理内存、中断、工作队列等资源
- 调试支持:提供充分的调试信息和状态监
7.3 扩展性考虑
- 协议支持:可以轻松添加新的快充协
- 硬件适配:通过设备树配置适配不同硬件
- 参数调整:支持运行时参数调整和优
- 性能监控:提供性能指标和统计信
更多推荐



所有评论(0)