/* soc should be 0.01% unit */
static int adc_get_soc(struct i2c_client *client)
{
	struct sec_fuelgauge_info *fuelgauge =
				i2c_get_clientdata(client);
	int soc;

	soc = adc_get_data_by_adc(fuelgauge,
		get_battery_data(fuelgauge).ocv2soc_table,
		get_battery_data(fuelgauge).ocv2soc_table_size,
		fuelgauge->info.voltage_ocv);

	return soc;
}
Esempio n. 2
0
static int adc_get_vcell(struct i2c_client *client)
{
	struct sec_fuelgauge_info *fuelgauge =
				i2c_get_clientdata(client);
	int vcell;

	vcell = adc_get_data_by_adc(fuelgauge,
		get_battery_data(fuelgauge).adc2vcell_table,
		get_battery_data(fuelgauge).adc2vcell_table_size,
		adc_get_adc_value(fuelgauge, SEC_BAT_ADC_CHANNEL_VOLTAGE_NOW));

	return vcell;
}
static int adc_get_current(struct i2c_client *client)
{
	union power_supply_propval value;
	struct sec_fuelgauge_info *fuelgauge =
				i2c_get_clientdata(client);
	int current_now;

	current_now = adc_get_data_by_adc(fuelgauge,
		get_battery_data(fuelgauge).adc2current_table,
		get_battery_data(fuelgauge).adc2current_table_size,
		adc_get_adc_value(fuelgauge, SEC_BAT_ADC_CHANNEL_CURRENT_NOW));

	if (!current_now) {
		psy_do_property("sec-charger", get,
			POWER_SUPPLY_PROP_CURRENT_NOW, value);
		current_now = value.intval;
	}

	return current_now;
}
static int get_event_compensation_voltage(
	struct sec_fuelgauge_info *fuelgauge, int event)
{
	int i, comp_value;

	comp_value = 0;
	for (i = 0; i < BATT_EVENT_NUM; i++) {
		if (event & (0x1 << i)) {
			comp_value += get_battery_data(fuelgauge).
				event_comp_voltage[i];
			dev_dbg(&fuelgauge->client->dev,
				"%s: event number (%d), comp value (%d)\n",
				__func__, i, get_battery_data(fuelgauge).
				event_comp_voltage[i]);
		}
	}

	dev_dbg(&fuelgauge->client->dev,
		"%s: event comp value (%dmV)\n", __func__, comp_value);
	return comp_value;
}
void board_fuelgauge_init(struct sec_fuelgauge_info *fuelgauge)
{
	sec_fuelgauge = fuelgauge;

	if (!fuelgauge->pdata->battery_data) {
		pr_info("%s : assign battery data\n", __func__);
			fuelgauge->pdata->battery_data = (void *)samsung_battery_data;
	}
	fuelgauge->pdata->capacity_max = CAPACITY_MAX;
	fuelgauge->pdata->capacity_max_margin = CAPACITY_MAX_MARGIN;
	fuelgauge->pdata->capacity_min = CAPACITY_MIN;

#if defined(CONFIG_FUELGAUGE_MAX17048)
	pr_info("%s: RCOMP0: 0x%x, RCOMP_charging: 0x%x, "
		"temp_cohot: %d, temp_cocold: %d, "
		"is_using_model_data: %d, type_str: %s, "
		"capacity_max: %d, capacity_max_margin: %d, "
		"capacity_min: %d, \n", __func__ ,
		get_battery_data(fuelgauge).RCOMP0,
		get_battery_data(fuelgauge).RCOMP_charging,
		get_battery_data(fuelgauge).temp_cohot,
		get_battery_data(fuelgauge).temp_cocold,
		get_battery_data(fuelgauge).is_using_model_data,
		get_battery_data(fuelgauge).type_str,
		fuelgauge->pdata->capacity_max,
		fuelgauge->pdata->capacity_max_margin,
		fuelgauge->pdata->capacity_min
		);
#endif
}
static int get_cable_compensation_voltage(
	struct sec_fuelgauge_info *fuelgauge, int vcell)
{
	int comp_value;

	comp_value = 0;
	comp_value = adc_get_data_by_adc(fuelgauge,
		get_battery_data(fuelgauge).cable_comp_voltage,
		get_battery_data(fuelgauge).cable_comp_voltage_size,
		vcell);

	/* no need to reset SOC with 0mA charging current */
	if (!fuelgauge->info.current_now)
		fuelgauge->info.reset_percentage = 0;

	/* rescale by charging current */
	comp_value = comp_value * fuelgauge->info.current_now / 1000;

	dev_dbg(&fuelgauge->client->dev,
		"%s: cable comp value (%dmV, current %dmA)\n", __func__,
		comp_value, fuelgauge->info.current_now);

	return comp_value;
}
static int adc_get_adc_value(
		struct sec_fuelgauge_info *fuelgauge, int channel)
{
	int adc;

	adc = adc_get_adc_data(fuelgauge, channel,
		get_battery_data(fuelgauge).adc_check_count);

	if (adc < 0) {
		dev_err(&fuelgauge->client->dev,
			"%s: Error in ADC\n", __func__);
		return adc;
	}

	return adc;
}
static void adc_monitor_work(struct work_struct *work)
{
	struct sec_fuelgauge_info *fuelgauge =
		container_of(work, struct sec_fuelgauge_info,
		info.monitor_work.work);

	fuelgauge->info.current_now = adc_get_current(fuelgauge->client);
	fuelgauge->info.voltage_now = adc_get_vcell(fuelgauge->client);
	if (fuelgauge->info.reset_percentage)
		adc_reset_voltage_avg(fuelgauge->client,
			fuelgauge->info.voltage_now,
			fuelgauge->info.reset_percentage);
	fuelgauge->info.voltage_avg = adc_get_avg_vcell(fuelgauge->client);
	if (fuelgauge->info.reset_percentage) {
		adc_reset_voltage_ocv(fuelgauge->client,
			fuelgauge->info.voltage_avg);
		fuelgauge->info.reset_percentage = 0;
	}
	fuelgauge->info.voltage_ocv = adc_get_ocv(fuelgauge->client);
	fuelgauge->info.current_avg =
		adc_get_current_average(fuelgauge->client);
	fuelgauge->info.capacity = adc_get_soc(fuelgauge->client);

	dev_info(&fuelgauge->client->dev,
		"%s:Vnow(%dmV),Vavg(%dmV),Vocv(%dmV),"
		"Inow(%dmA),Iavg(%dmA),SOC(%d%%)\n", __func__,
		fuelgauge->info.voltage_now, fuelgauge->info.voltage_avg,
		fuelgauge->info.voltage_ocv, fuelgauge->info.current_now,
		fuelgauge->info.current_avg, fuelgauge->info.capacity);

	if (fuelgauge->pdata->monitor_initial_count)
		schedule_delayed_work(&fuelgauge->info.monitor_work, HZ);
	else
		schedule_delayed_work(&fuelgauge->info.monitor_work,
			HZ * get_battery_data(fuelgauge).monitor_polling_time);

	if (fuelgauge->info.is_init) {
		fuelgauge->info.is_init--;
		adc_get_reset_percentage(fuelgauge);
	}

	/* save time of monitor */
	do_gettimeofday(&(fuelgauge->info.last_vcell_check_time));
}
Esempio n. 9
0
jstring Java_com_cloudminds_smartrobot_fragment_HomeFragment_getBatteryData(JNIEnv* env,
		jobject thiz, jobject obj) {

	struct battery_data battery;
	get_battery_data(&battery);

	jfieldID jfield;
	jclass objectClass = (*env)->FindClass(env,
			"com/cloudminds/smartrobot/bean/BatteryData");
	jfield = (*env)->GetFieldID(env, objectClass, "seq", "I");
	(*env)->SetIntField(env, obj, jfield, battery.seq);
	jfield = (*env)->GetFieldID(env, objectClass, "capacity", "F");
	(*env)->SetFloatField(env, obj, jfield, battery.capacity);
	jfield = (*env)->GetFieldID(env, objectClass, "residue_capacity", "F");
	(*env)->SetFloatField(env, obj, jfield, battery.residue_capacity);
	jfield = (*env)->GetFieldID(env, objectClass, "voltage", "F");
	(*env)->SetFloatField(env, obj, jfield, battery.voltage);
	jfield = (*env)->GetFieldID(env, objectClass, "current", "F");
	(*env)->SetFloatField(env, obj, jfield, battery.current);
	jfield = (*env)->GetFieldID(env, objectClass, "status", "I");
	(*env)->SetIntField(env, obj, jfield, battery.status);
	return (*env)->NewStringUTF(env, "getUltrasonicData");
}
Esempio n. 10
0
static void adc_monitor_work(struct work_struct *work)
{
	struct sec_fuelgauge_info *fuelgauge =
		container_of(work, struct sec_fuelgauge_info,
		info.monitor_work.work);

	fuelgauge->info.voltage_now = adc_get_vcell(fuelgauge->client);
	fuelgauge->info.voltage_avg = adc_get_avg_vcell(fuelgauge->client);
	fuelgauge->info.voltage_ocv = adc_get_ocv(fuelgauge->client);
	fuelgauge->info.current_now = adc_get_current(fuelgauge->client);
	fuelgauge->info.current_avg =
		adc_get_current_average(fuelgauge->client);
	fuelgauge->info.capacity = adc_get_soc(fuelgauge->client);

	dev_info(&fuelgauge->client->dev,
		"%s:Vnow(%dmV),Vavg(%dmV),Vocv(%dmV),"
		"Inow(%dmA),Iavg(%dmA),SOC(%d%%)\n", __func__,
		fuelgauge->info.voltage_now, fuelgauge->info.voltage_avg,
		fuelgauge->info.voltage_ocv, fuelgauge->info.current_now,
		fuelgauge->info.current_avg, fuelgauge->info.capacity);

	schedule_delayed_work(&fuelgauge->info.monitor_work,
		HZ * get_battery_data(fuelgauge).monitor_polling_time);
}
Esempio n. 11
0
void board_fuelgauge_init(struct sec_fuelgauge_info *fuelgauge)
{
	sec_fuelgauge = fuelgauge;

	if (!fuelgauge->pdata->battery_data) {
		pr_info("%s : assign battery data\n", __func__);
			fuelgauge->pdata->battery_data = (void *)samsung_battery_data;
	}

	fuelgauge->pdata->capacity_max = CAPACITY_MAX;
	fuelgauge->pdata->capacity_max_margin = CAPACITY_MAX_MARGIN;
	fuelgauge->pdata->capacity_min = CAPACITY_MIN;
#if defined(CONFIG_SEC_VIENNA_PROJECT) || defined(CONFIG_SEC_V2_PROJECT) ||\
	defined(CONFIG_MACH_PICASSO_LTE) || defined(CONFIG_MACH_MONDRIAN)
	fuelgauge->pdata->temp_adc_table = temp_table;
	fuelgauge->pdata->temp_adc_table_size = sizeof(temp_table)/sizeof(sec_bat_adc_table_data_t);
#endif

#if defined(CONFIG_FUELGAUGE_MAX17048)
	pr_info("%s: RCOMP0: 0x%x, RCOMP_charging: 0x%x, "
		"temp_cohot: %d, temp_cocold: %d, "
		"is_using_model_data: %d, type_str: %s, "
		"capacity_max: %d, capacity_max_margin: %d, "
		"capacity_min: %d, \n", __func__ ,
		get_battery_data(fuelgauge).RCOMP0,
		get_battery_data(fuelgauge).RCOMP_charging,
		get_battery_data(fuelgauge).temp_cohot,
		get_battery_data(fuelgauge).temp_cocold,
		get_battery_data(fuelgauge).is_using_model_data,
		get_battery_data(fuelgauge).type_str,
		fuelgauge->pdata->capacity_max,
		fuelgauge->pdata->capacity_max_margin,
		fuelgauge->pdata->capacity_min
		);
#endif
}
static int __devinit sec_fuelgauge_probe(struct i2c_client *client,
						const struct i2c_device_id *id)
{
	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
	struct sec_fuelgauge_info *fuelgauge;
	int ret = 0;
	union power_supply_propval raw_soc_val;

	dev_dbg(&client->dev,
		"%s: SEC Fuelgauge Driver Loading\n", __func__);

	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
		return -EIO;

	fuelgauge = kzalloc(sizeof(*fuelgauge), GFP_KERNEL);
	if (!fuelgauge)
		return -ENOMEM;

	mutex_init(&fuelgauge->fg_lock);

	fuelgauge->client = client;
	fuelgauge->pdata = client->dev.platform_data;

	i2c_set_clientdata(client, fuelgauge);

	fuelgauge->psy_fg.name		= "sec-fuelgauge";
	fuelgauge->psy_fg.type		= POWER_SUPPLY_TYPE_UNKNOWN;
	fuelgauge->psy_fg.get_property	= sec_fg_get_property;
	fuelgauge->psy_fg.set_property	= sec_fg_set_property;
	fuelgauge->psy_fg.properties	= sec_fuelgauge_props;
	fuelgauge->psy_fg.num_properties =
		ARRAY_SIZE(sec_fuelgauge_props);
	fuelgauge->capacity_max = fuelgauge->pdata->capacity_max;
	raw_soc_val.intval = SEC_FUELGAUGE_CAPACITY_TYPE_RAW;
	sec_hal_fg_get_property(fuelgauge->client,
			POWER_SUPPLY_PROP_CAPACITY, &raw_soc_val);
	raw_soc_val.intval /= 10;
	fuelgauge->is_reset = false;
	if(raw_soc_val.intval > fuelgauge->pdata->capacity_max)
		sec_fg_calculate_dynamic_scale(fuelgauge);

	if (!fuelgauge->pdata->fg_gpio_init()) {
		dev_err(&client->dev,
			"%s: Failed to Initialize GPIO\n", __func__);
		goto err_free;
	}

	if (!sec_hal_fg_init(fuelgauge->client)) {
		dev_err(&client->dev,
			"%s: Failed to Initialize Fuelgauge\n", __func__);
		goto err_free;
	}

	ret = power_supply_register(&client->dev, &fuelgauge->psy_fg);
	if (ret) {
		dev_err(&client->dev,
			"%s: Failed to Register psy_fg\n", __func__);
		goto err_free;
	}

	if (fuelgauge->pdata->fg_irq) {
		INIT_DEFERRABLE_WORK(
			&fuelgauge->isr_work, sec_fg_isr_work);

		ret = request_threaded_irq(fuelgauge->pdata->fg_irq,
				NULL, sec_fg_irq_thread,
				fuelgauge->pdata->fg_irq_attr | IRQF_ONESHOT,
				"fuelgauge-irq", fuelgauge);
		if (ret) {
			dev_err(&client->dev,
				"%s: Failed to Reqeust IRQ\n", __func__);
			goto err_supply_unreg;
		}

		ret = enable_irq_wake(fuelgauge->pdata->fg_irq);
		if (ret < 0)
			dev_err(&client->dev,
				"%s: Failed to Enable Wakeup Source(%d)\n",
				__func__, ret);
	}

	fuelgauge->is_fuel_alerted = false;
	if (fuelgauge->pdata->fuel_alert_soc >= 0) {
		if (sec_hal_fg_fuelalert_init(fuelgauge->client,
			fuelgauge->pdata->fuel_alert_soc))
			wake_lock_init(&fuelgauge->fuel_alert_wake_lock,
				WAKE_LOCK_SUSPEND, "fuel_alerted");
		else {
			dev_err(&client->dev,
				"%s: Failed to Initialize Fuel-alert\n",
				__func__);
			goto err_irq;
		}
	}

	fuelgauge->initial_update_of_soc = true;

	ret = sec_fg_create_attrs(fuelgauge->psy_fg.dev);
	if (ret) {
		dev_err(&client->dev,
			"%s : Failed to create_attrs\n", __func__);
		goto err_irq;
	}
	pr_info("%s: fg_irq: %d, capacity_max: %d, "
			"cpacity_max_margin: %d, capacity_min: %d,"
			"calculation_type: 0x%x, fuel_alert_soc: %d,\n"
			"repeated_fuelalert: %d, RCOMP0: 0x%x,"
			"RCOMP_charging: 0x%x, temp_cohot: %d,"
			"temp_cocold: %d, is_using_model_data: %d,"
			"type_str: %s,\n", __func__, fuelgauge->pdata->fg_irq,
			fuelgauge->pdata->capacity_max, fuelgauge->pdata->capacity_max_margin,
			fuelgauge->pdata->capacity_min, fuelgauge->pdata->capacity_calculation_type,
			fuelgauge->pdata->fuel_alert_soc, fuelgauge->pdata->repeated_fuelalert,
			get_battery_data(fuelgauge).RCOMP0,
			get_battery_data(fuelgauge).RCOMP_charging,
			get_battery_data(fuelgauge).temp_cohot,
			get_battery_data(fuelgauge).temp_cocold,
			get_battery_data(fuelgauge).is_using_model_data,
			get_battery_data(fuelgauge).type_str
		   );

	dev_dbg(&client->dev,
		"%s: SEC Fuelgauge Driver Loaded\n", __func__);
	return 0;

err_irq:
	if (fuelgauge->pdata->fg_irq)
		free_irq(fuelgauge->pdata->fg_irq, fuelgauge);
	wake_lock_destroy(&fuelgauge->fuel_alert_wake_lock);
err_supply_unreg:
	power_supply_unregister(&fuelgauge->psy_fg);
err_free:
	mutex_destroy(&fuelgauge->fg_lock);
	kfree(fuelgauge);

	return ret;
}
static void STBCFG01_ChargerControl(struct sec_charger_info *charger)
{
	int IFast, ITerm, ILim, VFloat;
	int termination_current;
	int charger_en;
	union power_supply_propval val;

	pr_info("[%s]cable_type = %d\n", __func__, charger->cable_type);

	if (charger->cable_type ==
	    POWER_SUPPLY_TYPE_BATTERY) {
		gpio_direction_output(ChargerData.GPIO_cd, 1);
	} else {
		if((charger->cable_type == POWER_SUPPLY_TYPE_MAINS) ||
		  (charger->cable_type == POWER_SUPPLY_TYPE_USB)) {
			psy_do_property("battery", get,
					POWER_SUPPLY_PROP_CHARGE_NOW, val);
			if (val.intval == SEC_BATTERY_CHARGING_1ST) {
				termination_current =
				charger->pdata->charging_current[
				charger->cable_type].full_check_current_1st;
			} else if (val.intval == SEC_BATTERY_CHARGING_2ND) {
				termination_current =
				charger->pdata->charging_current[
					charger->cable_type].full_check_current_2nd;
			}

			pr_info("[%s]charging_mode = %d\n",
				__func__, val.intval);

			IFast = STBCFG01_get_fast_current_limit_data(
				charger->pdata->charging_current[
				charger->cable_type].fast_charging_current);

			ITerm = STBCFG01_get_termination_current_limit_data(
				termination_current, val);

			ChargerData.Cfg1 = (IFast & 0x07)
				| ((get_battery_data(charger).IPre & 0x01) <<3)
				| ((ITerm & 0x0F) << 4);

			VFloat = STBCFG01_get_float_voltage_data(
				charger->pdata->chg_float_voltage);

			ChargerData.Cfg2 = (VFloat & 0x3F)
				| ((get_battery_data(charger).ARChg & 0x01) << 6)
				& 0x7F;

			ILim = STBCFG01_get_input_current_limit_data(
				charger->pdata->charging_current[
				charger->cable_type].input_current_limit);

			ChargerData.Cfg3 = (ILim & 0x07)
				| ((get_battery_data(charger).DICL_en & 0x01) << 3)
				| ((get_battery_data(charger).VDICL & 0x03) << 4)
				| ((get_battery_data(charger).IBat_lim & 0x03) << 6);

			ChargerData.Cfg4 = (get_battery_data(charger).TPre & 0x01)
				| ((get_battery_data(charger).TFast & 0x01) << 1)
				| (0x01 << 2) | ((get_battery_data(charger).PreB_en & 0x01) << 3)
				| ((get_battery_data(charger).LDO_UVLO_th & 0x01) << 5)
				| ((get_battery_data(charger).LDO_en & 0x01) << 6)
				| ((get_battery_data(charger).WD & 0x01) << 7);

			ChargerData.Cfg5 = ((get_battery_data(charger).FSW & 0x01) << 1)
				| ((get_battery_data(charger).DIChg_adj & 0x01) << 2);

//			STBCFG01_BatChg_Start(charger->client);
			STBCFG01_WriteChargerCnfData(charger->client, &ChargerData);
			STBCFG01_ReadChargerData(charger->client, &ChargerData);

			gpio_direction_output(ChargerData.GPIO_cd, 0);
		}
	}

#ifdef STBCFG01_DEBUG_MESSAGES_EXTRA_REGISTERS
			printk(" Cfg1=%x, Cfg2=%x, Cfg3=%x, Cfg4=%x, Cfg5=%x, Sts1=%x, Sts2=%x, Ien1=%x, Ien2=%x\n",
			       ChargerData.Cfg1, ChargerData.Cfg2, ChargerData.Cfg3,
			       ChargerData.Cfg4, ChargerData.Cfg5, ChargerData.Status1,
			       ChargerData.Status2, ChargerData.IntEn1, ChargerData.IntEn2);
#endif
}
bool sec_hal_chg_init(struct sec_charger_info *charger)
{
	int ret;

	/* init battery charger data structure */
	if (charger->pdata->battery_data)
	{
		ChargerData.GPIO_cd = get_battery_data(charger).GPIO_cd;
		ChargerData.GPIO_shdn = get_battery_data(charger).GPIO_shdn;
	} else {
		ChargerData.GPIO_cd = 0;
		ChargerData.GPIO_shdn = 0;
	}

	if (ChargerData.GPIO_cd) {
		ret = gpio_request(ChargerData.GPIO_cd, "stbcfg01_cd_pin");
		if (ret) {
			dev_err(&charger->client->dev, "STBCFG01 : Unable to get cd pin %d\n",
				ChargerData.GPIO_cd);
			return (ret);
		}
	} else {
		printk("STBCFG01 : CD pin not assigned in platformdata, will not be used\n");
	}

	ChargerData.Cfg1 = (get_battery_data(charger).IFast & 0x07)
		| ((get_battery_data(charger).IPre & 0x01) <<3)
		| ((get_battery_data(charger).ITerm & 0x0F) << 4);

	ChargerData.Cfg2 = (get_battery_data(charger).VFloat & 0x3F)
		| ((get_battery_data(charger).ARChg & 0x01) << 6)
		& 0x7F;

	ChargerData.Cfg3 = (get_battery_data(charger).Iin_lim & 0x07)
		| ((get_battery_data(charger).DICL_en & 0x01) << 3)
		| ((get_battery_data(charger).VDICL & 0x03) << 4)
		| ((get_battery_data(charger).IBat_lim & 0x03) << 6);

	ChargerData.Cfg4 = (get_battery_data(charger).TPre & 0x01)
		| ((get_battery_data(charger).TFast & 0x01) << 1)
		| (0x01 << 2) | ((get_battery_data(charger).PreB_en & 0x01) << 3)
		| ((get_battery_data(charger).LDO_UVLO_th & 0x01) << 5)
		| ((get_battery_data(charger).LDO_en & 0x01) << 6)
		| ((get_battery_data(charger).WD & 0x01) << 7);

	ChargerData.Cfg5 = ((get_battery_data(charger).FSW & 0x01) << 1)
		| ((get_battery_data(charger).DIChg_adj & 0x01) << 2);

	STBCFG01_BatChg_Start(charger->client);

#ifdef STBCFG01_DEBUG_MESSAGES_EXTRA_REGISTERS
			printk(" Cfg1=%x, Cfg2=%x, Cfg3=%x, Cfg4=%x, Cfg5=%x, Sts1=%x, Sts2=%x, Ien1=%x, Ien2=%x\n",
			       ChargerData.Cfg1, ChargerData.Cfg2, ChargerData.Cfg3,
			       ChargerData.Cfg4, ChargerData.Cfg5, ChargerData.Status1,
			       ChargerData.Status2, ChargerData.IntEn1, ChargerData.IntEn2);
#endif

	return true;
}
Esempio n. 15
0
static int adc_get_vcell(struct i2c_client *client)
{
	union power_supply_propval cable;
	union power_supply_propval event;
	union power_supply_propval is_charging;
	struct sec_fuelgauge_info *fuelgauge =
				i2c_get_clientdata(client);
	int vcell, vcell_raw;

	vcell = adc_get_data_by_adc(fuelgauge,
		get_battery_data(fuelgauge).adc2vcell_table,
		get_battery_data(fuelgauge).adc2vcell_table_size,
		adc_get_adc_value(fuelgauge, SEC_BAT_ADC_CHANNEL_VOLTAGE_NOW));
	vcell_raw = vcell;

	psy_do_property("battery", get,
		POWER_SUPPLY_PROP_ONLINE, cable);
	/* get current event status */
	event.intval = BATT_EVENT;
	psy_do_property("battery", get,
		POWER_SUPPLY_PROP_TECHNOLOGY, event);
	psy_do_property("battery", get,
		POWER_SUPPLY_PROP_CHARGE_NOW, is_charging);

	if (is_charging.intval != SEC_BATTERY_CHARGING_NONE) {
		/* compensate voltage by cable only in charging status */
		if (cable.intval != POWER_SUPPLY_TYPE_BATTERY)
			vcell += get_cable_compensation_voltage(
				fuelgauge, vcell);
	} else {
		/* need compensation before cable detection
		 * in power-off charging
		 */
		if ((cable.intval == POWER_SUPPLY_TYPE_BATTERY) &&
			(fuelgauge->pdata->is_lpm() ||
			fuelgauge->pdata->check_vbus_status())) {
			dev_dbg(&client->dev, "%s: VBUS compensation\n",
				__func__);
			vcell += get_cable_compensation_voltage(
				fuelgauge, vcell);
		}
	}

	if (event.intval) {
		if (fuelgauge->pdata->check_vbus_status() &&
			(event.intval & EVENT_BOOTING))
			dev_dbg(&client->dev, "%s: no event compensation "
				"in booting with charging\n", __func__);
		else
			vcell += get_event_compensation_voltage(
				fuelgauge, event.intval);
	}

#if defined(SEC_FUELGAUGE_ADC_DELTA_COMPENSATION)
	if (!fuelgauge->pdata->monitor_initial_count)
		vcell += get_delta_compensation_voltage(
			fuelgauge, vcell, vcell_raw);
#endif

	return vcell;
}
Esempio n. 16
0
static int get_delta_compensation_voltage(
	struct sec_fuelgauge_info *fuelgauge, int vcell, int vcell_raw)
{
	int last_time, delta_time, delta_voltage_now, delta_current_now;
	int delta_voltage_now_in_sec, delta_compensation_voltage;

	delta_compensation_voltage = 0;
	last_time = fuelgauge->info.last_vcell_check_time.tv_sec;
	do_gettimeofday(&(fuelgauge->info.last_vcell_check_time));
	if (last_time) {
		delta_time = fuelgauge->info.last_vcell_check_time.tv_sec -
			last_time;

		if (delta_time > get_battery_data(fuelgauge).delta_reset_time) {
			dev_dbg(&fuelgauge->client->dev,
				"%s: reset delta compensation\n", __func__);
			delta_voltage_now = 0;
			delta_current_now = 0;
			fuelgauge->info.current_compensation = 0;
			goto no_delta_compensation;
		}

		/* to get compensation voltage,
		 * use raw vcell without compensation
		 */
		delta_compensation_voltage = adc_get_data_by_adc(fuelgauge,
			get_battery_data(fuelgauge).cable_comp_voltage,
			get_battery_data(fuelgauge).cable_comp_voltage_size,
			vcell_raw) * fuelgauge->info.current_compensation /
			1000;

		delta_voltage_now = vcell + delta_compensation_voltage -
			fuelgauge->info.voltage_now;

		fuelgauge->info.delta_voltage_now_in_sec =
			delta_voltage_now * 1000 / delta_time;

		if (delta_voltage_now < 0)
			delta_voltage_now_in_sec =
				-(fuelgauge->info.delta_voltage_now_in_sec);
		else
			delta_voltage_now_in_sec =
				fuelgauge->info.delta_voltage_now_in_sec;

		if ((delta_time <
			get_battery_data(fuelgauge).delta_check_time) &&
			(delta_voltage_now_in_sec >
			get_battery_data(fuelgauge).delta_comp_limit)) {
			/* to get delta current,
			 * use raw vcell without compensation
			 */
			delta_current_now = -(delta_voltage_now * 1000 /
				adc_get_data_by_adc(fuelgauge,
				get_battery_data(fuelgauge).cable_comp_voltage,
				get_battery_data(fuelgauge).cable_comp_voltage_size,
				vcell));

			/* to show compensation value, added minus */
			dev_dbg(&fuelgauge->client->dev,
				"%s: delta compensation (%dmA)\n",
				__func__, -delta_current_now);
			fuelgauge->info.current_compensation +=
				delta_current_now;

			/* to get compensation voltage,
			 * use raw vcell without compensation
			 */
			delta_compensation_voltage =
				adc_get_data_by_adc(fuelgauge,
				get_battery_data(fuelgauge).cable_comp_voltage,
				get_battery_data(fuelgauge).cable_comp_voltage_size,
				vcell_raw) *
				fuelgauge->info.current_compensation / 1000;
		} else
			delta_current_now =
				fuelgauge->info.current_compensation;

		if (!delta_compensation_voltage) {
			dev_dbg(&fuelgauge->client->dev,
				"%s: no need delta compensation "
				"vcell raw %dmV, comp vol %dmV, dv %dmV\n",
				__func__, vcell_raw, delta_compensation_voltage,
				delta_voltage_now);
			fuelgauge->info.current_compensation = 0;
		}

no_delta_compensation:
		dev_dbg(&fuelgauge->client->dev,
			"%s: dtime %dsec, dvoltage %dmV, dcurrent %dmA, "
			"dvoltage/sec %duV, delta comp voltage %dmV, "
			"compensation current %dmA\n",
			__func__, delta_time,
			delta_voltage_now, delta_current_now,
			fuelgauge->info.delta_voltage_now_in_sec,
			delta_compensation_voltage,
			fuelgauge->info.current_compensation);
	}

	return delta_compensation_voltage;
}
Esempio n. 17
0
static int fuelgauge_parse_dt(struct device *dev,
			struct sec_fuelgauge_info *fuelgauge)
{
	struct device_node *np = dev->of_node;

	sec_battery_platform_data_t *pdata = fuelgauge->pdata;
	/* reset, irq gpio info */
	if (np == NULL)
		pr_err("%s np NULL\n", __func__);
	else {
		int ret;
		ret = pdata->fg_irq = of_get_named_gpio(np, "fuelgauge,fuel_int", 0);
		if (ret < 0)
			pr_err("%s error reading fg_irq = %d\n", __func__, pdata->fg_irq);

#if defined(CONFIG_FUELGAUGE_MAX17050)
		ret = of_property_read_u32(np, "fuelgauge,jig_gpio",
				&pdata->jig_irq);
		if (ret < 0)
			pr_err("%s error reading jig_gpio %d\n", __func__, ret);

		ret = of_get_named_gpio(np, "fuelgauge,bat_int", 0);
		ta_int_gpio = ret;
		sec_battery_pdata.bat_irq = gpio_to_irq(ret);
		if (ret < 0)
			pr_err("%s error reading bat_int = %d\n", __func__, ret);
		pr_err("%s: ta_int_gpio(%d), bat_irq(%d)\n",
			__func__, ret, sec_battery_pdata.bat_irq);
		pr_info("%s fg_irq: %d, jig_irq: %d, capacity_max: %d, "
				"cpacity_max_margin: %d, capacity_min: %d, "
				"calculation_type: 0x%x, fuel_alert_soc: %d,\n"
				"repeated_fuelalert: %d, Capacity: 0x%x, "
				"low_battery_comp_voltage: 0x%x, "
				"type_str: %s\n", __func__, pdata->fg_irq, pdata->jig_irq,
				pdata->capacity_max, pdata->capacity_max_margin,
				pdata->capacity_min, pdata->capacity_calculation_type,
				pdata->fuel_alert_soc, pdata->repeated_fuelalert,
				get_battery_data(fuelgauge).Capacity,
				get_battery_data(fuelgauge).low_battery_comp_voltage,
				get_battery_data(fuelgauge).type_str
				);
#else
		ret = of_get_named_gpio(np, "fuelgauge,bat_int", 0);
		if (ret > 0) {
			sec_battery_pdata.bat_irq_gpio = ret;
			sec_battery_pdata.bat_irq = gpio_to_irq(ret);
			pr_info("%s reading bat_int_gpio = %d\n", __func__, ret);
		}
		pr_info("%s: fg_irq: %d, capacity_max: %d, "
				"cpacity_max_margin: %d, capacity_min: %d,"
				"calculation_type: 0x%x, fuel_alert_soc: %d,\n"
				"repeated_fuelalert: %d, RCOMP0: 0x%x,"
				"RCOMP_charging: 0x%x, temp_cohot: %d,"
				"temp_cocold: %d, is_using_model_data: %d,"
				"type_str: %s,\n", __func__, pdata->fg_irq,
				pdata->capacity_max, pdata->capacity_max_margin,
				pdata->capacity_min, pdata->capacity_calculation_type,
				pdata->fuel_alert_soc, pdata->repeated_fuelalert,
				get_battery_data(fuelgauge).RCOMP0,
				get_battery_data(fuelgauge).RCOMP_charging,
				get_battery_data(fuelgauge).temp_cohot,
				get_battery_data(fuelgauge).temp_cocold,
				get_battery_data(fuelgauge).is_using_model_data,
				get_battery_data(fuelgauge).type_str
				);
#endif
	}
	return 0;
}