【环境信息】
CPU:RK3288
Android:7.1
Linux:4.4.143
充放电芯片:bq25703
PD芯片:fu***302
电量计:cw2015
【背景信息】
DRP/UFP/DFP/ASS
【原理说明】
To-do
【软件配置】
dts配置:kernel/arch/arm/boot/dts/rk3288-xxx.dts
&i2c5 {
status = “okay”;
i2c-scl-rising-time-ns = 《475》;
i2c-scl-falling-time-ns = 《26》;
clock-frequency = 《100000》;
bq25700: bq25700@6b {
compatible = “ti,bq25703”;
reg = 《0x6b》; ---》I2C slave address
extcon = 《&fu***0》; ---》外部连接器,PD
interrupt-parent = 《&gpio3》;
interrupts = 《RK_PD1 IRQ_TYPE_LEVEL_LOW》; ---》PD到SOC的中断
pinctrl-names = “default”;
pinctrl-0 = 《&charger_ok》;
ti,charge-current = 《4000000》;
ti,max-charge-voltage = 《8400000》;
ti,max-input-voltage = 《20000000》;
ti,max-input-current = 《6000000》;
ti,input-current-sdp = 《2000000》; //关机时,使用该电流
ti,input-current-dcp = 《2000000》;
ti,input-current-cdp = 《5000000》;
ti,input-current-dc = 《7000000》;
ti,minimum-sys-voltage = 《6000000》;
ti,otg-voltage = 《5000000》;
ti,otg-current = 《500000》;
ti,input-current = 《500000》;
pd-charge-only = 《0》; //将值设置为0即支持普通充电
status = “okay”;
};
fu***0: fu***30x@22 {
compatible = “fairchild,fu***302”;
reg = 《0x22》; // I2C slave address
pinctrl-names = “default”;
pinctrl-0 = 《&fu***0_int》;
//vbus-5v-gpios = 《&gpio0 RK_PC2 GPIO_ACTIVE_HIGH》;
int-n-gpios = 《&gpio0 RK_PA6 GPIO_ACTIVE_HIGH》; // 中断管脚
// discharge-gpios = 《&gpio0 RK_PB4 GPIO_ACTIVE_HIGH》;
charge-dev = 《&bq25700》; ---》指定充电设备
// support-uboot-charge = 《1》;
port-num = 《0》; //使用的u***控制器,关机充电时需要
status = “okay”;
};
}
&pinctrl {
。..
fu***30x {
fu***0_int: fu***0-int {
rockchip,pins = 《0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up》; //连接FUSB302 PD芯片的INT#管脚
};
};
。..
}
//电量计配置
&i2c0 {
clock-frequency = 《400000》;
CW2015@62 {
compatible = “cw201x”;
reg = 《0x62》;
bat_low_gpio = 《&gpio0 7 GPIO_ACTIVE_LOW》;
bat_config_info = 《0x15 0x7E 0x79 0x6E 0x6C 0x69 0x66 0x65
0x63 0x62 0x5C 0x58 0x52 0x52 0x49 0x31
0x29 0x23 0x24 0x26 0x29 0x37 0x4B 0x5C
0x62 0x45 0x0B 0x85 0x23 0x43 0x6C 0x81
0x83 0x82 0x83 0x85 0x3A 0x16 0x93 0x1B
0x07 0x45 0x35 0x66 0x8E 0x91 0x92 0x45
0x5B 0x78 0x9A 0xAD 0x80 0x81 0x8B 0xCB
0x2F 0x00 0x64 0xA5 0xB5 0xC1 0x46 0xAE》;
// is_u***_charge = 《1》;
monitor_sec = 《2》; //电量查询时间间隔,2S
virtual_power = 《0》;
divider_res1 = 《200》; //分压电阻大小
divider_res2 = 《200》;
status = “okay”;
};
配置文档:Documentation/devicetree/bindings/power/bq25703.txt:
Documentation/devicetree/bindings/mfd/fu***302.txt
Documentation/devicetree/bindings/power/cw2015_battery.txt
驱动目录:kernel/drivers/mfd/fu***302.c
kernel/drivers/power/bq25700_charger.c
kernel/drivers/power/cw2015_battery.c
【代码分析】
1、PD芯片模块&驱动加载
static int fu***30x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
。..
fu***_initialize_gpio ---》读取dts设备树,初始化gpio
fu***_initialize_timer ---》fu***_timer_handler回调
chip-》fu***30x_wq = create_workqueue(“fu***302_wq”);
INIT_WORK(&chip-》work, fu***302_work_func);
tcpm_init //PD reset、set and enable interrupt、
ret = devm_request_threaded_irq(&client-》dev,
chip-》gpio_int_irq,
NULL,
cc_interrupt_handler,
IRQF_ONESHOT | IRQF_TRIGGER_LOW,
client-》name,
chip);
}
fu***_timer_handler-》
queue_work(fu***30x_port_info-》fu***30x_wq,
&fu***30x_port_info-》work) // 将任务提交到工作队列
fu***302_work_func-》
cc_interrupt_handler-》
queue_work(chip-》fu***30x_wq, &chip-》work)-》
fu***302_work_func-》
state_machine_typec-》
2、充电IC bq25700 模块加载
bq25700_probe
i2c_check_functionality //是否支持 SMBUS 通信
devm_regmap_init_i2c //采用regmap api 操作 i2c,初始化 bq25700 的 regmap_config
devm_regmap_field_alloc //为 regmap 分配内存空间
i2c_set_clientdata
bq25700_field_read //读 chip id
bq25700_fw_probe
bq25700_fw_read_u32_props //获取 dts 中的属性
bq25700_hw_init //1. bq25700_chip_reset //芯片重启
//2. WDTWR_ADJ = 0 //disable watchdog
//3. 初始化电流电压和其他参数
//4. 配置 ADC 用以持续转化,禁能
bq25700_parse_dt //获取 dts 中的属性 pd-charge-only
bq25700_init_u***
u***_charger_wq = alloc_ordered_workqueue //分配工作队列,用于事件通知链
extcon_get_edev_by_phandle(dev, 0) //获取外部连接器 fu***302
bq25700_register_cg_nb(charger); //注册 charger 通知链。
bq25700_charger_evt_worker //初始化 charger 等待队列
bq25700_charger_evt_handel //判断 charger 类型,并使能 INPUT_CURRENT/CHARGE_CURRENT
bq25700_charger_evt_notifier //添加 charger 事件通知链
bq25700_register_cg_extcon //注册 charger 外部控制器,以及其事件通知链
bq25700_register_host_nb(charger); //注册 host 通知链
bq25700_register_discnt_nb(charger); //注册 disconnect 通知链
bq25700_register_pd_nb(charger); //注册 pd 通知链
schedule_delayed_work //提交任务到工作队列
bq25700_init_sysfs //创建 sysfs 中的属性节点
//根据 AC_STAT 确定触发条件,设定中断触发条件
device_init_wakeup
devm_request_threaded_irq(xx,bq25700_irq_handler_thread,xxx)
enable_irq_wake //使能中断唤醒
bq25700_power_supply_init //注册 power supply 的 desc,用于上传获取充电状态
-》power_supply_register-》bq25700_power_supply_get_property//获取系统属性的接口
通知实例
otg_mode_store-》rockchip_u***2phy_set_mode-》 (kernel/drivers/phy/rockchip/phy-rockchip-inno-u***2.c)
extcon_set_state_sync-》extcon_sync-》raw_notifier_call_chain
3、拔出AC,停止充电
1)注册任务与通知链
static int bq25700_register_discnt_nb(struct bq25700_device *charger)
{
。..
INIT_DELAYED_WORK(&charger-》discnt_work, bq25700_discnt_evt_worker); ---》创建discnt_work延时任务
charger-》cable_discnt_nb.notifier_call = bq25700_discnt_evt_notfier;
ret = extcon_register_notifier(charger-》cable_edev, EXTCON_USB, &charger-》cable_discnt_nb);
。..
}
2)流程梳理
bq25700_discnt_evt_notfier-》
queue_delayed_work(charger-》u***_charger_wq, &charger-》discnt_work, xxx)-》
bq25700_discnt_evt_worker-》
bq25700_discnt-》
bq25700_disable_charge
bq25700_typec0_discharge
power_supply_changed
4、PD work处理
1)注册任务与通知链
static int bq25700_register_pd_nb(struct bq25700_device *charger)
{
。..
INIT_DELAYED_WORK(&charger-》pd_work, bq25700_pd_evt_worker);
charger-》cable_pd_nb.notifier_call = bq25700_pd_evt_notifier;
extcon_register_notifier(charger-》cable_edev, EXTCON_CHG_USB_FAST, &charger-》cable_pd_nb);
。..
}
2)收到通知
bq25700_pd_evt_notifier-》
queue_delayed_work(charger-》u***_charger_wq, &charger-》pd_work,xxx)-》
bq25700_pd_evt_worker-》
bq25700_pd_connect-》获取PD协商出的电压和电流,设置charger输入电压和电流和充电电流
bq25700_enable_typec0-》
bq25700_get_chip_state-》
power_supply_changed-》
5、使能或禁止OTG功能
static int bq25700_register_host_nb(struct bq25700_device *charger)
{
。..
INIT_DELAYED_WORK(&charger-》host_work, bq25700_host_evt_worker); ---》创建host_work延时任务
charger-》cable_host_nb.notifier_call = bq25700_host_evt_notifier;
// extcon_register_notifier见。/kernel/drivers/extcon/extcon.c
ret = extcon_register_notifier(charger-》cable_edev, EXTCON_USB_HOST, &charger-》cable_host_nb);
。..
}
bq25700_host_evt_notifier-》
queue_delayed_work-》
bq25700_host_evt_worker-》
extcon_get_cable_state_-》获取cable/charger状态
bq25700_field_write(charger, EN_OTG, xxx); ---》使能或禁止OTG
6、充电事件处理
static int bq25700_register_cg_nb(struct bq25700_device *charger)
{
。..
INIT_DELAYED_WORK(&charger-》u***_work, bq25700_charger_evt_worker);
charger-》cable_cg_nb.notifier_call = bq25700_charger_evt_notifier;
bq25700_register_cg_extcon(charger, charger-》cable_edev, &charger-》cable_cg_nb);
。..
}
bq25700_charger_evt_notifier-》
queue_delayed_work-》
bq25700_charger_evt_worker-》
bq25700_charger_u***_bc_handel
bq25700_enable_charger-》 // SDP/DCP/CDP
power_supply_changed-》
【环境信息】
CPU:RK3288
Android:7.1
Linux:4.4.143
充放电芯片:bq25703
PD芯片:fu***302
电量计:cw2015
【背景信息】
DRP/UFP/DFP/ASS
【原理说明】
To-do
【软件配置】
dts配置:kernel/arch/arm/boot/dts/rk3288-xxx.dts
&i2c5 {
status = “okay”;
i2c-scl-rising-time-ns = 《475》;
i2c-scl-falling-time-ns = 《26》;
clock-frequency = 《100000》;
bq25700: bq25700@6b {
compatible = “ti,bq25703”;
reg = 《0x6b》; ---》I2C slave address
extcon = 《&fu***0》; ---》外部连接器,PD
interrupt-parent = 《&gpio3》;
interrupts = 《RK_PD1 IRQ_TYPE_LEVEL_LOW》; ---》PD到SOC的中断
pinctrl-names = “default”;
pinctrl-0 = 《&charger_ok》;
ti,charge-current = 《4000000》;
ti,max-charge-voltage = 《8400000》;
ti,max-input-voltage = 《20000000》;
ti,max-input-current = 《6000000》;
ti,input-current-sdp = 《2000000》; //关机时,使用该电流
ti,input-current-dcp = 《2000000》;
ti,input-current-cdp = 《5000000》;
ti,input-current-dc = 《7000000》;
ti,minimum-sys-voltage = 《6000000》;
ti,otg-voltage = 《5000000》;
ti,otg-current = 《500000》;
ti,input-current = 《500000》;
pd-charge-only = 《0》; //将值设置为0即支持普通充电
status = “okay”;
};
fu***0: fu***30x@22 {
compatible = “fairchild,fu***302”;
reg = 《0x22》; // I2C slave address
pinctrl-names = “default”;
pinctrl-0 = 《&fu***0_int》;
//vbus-5v-gpios = 《&gpio0 RK_PC2 GPIO_ACTIVE_HIGH》;
int-n-gpios = 《&gpio0 RK_PA6 GPIO_ACTIVE_HIGH》; // 中断管脚
// discharge-gpios = 《&gpio0 RK_PB4 GPIO_ACTIVE_HIGH》;
charge-dev = 《&bq25700》; ---》指定充电设备
// support-uboot-charge = 《1》;
port-num = 《0》; //使用的u***控制器,关机充电时需要
status = “okay”;
};
}
&pinctrl {
。..
fu***30x {
fu***0_int: fu***0-int {
rockchip,pins = 《0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up》; //连接FUSB302 PD芯片的INT#管脚
};
};
。..
}
//电量计配置
&i2c0 {
clock-frequency = 《400000》;
CW2015@62 {
compatible = “cw201x”;
reg = 《0x62》;
bat_low_gpio = 《&gpio0 7 GPIO_ACTIVE_LOW》;
bat_config_info = 《0x15 0x7E 0x79 0x6E 0x6C 0x69 0x66 0x65
0x63 0x62 0x5C 0x58 0x52 0x52 0x49 0x31
0x29 0x23 0x24 0x26 0x29 0x37 0x4B 0x5C
0x62 0x45 0x0B 0x85 0x23 0x43 0x6C 0x81
0x83 0x82 0x83 0x85 0x3A 0x16 0x93 0x1B
0x07 0x45 0x35 0x66 0x8E 0x91 0x92 0x45
0x5B 0x78 0x9A 0xAD 0x80 0x81 0x8B 0xCB
0x2F 0x00 0x64 0xA5 0xB5 0xC1 0x46 0xAE》;
// is_u***_charge = 《1》;
monitor_sec = 《2》; //电量查询时间间隔,2S
virtual_power = 《0》;
divider_res1 = 《200》; //分压电阻大小
divider_res2 = 《200》;
status = “okay”;
};
配置文档:Documentation/devicetree/bindings/power/bq25703.txt:
Documentation/devicetree/bindings/mfd/fu***302.txt
Documentation/devicetree/bindings/power/cw2015_battery.txt
驱动目录:kernel/drivers/mfd/fu***302.c
kernel/drivers/power/bq25700_charger.c
kernel/drivers/power/cw2015_battery.c
【代码分析】
1、PD芯片模块&驱动加载
static int fu***30x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
。..
fu***_initialize_gpio ---》读取dts设备树,初始化gpio
fu***_initialize_timer ---》fu***_timer_handler回调
chip-》fu***30x_wq = create_workqueue(“fu***302_wq”);
INIT_WORK(&chip-》work, fu***302_work_func);
tcpm_init //PD reset、set and enable interrupt、
ret = devm_request_threaded_irq(&client-》dev,
chip-》gpio_int_irq,
NULL,
cc_interrupt_handler,
IRQF_ONESHOT | IRQF_TRIGGER_LOW,
client-》name,
chip);
}
fu***_timer_handler-》
queue_work(fu***30x_port_info-》fu***30x_wq,
&fu***30x_port_info-》work) // 将任务提交到工作队列
fu***302_work_func-》
cc_interrupt_handler-》
queue_work(chip-》fu***30x_wq, &chip-》work)-》
fu***302_work_func-》
state_machine_typec-》
2、充电IC bq25700 模块加载
bq25700_probe
i2c_check_functionality //是否支持 SMBUS 通信
devm_regmap_init_i2c //采用regmap api 操作 i2c,初始化 bq25700 的 regmap_config
devm_regmap_field_alloc //为 regmap 分配内存空间
i2c_set_clientdata
bq25700_field_read //读 chip id
bq25700_fw_probe
bq25700_fw_read_u32_props //获取 dts 中的属性
bq25700_hw_init //1. bq25700_chip_reset //芯片重启
//2. WDTWR_ADJ = 0 //disable watchdog
//3. 初始化电流电压和其他参数
//4. 配置 ADC 用以持续转化,禁能
bq25700_parse_dt //获取 dts 中的属性 pd-charge-only
bq25700_init_u***
u***_charger_wq = alloc_ordered_workqueue //分配工作队列,用于事件通知链
extcon_get_edev_by_phandle(dev, 0) //获取外部连接器 fu***302
bq25700_register_cg_nb(charger); //注册 charger 通知链。
bq25700_charger_evt_worker //初始化 charger 等待队列
bq25700_charger_evt_handel //判断 charger 类型,并使能 INPUT_CURRENT/CHARGE_CURRENT
bq25700_charger_evt_notifier //添加 charger 事件通知链
bq25700_register_cg_extcon //注册 charger 外部控制器,以及其事件通知链
bq25700_register_host_nb(charger); //注册 host 通知链
bq25700_register_discnt_nb(charger); //注册 disconnect 通知链
bq25700_register_pd_nb(charger); //注册 pd 通知链
schedule_delayed_work //提交任务到工作队列
bq25700_init_sysfs //创建 sysfs 中的属性节点
//根据 AC_STAT 确定触发条件,设定中断触发条件
device_init_wakeup
devm_request_threaded_irq(xx,bq25700_irq_handler_thread,xxx)
enable_irq_wake //使能中断唤醒
bq25700_power_supply_init //注册 power supply 的 desc,用于上传获取充电状态
-》power_supply_register-》bq25700_power_supply_get_property//获取系统属性的接口
通知实例
otg_mode_store-》rockchip_u***2phy_set_mode-》 (kernel/drivers/phy/rockchip/phy-rockchip-inno-u***2.c)
extcon_set_state_sync-》extcon_sync-》raw_notifier_call_chain
3、拔出AC,停止充电
1)注册任务与通知链
static int bq25700_register_discnt_nb(struct bq25700_device *charger)
{
。..
INIT_DELAYED_WORK(&charger-》discnt_work, bq25700_discnt_evt_worker); ---》创建discnt_work延时任务
charger-》cable_discnt_nb.notifier_call = bq25700_discnt_evt_notfier;
ret = extcon_register_notifier(charger-》cable_edev, EXTCON_USB, &charger-》cable_discnt_nb);
。..
}
2)流程梳理
bq25700_discnt_evt_notfier-》
queue_delayed_work(charger-》u***_charger_wq, &charger-》discnt_work, xxx)-》
bq25700_discnt_evt_worker-》
bq25700_discnt-》
bq25700_disable_charge
bq25700_typec0_discharge
power_supply_changed
4、PD work处理
1)注册任务与通知链
static int bq25700_register_pd_nb(struct bq25700_device *charger)
{
。..
INIT_DELAYED_WORK(&charger-》pd_work, bq25700_pd_evt_worker);
charger-》cable_pd_nb.notifier_call = bq25700_pd_evt_notifier;
extcon_register_notifier(charger-》cable_edev, EXTCON_CHG_USB_FAST, &charger-》cable_pd_nb);
。..
}
2)收到通知
bq25700_pd_evt_notifier-》
queue_delayed_work(charger-》u***_charger_wq, &charger-》pd_work,xxx)-》
bq25700_pd_evt_worker-》
bq25700_pd_connect-》获取PD协商出的电压和电流,设置charger输入电压和电流和充电电流
bq25700_enable_typec0-》
bq25700_get_chip_state-》
power_supply_changed-》
5、使能或禁止OTG功能
static int bq25700_register_host_nb(struct bq25700_device *charger)
{
。..
INIT_DELAYED_WORK(&charger-》host_work, bq25700_host_evt_worker); ---》创建host_work延时任务
charger-》cable_host_nb.notifier_call = bq25700_host_evt_notifier;
// extcon_register_notifier见。/kernel/drivers/extcon/extcon.c
ret = extcon_register_notifier(charger-》cable_edev, EXTCON_USB_HOST, &charger-》cable_host_nb);
。..
}
bq25700_host_evt_notifier-》
queue_delayed_work-》
bq25700_host_evt_worker-》
extcon_get_cable_state_-》获取cable/charger状态
bq25700_field_write(charger, EN_OTG, xxx); ---》使能或禁止OTG
6、充电事件处理
static int bq25700_register_cg_nb(struct bq25700_device *charger)
{
。..
INIT_DELAYED_WORK(&charger-》u***_work, bq25700_charger_evt_worker);
charger-》cable_cg_nb.notifier_call = bq25700_charger_evt_notifier;
bq25700_register_cg_extcon(charger, charger-》cable_edev, &charger-》cable_cg_nb);
。..
}
bq25700_charger_evt_notifier-》
queue_delayed_work-》
bq25700_charger_evt_worker-》
bq25700_charger_u***_bc_handel
bq25700_enable_charger-》 // SDP/DCP/CDP
power_supply_changed-》
举报