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.

BQ28Z610: Driver for BMS

Part Number: BQ28Z610
Other Parts Discussed in Thread: BQSTUDIO

Hi All.

           I am trying to read the serial number from the BQ28Z610. I found that Linux kernel mainline driver do not have such an option. So to patch up. I am using the following 

ret = bq27xxx_read(di, 0x4E,false);

In datasheet the reading format is not mentioned as block. So getting bit confused.

-Curious beast

  • Hello Curious,

    Serial number is always 2 bytes. You can try it from bqStudio Advanced Comm function to confirm and determine that the read is similar. Interpretation of bytes is slightly different.

  • Hello Shiriish,

                              I am interfacing with the linux driver. I am  bit confused with the way I  can read the serial number. The datasheet says, that I should use the 4E for reading. But If I see other values in the same table which are blocks, I am getting bit confused.

     Refering to the Linux driver in the mainline kernel, Am I reading the correct value.

    -Curious

  • Hello Curious,

    I believe the linux driver does reads that are not preceded by writes. If you are just trying to read 0x4E, then that will not work.

    One way to do this is to write block 4E00 to address 0x00 followed by a read at address 00. Use the block read function and read out 4 bytes for testing. The first 2 bytes may be the command itself especially when address 0x3E is used instead of 0x00

    This is explained in the TRM  section 12.2 0x00, 0x01 AltManufacturerAccess() and 0x3E, 0x3F AltManufacturerAccess()

  • Hello Shrish,

    static int bq27xxx_battery_serialnumber(struct bq27xxx_device_info *di,
                   union power_supply_propval *val)
    {
       const int limit = 100;
       u16 cmd = 0x4E00;
       int ret, try = limit;

       ret = bq27xxx_write(di, BQ27XXX_REG_CTRL, cmd, false);
       if (ret < 0)
          return ret;

       do {
          BQ27XXX_MSLEEP(25);
          ret = bq27xxx_read(di, BQ27XXX_REG_CTRL, false);
          dev_warn(di->dev, "ret %d\n", ret);
          if (ret < 0)
             return ret;
       } while (--try);

       if (limit - try > 3)
          dev_warn(di->dev, "retries %d\n", limit - try);

       return 0;

    }
    I am trying out in this fashion. Based on your points. But I have not got correct results..
  • Hello Curious,

    I have not looked at the Linux code but i would suggest trying cmd=0x004E (Endianness reversed)

    And if you are adding a retry loop, it should include the write command too.

    If the above does not work, then for debug purposes, try cmd=0x00 which should return 0x2610

    Post the read results, sometimes that gives a clue.

  • Hi Shrish,

    static int bq27xxx_battery_serialnumber(struct bq27xxx_device_info *di,
                   union power_supply_propval *val)
    {
       const int limit = 10;
       u16 cmd = 0x0000;
       int ret, try = limit;

       do {
          ret = bq27xxx_write(di, BQ27XXX_REG_CTRL, cmd, false);
          if (ret < 0)
             return ret;

          BQ27XXX_MSLEEP(1);
          ret = bq27xxx_read(di, BQ27XXX_REG_CTRL, false);
          dev_warn(di->dev, "ret %d\n", ret);
          if (ret < 0)
             return ret;
       } while (--try);

       if (limit - try > 3)
          dev_warn(di->dev, "retries %d\n", limit - try);

       return 0;

    }
    With the following code the result I received was 
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: retries 10
  • Sorry, had a typo.

    Try with cmd=0x0001 and cmd=0x0100 and post both results.

  • Hi Srhish,

    static int bq27xxx_battery_serialnumber(struct bq27xxx_device_info *di,
                   union power_supply_propval *val)
    {
       const int limit= 10;
       u16 cmd = 0x0001;
       int ret, try = limit;

       do {
          ret = bq27xxx_write(di, BQ27XXX_REG_CTRL, cmd, false);
          if (ret < 0)
             return ret;

          BQ27XXX_MSLEEP(1);
          ret = bq27xxx_read(di, BQ27XXX_REG_CTRL, false);
          dev_warn(di->dev, "ret %d\n", ret);
          if (ret < 0)
             return ret;
       } while (--try);

       if (limit - try > 3)
          dev_warn(di->dev, "retries %d\n", limit - try);

       return 0;
    }
     
    bq27xxx-battery 1-0055: ret 65445
    bq27xxx-battery 1-0055: ret 65445
    bq27xxx-battery 1-0055: ret 65445
    bq27xxx-battery 1-0055: ret 65445
    bq27xxx-battery 1-0055: ret 65445
    bq27xxx-battery 1-0055: ret 65445
    bq27xxx-battery 1-0055: ret 65445
    bq27xxx-battery 1-0055: ret 65445
    bq27xxx-battery 1-0055: ret 65445
    bq27xxx-battery 1-0055: ret 65445
    bq27xxx-battery 1-0055: retries 10
    xT▒
    When used cmd = 0x100
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: ret 25091
    bq27xxx-battery 1-0055: ret 25091
    Today  I tried another approach..
    BQ27XXX_SERIAL_NUMBER = 0x4E 
    BQ27XXX_REG_SERIAL = 0
    static int bq27xxx_battery_serialnumber(struct bq27xxx_device_info *di,
                   union power_supply_propval *val)
    {
       const int limit = 10;
       u16 cmd = BQ27XXX_SERIAL_NUMBER;
       int ret, try = limit;
       char serial_number[4];

       do {
          ret = bq27xxx_write(di, BQ27XXX_REG_SERIAL, cmd, false);
          if (ret < 0)
             return ret;

          BQ27XXX_MSLEEP(1);
          ret = bq27xxx_read(di, BQ27XXX_REG_SERIAL, false);
          if (ret < 0)
             return ret;
       } while (--try);
       scnprintf(di->serial_number, 4, "%d",(u16)ret);
       val->strval = di->serial_number;

       return 0;
    }
    This is the driver which I am using for my experimentation.
    root@petalinux_delhi:~# cat /sys/class/power_supply/bq28z610-0/serial_number
    78
    Please let me know wherther I am on the right path?
  • Yes, you are on the right path with the first one =0x0001, then you should be able to read serial number.

    Note that 65545 = 0xFFA5

    Now try that with cmd=0x004E. That should give the serial number that you programmed in data flash.

    If you don't get expected results then replace   ret = bq27xxx_read(di, BQ27XXX_REG_CTRL, false); with  

    ret = bq27xxx_read(di, 0x40, false); or   ret = bq27xxx_read(di, 0x3E, false); One of these should give the right result.

  • Hi Shirish,

                      Thank you for the response. Our Hw engineer will test it with Bq studio. I will test it with my implementation against and I will update my results.

    -Curiousbeast

  • Hi Shirish,

                        Here are my results. 

    static int bq27xxx_battery_serialnumber(struct bq27xxx_device_info *di,
                   union power_supply_propval *val)
    {
       const int limit = 5;
       u16 cmd = BQ27XXX_SERIAL_NUMBER;
       int ret, try = limit;
       char data[6];
       u32 serialnumber;

       do {
          ret = bq27xxx_write(di, BQ27XXX_REG_SERIAL, cmd, false);
          if (ret < 0)
             return ret;

          BQ27XXX_MSLEEP(1);
          ret = bq27xxx_read_block(di, BQ27XXX_REG_SERIAL, data,sizeof(data)/sizeof(data[0]));
          if (ret < 0)
             return ret;
       } while (--try);

       serialnumber |= data[5]<<24;
       serialnumber |= data[4]<<16;
       serialnumber |= data[3]<<8;
       serialnumber = data[2];

       sprintf(di->serial_number, "%04x", serialnumber);
       val->strval = di->serial_number;
       return 0;
    }
    In addition to that I used i2cl tool  to check the same

    i2ctransfer -f -y 1 w3@0x55 0x3E 0x4E 0x00 && i2ctransfer -f -y 1 w1@0x55 0x3E r4

    In addition to that I got bqstudio and cross verified the device. 

    Thank you for your help and guidance.