
做了这么多年嵌入式开发和充电协议调试Type-C充电这块水有多深我算是踩了个遍。MTK6769这个平台在联发科的产品线里定位中端搭载它的设备往往主打性价比但恰恰是这类平台在量产项目里跑量最大、出的问题也最杂。这篇文章我把MTK6769平台Type-C充电的完整链路给你拆开讲透从硬件管脚怎么设计到PD协议握手怎么调试再到Android 15环境下软件栈怎么适配一次性说清楚。这篇文章不是什么产品发布会通稿是基于我实际调板子、抓总线、修bug过程中的一手经验。无论你是做驱动开发的、搞硬件设计的还是负责整机充电测试的只要跟Type-C充电沾边这篇文章都能给你省不少排查时间。MTK6769作为一颗12nm中端芯片充电方案没有旗舰平台那么封闭反而适合用来把整套机制学明白。1. MTK6769平台Type-C充电整体方案拆解1.1 MTK6769的平台定位与充电方案选型MTK6769是联发科Helio G70/G80系列芯片的代号定位入门到中端的手机、平板以及部分IoT设备。这颗芯片本身不管充电充电功能依赖外部充电IC比如MT6360、BQ25601这类加上PMIC内部的充电控制逻辑再由系统侧的Type-C控制器配合完成整套流程。在MTK的参考设计里Type-C控制器通常集成在PMIC内部或者用一颗单独的CC逻辑芯片来实现。选这个平台讲Type-C充电有个很明显的好处控制链路清晰。不像旗舰平台把很多东西封装得特别深寄存器一层套一层MTK6769的充电链路相对开放适合把原理吃透。很多团队上来就调PD协议结果充电IC压根没被正确配置CC管脚的默认连接状态都不对那就是在错误的地基上盖楼。把MTK6769上这套逻辑搞明白再去看天玑系列的高端方案思路完全能平移过去。1.2 一条完整的充电链路长什么样从充电器插进去那一刻起电流要经过的路径是适配器、Type-C线缆、USB连接器、VBUS管脚、充电IC的VBUS输入、充电开关管最后到电池。与此同时控制信号走的是另一条路连接器的CC管脚、CC逻辑与Rd下拉检测、Type-C控制器识别插入方向、启用D/D-或SBU切换之后PD协议通过CC线收发控制报文协商完成电压和电流再由充电IC调整输出。理解这条链路的关键在于电源路径负责送电信号路径负责谈判。很多人排查充电问题时只盯着电压电流有没有进来忽略了CC管脚上其实一直在传消息这件事。而且在Type-C时代电源和信号在物理上是分离的两个路径可以独立工作也可以互相牵制——这也是很多疑难杂症产生的根源。1.3 为什么Type-C充电比Micro-USB复杂老USB时代充电器和设备之间的协商很简单D/D-识别的就是电阻分压或者有无短接。到了Type-C加PD协议时代三层问题叠加在一起第一层是物理连接层。CC1和CC2管脚要检测线缆方向正反插都要能用这直接决定了数据通路的D/D-要不要交叉交换。第二层是协议层。充电器要支持PD协议会通过CC线上的BMC编码信号跟设备交换能力。协议报文的编解码、时序、重传机制每一项都可能出问题。第三层是策略层。设备端软件要根据当前电池电压、温度、系统功耗制定充电诉求动态申请合适的电压和电流档位。这三层任何一个环节掉链子表现出的现象可能都一样——充电慢或者不充电。但排查路径完全不同所以必须从整体结构上去理解才能精准定位问题到底出在哪一层。2. 硬件管脚与电路设计实战2.1 管脚功能速查CC、VBUS、DP/DN都在干嘛MTK6769平台上典型的Type-C接口管脚分配如下管脚方向作用关键参数CC1/CC2双向插入检测、方向识别、PD协议通信Rp/Rd阻值决定电源角色与电流能力VBUS输入/输出主电源通路耐压需覆盖适配器最高输出电压DP/DN双向USB 2.0数据通信在无数据需求时可复用为充电协商通道SBU1/SBU2双向音频/视频等附件信号充电场景下一般不关心D/D-双向BC1.2充电握手兼容老式充电器时使用从电路设计角度讲CC管脚上的下拉电阻Rd阻值固定为5.1kΩ这个值是Type-C规范规定的。设备作为Sink受电方时CC1和CC2都要接5.1kΩ下拉到地。适配器作为Source供电方时内部会上拉一个Rp上拉阻值不同代表不同的默认电流能力56kΩ对应500mA22kΩ对应1.5A10kΩ对应3A。设计时要注意这个默认能力是设备未协商前的保底电流PD协商成功后才可能拿到更高的功率。2.2 方向检测与CC逻辑的实现Type-C能够正反插靠的就是CC管脚的设计。设备端两个CC管脚都有5.1kΩ下拉适配器端两个CC管脚都有Rp上拉。当线缆插入时其中一条CC路径上的Rp和Rd会导通形成分压另一端CC没有连接保持空闲。芯片通过检测哪一边CC有拉高电平来判断线缆方向然后决定是否对D/D-进行交叉交换。在MTK6769平台这个交叉交换通常由Type-C MUX芯片或者PMIC内部的逻辑完成。软件上一般会看到类似typec_dir这样的寄存器位1表示正插、0表示反插。如果方向检测错误数据功能肯定会异常但有意思的是充电不一定会中断——因为VBUS和GND在Type-C接口上是中心对称的正反插都不影响供电。这一点在调试时非常容易误导人数据全通但充电有问题不一定跟方向检测有关但如果数据时通时断优先查CC管脚和MUX配置。我见过好几个项目Type-C方向检测的寄存器配置被低级错误覆盖了导致数据功能间歇性异常最终都是靠CC管脚波形定位出来的。2.3 过压保护与VBUS通路设计Type-C接口的VBUS在支持PD后最高能到20V这给硬件设计提出了硬性要求。VBUS输入端的TVS管要选钳位电压大于适配器最高输出电压的型号充电路径上要有OVP过压保护芯片或者集成在充电IC内部的高压保护。我遇到过一类很典型的低级问题板子标称支持PD快充但VBUS的TVS钳位电压只按9V选结果拿65W充电器一插瞬间过压打坏IC。所以硬件选型时要确认PDO档位里最高的那个电压TVS的VRWM至少留出20%以上的裕量。充电IC本身的选择上MTK6769平台的参考设计里通常配MT6360原生方案支持开关电容充电和最高90W左右的有线快充能力。如果项目用的是第三方充电IC比如南芯、天德钰、立锜软件上需要修改充电驱动中的充电IC切换逻辑这部分工作量比想象中大尤其是充电路径上的Bypass/Pump模式切换容易踩坑。我在一个项目里就遇到过第三方充电IC和PMIC的VBUS通路冲突充电电流始终上不去最后发现是两套驱动都在抢占VBUS通路控制权。3. PD协议实战从握手到动态协商3.1 PD协议到底在传什么PD协议USB Power Delivery跑在CC线上物理层用的是BMC编码半双工通信。消息有两大类控制消息比如GoodCRC、Accept、Reject和数据消息承载具体能力信息的PDO/APDO和请求消息RDO。平时常说的握手本质上是完成以下几件事物理层接触到对端设备通过CC线上的BMC信号发送能力源描述Source Capabilities列出充电器支持的电压/电流档位设备端选择其中一档发送请求Request充电器确认Accept PS_RDY双方进入协商好的电压电流模式。MTK平台的实际实现中这部分逻辑一部分在充电IC固件里完成一部分在Linux内核的TCPMType-C Port Manager驱动里。TCPM负责维护PD的状态机充电IC固件负责执行具体的电源路径切换。如果调试时发现抓PD报文很干净但就是不升压问题往往出在两个驱动之间的状态同步上——典型的就是TCPM已经发出了请求但充电IC还没准备好接收高压导致保护触发。3.2 PDO与APDO一档一档说清楚PDOPower Data Object是充电器能够提供的原始能力列表常见的有PDO类型电压电流典型场景Fixed PDO5V3A基础档位默认Fixed PDO9V2A普通快充Fixed PDO12V1.5A更高功率PPS APDO3.3V~11V3A动态调压快充固定PDO是定死的电压档位PPS是可变电压档位。设备请求PPS档位后可以通过DPM直接电源管理消息在区间内精细调压调压步进一般是20mV。国产手机的高功率快充很多就是基于PPS实现的比如标称66W的充电器实际是5V~11V/6A的PPS档位在跑。MTK6769项目在调PPS时有个常见的注意点内核的PPS算法mtk_charger的pe5/pe4代码路径默认的调压策略可能和目标产品定义不一致。比如有些方案需要先按固定电压冲到一定SOC再转PPS有些方案则要求全程PPS这些策略需要在disable_power_path和enable_power_path的参数配合下做耐心测试。我调过的一个项目里PPS调压完成后充电电流纹波特别大最后发现是调压步进设置得太小导致系统在目标电压附近反复震荡。3.3 动态协商与异常恢复流程PD协议不是握手完就完事运行过程中可能随时发生异常温度过高、充电器过热、线缆压降过大等。规范里对应处理的机制包括Hard Reset双方重新回到5V初始状态重新协商PD Reset设备发起重新枚举PS_RDY消息表示电源已经稳定设备可以开始拉流GOTO_MIN要求设备降低到最低电压档位重新协商。调试过程中Hard Reset是最容易遇到的问题。日志里如果大量出现Hard_Reset标志通常说明上位协商过程不稳定——有可能是充电器兼容性问题也有可能是设备端TCPM驱动在处理Reject消息时没做正确降级导致一直用最高档位去请求被充电器拒绝后触发硬复位。遇到这种情况我的习惯是先降级排查把设备请求的最高电压限制到9V看Hard Reset是否减少。如果减少说明策略层OK是充电器高电压档位的兼容性问题如果没变化说明问题出在TCPM或协议栈重点查驱动补丁是否合到位。4. Android 15环境的软件栈适配要点4.1 Linux内核侧的Type-C与充电框架MTK6769在Android 15上走的依旧是标准Linux内核加MTK补丁的组合。Type-C部分涉及的关键驱动节点有typec框架负责设备注册和状态机对应/sys/class/typectcpmType-C Port Manager处理CC检测、角色切换和PD状态机TCPCI驱动针对集成在充电IC内部的Type-C控制器封装的统一接口驱动。MTK在Android 15的适配中把不少顶层策略放到了drivers/misc/mediatek/charger/和drivers/power/supply/里。调试时最常用的sysfs节点是/sys/class/power_supply/下面的各个供电设备比如/sys/class/power_supply/mtk-master-charger/里能看到type、online、voltage_now这些属性。查找顺序建议先看type是否识别为USB_PD或者USB再看voltage_max和voltage_now是否匹配最后看online是否为1。注意/sys/class/power_supply/usb/type这个节点很关键它直接告诉你系统识别到了什么类型的充电器。如果显示USB而不是USB_PD说明PD协商根本没有成功问题大概率在协议或者物理层。4.2 设备树DTS的充电节点配置MTK6769项目的设备树里充电相关节点通常集中在mt6769_battery_prop.dtsi和scp_charger.dtsi这类文件中。关键字段包括max_charger_voltage最大充电压用于限制请求档位min_charger_voltage最小请求电压ac_charger_currentAC适配器下的最大充电电流charging_host_charger_currentUSB数据线充电时的电流qos_charging_limit_current系统高负载下的充电限流值pe5相关配置表示是否启用PPS等新协议支持。在Android 15上由于充电管理从老的battery服务迁移到了charge_policy服务DTS中的一些参数解读方式已经改变。如果你从Android 13老项目移植直接把mt6769_battery_prop.dtsi拷过来经常会遇到充电电流上不去的问题原因就是新策略框架会重新解析限流参数老字段不再生效。必须对照chargerpolicy的节点逐一确认。4.3 adb调试与sysfs检查技巧软件调试点上掌握以下命令基本可以应付大多数问题# 查看所有电源设备及状态 adb shell cat /sys/class/power_supply/*/type adb shell cat /sys/class/power_supply/*/online adb shell cat /sys/class/power_supply/*/voltage_now adb shell cat /sys/class/power_supply/*/current_now # 查看当前使用的充电协议 adb shell cat /sys/class/power_supply/mtk-master-charger/type adb shell cat /sys/class/power_supply/usb/type # 查看PD协商结果 adb shell cat /sys/class/typec/port0/power_role adb shell cat /sys/class/typec/port0/data_role adb shell cat /sys/class/typec/port0/usb_power_delivery/current_capabilities # 查看电荷状态和充电模式 adb shell cat /sys/class/power_supply/battery/status adb shell cat /sys/class/power_supply/battery/charge_type # charge_type 常见值: N/A, Trickle, Fast, Standard一个比较隐蔽的坑是Android 15对sysfs访问权限收紧不少节点默认ownerrootadb shell以shell用户访问会被拒绝。此时用adb root提权后重挂载或者直接在内核驱动里临时加打印来定位。我遇到过节点存在但权限是600导致读取失败的情况直接chmod 644就能解决但要注意这个改动在重启后会失效。4.4 充电策略与温控的联动Android 15的充电策略不是光看电压电流温控在里面占据很大权重。系统会从各个温度传感器电池NTC、充电IC温度、PCB温度汇总温度值然后根据thermalzone的温度阈值调整充电电流。MTK平台上的mtk_ts驱动绑定了多个thermal zone策略表写在mtk_thermal_config.c里。如果实测发现充电电流在某个电量段突然跌到很低别急着怀疑PD协商有问题先查thermal zone的当前温度和对应限流值。我处理过一台机器充电电流在电池40度时从3000mA掉到800mA一开始以为是协议问题后来查thermal日志发现是电池温度触发了第一级降流保护。把温控阈值按产品定义调整后问题解决。提示快充方案越激进温控和充电策略的耦合就越深。调温控阈值之前一定要让硬件和结构评估温度风险否则为了充电速度把安全裕量调没了量产后等着售后找上门吧。5. 常见问题排查与实测记录5.1 不充电或识别不到充电器表现插上充电器手机没有任何反应dmesg里看不到typec插拔事件。排查顺序量CC管脚电压。如果插入后CC电压仍为0说明连接器或者CC路径断路查设备树里typec控制器是否注册成功/sys/class/typec/port0是否存在查内核日志里的typec、tcpm、rt-pd-manager关键字插上原装线排除线缆问题。这类问题大部分是硬件问题但也不排除驱动没有把CC下拉使能。在板级调试阶段可以先在驱动里加打印确认Rp/Rd识别状态。我遇到过连接器厂商的料有批次性CC对地短路问题量产前一定要做CC管脚的电压抽检。5.2 只能5V充电无法协商到高电压表现手机能正常进PD模式/sys/class/power_supply/mtk-master-charger/type显示USB_PD但电压始终是5V。排查思路确认充电器本身支持的PDO列表用Power-Z之类的测试仪抓一次Source Capability消息确认设备端请求的PDO是否落在充电器支持范围内特别关注PPS的电压区间是否匹配检查内核日志里是否有Reject如果被Reject大概率是请求档位超出充电器能力检查DTS里的max_charger_voltage是否写得太低导致PD请求档位被限制。很多项目为了保证安全会把max_charger_voltage保守设置结果快充死活上不去。适度放宽后同步验证OVP的设计裕量即可。我在一个项目里排查了三天最后发现是DTS里一个毫伏单位换算写错了把9000mV写成了9000UV导致内核里被截断成9V的十分之一。5.3 反复Hard Reset表现充电过程中电压一升上去就掉下来反复循环日志里有大量Hard Reset。排查步骤用协议分析仪抓BMC物理层波形排除信号质量差导致的误码在TCPM驱动里开启debug确认是对端Reject还是本端超时确认线缆是否带E-Marker芯片5A以上电流必须带E-Marker不带会导致协商失败确认充电IC的固件版本兼容该PDO必要时升级固件。线缆E-Marker这块是很多人忽视的重灾区。Type-C规范里E-Marker芯片存储了线缆的电流能力、速率等关键信息如果线缆没带E-Marker或者E-Marker数据异常高功率协商就会失败。验证方法很简单把设备端请求的电流限制到3A以内如果Hard Reset明显减少基本就是E-Marker的问题。5.4 快充几分钟后电流骤降表现刚开始充电电流正常过几分钟后电流跌到一个很低的固定值。这类问题绝大多数是温控策略或者充电IC的温升保护在起作用。先排除热问题——查看thermal日志和充电IC温度。如果温度和限流点有对应关系那基本就是温控策略需要调整如果温度正常但电流仍然跌则需要查充电IC的寄存器里是否触发了JEITA低温充电保护或者过流保护。JEITA保护是另一个常见的坑电池温度在0度到5度之间只允许小电流充电45度以上也可能降流甚至禁止充电。这些阈值在battery配置文件里都可以调但改动要谨慎——JEITA本来就是为了锂电池安全定的标准随意放宽有安全隐患。5.5 充电实测参数记录模板下面是我调试时常用的实测记录模板做对比测试时特别方便测试场景Vbus电压(mV)充电电流(mA)电池电压(mV)电池温度(℃)充电IC温度(℃)协商协议原装充电器原装线10000310041003542PD/PPS原装充电器劣质线495090040803640USB(5V)第三方PD充电器11000190040503643PD/PPS电脑USB口495045040003335USB(BC1.2)别小看这根表格很多兼容性问题都是通过多场景对比发现规律后一击定位的。比如只有劣质线时电压掉到5V那就是线缆E-Marker缺失或压降过大导致的降级。如果第三方PD充电器充电电流低但电压正常则优先检查PDO匹配。6. 最后的调试心得分享做了这么多Type-C充电的项目我个人的体会是硬件管脚是根基协议握手是核心软件策略才是把产品做到好用的关键。三个环节的知识必须同时在线只懂驱动不懂硬件遇到管脚虚焊会排查半天只懂硬件不懂协议看到Hard Reset抓瞎只懂协议不懂策略产品体验一定很难看。最后分享一个小技巧调试PD充电时尽量不要直接依赖手机上的充电百分比和提示文案那些是经过多个策略层过滤后的结果。大步调试时我习惯直接用adb shell dumpsys battery结合cat /sys/class/power_supply/*/voltage_now和current_now来判断真实状态偶尔配合Power-Z抓一次物理层波形作为佐证基本能覆盖绝大多数调试场景。MTK6769平台算是把Type-C充电这套逻辑展现得比较完整的平台把这篇内容里的思路过一遍再去应对其他平台或者更高功率的方案也就不会觉得无从下手了。项目遇到问题不可怕可怕的是没有一套清晰的排查框架东一榔头西一棒子地试最后还得靠加打印一行行找。希望这篇内容的思路能帮你少走一些弯路。