This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TI bq27421 Linux driver

Other Parts Discussed in Thread: BQ27541, BQ24295, BQSTUDIO

We used TI bq27421 battery fuel gauge in the product.

1) About the product, please refer as follows:

1-1) SoC:  MIPS processor

1-2) OS: OpenWrt (Linux kernel 3.7.6)

1-3) The bq27421 is connected to the I2C-bus (400 KHz) via i2c-gpio.

2) About the Linux driver for bq27421, we found several sample codes in the WEB sites as follows:

2-1) Linux/Android Software Solutions for TI Single-cell Gas Gauges

  processors.wiki.ti.com/.../Android_Software_Solutions_for_TI_Single-cell_Gas_Gauges

2-2) android / kernel / tegra / b445e5296764d18861a6450f6851f25b9ca59dee / . / drivers / power

android.googlesource.com/.../power

2-2-1) bq27441_battery.c

2-3) android / kernel / msm.git / 511b239792d76efc7456ef92735a1257c95eac44 / . / drivers / power / 

android / kernel / msm.git / 511b239792d76efc7456ef92735a1257c95eac44 / . / drivers / power / 

2-3-1) bq27541_fuelgauge.c

2-4) In the Linux kernel downloaded from FTP site (ftp.kernel.org).

2-4-1)  linux-4.4/drivers/power/bq27xxx_battery.c

For the product, could you tell us which sample codes in item 2) should we use for bq27421?

Thank you.

  • You can use any of these as a starting point but you will have to modify them for the bq27421 (data memory loactions, if they are accessed).
  • Thank you for your kind help.

    1) We will use the Linux driver in the URL as follows:
    processors.wiki.ti.com/.../Android_Software_Solutions_for_TI_Single-cell_Gas_Gauges
    1-1) Linux driver : bq27x00_battery.c

    1) About the modification of the Linux driver, you mentioned the "data memory locations",
    could you to tell us in more details?
    Q1-1) Is the data memory related to "dm" in the "rom_mode_gauge_dm_init()" routine of the driver in item 1) ?

    2) The CNTL FUNCTION via Control(): 0x00 and 0x01
    2-1) In the Linux driver in item 1), we found the routine as follows:
    2-1-1) It adds a 5 ms sleeping between write and read.
    static int control_cmd_read(struct bq27x00_device_info *di, u16 cmd)
    {
    dev_dbg(di->dev, "%s: cmd - %04x\n", __func__, cmd);

    di->bus.write(di, BQ27XXX_REG_CTRL, cmd, false);

    msleep(5);

    return di->bus.read(di, BQ27XXX_REG_CTRL, false);
    }

    2-2) But in the Linux driver for BQ27541 downloaded from the URL as follows:
    android / kernel / msm.git / 511b239792d76efc7456ef92735a1257c95eac44 / . / drivers / power /

    android.googlesource.com/.../bq27541_fuelgauger.c

    2-2-1) In the following routine, it adds a 66us delay between the write and read.

    static int bq27541_chip_config(struct bq27541_device_info *di)
    {
    int flags = 0, ret = 0;

    bq27541_cntl_cmd(di, BQ27541_SUBCMD_CTNL_STATUS);
    udelay(66);
    ret = bq27541_read(BQ27541_REG_CNTL, &flags, 0, di);


    Q3) Should we add 66 us delay or 5 ms sleeping between write and read the CNTL FUNCTION ?

    Thank you.
  • 1-1: yes, this is related to the data memory. The basic communication is the same for many single cell gauges but parameters in data memory are in different subclasses and offsets within subclasses. Check the TRM for the bq27421 and modify any code that touches the data memory to make sure that the parameters are written to the correct data memory subclasses and offsets.

    2: A 66us delay is necessary between I2C commands. Please use 66us.
  • 1) The driver we downloaded from the URL as follows:
    processors.wiki.ti.com/.../Android_Software_Solutions_for_TI_Single-cell_Gas_Gauges
    1-1) Linux driver : bq27x00_battery.c

    1-1-1) The driver contains the following structure.
    static struct dm_reg bq274xx_dm_regs[] = {
    {82, 0, 2, 1000}, /* Qmax */
    {82, 5, 1, 0x81}, /* Load Select */
    {82, 10, 2, 1340}, /* Design Capacity */
    {82, 12, 2, 3700}, /* Design Energy */
    {82, 16, 2, 3250}, /* Terminate Voltage */
    {82, 27, 2, 110}, /* Taper rate */
    };

    1-1-2) Does the data memory you mentioned above mean the structure in 1-1-1)?

    Thank you.
  • This structure refers to data which is stored in data memory.

  •  About the TI bq27421 fuel gauge on the PCB Assembly of the product, the Linux driver failed to

    access the Control() – SubCommand.

     

       1) The information of the product

       1-1) MIPS processor

       1-2) OS: Linux OpenWrt 3.7.6

       1-3) The 2 pins of I2C bus are generated by the 2 GPIO pins of the processor (“i2c-gpio” in Linux kernel).

       1-3-1) The frequency of I2C-bus is around 400KHz.

     

       2) About the access to the SubCommand, we measured the signaling of I2C bus.

       2-1) We use Agilent MSO9064A (Mixed Signal Oscilloscope).

    2-1-1) The 3 lines in the screen of Agilent MSO9064A:

      Yellow line: SCL of I2C

      Green line:  SDA of I2C

      Blue line: GPIO

     

       2-2) The bytes of data communication over the I2C-bus : 9-byte

       2-2-1) The first 4-byte: 

                     Write    0xaa, 0x00, 0x01, 0x00

       2-2-2) The next 2-byte

                     Write    0xaa, 0x00

       2-2-3) The last 3-byte

                     Read    0xab, 0x3f, 0xff

       2-3-3-1) The last 2-byte (0x3f, 0xff) are the value read from SubCommand and are incorrect value.

     

     2-3) About the waveforms of I2C-bus for the data communication (9-byte), please refer to the attachment below.

                The password to decompress the attachment is : 1234

       2-3-1) IG1_I2C_All.jpg

                     The picture describes the offset of time is around 110.08690179 ms between the first byte and the 5th byte..

       2-3-2) IG1_I2C_byte1234.jpg

                     The picture describes the waveforms of the first 4-byte.

       2-3-3) IG1_I2C_byte56789.jpg

                     The picture describes the waveforms of the last 5-byte.

       2-3-4) IG1_I2C_byte12.jpg

                     The picture describes the bit-pattern waveforms of the first 2-byte.

       2-3-5) IG1_I2C_byte3.jpg

                     The picture describes the bit-pattern waveforms of the 3th byte.

       2-3-6) IG1_I2C_byte4.jpg

                      The picture describes the bit-pattern waveforms of the 4th byte.

       2-3-7) IG1_I2C_byte56.jpg

                       The picture describes the bit-pattern waveforms of the 5th and 6th bytes.

       2-3-8) IG1_I2C_byte7.jpg

                       The picture describes the bit-pattern waveforms of the 7th byte.

       2-3-9) IG1_I2C_byte89.jpg

                       The picture describes the bit-pattern of 8th and  9th bytes.

     

       Are these information above enough?

       Could you do us a favor to tell us your comment ASAP?

     

       Thank you.

     

     

    I2C_bq27421_waveforms_09072016.7z

  • The sequence looks correct but your I2C rising edges are very slow. What is the value of your pull-up resistors and what is the total capacitive load on your I2C bus? Your scope screenshots show that the pull-ups are not strong enough.

  • 1) About the pull-up resistors, they are 10K ohm.

    1-1) About the details, please refer to the picture below (I2C_bus_pull-ups.jpg).

    2) About the total capacitive load on the I2C bus, please refer to the picture below (I2C_bus_bq27421.jpg).

    2-1)  The I2C_SCL and I2C_SDA connections are connected to the SCL and SDA pins of bq27421 directly.

    3) About the "pull-ups are not strong enough" issue, do you mean that we should reduce

    the value of pull-up resistors to higher the I2C rising edges?

    For examples:  reduce to 5K ohm.

    4) Is it useful for this issue if reducing the frequency of I2C bus to 100KHz?

    Thank you.

  • Thank you for your kind help.

    After we reduced the frequency of I2C-bus, it is OK to read the DEVICE_TYPE SubCommand now.

    1) In the "rom_mode_gauge_dm_init()" routine, it call the "rom_mode_gauge_init_completed()" routine.
    1-1) And in the "rom_mode_gauge_init_completed()" routine, it will read "CONTROL_STATUS" SubCommand.
    1-1-1) But the reading to this SubCommand always return 0x8 until timeout.
    1-2) And the INITCOMP bit (bit-7 of low byte) is not set.

    Why was the INITCOMP bit not set?

    Could you do us a favor to tell us your comment?
    Thank you.
  • If you want to use 400kHz SCL then you should reduce the pull up resistors. See http://www.ti.com/lit/an/slva689/slva689.pdf for more details.

    The gauge will only set INITCOMP when it detects a battery. See 2.4.2 in http://www.ti.com/lit/ug/sluuac5c/sluuac5c.pdf. Did the gauge detect a battery?

  • Thank you for your kind help.

    1) About the pull-up resistors

    1-1) There are 3 I2C slaves on the I2C-bus of the current PCB Assembly as follows:

    >> TI BQ24295, TI BQ27421, and NXP PCA9551

    1-1-1) The TI BQ24295 and NXP PCA9551 worked fine on 400KHz and 10K ohm pull-up resistors.

    1-1-2) We changed the pull-up resistors to 5K ohm, and the SubCommands of TI BQ27421 cannot be accessed on 400KHz.

    1-2) Are the "Pullup Resistor Calculation" in the "I2C Bus Pullup Resistor Calculation" document applicable for all the 3 I2C slaves

    or only for TIBQ27421?

    2) We connected the battery module, and it still displayed the error messages (INITCOMP not set after 100 seconds).

    2-1) We used "cat" command to view the content of the "power_supply/present" file in the file-system of the device and it displayed '1'.

    2-1-1) Does the "present" file mean whether the battery is detected ot not?

    2-2) Could you do us a favor to tell us your comment?

    Have a nice day.

  • 1: The document that I linked to applies to all devices on the I2C bus. However, the bq27421 has additional timing requirements between packets if you use 400kHz SCL. Check the datasheet for further details (esp. the 66us bus free time and the single packet restrictions for SCL > 100kHz).

    2: I can't tell what the expected result from the linux driver/file system is. INITCOMP should be set after 100 seconds so if it is not then there is something wrong with the battery detection.

  • Thank you for your kind help.

    About the INITCOMP bit, after POR, the gauge will load data from ROM into the RAM (data memory).

    And you told us that it is necessary to customize the data memory for the processor.

    So, this INITCOMP bit is related to the customization of data memory.

    Could you do us a favor to tell us how to customize the data memory for the processor?

    Thank you.

  • The gauge will load its default configuration from ROM during start-up. Once the initialization is completed (which includes copying ROM to RAM), the gauge will set the INITCOMP bit, indicating that it is ready to operate.

    If you want to customize the data memory for your system (set gauging parameters) then you can either use bqStudio and an EVM to set all gauging parameters as needed and then export a gm.fs file which includes all write commands that need to be executed by the system on the I2C bus to configure the gauge, or you can hard code the new configuration into your driver following the example in www.ti.com/.../sluuah7b.pdf

  • Thank you for your kind help.

    We designed the BQ27421 gauge the first time.

    1) In the Linux driver of TI BQ27421 (bq27x00_battery.c), there are many codes for the data memory (dm).

    These codes contains the string "dm" in the Linux driver.

    For examples: dm_regs, bq274xx_dm_regs[], and etc.

    Q-1) Could you tell us how to customize the codes for data memory (dm) in the Linux driver?

    2) You mentioned as follows:

    >> The gauge will load its default configuration from ROM during start-up.

    >> Once the initialization is completed (which includes copying ROM to RAM),

    >>  the gauge will set the INITCOMP bit, indicating that it is ready to operate

    Q2-1) Does the RAM mean the data memory (dm)?

    Q2-2) If the RAM is the data memory, should the codes for data memory in the Linux driver be customized for the processor

    before the copying ROM to RAM?

    3) You mentioned as follows:

    >> or you can hard code the new configuration into your driver following the example in www.ti.com/.../sluuah7b.pdf

    3-1) According to the Figure 1. of the document, the [Configure Standard Data Memory Parameters] block is executed

    after the [CFGUPMODE == 1] block.

    3-2) The error messages (INITCOMP not set after 100 seconds) is displayed by the Linux driver are in rom_mode_gauge_dm_init() routine.

    3-2-1) It calls rom_mode_gauge_init_completed() routine to poll the INITCOMP bit.

    3-2-2) If timeout, it displayed the error messages.

    If OK, it will call enter_cfg_update_mode() to write the  CFGUPDATE SubCommand.

    3-2-3) So, the error occurred before the [CFGUPMODE == 1] block in the Figure 1. of the document.

    3-2-4) The [Configure Standard Data Memory Parameters] block in the Figure 1. of the document is not executed yet.

    Q3-3) Is the root cause of the error data memory (dm) not correctly customized in the Linux driver?

    Thank you.

  • Thank you for your kind help.

    The BQ27421 gauge works on 100 KHz (the frequency of I2C-bus) in the product now.

    And we are customizing the driver and debugging the 400 KHz issue in the product.

    Please do us a favor to close this case.

    Have a nice day.