瑞芯微Rockchip开发者社区
直播中

话多显蠢

9年用户 721经验值
擅长:479461
私信 关注
[问答]

如何去实现Android7.1 RK3288充放电管理的设计呢

如何去实现Android7.1 RK3288充放电管理的设计呢?其代码该怎样去实现呢?

回帖(2)

唐般远

2022-3-4 10:51:12
  【环境信息】
  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-》
 
举报

林秀玲

2022-3-4 10:51:15
 7、charger中断处理
  bq25700_irq_handler_thread
  【日志信息】
  1、插入充电器打印
  [ 1561.796236] state_machine_typec unattached=2
  [ 1562.054372] state_machine_typec attach_wait_sink=3 打印35次
  [ 1562.059987] state_machine_typec attached_sink=6
  [ 1562.060071] allen_debug:fu***_state_attached_sink,1648
  [ 1562.060754] fu***302 5-0022: CC connected in CC1 as UFP
  [ 1562.060858] jon debug:::u***_mode:30
  [ 1562.060916] force_u***_mode_store 0-》0
  [ 1562.060963] jon debug:::u***_mode set 0
  [ 1562.062994] state_machine_typec policy_snk_startup=19
  [ 1562.064720] bq25700_discnt_evt_worker line1640
  [ 1562.069680] state_machine_typec policy_snk_discovery=20
  [ 1562.071540] state_machine_typec policy_snk_wait_caps=21
  [ 1562.089561] bq25700_irq_handler_thread line1261 irq=198 00
  [ 1562.099482] bq25700_host_evt_worker line1550
  [ 1562.104086] healthd: battery l=47 v=7254 t=18.8 h=2 st=3 chg=u
  [ 1562.141302] rk_battery_charger_detect_cb , battery_charger_detect 2
  [ 1562.148692] bq25700_charger_evt_worker line1503 u***_bc=1
  [ 1562.162912] healthd: battery l=47 v=7254 t=18.8 h=2 st=3 chg=u
  [ 1562.182576] state_machine_typec policy_snk_wait_caps=21
  [ 1562.184020] state_machine_typec policy_snk_evaluate_caps=22
  [ 1562.187441] state_machine_typec policy_snk_select_cap=23
  [ 1562.189049] state_machine_typec policy_snk_select_cap=23
  [ 1562.195351] state_machine_typec policy_snk_select_cap=23
  [ 1562.196795] state_machine_typec policy_snk_transition_sink=24
  [ 1562.211321] healthd: battery l=47 v=7256 t=18.8 h=2 st=2 chg=u
  [ 1562.375627] state_machine_typec policy_snk_transition_sink=24
  [ 1562.375649] fu***302 5-0022: PD connected as UFP, fetching 5V ---》协商完成,UFP模式
  [ 1562.377014] state_machine_typec policy_snk_ready=25
  [ 1562.377050] bq25700_discnt_evt_worker line1640
  [ 1562.385335] bq25700_pd_evt_worker line1384
  [ 1562.408119] jon SET vol_idx: 164mv
  [ 1562.408132] jon SET cur_idx: 60mA
  [ 1562.408138] jon SET harger-》init_data.ichg: 62mA
  [ 1562.435576] bq25700_host_evt_worker line1550
  [ 1562.440200] healthd: battery l=47 v=7256 t=18.8 h=2 st=2 chg=u
  [ 1562.696760] state_machine_typec policy_snk_ready=25
  2、拔出充电器打印
  [ 4072.872299] bq25700_irq_handler_thread line1261 irq=198 00 ---》irq_flag = IRQF_TRIGGER_LOW
  [ 4072.906988] rk_battery_charger_detect_cb , battery_charger_detect 1
  [ 4072.912096] state_machine_typec line2882 unattached=2
  [ 4072.914829] bq25700_charger_evt_worker line1503 u***_bc=1 ---》bq25700_charger_u***_bc_handel
  [ 4072.919668] state_machine_typec line2882 attach_wait_sink=3 打印多次
  3、正常充电流程
  【环境操作】
  1、查看电池文件系统
  rk3288:/ # ls -l 。/sys/devices/platform/ff170000.i2c/i2c-5/5-006b/power_supply/bq25700-charger
  -r–r--r-- 1 root root 4096 2021-10-22 20:42 charge_control_limit_max
  -r–r--r-- 1 root root 4096 2021-10-22 20:42 constant_charge_current
  -r–r--r-- 1 root root 4096 2021-10-22 20:42 constant_charge_current_max
  -r–r--r-- 1 root root 4096 2021-10-22 20:42 constant_charge_voltage
  -r–r--r-- 1 root root 4096 2021-10-22 20:42 constant_charge_voltage_max
  -r–r--r-- 1 root root 4096 2021-10-22 20:35 current_max
  lrwxrwxrwx 1 root root 0 2021-10-22 20:42 device -》 …/…/…/5-006b
  -r–r--r-- 1 root root 4096 2021-10-22 20:42 health
  -r–r--r-- 1 root root 4096 2021-10-22 20:42 input_current_limit
  -r–r--r-- 1 root root 4096 2021-10-22 20:42 manufacturer
  -rwxrwxrwx 1 root root 4096 2021-10-22 20:47 online
  drwxr-xr-x 2 root root 0 2021-10-22 20:35 power
  -r–r--r-- 1 root root 4096 2021-10-22 20:42 status
  lrwxrwxrwx 1 root root 0 2021-10-22 20:42 subsystem -》 …/…/…/…/…/…/…/class/power_supply
  -r–r--r-- 1 root root 4096 2021-10-22 20:35 type
  -rw-r–r-- 1 root root 4096 2021-10-22 20:35 uevent
  -r–r--r-- 1 root root 4096 2021-10-22 20:35 voltage_max
  rk3288:/ # ls -l 。/sys/bus/i2c/drivers/bq25700-charger
  total 0
  lrwxrwxrwx 1 root root 0 2021-10-22 20:42 5-006b -》 …/…/…/…/devices/platform/ff170000.i2c/i2c-5/5-006b
  –w------- 1 root root 4096 2021-10-22 20:42 bind
  –w------- 1 root root 4096 2021-10-22 20:42 uevent
  –w------- 1 root root 4096 2021-10-22 20:42 unbind
  【参考接口】
  1、delay_work延时工作
  INIT_DELAYED_WORK(dwork, work);
  //参数1是个delayed_work结构体,参数2是个函数名
  schedule_delayed_work (struct delayed_work *dwork, unsigned long delay);
  //将当前dwork变量进入到等待队列中,在后续的delay时间后,将会调用dwork变量对应的work函数
  bool cancel_delayed_work(struct delayed_work *dwork);
  //如果当前dwork在等待队列中,则将取消掉
  2、notifier通知机制
  /*
  * RAW_NOTIFIER_HEAD是定义一个通知链的头部结点,
  * 通过这个头部结点可以找到这个链中的其它所有的notifier_block
  */
  static RAW_NOTIFIER_HEAD(test_chain);
  /*
  * 自定义的注册函数,将notifier_block节点加到刚刚定义的test_chain这个链表中来
  * raw_notifier_chain_register会调用notifier_chain_register
  */
  raw_notifier_chain_register(&test_chain, nb); // nb为struct notifier_block
  /*
  * 自定义的通知链表的函数,即通知test_chain指向的链表中的所有节点执行相应的函数
  */
  raw_notifier_call_chain(&test_chain, val, NULL);
举报

更多回帖

发帖
×
20
完善资料,
赚取积分