[Linux driver] Detailed debugging of Android charging chip bq24735

1. Introduction to bq24735

The bq24735 is a high efficiency synchronous battery charger.

The bq24735 uses Smart Boost technology to allow the battery to release energy into the system when the system power demand is temporarily higher than the adapter's maximum power level, thus protecting the adapter from damage.

The bq24735 uses 2 charge pumps to drive n-channel MOSFETs (ACFET, RBFET and BATFET) separately for automatic system power selection.

SMBus (I2C bus) controlled input current, charge current, and charge voltage DACs allow for very high regulation accuracy that can be easily programmed by the system power management microcontroller.

The bq24735 uses an internal input current register or an external ILIM pin to slow down PWM modulation to reduce charging current.

Second, the Linux kernel charging architecture

To understand the bq24735 driver, you must first understand the Android power supply system framework. The most important knowledge point is power supply.

1. Android power supply system framework

​​

Power supply (hereinafter referred to as psy) is a subsystem abstracted from the power supply driver in Linux, and an important part of Linux power management.

psy is an intermediate layer, which is part of the device driver in the kernel. The function of psy is to summarize various power supply status information to the user space.

All kinds of abstracted information are called properties, for example, whether the power supply device is connected corresponds to POWER_SUPPLY_PROP_ONLINE .

2. Power supply function

The software architecture of power_supply:

Power supply framework features include:

  1. Abstract the commonality of PSY devices and provide a unified API to user space;
  2. Provides a simple and unified way for the writing of the underlying PSY driver, while encapsulating and implementing common logic.

The power supply class is located in the drivers/power/ directory and mainly consists of 3 parts (refer to the software architecture in the following figure):

  • 1) power_supply_core, which is used to abstract core data structures and implement common logic. Located in drivers/power/power_supply_core.c.
  • 2) power_supply_sysfs, which implements sysfs and uevent functions. Located in drivers/power/power_supply_sysfs.c.
  • 3) power_supply_leds, based on the Linux led class, provides a general implementation of PSY device status indication. Located in drivers/power/power_suppply_leds.c.

Finally, the driver engineer can implement specific PSY drivers based on the power supply class, mainly dealing with platform-related and hardware-related logic. These drivers are located in the drivers/power/power_supply directory.

3. Driver layer function

In the driver layer, there are mainly two modules, which are related to battery monitoring (fuelgauge) and driver related to charging and discharging management (charger) (corresponding to battery.c and charger.c in the figure). These two modules mainly deal with hardware-related Logic, when the hardware state changes, the relevant interrupt will be triggered, the driver layer will call the corresponding interrupt function, and update and modify the corresponding psy node value.

The fuelgauge driver is mainly responsible for providing the current battery power and health status information to the upper android system, etc. In addition to this, it also provides battery-related information to the charger driver; the charger driver is mainly responsible for the plugging and unplugging detection of the power cord, and charging Discharge process management.

For battery management, there are fuel gauge ICs and charge and discharge ICs on the hardware. Of course, some manufacturers will integrate fuel gauge and charge and discharge functions into one IC for cost considerations. What's more, they may also integrate PMU functions. on a silicon surface.

4. Other issues

Q: How does android know what power supply is currently, whether it is charging or not?

A: The uevent mechanism (essentially a socket in the form of net_link) (widely used in hotplug), when charging is inserted and disconnected, the kernel tells android by sending uevent information.

Q: How does android know various parameters and update them?

Answer: Send a notification to the upper layer through kobject_uevent, and the upper layer reads the sys-related file attributes

The following is the sysfs file directory of a platform

root@********_arm64:/sys/class # pwd
sys/class/power_supply
root@********_arm64:/sys/class/power_supply # ls
ac
battery
bq24735@5-0009
usb
root@********_arm64:/sys/class/power_supply # cd bq24735@5-0009
cd bq24735@5-0009
root@*********_arm64:/sys/class/power_supply/bq24735@5-0009 # ls
device
online
power
status
subsystem
type
uevent                                                                              

[Article Welfare] The editor has sorted out some learning books and materials that I think are better. If you need it, you can reply by private message [ Core ] Get it for free! !

Three, bq24735 driver implementation

The following is based on a certain soc to explain how to make our products support bq24735.

1. Hardware connection diagram

The following is a typical bq24735 circuit connection diagram:
 When there is no power supply, the bq24735 will directly pass the battery to the step-down circuit to power the system.
When there is power supply, the bq24735 will charge the battery.

2. Pin Description

Here we only introduce the pins related to driving

3. Register

The registers used by the bq24735 are as follows:

  1. Charge Options Register Charge Options Register [reset = 0x12H]


The most important two bits bit[4]/bit[0]
bit:[4]

0: AC adapter不在 (ACDET < 2.4 V)  
1: AC adapter存在(ACDET > 2.4 V)

bit:[0]

0: 使能充电
1: 抑制充电

This register is readable and writable.
If you want to judge whether it is currently charging, you can read this register, and confirm by judging whether bit[0] is 0.
If you want to judge whether it is currently there, you can read this register, and judge the bit [4] is 1 to confirm

  1. Charge Current Register (0x14H)

The charge current can be set through this register.

For example, we want to set the charging current to 3072mA,
the value is 2048+1024, the corresponding bite[10]/[11] is 1, and the other bits are 0

1100 0000 0000

That is, set the register value to:0xC00

  1. Charge Voltage Register (0x15H)

    The setting method of this register is similar to充电电流寄存器

  2. Input Current Input Current Register (0x3FH)

    The setting method of this register is similar to充电电流寄存器

  3. 0xfe, 0xff
    these two registers read MANUFACTURER_ID and DEVICE_ID respectively

The two values ​​are: 0x0040, 0x000B

When the driver is initialized, it can be judged by reading the values ​​of these two registers whether the driver matches the hardware.

Note:
Usually register 0x14, 0x15, 0x3F values ​​need to ask hardware engineer

4. Device tree

bq24735@9 {
    
    
	compatible = "ti,bq24735";
	reg = <0x9>;
	ti,ac-detect-gpios = <&gpio 72 0x1>;
	ti,charge-current =<0x600>;
	ti,charge-voltage=<0x41a0>;
	ti,input-current =<0x800>;
}

Parameter Description

compatible :用于和驱动的结构体i2c_driver的driver.of_match_table->compatible属性进行匹配
reg:bq24735从设备地址(I2C)
ti,ac-detect-gpios:中断使用的gpio,第三个参数是该pin默认电平
ti,charge-current :充电电流
ti,charge-voltage :充电电压
ti,input-current  :输入电流

5. Driver explanation

  1. Driver file
    The driver already exists in the kernel code
drivers\power\bq24735-charger.c

However, the driver often needs to be modified to adapt to the actual solution.

The driver is based on the I2C bus, and the corresponding structure variables are defined as follows:

static struct i2c_driver bq24735_charger_driver = {
    
    
	.driver = {
    
    
		.name = "bq24735-charger",
		.owner = THIS_MODULE,
		.of_match_table = bq24735_match_ids,
	},
	.probe = bq24735_charger_probe,
	.remove = bq24735_charger_remove,
	.id_table = bq24735_charger_id,
};
  1. main function
static bool bq24735_charger_is_present(struct bq24735 *charger)
判断bq24735 是否存在
其实就是读取寄存器0x12的值,判断bit[4]值是否为1
static int bq24735_charger_is_charging(struct bq24735 *charger)
判断bq24735 是否在充电
其实就是读取寄存器0x12的值,判断bit[0]值是否为0
static inline int bq24735_enable_charging(struct bq24735 *charger)
使能充电
将寄存器寄存器0x12的bit[0]0
static inline int bq24735_disable_charging(struct bq24735 *charger)
禁止充电
将寄存器寄存器0x12的bit[0]1
static int bq24735_config_charger(struct bq24735 *charger)
配置充电电压(寄存器0x15)、充电电流(寄存器0x14)、输入电流(寄存器0x3f)
static irqreturn_t bq24735_charger_isr(int irq, void *devid)
中断处理函数,
当bq24735充电状态发生变化的时候,会发送中断给cpu
此时可以通过I2C来读取寄存器0x12的内容来获取bq24735当前状态
static int bq24735_charger_get_property(struct power_supply *psy,
					enum power_supply_property psp,
					union power_supply_propval *val)
提供给power supply子系统的回调函数
该函数用于获取bq24735当前状态

状态包括
enum {
    
    
	POWER_SUPPLY_STATUS_UNKNOWN = 0,
	POWER_SUPPLY_STATUS_CHARGING,  //正在充电
	POWER_SUPPLY_STATUS_DISCHARGING, 
	POWER_SUPPLY_STATUS_NOT_CHARGING,//没有充电
	POWER_SUPPLY_STATUS_FULL,//充满
};
  1. probe process

Here, the process of detecting MANUFACTURER_ID and DEVICE_ID has been slightly modified. It will only be checked and configured when bq24735 is present.

In addition, there is the most important institution

	supply_desc->name = name;
	supply_desc->type = POWER_SUPPLY_TYPE_MAINS;
	supply_desc->properties = bq24735_charger_properties;
	supply_desc->num_properties = ARRAY_SIZE(bq24735_charger_properties);
	supply_desc->get_property = bq24735_charger_get_property;
supply_desc->properties
	提供给power supply架构可以访问的命令的集合,
	这些命令需要在函数supply_desc->get_property增加对应的命令代码
supply_desc->get_property
	power supply会定时通过该回调函数获取充电芯片是否在线、是否在充电等状态
  1. Code architecture

    This architecture is the architecture drawn by Yikoujun according to the platform in the project. The architecture of other platforms may be different, and
    specific problems need to be analyzed in detail.

Fourth, log

The following log is the boot process log, the
first step is
to start with battery power


After booting, plug in the power supply to charge, after plugging in the power
supply, the bq24735 will trigger an interrupt:

then disconnect the power supply to stop charging

Guess you like

Origin blog.csdn.net/daocaokafei/article/details/123122783