Ejemplo n.º 1
0
/*M-MT:setup discharge/charge current threshold.*/
int bq27410_write_current_threshold(struct i2c_client *client)
{
	int ret = 0;
	int dsg_current_threshold = 0;
	u8 buf[16];

	// 1. unseal bq27410.
	bq27410_unseal_device();

	// 2. write BlockDataControl command to enable block data flash control.
	buf[0] = 0x00;
	bq27410_write(client,0x61,buf,1);
	udelay(66);

	// 3. write subclass id.
	buf[0] = 0x51;
	bq27410_write(client,0x3E,buf,1);
	udelay(66);

	// 4. write subclass current offset.
	buf[0] = 0x00;
	bq27410_write(client,0x3F,buf,1);
	udelay(66);

	// 5. read old dsg current.
	ret = bq27410_read(client,0x40,buf,2);
	dsg_current_threshold = get_unaligned_le16(buf);
	DBG("dsg_current_threshold = 0x%x \n",dsg_current_threshold);
#if 0
	ret = bq27410_read(client,0x40,buf,16);
	{
		int i;
		for(i =0; i< 16; i++)
		{
			DBG("0x%x ",buf[i]);
		}
		DBG(" \n");
	}
#endif

	// 6. read old checksum.
	//ret = bq27410_read(client,0x60,buf,1);
	//DBG("checksum = 0x%x \n",buf[0]);
#if 0
	// 7. write new taper current.
	buf[0] = 0x00;
	buf[1] = 0xC8;
	bq27410_write(client,0x40,buf,2);
	udelay(66);
	ret = bq27410_read(client,0x40,buf,2);
	dsg_current_threshold = get_unaligned_le16(buf);
	DBG("dsg_current_threshold =0x%x \n",dsg_current_threshold);	
	// 8. write new checksum.
#endif
	bq27410_soft_reset();
	bq27410_sealed();

	return 0;
}
Ejemplo n.º 2
0
/*
 * Return the battery Relative State-of-Charge
 * Or < 0 if something fails.
 */
static int bq27410_battery_rsoc(struct bq27410_device_info *di)
{
	int ret;
	int rsoc = 0;
	int flags = 0;
	int status = 0;
	u8 buf[2];

	if(virtual_battery_enable == 1)
		return 50/*100*/;
	
	ret = bq27410_read(di->client,BQ27410_REG_STATE_OF_CHARGER,buf,2); 
	if (ret<0) {
		dev_err(di->dev, "error reading relative State-of-Charge\n");
		return ret;
	}

	rsoc = get_unaligned_le16(buf);
	DBG("Enter:%s %d--read reaming capacity = %d\n",__FUNCTION__,__LINE__,rsoc);

	/* covert the capacity range */
	rsoc = min(rsoc, 100);
	if ((g_pdata != NULL) && g_pdata->capacity_max && g_pdata->capacity_min) {
		rsoc = max(rsoc, g_pdata->capacity_min);
		rsoc = ((rsoc - g_pdata->capacity_min) * 100 +
			(g_pdata->capacity_max - g_pdata->capacity_min) / 2)
			/ (g_pdata->capacity_max - g_pdata->capacity_min);
	}
	bq27410_cap = rsoc;

	/*check full flags,if not full, show 99%*/
	ret = bq27410_read(di->client,BQ27410_REG_FLAGS, buf, 2);
	if (ret < 0) {
		dev_err(di->dev, "error reading flags\n");
		return ret;
	}

	flags = get_unaligned_le16(buf);
	DBG("Enter:%s %d--flags = 0x%x\n",__FUNCTION__,__LINE__,flags);

	if ((bq27410_cap > 99) && (flags & BQ27410_FLAG_FC))
		status = POWER_SUPPLY_STATUS_FULL;

	if(status != POWER_SUPPLY_STATUS_FULL)
		rsoc = min(rsoc, 99);

	DBG("Enter:%s %d--cal rsoc = %d\n",__FUNCTION__,__LINE__,rsoc);

	return rsoc;
}
Ejemplo n.º 3
0
static int bq27410_health_status(struct bq27410_device_info *di,
				  union power_supply_propval *val)
{
	u8 buf[2] = {0};
	int flags = 0;
	int status;
	int ret;
	
	if(virtual_battery_enable == 1)
	{
		val->intval = POWER_SUPPLY_HEALTH_GOOD;
		return 0;
	}

	ret = bq27410_read(di->client,BQ27410_REG_FLAGS, buf, 2);
	if (ret < 0) {
		dev_err(di->dev, "error reading flags\n");
		return ret;
	}

	flags = get_unaligned_le16(buf);
	DBG("Enter:%s %d--status = %x\n",__FUNCTION__,__LINE__,flags);
	
	if (flags & BQ27410_FLAG_SOCF)
		status = POWER_SUPPLY_HEALTH_DEAD;
	else if(flags & BQ27410_FLAG_OTC)
		status = POWER_SUPPLY_HEALTH_OVERHEAT;
	else
		status = POWER_SUPPLY_HEALTH_GOOD;

	val->intval = status;

	return 0;
}
Ejemplo n.º 4
0
static int bq27410_battery_voltage(struct bq27410_device_info *di)
{
	int ret;
	u8 buf[2] = {0};
	int volt = 0;

	if(virtual_battery_enable == 1)
		return 4000000/*4000000*/;

	ret = bq27410_read(di->client,BQ27410_REG_VOL,buf,2); 
	if (ret<0) {
		dev_err(di->dev, "error reading voltage\n");
		return ret;
	}

	volt = get_unaligned_le16(buf);

	if(di->bat_num == 2){
		volt = volt * 1000 * 2;
	}else{
		volt = volt * 1000;
	}

	DBG("Enter:%s %d--volt = %d\n",__FUNCTION__,__LINE__,volt);

	return volt;
}
Ejemplo n.º 5
0
/*
 * Return the battery average current
 * Note that current can be negative signed as well
 * Or 0 if something fails.
 */
static int bq27410_battery_current(struct bq27410_device_info *di)
{
	int ret;
	int curr = 0;
	u8 buf[2] = {0};

	if(virtual_battery_enable == 1)
		return 11000/*22000*/;

	ret = bq27410_read(di->client,BQ27410_REG_AVERAGE_CURRENT,buf,2);
	if (ret<0) {
		dev_err(di->dev, "error reading current\n");
		return 0;
	}

	curr = get_unaligned_le16(buf);
	DBG("curr = %x \n",curr);

	if(curr > 0x8000){
		curr = 0xFFFF ^ (curr -1);
	}

	curr = curr * 1000;

	DBG("Enter:%s %d--curr = %d\n",__FUNCTION__,__LINE__,curr);

	return curr;
}
Ejemplo n.º 6
0
static int bq27410_battery_temperature(struct bq27410_device_info *di)
{
	int ret;
	int temp = 0;
	u8 buf[2] ={0};

	if(virtual_battery_enable == 1)
		return 125/*258*/;

	ret = bq27410_read(di->client,BQ27410_REG_TEMP,buf,2);
	if (ret<0) {
		dev_err(di->dev, "error reading temperature\n");
		return ret;
	}

	temp = get_unaligned_le16(buf);
	//temp = 5 * temp / 2;
	temp = temp - 2731;  //K

	DBG("Enter:%s %d--temp = %d\n",__FUNCTION__,__LINE__,temp);

#if defined(CONFIG_CHARGER_LIMITED_BY_TEMP)
		if((temp >= 450) && (0 == charge_en_flags)){
			bq24196_charge_disable();
			charge_en_flags = 1;
		}else if((temp <= 400) && (1 == charge_en_flags)){
			bq24196_charge_en();
			charge_en_flags = 0;
		}
#endif
	return temp;
}
Ejemplo n.º 7
0
/*M-MT:write batt insert command.*/
int bq27410_write_batt_insert(struct i2c_client *client)
{
	int ret = 0;
	int control_status = 0;
	u8 buf[2];
	int flags = 0;

	if(g_bq27410_mode == BQ27410_NORMAL_MODE){
		buf[0] = 0x00;	//CONTROL_STATUS
		buf[1] = 0x00;
		bq27410_write(client,0x00,buf,2);
		udelay(66);
		ret = bq27410_read(client,0x00,buf,2);
		control_status = get_unaligned_le16(buf);
		printk("control_status=0x%x \n",control_status);

		ret = bq27410_read(client,BQ27410_REG_FLAGS, buf, 2);
		if (ret < 0) {
			DBG("error reading flags\n");
			return ret;
		}
		flags = get_unaligned_le16(buf);

		printk("1 Enter:%s --flags = 0x%x\n",__FUNCTION__,flags);

		if (!(flags & BQ27410_FLAG_BAT_DET))
		{
			buf[0] = 0x0c;				//batt insert
			buf[1] = 0x00;
			bq27410_write(client,0x00,buf,2);
			udelay(66);

			ret = bq27410_read(client,BQ27410_REG_FLAGS, buf, 2);
			if (ret < 0) {
				DBG("error reading flags\n");
				return ret;
			}
			flags = get_unaligned_le16(buf);
			if (!(flags & BQ27410_FLAG_BAT_DET)){
				printk("27410: %s, flags = 0x%x, set virtual_battery_enable = 1\n",__FUNCTION__,flags);
				virtual_battery_enable = 1;
			}
		}
	}

	return 0;
}
Ejemplo n.º 8
0
void bq27410_sealed(void)
{
	int ret = 0;
	u8 buf[2];

	if(g_bq27410_mode == BQ27410_NORMAL_MODE){
		buf[0] = 0x20;						//seal
		buf[1] = 0x00;
		bq27410_write(g_client,0x00,buf,2);
		udelay(66);
		ret = bq27410_read(g_client,0x00,buf,2);
	}
}
Ejemplo n.º 9
0
static int bq27410_battery_status(struct bq27410_device_info *di,
				  union power_supply_propval *val)
{
	u8 buf[2] = {0};
	int flags = 0;
	int status = 0;
	int ret = 0;

	if(virtual_battery_enable == 1)
	{
		val->intval = POWER_SUPPLY_STATUS_FULL;
		return 0;
	}

	ret = bq27410_read(di->client,BQ27410_REG_FLAGS, buf, 2);
	if (ret < 0) {
		dev_err(di->dev, "error reading flags\n");
		return ret;
	}

	flags = get_unaligned_le16(buf);

	DBG("Enter:%s %d--flags = 0x%x\n",__FUNCTION__,__LINE__,flags);

	if ((g_pdata != NULL) && g_pdata->get_charging_stat)
	{
#ifdef CONFIG_BATTERY_BQ24196_OTG_MODE
		if(!(*g_pdata->get_charging_stat)() || (bq24196_mode == 1))
#else
		if(!(*g_pdata->get_charging_stat)())
#endif
			status = POWER_SUPPLY_STATUS_DISCHARGING;
		else if(1 == (*g_pdata->get_charging_stat)()){
			if ((bq27410_cap > 99) && (flags & BQ27410_FLAG_FC))
				status = POWER_SUPPLY_STATUS_FULL;
			else
				status = POWER_SUPPLY_STATUS_CHARGING;
		}
	}

	val->intval = status;

	DBG("Enter:%s %d--status = %x\n",__FUNCTION__,__LINE__,status);
	return 0;
}
Ejemplo n.º 10
0
static int bq27410_battery_rsoc_level(struct bq27410_device_info *di,
								union power_supply_propval *val)
{
	u8 buf[2] = {0};
	int flags = 0;
	int status = 0;
	int ret = 0;

	if(virtual_battery_enable == 1)
	{
		val->intval = POWER_SUPPLY_STATUS_FULL;
		return 0;
	}

	ret = bq27410_read(di->client,BQ27410_REG_FLAGS, buf, 2);
	if (ret < 0) {
		dev_err(di->dev, "error reading flags\n");
		return ret;
	}

	flags = get_unaligned_le16(buf);

	DBG("Enter:%s %d--flags = 0x%x\n",__FUNCTION__,__LINE__,flags);

	if (flags & BQ27410_FLAG_FC)
		status = POWER_SUPPLY_STATUS_FULL;
	else if (flags & BQ27410_FLAG_SOC1)
		status = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
	else if (flags & BQ27410_FLAG_SOCF)
		status = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
	else
		status = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;

	val->intval = status;

	DBG("Enter:%s %d--status = %x\n",__FUNCTION__,__LINE__,status);
	return 0;

}
Ejemplo n.º 11
0
static int bq27410_update_flash_data(struct file *filp, const char __user *buff, unsigned long len, void *data)
{
	int ret = 0;
	u8 buf[2];
	bq27410_unseal_device();

	bq27410_update_enter_rom_mode();
	ret = bq27410_read(g_client,0x66,buf,2);
	if(ret < 0)
		bq27410_update_flag = 1;
	else
		ret = bq27410_update_fw(filp, buff, len, data);

	g_bq27410_mode = BQ27410_NORMAL_MODE;
	g_client->addr = 0x55;
	bq27410_exit_rom_mode();

	bq27410_soft_reset();
	bq27410_sealed();

	return ret;
}
Ejemplo n.º 12
0
static int bq27410_battery_temperature(struct bq27410_device_info *di)
{
	int ret;
	int temp = 0;
	u8 buf[2] ={0};

	if(virtual_battery_enable == 1)
		return 125/*258*/;

	ret = bq27410_read(di->client,BQ27410_REG_TEMP,buf,2);
	if (ret<0) {
		dev_err(di->dev, "error reading temperature\n");
		return ret;
	}

	temp = get_unaligned_le16(buf);
	//temp = 5 * temp / 2;
	temp = temp - 2731;  //K

	DBG("Enter:%s %d--temp = %d\n",__FUNCTION__,__LINE__,temp);

	return temp;
}
Ejemplo n.º 13
0
static void bq27410_battery_work(struct work_struct *work)
{
	struct bq27410_device_info *di = container_of(work, struct bq27410_device_info, work.work); 
	int ret = 0;
	u8 buf[2];
	int battflags = 0;
	static int flag = 0;

	if(flag == 0){
#if 0
		mutex_lock(&g_bq27410_mutex);
		bq27410_write_batt_insert(g_client);
		mutex_unlock(&g_bq27410_mutex);

		virtual_battery_enable = 0;
		flag = 1;
#else
		mutex_lock(&g_bq27410_mutex);
		ret = bq27410_read(g_client,BQ27410_REG_FLAGS, buf, 2);
		if (ret < 0) {
			DBG("error reading flags\n");
			return ret;
		}
		mutex_unlock(&g_bq27410_mutex);
		battflags = get_unaligned_le16(buf);
		if ((battflags & BQ27410_FLAG_BAT_DET)){
			printk("27410: %s, battflags = 0x%x, set virtual_battery_enable = 0\n",__FUNCTION__,battflags);
			flag = 1;
			virtual_battery_enable = 0;
		}
#endif
	}

	bq27410_battery_update_status(di);
	/* reschedule for the next time */
	schedule_delayed_work(&di->work, di->interval);
}
Ejemplo n.º 14
0
static int bq27410_update_fw(struct file *filp,  char *buff, unsigned long len, void *data)
{
	struct file * file_data = NULL;
	mm_segment_t old_fs;
	int file_len;
	char *data_buf = NULL;
	int ret;
	char buf[128];
	char *pch = NULL;
	s32 base = 16;
	int count = 0;
	int wCount = 0;
	int xCount = 0;
	int cCount = 0;
	#define isspace(c)	((c) == ' ')

	file_len = update_get_flen(buff);

	///Open update file.
	file_data = update_file_open(buff, &old_fs);
	if(file_data == NULL)
	{
		return -1;
	}
	data_buf = kzalloc(file_len, GFP_KERNEL);

	if(file_len > 0)
	{
		ret = file_data->f_op->read(file_data, data_buf, file_len, &file_data->f_pos);					
		//printk("get file strlen(data_buf): %d.\n", strlen(data_buf));

		pch = data_buf;
		while(count < file_len)
		{
			if(*pch == 'W')
			{
				wCount = 0;
				pch +=2;
				count +=2;
				while(*pch != 'W' && *pch != 'X' && *pch != 'C')
				{
					while(isspace(*pch))
					{
						pch++;
						count ++;
					}

					ret = simple_strtoul(pch, NULL, base);
					buf[wCount] = ret;
					wCount++;
					//printk("%x ", ret);
					pch +=2;
					count +=2;
					while((*pch == '\r') || (*pch == '\n'))
					{
						pch +=2;
						count +=2;
					}
				}
				//printk("\n");
				//printk("\n W count = %d , wCount=%d\n", count, wCount);
				ret = bq27410_write(g_client,buf[1],&buf[2],wCount - 2);
				//printk("W ret =%d ", ret);
			}
			else if(*pch == 'X')
			{
				xCount = 0;
				pch +=2;
				count +=2;
				while(*pch != 'W' && *pch != 'X' && *pch != 'C')
				{
					while(isspace(*pch))
					{
						pch++;
						count ++;
					}

					ret = simple_strtoul(pch, NULL, 10);
					//printk("%d ", ret);
					xCount++;

					if(ret < 0x10)
					{
						pch +=1;
						count +=1;
					}
					else if(ret < 0x100){
						pch +=2;
						count +=2;
					}
					else if(ret < 0x1000){
						pch +=3;
						count +=3;		
					}
					else if(ret < 0x10000){
						pch +=4;
						count +=4;		
					}

					while((*pch == '\r') || (*pch == '\n'))
					{
						pch +=2;
						count +=2;
					}

					if(ret == 4000)
					{
						count = file_len;
						break;
					}
				}
				//printk("\n X count = %d, xCount=%d \n", count, xCount);
				//printk("\n");				
				msleep(ret);
			}
			else if(*pch == 'C')
			{
				cCount = 0;
				pch +=2;
				count +=2;
				while(*pch != 'W' && *pch != 'X' && *pch != 'C')
				{
					while(isspace(*pch))
					{
						pch++;
						count ++;
					}

					ret = simple_strtoul(pch, NULL, base);
					buf[cCount] = ret;					
					//printk("%x ", ret);
					cCount++;

					pch +=2;
					count +=2;
					while((*pch == '\r') || (*pch == '\n'))
					{
						pch +=2;
						count +=2;

						break;
					}
				}
				//printk("\n");
				//printk("\n C count = %d , cCount=%d\n", count, cCount);
				ret = bq27410_read(g_client,buf[1],&buf[2],cCount - 2);
				//printk("C ret =%d ", ret);
			}
		}
	}

	if(data_buf){
		kfree(data_buf);
		data_buf = NULL;
	}
	///Close file
	update_file_close(file_data, old_fs);

	return 0;
}
Ejemplo n.º 15
0
static int bq27410_battery_probe(struct i2c_client *client,
				 const struct i2c_device_id *id)
{
	struct bq27410_device_info *di;
	int retval = 0;
	u8 buf[2];
	struct bq27410_platform_data *pdata;
	
	DBG("**********  bq27410_battery_probe**************  \n");
	
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)){
		client->addr = 0x0B;
		if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)){
			return -ENODEV;
		}
		else{
			g_bq27410_mode = BQ27410_ROM_MODE;
		}
	}
	else{
		g_bq27410_mode = BQ27410_NORMAL_MODE;
	}
	printk("+ g_bq27410_mode=%d \n", g_bq27410_mode);
	
	pdata = client->dev.platform_data;
	g_pdata = pdata;
	g_client = client;

	di = kzalloc(sizeof(*di), GFP_KERNEL);
	if (!di) {
		dev_err(&client->dev, "failed to allocate device info data\n");
		retval = -ENOMEM;
		goto batt_failed_2;
	}
	mutex_init(&g_bq27410_mutex);
		

	i2c_set_clientdata(client, di);
	di->dev = &client->dev;
	di->bat.name = "battery";
	di->client = client;
	/* 4 seconds between monotor runs interval */
	di->interval = msecs_to_jiffies(4 * 1000);
	
	di->bat_num = pdata->bat_num;
	di->dc_check_pin = pdata->dc_check_pin;
	di->bat_check_pin = pdata->bat_check_pin;
	di->wake_irq = pdata->low_power_pin;
	
	if (pdata->io_init)
		pdata->io_init();

	bq27410_di = di;
	retval = bq27410_read(client,0x00,buf,2);
	if(retval < 0){
		printk("failed to find bq27410\n");
		goto batt_failed_2;
	}else{
		rk30_bat_unregister();
		bq27410_init = 1;
	}

	//command batt insert.
	bq27410_write_batt_insert(client);

	if(g_bq27410_mode == BQ27410_NORMAL_MODE){

		if(!bq27410_read_control_status(client))
		{
			virtual_battery_enable = 1;

			bq27410_powersupply_init(di);
			retval = power_supply_register(&client->dev, &di->bat);

			INIT_DELAYED_WORK(&di->update_work, bq27410_battery_update_work);
			schedule_delayed_work(&di->update_work, msecs_to_jiffies(15 * 1000));
		}
		else{
			printk("NOT need bq27410_update_firmware \n");
			bq27410_powersupply_init(di);
			
			retval = power_supply_register(&client->dev, &di->bat);
			if (retval) {
				dev_err(&client->dev, "failed to register battery\n");
				goto batt_failed_4;
			}
			INIT_DELAYED_WORK(&di->work, bq27410_battery_work);
			schedule_delayed_work(&di->work, di->interval);
			dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION);
		}
	}
	else
	{
		INIT_DELAYED_WORK(&di->update_work, bq27410_battery_update_work);
		schedule_delayed_work(&di->update_work, msecs_to_jiffies(15 * 1000));
	}
	printk("- g_bq27410_mode=%d \n", g_bq27410_mode);
	
	//M-MT:setup discharge/charge current threshold. 
	//bq27410_write_current_threshold(client);

	// battery low irq
	if(pdata->low_power_pin != INVALID_GPIO)
	{
		di->wake_irq = gpio_to_irq(pdata->low_power_pin);
		retval = request_irq(di->wake_irq, bq27410_bat_wakeup, IRQF_TRIGGER_FALLING, "bq27410_battery", di);
		if (retval) {
			printk("failed to request low_power_pin irq\n");
			goto err_batirq_failed;
		}

		INIT_DELAYED_WORK(&di->wakeup_work, bq27410_battery_wake_work);
		enable_irq_wake(di->wake_irq);
	}
	
	bq27410_proc_entry = create_proc_entry("bq27410-update", 0666, NULL);
	if(bq27410_proc_entry == NULL)
	{
		printk("Malata bq27410 Couldn't create proc entry!\n");
		return -ENOMEM;
	}
	else
	{
		printk("Malata bq27410 Create proc entry success!\n");
		bq27410_proc_entry->write_proc = bq27410_update_write;
		bq27410_proc_entry->read_proc = bq27410_update_read;
	}

	battery_capacity_check(di);

	return 0;

batt_failed_4:
	kfree(di);
batt_failed_2:

err_batirq_failed:
	gpio_free(pdata->bat_check_pin);

	return retval;
}