MTK Linux Charger驱动分析(二) - power_supply_core.c

Linux内核中电源供应类(Power Supply Class)的核心实现,文件名power_supply_core.c。它提供了一个通用的框架,用于管理各种电源供应设备,如电池、充电器、AC电源等。该类允许驱动程序注册电源供应设备,并通过sysfs接口暴露属性(如电压、电流、容量等),便于用户空间程序监控和控制电源状态。

文件的主要功能包括:

  • 电源供应设备的注册和注销:允许驱动注册电源供应,并处理依赖关系(如一个电源是否由另一个供应)。
  • 属性管理:通过power_supply_desc结构定义电源的属性,并提供获取/设置属性的接口。
  • 事件通知:使用通知链(notifier)和工作队列处理电源变化事件。
  • 设备树支持(在CONFIG_OF启用时):从设备树中解析电源供应关系和电池信息。
  • 热管理和冷却设备集成(在CONFIG_THERMAL启用时):与热管理系统集成,允许监控温度并调整充电限值。
  • 电池信息解析:从设备树中提取电池参数,如容量、电压阈值、OCV(开路电压)表格等。
  • 辅助函数:如检查电源供应关系、计算电阻或容量等。

文件使用模块化设计,导出符号供其他内核模块使用(如驱动程序)。它支持延迟注册以避免探针函数中的竞争条件,并处理电源间的依赖(如供应商-消费者关系)。

文件分为几个部分:

  • 全局变量和结构定义。
  • 电源变化处理函数。
  • 延迟注册工作。
  • 设备树相关函数(条件编译)。
  • 供应关系检查和查询函数。
  • 属性设置和获取函数。
  • 引用计数管理(get/put)。
  • 电池信息处理函数。
  • 热管理和冷却函数(条件编译)。
  • 注册/注销核心函数。
  • 模块初始化/退出。

下面,我将按文件中的出现顺序,逐个函数进行详细说明。每个函数的说明包括:

  • 函数签名:参数和返回值。
  • 目的:函数的作用。
  • 详细说明:内部逻辑、关键点、潜在问题。
  • 使用场景:何时调用。

为了清晰,我使用表格列出所有函数及其简要描述,然后逐一展开细节。

函数列表表格
函数名 简要描述
__power_supply_is_supplied_by 检查一个电源是否由另一个电源供应,支持supplied_to和supplied_from模式。
__power_supply_changed_work 处理电源变化时通知依赖的电源。
power_supply_changed_work 工作队列函数,处理电源变化事件,包括通知和更新。
power_supply_changed 标记电源变化并调度工作队列。
power_supply_deferred_register_work 延迟注册工作,等待父设备探针完成后再触发变化事件和冷却注册。
__power_supply_populate_supplied_from 从设备树填充supplied_from列表(CONFIG_OF)。
power_supply_populate_supplied_from 遍历所有电源填充supplied_from(CONFIG_OF)。
__power_supply_find_supply_from_node 检查设备节点是否匹配电源的of_node(CONFIG_OF)。
power_supply_find_supply_from_node 在类中查找匹配设备节点的电源(CONFIG_OF)。
power_supply_check_supplies 检查并填充电源的供应列表,从设备树或属性读取。
__power_supply_am_i_supplied 检查电源是否被另一个电源供应并在线(辅助函数)。
power_supply_am_i_supplied 检查电源是否有在线供应商。
__power_supply_is_system_supplied 检查非电池电源是否在线(辅助函数)。
power_supply_is_system_supplied 检查系统是否有在线电源(非电池)。
__power_supply_get_supplier_max_current 获取供应商的最大电流(辅助函数)。
power_supply_set_input_current_limit_from_supplier 从供应商设置输入电流限制。
power_supply_set_battery_charged 设置电池为已充满(仅电池类型)。
power_supply_match_device_by_name 匹配电源名称的设备(辅助函数)。
power_supply_get_by_name 通过名称获取电源引用。
power_supply_put 释放电源引用。
power_supply_match_device_node 匹配设备节点的电源(CONFIG_OF,辅助函数)。
power_supply_get_by_phandle 通过phandle获取电源引用(CONFIG_OF)。
power_supply_match_device_node_array 匹配多个设备节点的电源(CONFIG_OF,辅助函数)。
power_supply_get_by_phandle_array 通过phandle数组获取多个电源引用(CONFIG_OF)。
devm_power_supply_put 设备管理释放电源引用(CONFIG_OF)。
devm_power_supply_get_by_phandle 设备管理的phandle获取电源(CONFIG_OF)。
power_supply_get_battery_info 从设备树解析电池信息。
power_supply_put_battery_info 释放电池信息分配的内存。
power_supply_temp2resist_simple 根据温度查找电池内部电阻百分比。
power_supply_ocv2cap_simple 根据OCV查找电池容量。
power_supply_find_ocv2cap_table 查找最匹配温度的OCV表格。
power_supply_batinfo_ocv2cap 使用电池信息计算OCV到容量的映射。
power_supply_get_property 获取电源属性值。
power_supply_set_property 设置电源属性值。
power_supply_property_is_writeable 检查属性是否可写。
power_supply_external_power_changed 通知外部电源变化。
power_supply_powers 在sysfs中创建"powers"链接。
power_supply_dev_release 释放电源设备内存。
power_supply_reg_notifier 注册电源通知器。
power_supply_unreg_notifier 注销电源通知器。
power_supply_read_temp 读取温度(CONFIG_THERMAL)。
psy_register_thermal 注册热区设备(CONFIG_THERMAL)。
psy_unregister_thermal 注销热区设备(CONFIG_THERMAL)。
ps_get_max_charge_cntl_limit 获取最大充电控制限值(CONFIG_THERMAL)。
ps_get_cur_charge_cntl_limit 获取当前充电控制限值(CONFIG_THERMAL)。
ps_set_cur_charge_cntl_limit 设置当前充电控制限值(CONFIG_THERMAL)。
psy_register_cooler 注册冷却设备(CONFIG_THERMAL)。
psy_unregister_cooler 注销冷却设备(CONFIG_THERMAL)。
__power_supply_register 内部注册电源供应。
power_supply_register</
<think>好的,我现在需要帮用户解决MTK PD充电中的ALG_NOT_READY问题,同时解释POWER_SUPPLY_PROP_CAPACITY的相关疑问。首先,回顾之前的对话,用户之前已经询问过ALG_NOT_READY的问题,并且我给出了原因和解决方案,现在用户可能遇到了更深层次的问题,或者之前的解决方案没有完全解决问题。 首先,用户提到参考的引用内容,其中引用[1]是关于电池容量级别的枚举,引用[2]说明了MTK PD如何获取充电IC状态和电池信息,引用[3]是电源供应子系统的初始化代码。用户现在想结合这些信息,解决ALG_NOT_READY和POWER_SUPPLY_PROP_CAPACITY的问题。 对于ALG_NOT_READY问题,之前已经分析过可能的原因,比如初始化失败、电流配置异常、PD协议握手失败。用户现在可能需要更详细的排查步骤,或者想了解如何结合电源供应子系统的信息来诊断问题。引用[2]提到MTK PD从mtk_pd_hal.c获取充电IC状态,这可能涉及到充电IC是否支持PD协议,电压电流配置是否正确。如果充电IC不支持PD,或者配置不正确,可能导致ALG_NOT_READY错误。 另外,用户提到的POWER_SUPPLY_PROP_CAPACITY是电源供应子系统中的一个属性,表示电池容量百分比。引用[1]中的枚举可能用于表示不同的容量级别,比如低电量、正常、充满等。用户可能遇到电池容量检测不准确的问题,或者想知道这个属性如何影响充电过程。例如,如果系统检测到电池容量处于CRITICAL级别,可能会限制充电电流,导致充电算法无法就绪。 接下来,我需要将这些问题结合起来。ALG_NOT_READY可能与充电IC的状态获取有关,而POWER_SUPPLY_PROP_CAPACITY的准确性可能影响充电算法的判断。例如,如果电池温度不在正常范围内(根据状态机S_ready的条件),充电算法可能无法启动,导致ALG_NOT_READY。同时,如果电源供应子系统未能正确报告电池容量或状态,充电管理模块可能无法进行正确的决策。 需要检查的几个方面: 1. 充电IC的初始化是否正确,包括设备树中的配置,确保充电IC被正确识别,回调函数绑定正确。 2. PD协议握手过程中,充电器是否支持所需的电压和电流,这涉及到引用[2]中提到的充电IC状态获取。 3. 电池信息的准确性,包括容量、温度、电压等,这些信息通过POWER_SUPPLY_PROP_CAPACITY和其他属性上报,如果这些数据异常,可能导致充电算法无法就绪。 4. 电源供应子系统的初始化是否正确,引用[3]中的代码显示电源供应子系统的初始化过程,如果这部分有问题,可能导致电池信息无法正确传递到充电管理模块。 可能的解决方案包括: -驱动代码中添加更多的调试信息,检查充电IC是否被正确识别,回调函数是否被调用。 - 使用工具抓取PD协议交互数据,确认充电器是否响应正确的电压电流请求。 - 检查电池驱动的实现,确保POWER_SUPPLY_PROP_CAPACITY等属性正确更新,特别是温度、电压和电流的检测。 - 确认设备树中充电IC的配置,尤其是多个充电IC时的优先级设置,确保PD充电IC被正确选择。 此外,用户可能需要具体的代码示例或调试命令,比如如何通过sysfs查看电池属性,如何抓取PD协议日志,或者如何在驱动中添加调试打印。结合用户提供的引用内容,特别是引用[3]中的初始化代码,可能需要检查电源供应子系统的注册和属性初始化是否正确,确保电池信息能够被充电管理模块正确获取。 最后,需要验证充电状态机的条件是否满足,比如总线电压、充电电流、电池温度是否在允许范围内,这些条件不满足也会导致ALG_NOT_READY错误。用户可能需要检查硬件电路,比如Type-C接口的CC引脚电阻配置是否正确,或者软件中的温度阈值设置是否合理。 总结来说,解决ALG_NOT_READY问题需要从充电IC初始化、PD协议交互、电池信息准确性以及电源供应子系统的正确配置多个方面进行排查,同时结合POWER_SUPPLY_PROP_CAPACITY的解释,确保系统能够正确获取和处理电池状态信息。</think>#### MTK PD充电ALG_NOT_READY问题深度解决方案 --- ### 一、ALG_NOT_READY问题核心排查 1. **充电IC状态验证(结合引用[2])** - 检查充电IC是否支持PD协议: ```c // 在mtk_pd_hal.c中添加调试代码 if (!chg_ic->support_pd) { pr_err("PD_NOT_SUPPORTED: IC=%s", chg_ic->name); // 输出具体充电IC型号 } ``` - 通过设备树确认PD充电IC优先级: ```dts charger: charger@6a { compatible = "mediatek,mt6360-charger"; reg = <0x6a>; mt,charger-name = "primary_chg"; // 必须标记为primary }; ``` 2. **协议栈交互分析** - 使用MTK PD调试工具抓取协议交互: ```shell adb shell "echo 1 > /sys/class/power_supply/usb/pd_dbg_dump" # 启用PD协议调试 dmesg | grep "PD_NEGO" # 查看电压/电流协商记录 ``` - 典型错误日志模式: ``` [ 123.456] PD_ERR: Request 9V/2A rejected (SVID:0xFF00) [ 123.457] PD_ALG: ALG_NOT_READY: Unsupported PDO ``` --- ### POWER_SUPPLY_PROP_CAPACITY详解(结合引用[1]) 1. **容量属性与充电状态机关联** $$ C_{bat} = \frac{Q_{now}}{Q_{full}} \times 100\% $$ - 系统通过以下逻辑限制充电: ```c if (capacity_level == POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL) { limit_charge_current(500mA); // 低电量保护模式 } ``` 2. **关键代码路径分析(引用[3])** - 属性注册流程: ```c // power_supply_core.c static struct power_supply_attr power_supply_attrs[] = { POWER_SUPPLY_ATTR(capacity), // 对应/sys/class/power_supply/*/capacity POWER_SUPPLY_ATTR(temp), // 温度检测 POWER_SUPPLY_ATTR(voltage_now), // 实时电压 }; ``` - 电池驱动实现示例: ```c static int battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { switch (psp) { case POWER_SUPPLY_PROP_CAPACITY: val->intval = calculate_battery_capacity(); // 调用电量计算法 break; } return 0; } ``` --- ### 三、复合问题处理流程 1. **交叉验证步骤** | 检测项 | 命令/方法 | 预期结果 | |------------------------|-----------------------------------|------------------------------| | 充电IC状态 | `cat /sys/class/power_supply/*/type` | 显示"USB_PD"或"PD" | | 电池容量准确性 | `cat /sys/class/power_supply/battery/capacity` | 与实际电量误差≤3% | | 温度检测 | `cat /sys/class/power_supply/battery/temp` | 15℃~45℃ | 2. **驱动层增强调试(示例)** ```c // 在充电算法中插入状态检查 if (alg_state == ALG_NOT_READY) { pr_info("DEBUG: chg1_dev=%p, do_algorithm=%pf, temp=%d", info->chg1_dev, info->do_algorithm, battery_temp); dump_stack(); // 输出调用栈 } ``` --- ### 四、硬件协同排查 1. **Type-C接口参数要求** | CC引脚配置 | 电阻值 | 对应模式 | |------------|-----------|----------------| | Rd | 5.1kΩ | UFP(设备端) | | Rp | 56kΩ | DFP(主机端) | - 测量方法: $$ R_{CC} = \frac{V_{pullup} - V_{measured}}{I_{test}} $$ 2. **典型故障场景** - **案例1**:CC引脚虚焊导致Rp电阻异常 现象:PD协议反复触发`ALG_NOT_READY` 修复:补焊Type-C连接器后恢复 - **案例2**:电量计校准错误 现象:`POWER_SUPPLY_PROP_CAPACITY`显示100%但实际未充满 修复:执行`echo 1 > /sys/class/power_supply/battery/reset`重置电量计 --- ### 五、进阶工具使用 1. **MTK PACT工具协议分析** ```python # 连接设备抓取实时PD报文 from mtk_pd_tools import PDMonitor mon = PDMonitor(port="/dev/ttyUSB1", baudrate=115200) mon.start_capture(filter_types=["PD_CTRL_GOOD_CRC", "PD_DATA_SOURCE_CAP"]) ``` 2. **电池系统事件跟踪** ```shell # 使用ftrace抓取电源事件 echo 1 > /sys/kernel/debug/tracing/events/power/enable cat /sys/kernel/debug/tracing/trace_pipe | grep "battery_status" ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值