rockchip的一部分板子上都有快充芯片FUSB302,支持PD协商电压和电流
设备树内,FUSB30芯片挂载在i2c4下
&i2c4 {
status = "okay";
i2c-scl-rising-time-ns = <475>;
i2c-scl-falling-time-ns = <26>;
fusb0: fusb30x@22 {
compatible = "fairchild,fusb302";
reg = <0x22>;
pinctrl-names = "default";
pinctrl-0 = <&fusb0_int>;
int-n-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
vbus-5v-gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>;
status = "okay";
};
};
进入内核,make menuconfig
打开fusb30的驱动支持
配置好进入系统查看i2c4下挂载的设备,可以看到快充芯片成功挂载
在RK3399的充电管理中,FUSB302是与 bq25700 和 CW2015 芯片配合使用的,因为我的板子没有 bq25700 和 CW2015 芯片,所以在选择最大电压和电流时,无法通过设备树修改VBUS脚的输入电压和电流,只能通过修改FUSB302的驱动程序
FUSB302驱动源码位置kernel/drivers/mfd/fusb302.c
最大电流电压设置函数
static int fusb302_set_pos_power_by_charge_ic(struct fusb30x_chip *chip)
{
struct power_supply *psy = NULL;
union power_supply_propval val;
enum power_supply_property psp;
int max_vol, max_cur;
max_vol = 0;
max_cur = 0;
psy = power_supply_get_by_phandle(chip->dev->of_node, "charge-dev");
if (!psy || IS_ERR(psy))
return -1;
psp = POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX;
if (power_supply_get_property(psy, psp, &val) == 0)
max_vol = val.intval / 1000;
psp = POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;
if (power_supply_get_property(psy, psp, &val) == 0)
max_cur = val.intval / 1000;
if (max_vol > 0 && max_cur > 0)
fusb_set_pos_power(chip, max_vol, max_cur);
return 0;
}
通过匹配设备树中的"charge-dev"节点,而"charge-dev"节点是关于bq25700芯片的描述,在没有bq25700芯片的情况下,通过源码直接设置最大电流和电压,所以将源码改为
static int fusb302_set_pos_power_by_charge_ic(struct fusb30x_chip *chip)
{
int max_vol, max_cur;
max_vol = 12000; //12V
max_cur = 3000; //3A
if (max_vol > 0 && max_cur > 0)
fusb_set_pos_power(chip, max_vol, max_cur);
return 0;
}
调试记录
使用typec的5V电压启动时,从log打印来看并没有触发FUSB302的中断信息,即没有PD协议的通信,i2c4下FUSB302成功挂载。
换为电源适配器(充电宝)12V、3A供电,开发板无法启动,串口没有任何输出。
与瑞芯微工程师沟通,选用外部供电的方式启动,此处需要断开Typec的电源线,防止倒灌,仅使用Typec的cc通信。随后拔插Typec线,观察log输出信息,是否有PD中断,因为每次拔出Typec线都会触发FUSB302的中断,拉低VBUS,测试log有打印,且可以检测到中断信号。实际测量Typec处的电压,也符合log输出的fetching 5V电压,但5V是不符合快充的
添加DEBUG信息
diff --git a/arch/arm64/configs/rockchip_defconfig b/arch/arm64/configs/rockchip_defconfig
index b0f9a34..ca4258f 100644
--- a/arch/arm64/configs/rockchip_defconfig
+++ b/arch/arm64/configs/rockchip_defconfig
@@ -930,6 +930,7 @@ CONFIG_CRYPTO_ANSI_CPRNG=y
CONFIG_CRYPTO_DEV_ROCKCHIP=y
CONFIG_CRYPTO_DEV_ROCKCHIP_DEV=y
CONFIG_PRINTK_TIME=y
+CONFIG_CONSOLE_LOGLEVEL_DEFAULT=8
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
diff --git a/drivers/mfd/fusb302.c b/drivers/mfd/fusb302.c
index 205739f..02477e1 100644
--- a/drivers/mfd/fusb302.c
+++ b/drivers/mfd/fusb302.c
@@ -9,6 +9,7 @@
* Some ideas are from chrome ec and fairchild GPL fusb302 driver.
*/
+#define DEBUG
#include <linux/delay.h>
#include <linux/extcon-provider.h>
#include <linux/gpio.h>
@@ -169,6 +170,7 @@ static void fusb_set_pos_power(struct fusb30x_chip *chip, int max_vol,
int pos_find;
int tmp;
+ printk("fusb302---->%s\n",__func__);
pos_find = 0;
for (i = PD_HEADER_CNT(chip->rec_head) - 1; i >= 0; i--) {
switch (CAP_POWER_TYPE(chip->rec_load[i])) {
@@ -184,6 +186,8 @@ static void fusb_set_pos_power(struct fusb30x_chip *chip, int max_vol,
tmp = CAP_FPDO_CURRENT(chip->rec_load[i]);
chip->pd_output_cur = tmp * 10;
pos_find = 1;
+ printk("fusb302---->%s:pd_output_vol=%d,pd_output_cur=%d\n",
+ __func__,chip->pd_output_vol,chip->pd_output_cur);
}
break;
case 1:
@@ -219,8 +223,10 @@ static int fusb302_set_pos_power_by_charge_ic(struct fusb30x_chip *chip)
max_vol = 0;
max_cur = 0;
psy = power_supply_get_by_phandle(chip->dev->of_node, "charge-dev");
- if (!psy || IS_ERR(psy))
+ if (!psy || IS_ERR(psy)) {
+ printk("fusb302---->%s:get power supply error!\n",__func__);
return -1;
+ }
psp = POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX;
if (power_supply_get_property(psy, psp, &val) == 0)
@@ -230,6 +236,7 @@ static int fusb302_set_pos_power_by_charge_ic(struct fusb30x_chip *chip)
if (power_supply_get_property(psy, psp, &val) == 0)
max_cur = val.intval / 1000;
+ printk("fusb302---->%s:max_vol=%d,max_cur=%d\n",__func__,max_vol,max_cur);
if (max_vol > 0 && max_cur > 0)
fusb_set_pos_power(chip, max_vol, max_cur);
@@ -2526,6 +2533,10 @@ static void fusb_state_snk_evaluate_caps(struct fusb30x_chip *chip, u32 evt)
/* Fixed Supply */
if (CAP_FPDO_VOLTAGE(chip->rec_load[tmp]) <= 100)
chip->pos_power = tmp + 1;
+ printk("fusb302---->%s:get vol = %d\n",
+ __func__,CAP_FPDO_VOLTAGE(chip->rec_load[tmp]) * 50);
+ printk("fusb302---->%s:get cur = %d\n",
+ __func__,CAP_FPDO_CURRENT(chip->rec_load[tmp]) * 10);
break;
case 1:
/* Battery */
如果出现修改后不能打印printk的信息
查看printk打印等级
root@linaro-alip:/# cat /proc/sys/kernel/printk
7 4 1 7
直接去kernel/include/linux/printk.h内修改
diff --git a/include/linux/printk.h b/include/linux/printk.h
index 9729565c25ff..ab982911ab26 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -39,7 +39,7 @@ static inline const char *printk_skip_level(const char *buffer)
#define CONSOLE_LOGLEVEL_SILENT 0 /* Mum's the word */
#define CONSOLE_LOGLEVEL_MIN 1 /* Minimum loglevel we let people use */
#define CONSOLE_LOGLEVEL_QUIET 4 /* Shhh ..., when booted with "quiet" */
-#define CONSOLE_LOGLEVEL_DEFAULT 7 /* anything MORE serious than KERN_DEBUG */
+#define CONSOLE_LOGLEVEL_DEFAULT 8 /* anything MORE serious than KERN_DEBUG */
#define CONSOLE_LOGLEVEL_DEBUG 10 /* issue debug messages */
#define CONSOLE_LOGLEVEL_MOTORMOUTH 15 /* You can't shut this one up */
启动后,插入Typec的log打印如下,其中power list下的电压和电流信息即为PD协议获取的电源适配器支持的电压和电流,经过跟电源适配器out电压电流信息对比,可以对应上
[ 39.303566] fusb302 4-0022: port 0, state 6
[ 39.306089] fusb302 4-0022: port 0, state 19
[ 39.306484] fusb302 4-0022: QHYCCD CC connected in CC1 as UFP
[ 39.309857] fusb302 4-0022: port 0, state 20
[ 39.310274] fusb302 4-0022: port 0
[ 39.310650] fusb302 4-0022: orientation 2
[ 39.311076] fusb302 4-0022: power_role 0
[ 39.311451] fusb302 4-0022: data_role 0
[ 39.311825] fusb302 4-0022: cc 1
[ 39.312256] fusb302 4-0022: pd 0
[ 39.312631] fusb302 4-0022: enter_mode 0
[ 39.313052] fusb302 4-0022: pin support 0
[ 39.313426] fusb302 4-0022: pin def 0
[ 39.313799] fusb302 4-0022: attention 0
[ 39.320008] fusb302 4-0022: port 0, state 21
[ 39.321686] rockchip-dwc3 usb0: USB peripheral connected
[ 39.491477] fusb302 4-0022: port 0, state 22
-------------power list-------------------
[ 39.494320] fusb302---->fusb_state_snk_evaluate_caps:get vol = 5000
[ 39.494897] fusb302---->fusb_state_snk_evaluate_caps:get cur = 3000
[ 39.495567] fusb302---->fusb_state_snk_evaluate_caps:get vol = 9000
[ 39.496181] fusb302---->fusb_state_snk_evaluate_caps:get cur = 3000
[ 39.496744] fusb302---->fusb_state_snk_evaluate_caps:get vol = 12000
[ 39.497373] fusb302---->fusb_state_snk_evaluate_caps:get cur = 3000
[ 39.497937] fusb302---->fusb_state_snk_evaluate_caps:get vol = 15000
[ 39.498559] fusb302---->fusb_state_snk_evaluate_caps:get cur = 3000
[ 39.499170] fusb302---->fusb_state_snk_evaluate_caps:get vol = 20000
[ 39.499753] fusb302---->fusb_state_snk_evaluate_caps:get cur = 2000
通过测量VBUS_TYPEC0,可以测量到驱动内设置的12V电压
修改驱动为15V,重新烧录内核测量,可以测量到15V电压
我们在power设置的函数中设置15V 3A,使用支持15V 3A的充电宝供电能够测量到15V,切换为最大10V 2.25A的充电宝来供电只能测量到5V,如何使其能支持10V
另外测量发现,当开发板连接串口和eDP时,电流倒灌会导致VBUS_TYPEC处能够测量到电压,此时连接快充线,开发板无法启动,去除所有的负载,连接快充线,测试点处能够测得15V电压,随后再连接eDP线,屏幕没有显示
先去除所有负载,开机后插入usb转串口和hdmi线,进入系统dmesg打印查看信息
发现了hdmi报错信息
[ 58.469496] dwhdmi-rockchip ff940000.hdmi: failed to get edid
[ 58.625464] dwhdmi-rockchip ff940000.hdmi: failed to get edid
检查硬件部分,上文提到的供电部分需要加二极管隔断,防止电流倒灌对PD协议造成影响。