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.

BQ27621-G1: question about Unsel and seal mode

Part Number: BQ27621-G1

Hi team,

customer use BQ27621-G1, have below questions

1. In the initialize, customer change to unseal mode, and check the register status,confirm that the device enter to unseal mode. then, write register, change to seal mode, check the status register foun it still unseal mode. quesiton is how to enter seal mode correctly?

2. firstly, customer read 0x40 register data, it is 0x8a. then, they change 32bit of 0x40, read reg 0x60 again, found the data of reg 0x60 still is 0x8a. they can't unpdate checksum registers.

I attached customer code file, please help check what cause this issue. thanks

BQ27621.c
/*
 *
 * Battery driver for BQ27621-G1
 */
#include <ti/devices/cc13x2_cc26x2/driverlib/cpu.h>
#include "Alipower.h"
#include "board_uart.h"
#include "Bq.h"
#include "onboard.h"
#define BQ27621_ADDR                  0x55
#define BQ27621_ADDR_FLAGS                  0x55
#define BQ27621_TYPE_ID                     0x0621
#define REG_CTRL                            0x00
#define REG_TEMPERATURE                     0x02
#define REG_VOLTAGE                         0x04
#define REG_FLAGS                           0x06
#define REG_NOMINAL_CAPACITY                0x08
#define REG_FULL_AVAILABLE_CAPACITY         0x0a
#define REG_REMAINING_CAPACITY              0x0c
#define REG_FULL_CHARGE_CAPACITY            0x0e
#define REG_EFFECTIVE_CURRENT               0x10
#define REG_AVERAGE_POWER                   0x18
#define REG_STATE_OF_CHARGE                 0x1c
#define REG_INTERNAL_TEMPERATURE            0x1e
#define REG_REMAINING_CAPACITY_UNFILTERED   0x28
#define REG_REMAINING_CAPACITY_FILTERED     0x2a
#define REG_FULL_CHARGE_CAPACITY_UNFILTERED 0x28
#define REG_FULL_CHARGE_CAPACITY_FILTERED   0x2a
#define REG_STATE_OF_CHARGE_UNFILTERED      0x30
#define REG_OP_CONFIG                       0x3a
#define REG_DESIGN_CAPACITY                 0x3c
#define REG_DATA_CLASS                      0x3e
#define REG_DATA_BLOCK                      0x3f   //
#define REG_BLOCK_DATA_CHECKSUM             0x60
#define REG_BLOCK_DATA_CONTROL              0x61
#define REGISTERS_BLOCK_OFFSET                64
#define REGISTERS_BLOCK_OP_CONFIG           0x40
#define REGISTERS_BLOCK_OP_CONFIG_B         0x42
#define REGISTERS_BLOCK_DF_VERSION          0x43
/* State block */
#define STATE_BLOCK_OFFSET                    82

#if 1
#define STATE_BLOCK_DESIGN_CAPACITY         0x43
#define STATE_BLOCK_DESIGN_ENERGY           0x45
#define STATE_BLOCK_TERMINATE_VOLTAGE       0x49
#define STATE_BLOCK_TAPER_RATE              0x54
#else
#define STATE_BLOCK_DESIGN_CAPACITY         0x4A
#define STATE_BLOCK_DESIGN_ENERGY           0x4C
#define STATE_BLOCK_TERMINATE_VOLTAGE       0x50
#define STATE_BLOCK_TAPER_RATE              0x5B

#endif
/* BQ27621 Control subcommands */
#define CONTROL_CONTROL_STATUS   0x00
#define CONTROL_DEVICE_TYPE      0x01
#define CONTROL_FW_VERSION       0x02
#define CONTROL_PREV_MACWRITE    0x07
#define CONTROL_CHEM_ID          0x08
#define CONTROL_BAT_INSERT       0x0C
#define CONTROL_BAT_REMOVE       0x0D
#define CONTROL_TOGGLE_POWERMIN  0x10
#define CONTROL_SET_HIBERNATE    0x11
#define CONTROL_CLEAR_HIBERNATE  0x12
#define CONTROL_SET_CFGUPDATE    0x13
#define CONTROL_SHUTDOWN_ENABLE  0x1B
#define CONTROL_SHUTDOWN         0x1C
#define CONTROL_SEALED           0x20
#define CONTROL_TOGGLE_GPOUT     0x23
#define CONTROL_ALT_CHEM1        0x31
#define CONTROL_ALT_CHEM2        0x32
#define CONTROL_RESET            0x41
#define CONTROL_SOFT_RESET       0x42
#define CONTROL_EXIT_CFGUPDATE   0x43
#define CONTROL_EXIT_RESIM       0x44
#define CONTROL_UNSEAL           0x8000
/* BQ27621 Status bits */
#define STATUS_SHUTDOWNEN        0x8000
#define STATUS_WDRESET           0x4000
#define STATUS_SS                0x2000
#define STATUS_CALMODE           0x1000
#define STATUS_OCVCMDCOMP        0x0200
#define STATUS_OCVFAIL           0x0100
#define STATUS_INITCOMP          0x0080
#define STATUS_HIBERNATE         0x0040
#define STATUS_POWERMIN          0x0020
#define STATUS_SLEEP             0x0010
#define STATUS_LDMD              0x0008
#define STATUS_CHEMCHNG          0x0001
/* BQ27621 Flags bits */
#define FLAGS_OT                 0x8000
#define FLAGS_UT                 0x4000
#define FLAGS_FC                 0x0200
#define FLAGS_CHG                0x0100
#define FLAGS_OCVTAKEN           0x0080
#define FLAGS_ITPOR              0x0020
#define FLAGS_CFGUPD             0x0010
#define FLAGS_BAT_DET            0x0008
#define FLAGS_SOC1               0x0004
#define FLAGS_SOCF               0x0002
#define FLAGS_DSG                0x0001


#define I2C_PORT_BATTERY         0x55
#define EC_ERROR_UNKNOWN         1
#define EC_SUCCESS               0
#define EC_ERROR_UNIMPLEMENTED   1

#define BQ27621_DM_DATA          0x40
#define BQ27621_DM_SZ            32

union ComTpye
{
    uint16_t iRet;
    uint8_t NumArrary[2];
};


void Udelay(unsigned int per)
{
	CPUdelay(per);

}

struct bq27621_dm_buf {
    uint8_t class;
    uint8_t block;
    uint8_t data[BQ27621_DM_SZ];
    bool has_data, dirty;
};

struct bq27621_dm_reg {
    uint8_t subclass_id;
    uint8_t offset;
    uint8_t bytes;
    uint16_t min, max;
};

enum bq27621_dm_reg_id {
    BQ27621_DM_DESIGN_CAPACITY = 0,
    BQ27621_DM_DESIGN_ENERGY,
    BQ27621_DM_TERMINATE_VOLTAGE,
};


/*
 * There are some parameters that need to be defined in the board file:
 * BQ27621_TOGGLE_POWER_MIN -  Put it in minimum power mode
 *    (may affect I2C timing)
 * BQ27621_DESIGN_CAPACITY -   mAh 450
 * BQ27621_DESIGN_ENERGY -     Design Capacity x 3.7
 * BQ27621_TERMINATE_VOLTAGE - mV 3000
 * BQ27621_TAPER_CURRENT -     mA  25
 * BQ27621_CHEM_ID -           0x1202 (DEFAULT) 0x1210 (ALT_CHEM1)
 *                             0x354 (ALT_CHEM2)
 *
 * For extra large or extra small batteries, this driver scales everything but
 * voltages.  The recommended range is 150mAh - 6Ah
 *
 */

#define BQ27621_DESIGN_CAPACITY   450//450
#define BQ27621_DESIGN_ENERGY     1665//1665 //(450*3.7)
#define BQ27621_TERMINATE_VOLTAGE 3300//3300
#define BQ27621_TAPER_CURRENT    90//500// 90  //25
#define BQ27621_CHEM_ID           0x1202


#define BQ27621_SCALE_FACTOR (BQ27621_DESIGN_CAPACITY < 150 ? 10.0 : \
				(BQ27621_DESIGN_CAPACITY > 6000 ? 0.1 : 1))
				
#define BQ27621_UNSCALE(x)   (BQ27621_SCALE_FACTOR == 10 ? (x) / 10 : \
				(BQ27621_SCALE_FACTOR == 0.1 ? (x) * 10 : (x)))


#define BQ27621_TAPER_RATE  ((int)(BQ27621_DESIGN_CAPACITY/    \
				(0.1 * BQ27621_TAPER_CURRENT)))


#define BQ27621_SCALED_DESIGN_CAPACITY ((int)(BQ27621_DESIGN_CAPACITY *   \
					BQ27621_SCALE_FACTOR))


#define BQ27621_SCALED_DESIGN_ENERGY   ((int)(BQ27621_DESIGN_CAPACITY *   \
					BQ27621_SCALE_FACTOR))




/*
 *Everything is LSB first.  Parameters need to be converted.
 *
 * The values from the data sheet are already LSB-first.
 */

#define ENDIAN_SWAP_2B(x)     ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))

#define DESIGN_CAPACITY       ENDIAN_SWAP_2B(BQ27621_SCALED_DESIGN_CAPACITY)

#define DESIGN_ENERGY         ENDIAN_SWAP_2B(BQ27621_SCALED_DESIGN_ENERGY)

#define TAPER_RATE            ENDIAN_SWAP_2B(BQ27621_TAPER_RATE)

#define TERMINATE_VOLTAGE     ENDIAN_SWAP_2B(BQ27621_TERMINATE_VOLTAGE)




static uint8_t bq27621_read(int offset, int *data)
{
    uint8_t status=1;

    union ComTpye CommandData;

    uint8_t data1[2]={0};

    status=Ali_I2c_read( (uint8_t*)(&offset) ,data1, 2, BQ27621_ADDR ); //(uint8_t*)

#if 1
	CommandData.NumArrary[0]=data1[0];

	CommandData.NumArrary[1]=data1[1];
#else
	CommandData.NumArrary[0]=data1[1];

	CommandData.NumArrary[1]=data1[0];
#endif

	*data=CommandData.iRet ;

	return status ;

}

static uint8_t bq27621_read8(int offset, int *data)
{

	return Ali_I2c_read((uint8_t*)(&offset),(uint8_t*)data,1,BQ27621_ADDR);
}

static uint8_t bq27621_write(int offset, int data)
{
    union ComTpye CommandData;

    CommandData.iRet=(uint16_t)(data);

//    Printf("CommandData.NumArrary[0]->[0x%x]\n",CommandData.NumArrary[0]);
//    Printf("CommandData.NumArrary[1]->[0x%x]\n",CommandData.NumArrary[1]);
#if 1
    uint8_t txBuffer[ ]={(uint8_t)offset,CommandData.NumArrary[0],CommandData.NumArrary[1]};
#else

	uint8_t txBuffer[ ]={(uint8_t)offset,CommandData.NumArrary[1],CommandData.NumArrary[0]};


#endif

	return Ali_I2c_write(txBuffer, 3, BQ27621_ADDR);

}

static uint8_t bq27621_write8(int offset, int data)
{

    uint8_t txBuffer[2]={(uint8_t)offset,(uint8_t)data};

    return Ali_I2c_write(txBuffer, 2, BQ27621_ADDR);
}

//added by lee
void bq27621_delay_msek(uint32_t msek)
{
    /*Here you can write your own delay routine*/

    CPUdelay(12000 * msek);
}

static uint8_t bq27621_battery_cfgupdate_priv(bool active)
{
    const uint8_t limit = 100;
    int cmd = active ? CONTROL_SET_CFGUPDATE : CONTROL_SOFT_RESET;
    int try = limit;
    int flags = 0;
    uint8_t ret;

    ret = bq27621_write(REG_CTRL, &cmd);
    if (ret == 1)
        return ret;

    do {

        bq27621_delay_msek(25);

		if(cmd==CONTROL_SOFT_RESET)
			ret = bq27621_write(REG_CTRL, &cmd);

        ret = bq27621_read(REG_FLAGS,&flags);

        if (ret ==1 )
            return ret;
    } while (!!(flags & ((1 << 4))) != active && --try);

    return 0;
}


static uint8_t bq27621_battery_set_cfgupdate(void)
{
    int ret = bq27621_battery_cfgupdate_priv(true);

    if (ret ==1 )
    {
        Printf("bus error on set_cfgupdate: %d\n", ret);
    }

    return ret;
}

static int bq27621_battery_soft_reset(void)
{
    int ret = bq27621_battery_cfgupdate_priv(false);

    if (ret ==1)
    {
        Printf("bus error on soft_reset: %d\n", ret);
    }
    return ret;
}

//added end

static int bq27621_probe(void)
{
    uint8_t rv;
	int battery_type_id,RecData;

	rv=bq27621_write(REG_CTRL, CONTROL_DEVICE_TYPE);

	rv |=bq27621_read(REG_CTRL, &battery_type_id);

	Printf(" battery type id is 0x%04x\n",battery_type_id);

	rv |= bq27621_write(REG_CTRL , CONTROL_CHEM_ID); // 0x08  CONTROL_CHEM_ID

    rv |= bq27621_read(REG_CTRL, &RecData);

    Printf("CONTROL CHEM ID[0x%04x]\n",RecData);


	if (rv)
		return rv;

	if (battery_type_id == BQ27621_TYPE_ID)
	{
	    Printf("identify  the BQ27621\n");

		return EC_SUCCESS;
	}

	return EC_ERROR_UNKNOWN;
}
static int bq27621_unseal(void)
{

	bq27621_write(REG_CTRL, CONTROL_UNSEAL);
	bq27621_write(REG_CTRL, CONTROL_UNSEAL);

	return 1;


}
static int bq27621_enter_config_update(void)
{

	int tries, flags = 0, rv = EC_SUCCESS;

	/* Enter Config Update Mode (Can take up to a second) */
	for (tries = 2000; tries > 0 && !(flags & FLAGS_CFGUPD) &&
					(rv == EC_SUCCESS); tries--)
	{
	    
		rv |= bq27621_write(REG_CTRL, CONTROL_SET_CFGUPDATE);

		//step 3
		rv |= bq27621_read(REG_FLAGS, &flags);

	}

	Printf("tries[%d]\n",tries);

	if (tries == 0)
	{
		return 1;
	}
	else
		return 0;
}

static int bq27621_enter_block_mode(int block)
{
	int rv;
	Printf("step 4 before\n");
	//step 4
	rv = bq27621_write8(REG_BLOCK_DATA_CONTROL, 0); //REG_BLOCK_DATA_CONTROL   0x61
	Printf("step 4 after\n");


	Printf("step 5 before\n");
	//setp 5
	rv |= bq27621_write8(REG_DATA_CLASS, block);  // 0x52
	Printf("step 5 after\n");


	Printf("step 6 before\n");
	//step 6
	rv |= bq27621_write8(REG_DATA_BLOCK, 0);
	
	Printf("step 6 after\n");
	
	CPUdelay(12000);//udelay(500); /* Shouldn't be needed, doesn't work without it. */


	return rv;
}

static int verity_ramupdate_correctly(uint8_t newchecknum)
{
	int rv;
	uint32_t chksum=0;
	
	rv = bq27621_write8(REG_DATA_CLASS, 0x52);  // 0x52

	if(rv==1)
	{
		Printf("write reg data class faile\n");
	}
	
	rv = bq27621_write8(REG_DATA_BLOCK, 0);

	if(rv ==1)
	{
		Printf("write reg data block faile\n");
	}

	rv = bq27621_read(REG_BLOCK_DATA_CHECKSUM,&chksum);

	if(rv ==1)
	{
		Printf("read reg  block data checksum faile\n");
	}

	if (newchecknum !=chksum)
	{
		Printf("newchecknum[0x%x] !=chksum[0x%x]\n",newchecknum,chksum);
		return 1;
	}

	return 0;
	 

}



#if 0
static int bq27621_seal(void)
{

lulu:
	int rv = 0;
	int status = 0, param = 0, checksum = 0;
	rv |= bq27621_write(REG_CTRL, CONTROL_CONTROL_STATUS);
	
	rv |= bq27621_read(REG_CTRL, &status);
	if (status & STATUS_SS) /* Already sealed */
	{
		Printf("bq27621 seal Already sealed\n");
		return EC_SUCCESS;
	}
#if 1
	/* Enter Config Update Mode */
#if 0
	rv = bq27621_enter_config_update();
#else
	rv = bq27621_battery_set_cfgupdate( );
#endif
	if (rv)
	{
	    Printf("Enter Config Update Mode faile\n");
		return rv;
	}
	/* Set up block RAM update */
	rv = bq27621_enter_block_mode(REGISTERS_BLOCK_OFFSET);
	if (rv)
	{
	    Printf("Set up block RAM update faile\n");
		return rv;
	}

	rv = bq27621_read8(REG_BLOCK_DATA_CHECKSUM, &checksum);

	if (rv)
	{
	    Printf("Read REG_BLOCK_DATA_CHECKSUM faile\n");
		return rv;
	}
	checksum = 0xff - checksum;
	rv = bq27621_read8(REGISTERS_BLOCK_OP_CONFIG_B, &param);
	
	checksum -= param; /* 1B */
	param |= 1<<5; /* Set DEF_SEAL */
	rv = bq27621_write8(REGISTERS_BLOCK_OP_CONFIG_B, param);
	
	checksum += param; /* 1B */
	checksum = 0xff - (0xff & checksum);
	rv = bq27621_write8(REG_BLOCK_DATA_CHECKSUM, checksum);
	
	if (rv)
	{
	    Printf("REG BLOCK DATA CHECKSUM FAILE.....\n");
		return rv;
	}

	CPUdelay(12000*100);
#endif

	/* Exit Update */
	rv = bq27621_battery_soft_reset();

    rv = bq27621_write(REG_CTRL, CONTROL_SEALED);

	rv |= bq27621_write(REG_CTRL, CONTROL_CONTROL_STATUS);


	rv |= bq27621_read(REG_CTRL, &status);

	if (status & STATUS_SS) /* Already sealed */
	{
		Printf("bq27621 seal Already sealed\n");
		return EC_SUCCESS;
	}
	else
	{
	    Printf("bq27621 seal set up faile.........\n");
//	    goto lulu;
	}
	
	return rv;
}
#else
static int bq27621_seal(void)
{
    int rv = 0;
    int status = 0, param = 0, checksum = 0;
    rv |= bq27621_write(REG_CTRL, CONTROL_CONTROL_STATUS);
    rv |= bq27621_read(REG_CTRL, &status);
    if (status & STATUS_SS) /* Already sealed */
        return EC_SUCCESS;
    /* Enter Config Update Mode */
    rv = bq27621_enter_config_update();
 //   rv = bq27621_battery_set_cfgupdate();
    if (rv)
        return rv;
    /* Set up block RAM update */
    rv = bq27621_enter_block_mode(REGISTERS_BLOCK_OFFSET);
    if (rv)
        return rv;
    rv = bq27621_read8(REG_BLOCK_DATA_CHECKSUM, &checksum);
    if (rv)
        return rv;
    checksum = 0xff - checksum;
    rv = bq27621_read8(REGISTERS_BLOCK_OP_CONFIG_B, &param);
    checksum -= param; /* 1B */
    param |= 1<<5; /* Set DEF_SEAL */
    rv = bq27621_write8(REGISTERS_BLOCK_OP_CONFIG_B, param);
    checksum += param; /* 1B */
    checksum = 0xff - (0xff & checksum);
    rv = bq27621_write8(REG_BLOCK_DATA_CHECKSUM, checksum);
    if (rv)
        return rv;
    /* Exit Update */
    rv = bq27621_battery_soft_reset();

    return rv;
}


#endif

#define CHECKSUM_2B(x) ((x & 0xff) + ((x>>8) & 0xff))  //閹跺﹨顕伴崙铏规畱16bit閻ㄥ嫭鏆熼幑顔藉閸掑棛娴夐崝锟?

static uint8_t bq27621_read_block(int offset, uint8_t *data,uint8_t len);

static uint8_t bq27621_battery_checksum_dm_block(struct bq27621_dm_buf *buf);

static uint8_t bq27621_write_block(int offset, uint8_t *data,uint8_t len);

uint8_t Checkdata[BQ27621_DM_SZ]={0};
uint8_t Checknum1;


#if 1
int bq27621_init(void)
{
	int rv;
	int status = 0, param = 0, checksum = 1;

cool:

//	bq27621_write(REG_CTRL, CONTROL_RESET);	//added by lee for debug

	rv = bq27621_probe();

	if (rv)
	{
	    Printf("return bq27621 probe\n");
	}


	/* Unseal the device if necessary */
	rv |= bq27621_write(REG_CTRL, CONTROL_CONTROL_STATUS);

	rv |= bq27621_read(REG_CTRL, &status);

	//step 1
    if (status & STATUS_SS)
	{
	    Printf("will set unseal ...[0x%x]\n",status & STATUS_SS);
		rv |= bq27621_unseal();
	}

//added by lee
    rv |= bq27621_write(REG_CTRL, CONTROL_CONTROL_STATUS);

    rv = bq27621_read(REG_CTRL, &status);

    if (!(status & STATUS_SS))
    {
        Printf("set unseal modem success\n");

    }
    else
    {
        Printf("status is [0x%x]\n",status & STATUS_SS);
        goto cool;
    }

//added end
	/* Select the alternate chemistry if needed */
	rv = bq27621_write(REG_CTRL, CONTROL_CHEM_ID);

	rv |= bq27621_read(REG_CTRL, &param);

	param = BQ27621_CHEM_ID;  //added for test by lee

	if (param != BQ27621_CHEM_ID)
	{ /* Change needed */

		if (BQ27621_CHEM_ID == 0x1202)
		{ /* Return to default */
			rv |= bq27621_write(REG_CTRL, CONTROL_RESET);

			Printf("Return to default 0x1202\n");
		}
		else
		{
			rv |= bq27621_enter_config_update();

			if (BQ27621_CHEM_ID == 0x1210)
			{
			    Printf("chem id is 0x1210\n");

				rv |= bq27621_write(REG_CTRL,CONTROL_ALT_CHEM1);
			}
			
			if (BQ27621_CHEM_ID == 0x0354)
			{
			    Printf("chem id is 0x0354\n");

				rv |= bq27621_write(REG_CTRL,CONTROL_ALT_CHEM2);
			}
		/*
		 * The datasheet recommends checking the status here.
		 *
		 * If the CHEMCHG is active, it wasn't successful.
		 *
		 * There's no recommendation for what to do if it isn't.
		 */
			rv |= bq27621_write(REG_CTRL, CONTROL_EXIT_CFGUPDATE);
		}
	}

	//step 2
//	rv = bq27621_enter_config_update();
	rv=bq27621_battery_set_cfgupdate();
	if (rv)
	{
	    Printf("return bq27621 enter config update faile\n");

	}
	CPUdelay(120000);

	/* Set up block RAM update */
	rv = bq27621_enter_block_mode(STATE_BLOCK_OFFSET);
	if (rv)
	{

	    Printf("return bq27621 enter block mode faile\n");

	}

	struct bq27621_dm_buf databuf={0};
	struct bq27621_dm_buf databuf1={0};

	bq27621_read_block(BQ27621_DM_DATA, &databuf.data[0], BQ27621_DM_SZ);

	bq27621_battery_checksum_dm_block(&databuf);

lolo:	

	//step 7
	rv = bq27621_read8(REG_BLOCK_DATA_CHECKSUM, &checksum); //绗竴姝ュ厛璇诲嚭checksum

	Printf("read the org reg block data checksum is 0x%x\n",checksum);


	databuf.data[0]=1;
	databuf.data[1]=2;
	databuf.data[2]=3;
	databuf.data[3]=4;
	databuf.data[4]=5;
	databuf.data[5]=6;
	databuf.data[6]=7;


	bq27621_write_block(BQ27621_DM_DATA, &databuf.data[0],BQ27621_DM_SZ);

	bq27621_read_block(BQ27621_DM_DATA, &databuf1.data[0], BQ27621_DM_SZ);

	checksum=bq27621_battery_checksum_dm_block(&databuf1);
	
	databuf.data[0]=checksum;


#if 0	
	checksum = 0xff - checksum;

	//step 8
	rv = bq27621_read(STATE_BLOCK_DESIGN_CAPACITY, &param);
	checksum -= CHECKSUM_2B(param);

	rv |= bq27621_read(STATE_BLOCK_DESIGN_ENERGY, &param);
	checksum -= CHECKSUM_2B(param);

	rv |= bq27621_read(STATE_BLOCK_TERMINATE_VOLTAGE, &param);
	checksum -= CHECKSUM_2B(param);

	rv |= bq27621_read(STATE_BLOCK_TAPER_RATE, &param);
	checksum -= CHECKSUM_2B(param);


	rv = bq27621_write(STATE_BLOCK_DESIGN_CAPACITY, DESIGN_CAPACITY);
	checksum += CHECKSUM_2B(DESIGN_CAPACITY);            //寮�濮嬭绠梟ew_Csum


	rv |= bq27621_write(STATE_BLOCK_DESIGN_ENERGY, DESIGN_ENERGY);
	checksum += CHECKSUM_2B(DESIGN_ENERGY);


	rv |= bq27621_write(STATE_BLOCK_TERMINATE_VOLTAGE, TERMINATE_VOLTAGE);
	checksum += CHECKSUM_2B(TERMINATE_VOLTAGE);


	rv |= bq27621_write(STATE_BLOCK_TAPER_RATE, TAPER_RATE);
	checksum += CHECKSUM_2B(TAPER_RATE);


	checksum = 0xff - (0xff & checksum);

	Printf("step 10 before\n");
	
	Printf("checksum[0x%x]\n",checksum);

//	bq27621_enter_block_mode(STATE_BLOCK_OFFSET);

#endif


	rv = bq27621_write8(REG_BLOCK_DATA_CHECKSUM, checksum);

	bq27621_read8(REG_BLOCK_DATA_CHECKSUM, &checksum);   //

	Printf("now read checksum from reg[0x%x]\n",checksum);

    if(checksum==0x8a)
    {
        Printf("updata faile");
    }

	Printf("step 10 after\n");
	
	/*
		Exit CONFIG UPDATE mode by sending SOFT_RESET subcommand,
	*/
#if 0
	bq27621_battery_soft_reset();
#else
	bq27621_write(REG_CTRL, CONTROL_RESET);
#endif
//	bq27621_write(REG_CTRL, CONTROL_SEALED);
	CPUdelay(12000);

    bq27621_write(REG_CTRL, CONTROL_CONTROL_STATUS);

    bq27621_read(REG_CTRL, &status);

    if (status & STATUS_SS) /* Already sealed */
    {
        Printf("bq27621 seal  success\n");
 //       return EC_SUCCESS;
    }
    else
    {
        Printf("bq27621 seal set up faile.........\n");
     
    }
    

#if 0

lulu:
//    bq27621_seal();

//    bq27621_battery_soft_reset();

//    bq27621_write(REG_CTRL, CONTROL_SEALED);

    rv |= bq27621_write(REG_CTRL, CONTROL_CONTROL_STATUS);

    rv |= bq27621_read(REG_CTRL, &status);

    if (status & STATUS_SS) /* Already sealed */
    {
        Printf("bq27621 seal  success\n");
 //       return EC_SUCCESS;
    }
    else
    {
        Printf("bq27621 seal set up faile.........\n");
//        goto lulu;
    }


#endif


	int capacity=0;
#if 0
	battery_design_capacity(&capacity);

	if(capacity !=BQ27621_DESIGN_CAPACITY)
	{
	    Printf("<<<<<capacity !=BQ27621_DESIGN_CAPACITY2>>>>>>>>>\n");

//	    bq27621_write(REG_CTRL, CONTROL_SOFT_RESET);
//	    SystemReset();
	    CPUdelay(12000*10);
//	    goto cool;
	}
	else
	{
	    Printf("<<<<<<<<<<<<BQ27621_DESIGN_CAPACITY[%d]2>>>>>>>>>>>>\n",capacity);
	}
#endif

	rv |=battery_remaining_capacity(&capacity);

	Printf("capacity[%%%d]\n",capacity);



	return rv;
}

#else


int bq27621_init(void)
{

	int rv;
	int status = 0, param = 0, checksum = 0,capacity =0;
cool:
	#if 1
	 //added by lee
	bq27621_write(REG_CTRL, CONTROL_SOFT_RESET);
	CPUdelay(12000*100);
	//added end
	#endif

	Printf("==============================\n");
	Printf("==============================\n");
	Printf("==============================\n");
	Printf("==============================\n");
	
	
	rv = bq27621_probe();
	if (rv)
		return rv;
	
	/* Unseal the device if necessary */
	rv |= bq27621_write(REG_CTRL, CONTROL_CONTROL_STATUS);

	rv |= bq27621_read(REG_CTRL, &status);
	if (status & STATUS_SS)
	{
	    Printf("set unseal modem\n");
		rv |= bq27621_unseal();
	}

//added by lee
    rv |= bq27621_write(REG_CTRL, CONTROL_CONTROL_STATUS);

    rv = bq27621_read(REG_CTRL, &status);

    if (!(status & STATUS_SS))
    {
        Printf("set unseal modem success\n");

    }
    else
    {
        Printf("status is [0x%x]\n",status & STATUS_SS);
        goto cool;
    }

//added end

//	if (rv)
//		return rv;
	/* Select the alternate chemistry if needed */
	rv = bq27621_write(REG_CTRL, CONTROL_CHEM_ID);

	rv |= bq27621_read(REG_CTRL, &param);
	if (param != BQ27621_CHEM_ID) 
	{ /* Change needed */
		if (BQ27621_CHEM_ID == 0x1202) { /* Return to default */
			rv |= bq27621_write(REG_CTRL, CONTROL_RESET);
		} else {
			rv |= bq27621_enter_config_update();
			if (BQ27621_CHEM_ID == 0x1210)
				rv |= bq27621_write(REG_CTRL,
					CONTROL_ALT_CHEM1);
			if (BQ27621_CHEM_ID == 0x0354)
				rv |= bq27621_write(REG_CTRL,
					CONTROL_ALT_CHEM2);
		/*
		 * The datasheet recommends checking the status here.
		 *
		 * If the CHEMCHG is active, it wasn't successful.
		 *
		 * There's no recommendation for what to do if it isn't.
		 */
			rv |= bq27621_write(REG_CTRL, CONTROL_EXIT_CFGUPDATE);
		}
	}
	
//	if (rv)
//		return rv;
#if 0
	rv = bq27621_enter_config_update();
#else
	rv = bq27621_battery_set_cfgupdate( );
#endif
//	if (rv)
//		return rv;
	/* Set up block RAM update */
	rv = bq27621_enter_block_mode(STATE_BLOCK_OFFSET);
//	if (rv)
//		return rv;
	Printf("REG_BLOCK_DATA_CHECKSUM before\n");
	rv = bq27621_read8(REG_BLOCK_DATA_CHECKSUM, &checksum);
//	rv = bq27621_read(REG_BLOCK_DATA_CHECKSUM, &checksum);
	Printf("REG_BLOCK_DATA_CHECKSUM after\n");

//	if (rv)
//		return rv;
	checksum = 0xff - checksum;
	rv = bq27621_read(STATE_BLOCK_DESIGN_CAPACITY, &param);

	checksum -= CHECKSUM_2B(param);
	rv |= bq27621_read(STATE_BLOCK_DESIGN_ENERGY, &param);


	checksum -= CHECKSUM_2B(param);
	rv |= bq27621_read(STATE_BLOCK_TERMINATE_VOLTAGE, &param);


	checksum -= CHECKSUM_2B(param);
	rv |= bq27621_read(STATE_BLOCK_TAPER_RATE, &param);


	checksum -= CHECKSUM_2B(param);
//	if (rv)
//		return rv;
	rv = bq27621_write(STATE_BLOCK_DESIGN_CAPACITY, DESIGN_CAPACITY);

	checksum += CHECKSUM_2B(DESIGN_CAPACITY);
	rv |= bq27621_write(STATE_BLOCK_DESIGN_ENERGY, DESIGN_ENERGY);

	checksum += CHECKSUM_2B(DESIGN_ENERGY);
	rv |= bq27621_write(STATE_BLOCK_TERMINATE_VOLTAGE, TERMINATE_VOLTAGE);

	checksum += CHECKSUM_2B(TERMINATE_VOLTAGE);
	rv |= bq27621_write(STATE_BLOCK_TAPER_RATE, TAPER_RATE);

	checksum += CHECKSUM_2B(TAPER_RATE);
	checksum = 0xff - (0xff & checksum);
//	if (rv)
//		return rv;
	rv = bq27621_write8(REG_BLOCK_DATA_CHECKSUM, checksum);

	//Exit CONFIG UPDATE mode by sending SOFT_RESET subcommand,
#if 0
	rv |= bq27621_write(REG_CTRL, CONTROL_SOFT_RESET);
	if (rv)
		return rv;
#else

lulu:
	rv |=bq27621_battery_soft_reset();

	bq27621_write(REG_CTRL, CONTROL_SEALED);

//    if (rv)
//        return rv;
#endif

#if 1
	bq27621_seal();
//#else

    bq27621_write(REG_CTRL, CONTROL_CONTROL_STATUS);

    bq27621_read(REG_CTRL, &status);

    if (status & STATUS_SS) /* Already sealed */
    {
        Printf("bq27621 seal  success\n");
//      return EC_SUCCESS;
    }
    else
    {
        Printf("bq27621 seal faile[0x%x]\n",status & STATUS_SS);
 //       goto lulu;
    }

#endif	

    battery_design_capacity(&capacity);

    if(capacity !=BQ27621_DESIGN_CAPACITY)
    {
        Printf("<<<<<capacity[%d] !=BQ27621_DESIGN_CAPACITY2>>>>>>>>>\n",capacity);

//      bq27621_write(REG_CTRL, CONTROL_SOFT_RESET);
//      SystemReset();
        CPUdelay(12000*10);
        goto cool;
    }
    else
    {
        Printf("<<<<<<<<<<<<BQ27621_DESIGN_CAPACITY[%d]2>>>>>>>>>>>>\n",capacity);
    }

    battery_remaining_capacity(&capacity);

    Printf("capacity[%%%d]\n",capacity);
}

#endif





static int bq27621_battery_unseal(void)
{
    int ret,status;

    ret =bq27621_write(REG_CTRL, CONTROL_UNSEAL);
    if (ret == 1)
        goto out;

    ret = bq27621_write(REG_CTRL, CONTROL_UNSEAL);
    if (ret == 1)
        goto out;

    bq27621_write(REG_CTRL, CONTROL_CONTROL_STATUS);

    bq27621_read(REG_CTRL, &status);

    if (!(status & STATUS_SS))
    {
        Printf("set unseal modem success\n");
    }
    else
    {
        Printf("set unseal modem faile status is [0x%x]\n",status & STATUS_SS);

        goto out;
    }



    return 0;

out:
    Printf("error on unseal: %d\n", ret);
    return ret;
}

static int bq27621_battery_seal(void)
{
    int ret,status;

    ret = bq27621_write(REG_CTRL, CONTROL_SEALED);

    if (ret == 1)
    {
        Printf("bus error on seal: %d\n", ret);
        return ret;
    }

    ret = bq27621_read(REG_CTRL, &status);

    if (status & STATUS_SS) /* Already sealed */
    {
        Printf("bq27621 seal Already sealed\n");

        return 0;
    }
    else
    {
        Printf("bq27621 seal set up faile.........\n");

        return 1;
    }

    return 0;
}



static uint8_t bq27621_read_block(int offset, uint8_t *data,uint8_t len)
{
    return Ali_I2c_read((uint8_t*)(&offset),(uint8_t*)data,len,BQ27621_ADDR);
}

//err
static uint8_t bq27621_write_block(int offset, uint8_t *data,uint8_t len)
{
    uint8_t txBuffer[BQ27621_DM_SZ +1]={0};

    txBuffer[0]=(uint8_t)offset;

    memcpy(&txBuffer[1],data,len);

    return Ali_I2c_write(txBuffer, len+1, BQ27621_ADDR);
}

static uint8_t bq27621_battery_checksum_dm_block(struct bq27621_dm_buf *buf)
{
    uint16_t sum = 0;
    int i;

	Printf("checksum_dm_block:\n");
	
    for (i = 0; i < BQ27621_DM_SZ; i++)
    {
    	Printf("0x%02x ",buf->data[i]);
        sum += buf->data[i];
    }

	Printf("\n");
    
    sum &= 0xff;
	
    Printf("myself compute checksum dm block is [0x%x]\n",0xff - sum);

    return 0xff - sum;
}

static uint16_t *bq27621_dm_reg_ptr(struct bq27621_dm_buf *buf,
                      struct bq27621_dm_reg *reg)
{
    Printf("reg->offset[%d]\n",reg->offset);

    return (uint16_t *) (buf->data + reg->offset % BQ27621_DM_SZ);

}

static void bq27621_battery_update_dm_block(struct bq27621_dm_buf *buf,enum bq27621_dm_reg_id reg_id,
                                            uint32_t val)
{

    static struct bq27621_dm_reg bq27621_dm_regs[] = {
        [BQ27621_DM_DESIGN_CAPACITY]   = { 82, 3, 2,    0,  DESIGN_CAPACITY },
        [BQ27621_DM_DESIGN_ENERGY]     = { 82, 5, 2,    0,  DESIGN_ENERGY },
        [BQ27621_DM_TERMINATE_VOLTAGE] = { 82, 9, 2,    0,  TERMINATE_VOLTAGE },
    };

    struct bq27621_dm_reg *reg = bq27621_dm_regs;

    uint16_t *prev = bq27621_dm_reg_ptr(buf, &reg[reg_id]); //鑾峰彇鎸囧悜prev鐨勫湴鍧�

    if (prev == NULL)
    {
        Printf("buffer does not match dm spec\n");
        return;
    }

    Printf("DESIGN_CAPACITY[0x%x]\n",DESIGN_CAPACITY);

    Printf("DESIGN_ENERGY[0x%x]\n",DESIGN_ENERGY);

    Printf("TERMINATE_VOLTAGE[0x%x]\n",TERMINATE_VOLTAGE);

    if (reg->bytes != 2)
    {
        Printf("dm spec has unsupported byte size\n");
        return;
    }

    if (!buf->has_data)  //鍦╞q27621_battery_read_dm_block()鍑芥暟涓疄锟?
        return;

    *prev =val;  //杩欐鏄繖涓嚱鏁扮殑鍏抽敭

    Printf("val[0x%x]\n",*prev);

    buf->dirty = true;
}

static int bq27621_battery_read_dm_block(struct bq27621_dm_buf *buf)
{
    int ret;

    buf->has_data = false;

    bq27621_write8(REG_BLOCK_DATA_CONTROL, 0);

	/*
	    bd.class=82;
    	bd.block=3/BQ27621_DM_SZ ;
	*/
    //step 5
    ret = bq27621_write(REG_DATA_CLASS, 82); //Data Class  buf->class
    if (ret ==1)
    {
        Printf("read reg data class err\n");
        goto out;
    }
    //step 6
    ret = bq27621_write(REG_DATA_BLOCK,0); //Data Block  buf->block
    if (ret ==1)
    {
        Printf("read reg data block err\n");
        goto out;
    }

    bq27621_delay_msek(1);
#if 1
    ret = bq27621_read_block(BQ27621_DM_DATA, buf->data, BQ27621_DM_SZ); // Block Data
    if (ret ==1)
    {
        Printf("read dm data err\n");
        goto out;
    }
    else
    {
        Printf("dm data buf :\n");
        for(int i=0;i<BQ27621_DM_SZ;i++)
        {
            Printf("0x%x ",buf->data[i]);
        }
        Printf("\n");
    }
#endif
    //ret鏄痓q27xxx_read璇诲嚭瀵勫瓨鍣ㄧ殑鏁版嵁
    bq27621_read(REG_BLOCK_DATA_CHECKSUM, &ret);  //璇诲彇BQ27XXX_DM_CKSUM瀵勫瓨锟?

	Printf("the read reg block local data checsum data is 0x%x\n",ret);

    if ((uint8_t)ret != bq27621_battery_checksum_dm_block(buf))
    {
        ret = 1;

        Printf("========>battery checksum dm block err\n");
  //      goto out;
    }
    else
    {
        Printf("reg block data checksum right\n");
    }

    buf->has_data = true;   //琛ㄧず鏁版嵁宸茬粡璇诲嚭鏉ヤ簡
    buf->dirty = false;

    return 0;

out:
    return ret;
}

static int bq27621_battery_write_dm_block(struct bq27621_dm_buf *buf)
{
    int ret;


    ret = bq27621_battery_set_cfgupdate();
//    if (ret ==1)
//        return ret;


    ret = bq27621_write(REG_CTRL,0);
//    if (ret == 1)
//        goto out;

    ret = bq27621_write(REG_DATA_CLASS, buf->class);
//    if (ret == 1)
//        goto out;

    ret = bq27621_write(REG_DATA_BLOCK, buf->block);
//    if (ret == 1)
//        goto out;

    bq27621_delay_msek(1);

    ret = bq27621_write_block(BQ27621_DM_DATA, buf->data, BQ27621_DM_SZ);
//    if (ret == 1)
//        goto out;
	Printf("-----1-----\n");
    ret = bq27621_write8(REG_BLOCK_DATA_CHECKSUM,bq27621_battery_checksum_dm_block(buf));

	bq27621_read(REG_BLOCK_DATA_CHECKSUM,&Checknum1);

	Printf("read myself checknum from register is [0x%x]\n",Checknum1);
    
    Printf("-----2-----\n");
//    if (ret == 1)
//        goto out;

    /* DO NOT read BQ27XXX_DM_CKSUM here to verify it! That may cause NVM
     * corruption on the '425 chip (and perhaps others), which can damage
     * the chip.
     */

    bq27621_delay_msek(1);

    ret = bq27621_battery_soft_reset();
    if (ret == 1)
        return ret;


    return 0;

out:
    bq27621_battery_soft_reset();

    Printf("bus error writing chip memory: %d\n", ret);

    return ret;
}


int bq27621_init0(void)
{
    int rv;
    int status = 0, param = 0, checksum = 0,capacity =0;

    struct bq27621_dm_buf bd = {0};
    struct bq27621_dm_buf bt = {0};

    bd.class=82;
    bd.block=3/BQ27621_DM_SZ ;

    bt.class=82;
    bt.block=9/BQ27621_DM_SZ;

    bq27621_probe();

    bq27621_battery_unseal();

    /*
                  鎶奲d.class鍜宐d.block鍐欏叆鍒板搴斿瘎瀛樺櫒
                  璇诲嚭bd.data鏁版嵁
    */
    bq27621_battery_read_dm_block(&bd);  //瀹屽杽bd

    /* assume design energy & capacity are in same block */
    bq27621_battery_update_dm_block(&bd,
                BQ27621_DM_DESIGN_CAPACITY,
                DESIGN_CAPACITY);

    bq27621_battery_update_dm_block(&bd,
                BQ27621_DM_DESIGN_ENERGY,
                DESIGN_ENERGY);

    bq27621_battery_read_dm_block(&bt);

    bq27621_battery_update_dm_block(&bt,
                BQ27621_DM_TERMINATE_VOLTAGE,
                TERMINATE_VOLTAGE);

    bq27621_battery_write_dm_block(&bd);

    bq27621_battery_write_dm_block(&bt);

    bq27621_battery_seal();

    bq27621_write(REG_CTRL, CONTROL_RESET);


    battery_design_capacity(&capacity);

    if(capacity !=BQ27621_DESIGN_CAPACITY)
    {
        Printf("<<<<<capacity[%d]->[%d] !=BQ27621_DESIGN_CAPACITY2>>>>>>>>>\n",capacity,DESIGN_CAPACITY);

//      bq27621_write(REG_CTRL, CONTROL_SOFT_RESET);
//      SystemReset();
        CPUdelay(12000*10);
    }
    else
    {
        Printf("<<<<<<<<<<<<BQ27621_DESIGN_CAPACITY[%d]2>>>>>>>>>>>>\n",capacity);
    }

    battery_remaining_capacity(&capacity);

    Printf("capacity[%%%d]\n",capacity);

    return 0;

}


void probe_type_id_init(void)
{
	int rv = EC_SUCCESS;
	bq27621_write(REG_CTRL, CONTROL_RESET);
	rv = bq27621_probe();
	if (rv)
		return;
	rv = bq27621_init();
	if (rv) { /* Try it once more */
		rv = bq27621_write(REG_CTRL, CONTROL_RESET);
	  rv |= bq27621_init();
	}
}

void sleep_bq27621(void)
{
    bq27621_write(REG_CTRL, CONTROL_SHUTDOWN_ENABLE);
    bq27621_write(REG_CTRL, CONTROL_SHUTDOWN);
}

#if 1
//DECLARE_HOOK(HOOK_INIT, probe_type_id_init, HOOK_PRIO_DEFAULT);
/* Some of the functions to make this battery "smart" */
int battery_device_name(char *device_name, int buf_size)
{
	return EC_ERROR_UNIMPLEMENTED;
}
int battery_state_of_charge_abs(int *percent)
{
	return EC_ERROR_UNIMPLEMENTED;
}

unsigned int recount=0;
int battery_remaining_capacity(int *capacity)
{
	int scaled_value, err_code,status,param,rv;

	bq27621_write(REG_CTRL, CONTROL_CONTROL_STATUS);

	rv |= bq27621_read(REG_CTRL, &status);
	
	if (status & STATUS_SS) /* Already sealed */
	{
		Printf("bq27621 seal Already sealed\n");
//		return EC_SUCCESS;
	}


	battery_design_capacity(&scaled_value) ;

	Printf("REG DESIGN CAPACITY %d\n",scaled_value);
	
	err_code = bq27621_read(REG_REMAINING_CAPACITY, &scaled_value); //REG_NOMINAL_CAPACITY REG_REMAINING_CAPACITY

	Printf("scaled_value->[%d]\n",scaled_value);

//	if(scaled_value>460)
//	    SystemReset();

	
	*capacity = BQ27621_UNSCALE(scaled_value); //*100/458

	Printf("*capacity[%d]\n",*capacity);

	*capacity = *capacity >439?439:*capacity;

	Printf("capacity->[%d]\n",*capacity);

	*capacity=(*capacity)*100/439;

	return err_code;
}
int battery_full_charge_capacity(int *capacity)
{
	int scaled_value, err_code;
	err_code = bq27621_read(REG_FULL_CHARGE_CAPACITY, &scaled_value);
	*capacity = BQ27621_UNSCALE(scaled_value);
	return err_code;
}
int battery_time_to_empty(int *minutes)
{
	return EC_ERROR_UNIMPLEMENTED;
}
int battery_time_to_full(int *minutes)
{
	return EC_ERROR_UNIMPLEMENTED;
}
int battery_cycle_count(int *count)
{
	return EC_ERROR_UNIMPLEMENTED;
}

int battery_time_at_rate(int rate, int *minutes)
{
    return EC_ERROR_UNIMPLEMENTED;
}

int battery_design_capacity(int *capacity)
{
	int scaled_value, err_code;
	err_code = bq27621_read(REG_DESIGN_CAPACITY, &scaled_value);
	*capacity = BQ27621_UNSCALE(scaled_value);
	return err_code;
}
#endif

int battery_device_chemistry(void)
{
	uint32_t rv;
	int param;
	rv = bq27621_write(REG_CTRL, CONTROL_CHEM_ID);
	rv |= bq27621_read(REG_CTRL, &param);
	if (param == 0x1202)
	{
		Printf("0x1202 (default)\n");
	}
	if (param == 0x1210)
	{
	    Printf("0x1210 (ALT_CHEM1)\n");
	}
	if (param == 0x0354)
	{
	    Printf("0x0354 (ALT_CHEM2)\n");
	}
	return EC_SUCCESS;
}

#if 0
int battery_serial_number(int *serial)
{
	return EC_ERROR_UNIMPLEMENTED;
}
int battery_manufacture_date(int *year, int *month, int *day)
{
	return EC_ERROR_UNIMPLEMENTED;
}
int battery_design_voltage(int *voltage)
{
	*voltage = BATTERY_VOLTAGE_NORMAL;
	return EC_SUCCESS;
}
int battery_get_mode(int *mode)
{
	return EC_ERROR_UNIMPLEMENTED;
}
int battery_status(int *status)
{
	return EC_ERROR_UNIMPLEMENTED;
}
enum battery_present battery_is_present(void)
{
	return EC_ERROR_UNIMPLEMENTED;
}

void battery_get_params(struct batt_params *batt)
{
	/* Reset flags */
	batt->flags = 0;
	if (bq27621_read(REG_TEMPERATURE, &batt->temperature))
		batt->flags |= BATT_FLAG_BAD_TEMPERATURE;
	else
		batt->flags |= BATT_FLAG_RESPONSIVE; /* Battery is responding */
	if (bq27621_read8(REG_STATE_OF_CHARGE, &batt->state_of_charge))
		batt->flags |= BATT_FLAG_BAD_STATE_OF_CHARGE;
	if (bq27621_read(REG_VOLTAGE, &batt->voltage))
		batt->flags |= BATT_FLAG_BAD_VOLTAGE;
	batt->flags |= BATT_FLAG_BAD_CURRENT;
	batt->current = 0;
	/* Default to not desiring voltage and current */
	batt->desired_voltage = batt->desired_current = 0;
}
/* Wait until battery is totally stable */
int battery_wait_for_stable(void)
{
	/* TODO(crosbug.com/p/30426): implement me */
	return EC_SUCCESS;
}
#ifdef CONFIG_CMD_BATDEBUG
	#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args)
#else
	#define CPRINTF(format, args...)
#endif
#ifdef CONFIG_CMD_BATDEBUG
static int command_fgunseal(int argc, char **argv)
{
	int rv = EC_SUCCESS;
	if (argc > 1)
		return EC_ERROR_PARAM_COUNT;
	rv = bq27621_unseal();
	return rv;
}
DECLARE_CONSOLE_COMMAND(fgunseal, command_fgunseal,
			"",
			"Unseal the fg");
static int command_fgseal(int argc, char **argv)
{
	int rv = EC_SUCCESS;
	if (argc > 1)
		return EC_ERROR_PARAM_COUNT;
	rv = bq27621_seal();
	return rv;
}
DECLARE_CONSOLE_COMMAND(fgseal, command_fgseal,
			"",
			"Seal the fg");
static int command_fginit(int argc, char **argv)
{
	int rv = EC_SUCCESS;
	int force = 0;
	int flags = 0;
	int unconfigured = 0;
	char *e;
	if (argc > 2)
		return EC_ERROR_PARAM_COUNT;
	if (argc == 2) {
		force = strtoi(argv[1], &e, 0);
		if (*e)
			return EC_ERROR_PARAM1;
	}
	rv = bq27621_read(REG_FLAGS, &flags);
	unconfigured = flags & FLAGS_ITPOR;
	if (!unconfigured && force) {
		rv |= bq27621_write(REG_CTRL, CONTROL_RESET);
		unconfigured = (rv == EC_SUCCESS);
	}
	if (unconfigured)
		rv |= bq27621_init();
	return rv;
}
DECLARE_CONSOLE_COMMAND(fginit, command_fginit,
			"[force]",
			"Initialize the fg");
static int command_fgprobe(int argc, char **argv)
{
	int rv = EC_SUCCESS;
	if (argc != 1)
		return EC_ERROR_PARAM_COUNT;
	rv = bq27621_probe();
	return rv;
}
DECLARE_CONSOLE_COMMAND(fgprobe, command_fgprobe,
			"",
			"Probe the fg");
static int command_fgrd(int argc, char **argv)
{
	int cmd, len;
	int rv = EC_SUCCESS;
	int data;
	char *e;
	if (argc < 3)
		return EC_ERROR_PARAM_COUNT;
	cmd = strtoi(argv[1], &e, 0);
	if (*e)
		return EC_ERROR_PARAM1;
	len = strtoi(argv[2], &e, 0);
	if (*e)
		return EC_ERROR_PARAM2;
	if (len == 2)
		rv = bq27621_read(cmd, &data);
	else if (len == 1)
		rv = bq27621_read8(cmd, &data);
	else
		return EC_ERROR_PARAM2;
	CPRINTF("Read %d bytes @0xaa %0x: 0x%0x\n", len, cmd, data);
	return rv;
}
DECLARE_CONSOLE_COMMAND(fgrd, command_fgrd,
			"cmd len",
			"Read _len_ words from the fg");
static int command_fgcmd(int argc, char **argv)
{
	int cmd, data, byte = 0;
	char *e;
	if (argc < 3 || argc > 4)
		return EC_ERROR_PARAM_COUNT;
	cmd = strtoi(argv[1], &e, 0);
	if (*e)
		return EC_ERROR_PARAM1;
	data = strtoi(argv[2], &e, 0);
	if (*e)
		return EC_ERROR_PARAM2;
	if (argc >= 4) {
		byte = strtoi(argv[3], &e, 0);
		if (*e)
			return EC_ERROR_PARAM3;
	}
	if (byte) {
		CPRINTF("Write a byte @0xaa %0x: 0x%0x\n", cmd, data);
		return bq27621_write8(cmd, data);
	} else {
		CPRINTF("Write 2 bytes @0xaa %0x: 0x%0x\n", cmd, data);
		return bq27621_write(cmd, data);
	}
}
DECLARE_CONSOLE_COMMAND(fgcmd, command_fgcmd,
			"cmd data [byte]",
			"Send a cmd to the fg");
static int command_fgcmdrd(int argc, char **argv)
{
	int cmd, data, val;
	int rv = EC_SUCCESS;
	char *e;
	if (argc < 3)
		return EC_ERROR_PARAM_COUNT;
	cmd = strtoi(argv[1], &e, 0);
	if (*e)
		return EC_ERROR_PARAM1;
	data = strtoi(argv[2], &e, 0);
	if (*e)
		return EC_ERROR_PARAM2;
	rv = bq27621_write(cmd, data);
	rv |= bq27621_read(cmd, &val);
	CPRINTF("Read: @0xaa (%x %x) %x\n", cmd, data, val);
	return rv;
}
DECLARE_CONSOLE_COMMAND(fgcmdrd, command_fgcmdrd,
			"cmd data",
			"Send a 2-byte cmd to the fg, read back the 2-byte result");
#endif /* CONFIG_CMD_BATDEBUG */

#endif

  • Hello Betty,

    We will take a look and get back to you soon.

    Sincerely,

    Wyatt Keller

  • Hello Betty,

    To seal they will need to send the command x0020 to control (send x20 to x00 and x00 to x01). Can you clarify what the customer is trying to do for part 2? Are they trying to write or read from the gauge?

  • I have done this step in the process, in the code I presented to you have already made, before entering the seal mode, for reading and modifying the register in value, there is a problem: chip electric accordingly after initialization, I read the BlockData block 32 bytes of data in a row, and has carried on the check, checksum is 0x8a after I read 0x60, calibration and also read the default to 0x8a, illustrate my calibration method is right, then I modify the readout 32 bytes, and calculate the checksum, the new 32 bytes written to address 0x40 register,The new checksum is written to 0x60, and 32 bytes of data are written successfully. However, after the checksum is written, it is read back to find 0x8a, indicating that the checksum register is not written successfully.

  • HI,

    Can you re-read the values you wrote and see if it matches what you wrote there? Also, can you clarify if the checksum is wrong or the data is wrong after doing this?.