PD快充 - fusb302驱动调试笔记

一、fusb302介绍

Fusb302是可编程的USB Type-C控制器,支持识别各种USB 设备和对应的状态;且支持最高100W的PD协议。

Fusb302用CC1/CC2引脚与typeC电源适配器通信,通过PD协议来设置电源适配器的输出电压和电流,从而达到控制充电电压电流,实现快充的目的。

说白了,就是通过 PD协议 控制电源适配器,从VBUS输出不同功率的电源(最高100W)。

 二、fusb302引脚功能

引脚

功能

CC1/CC2

主要用来 PD协议通信 或 其他:

1)探测USB连接,区分正反面,区分DFP和UFP的主从关系

2)配置Vbus,有USB Type-C和USB Power Delivery两种模式

3)配置Vconn,当线缆里有芯片的时候,一个cc传输信号,一个cc变成供电Vconn,用来给线缆里的芯片供电(3.3V或5V);

4)如果CC通道连接其他配置,如连接音频配件、DP、PCIE时,CC通道配置是不同的。

VBUS

VBUS为电源适配器提供的用来给电池充电的总线电源,USB PD协议可配置电压和电流,最大100W,如:20V 5A

VCONN

当线缆里有芯片的时候,一个cc传输信号,一个cc变成供电Vconn,用来给线缆里的芯片供电(3.3V或5V)

INIT_N

中断输出,当有事件发生时,用于通知处理器读取I2C寄存器数据。如:插入/拔出typeC,INIT_N都会拉低一下。

SCL、SDA

I2C时钟、数据引脚

介绍:

1、主从

SRC:Source,供电端如:充电器。

SNK:Sink,受电端如:手电筒。

2、DFP、UFP、DRP用途解析

① DFP:Source,下行端口,可以理解为一个Host,DFP作为source给VBUS和vcon供电的,简单理解为一个提供电源的设备,如:电源适配器。

② UFP:Sink,上行端口,可以理解为Device,UFP可以理解为受电端口,DFP为供电端口,UFP从VBUS中取电,并可提供数据。典型设备如:U盘、移动硬盘。

③ DRP:双角色端口,DRP既可以做DFP(Source)又可以做UFP(Sink),也可以在DFP和UFP间动态切换,典型设备是:笔记本电脑、充电宝。

充电宝为UFP(Sink)的应用:电源适配器给充电宝充电。

充电宝为DFP(Source)的应用:充电宝给手机或其他设备充电。

三、fusb302驱动移植及修改方法

与供应商沟通,原厂前期只提供了mcu的代码没提供linux的。因此移植瑞芯微的板子里的fusb302驱动到酷芯平台。

1、将fusb302驱动编译成.ko,并加载

1)设备树dts添加子节点,fusb302挂载 i2c3上

&i2c3 {
         status = "okay";
         fusb0:fusb30x@22 {
                 compatible = "fairchild,fusb302";
                 reg = <0x22>;                                    //设备地址
                 int-n-gpios = <&porta0 4 GPIO_ACTIVE_HIGH>;     //GPIO_A0_4
                 status = "okay";
         };
};

引脚配置如下:

i2c 和 gpio 引脚

 2)Makefile

KERN_DIR = /home/dongao/share/kernel/linux-linaro-stable-lsk-v4.9-17.07  #内核路径

all:
    make -C $(KERN_DIR) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- M=`pwd` modules 

clean:
    make -C $(KERN_DIR) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- M=`pwd` modules clean
    rm -rf modules.order

obj-m    += fusb302.o

3)加载并测试

删除没有定义的 extcon相关函数。

$ make                                //ubuntu下编译生成 fusb302.ko

$ insmod fusb302.ko        //ARM板加载驱动

发现问题:

问题1:probe() 中的 devm_extcon_dev_allocate() 函数会失败。

 解决方法:内核配置 extcon。

问题2:酷芯提供的内核的 drivers\extcon\extcon.c 中的 extcon_info[] 没有定义 EXTCON_USB_VBUS_EN

解决方法:按照rk内核的extcon.c文件,extcon_info[]数组添加 EXTCON_USB_VBUS_EN 如下。

struct __extcon_info {
    unsigned int type;
    unsigned int id;
    const char *name;

} extcon_info[] = {
    ...
/* 2022-08-22 donga add */
       [EXTCON_USB_VBUS_EN] = {
                .type = EXTCON_TYPE_USB,
                .id = EXTCON_USB_VBUS_EN,
                .name = "USB_VBUS_EN",
        },
    ...
}

问题3:正常运行probe()后,插上typec电源适配器后,发现电源适配器不停的发送 Hard Rest。

分析原因:PD协议对实时性要求比较高,fusb302收到适配器适配器的cap自动返回GoodCRC之后,要在15ms内发送request,不然电源适配器会发送HardReset命令。rk平台主频高,每个打印信息也只消耗1ms左右,而酷芯为900M主频,每个打印信息都间隔10ms左右。因此没来得及发送request。

解决方法:见修改驱动源码。

借用一张网图,描述PD协议交互过程:

 2、修改驱动源码

修改方向:发送完GoodCRC后,会触发 INTERRUPTB_GCRCSENT 中断,状态机中尽量减少不需要的分支。

 

 之后,经过多次HardRest,某次及时request进入正常充电。(此时代码不稳定,我想要每次都能立刻request进入正常充电)。继续调试代码。

同时,测试typeC拔出时,应该能产生INIT_N中断。示波器测INIT_N脚,确实有拉低的动作,奇怪为什么没有运行中断处理函数?

原因:驱动代码中断配置成 IRQF_ONESHOT | IRQF_TRIGGER_LOW 模式,中断处理函数中关中断,工作队列再开中断。之后就无法触发了。(如果不关开中断,可以一直触发)。这个问题找厂家协助处理中。。。

测试发现下降沿触发不会出现这样的问题,因此对代码作出修改,改为 IRQF_TRIGGER_FALLING 模式加载驱动时,还需判断 type-C插入状态。

如下:

3、验证fusb302驱动,结合bq25720 充电管理IC

fusb302只是控制typeC电源适配器的VBUS脚输入的电压和电流。充电还需要充电管理IC,这里为 bq25720(驱动方法看相关文档)。

如:项目中fusb302控制电压适配器VBUS输出为 9V 3A,再通过 bq25720 限制到 8V 2A(实际看功率,要比VBUS的功率小),最终给电池充电。

 硬件环境:

 

 PD快充流程:

1)fusb302 原理图

2)加载驱动

$ insmod fusb302.ko                 //ARM板加载fusb302.ko驱动

$ insmod bq25720_charger.ko //ARM板加载bq25720_charger.ko驱动

3)逻辑分析仪采集CC1/2 PD协议通信过程

Sink发送Soft_Rest信号

 Sink请求

 

至此,每次插上type-c充电时,电流计能检测到 9V 2.2A左右。与我代码里设置的值一致。

附上源码:https://download.csdn.net/download/hinewcc/87589264

猜你喜欢

转载自blog.csdn.net/hinewcc/article/details/129640477