Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2e9b45c5 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "power: bcl_peripheral: Recalibrate BCL after FG switch current sensing"

parents 8c7b9489 4eef3781
Loading
Loading
Loading
Loading
+91 −15
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <linux/spmi.h>
#include <linux/mutex.h>
#include <linux/msm_bcl.h>
#include <linux/power_supply.h>

#define BCL_DRIVER_NAME         "bcl_peripheral"
#define BCL_VBAT_INT_NAME       "bcl-low-vbat-int"
@@ -103,8 +104,10 @@ struct bcl_peripheral_data {
	int                     scaling_factor;
	int                     offset_factor_num;
	int                     offset_factor_den;
	int                     offset;
	int                     gain_factor_num;
	int                     gain_factor_den;
	int                     gain;
	uint32_t                polling_delay_ms;
	int			inhibit_derating_ua;
	int (*read_max)         (int *adc_value);
@@ -118,11 +121,15 @@ struct bcl_device {
	uint16_t                base_addr;
	uint16_t                pon_spare_addr;
	uint8_t                 slave_id;
	int                     i_src;
	struct workqueue_struct *bcl_isr_wq;
	struct bcl_peripheral_data   param[BCL_PARAM_MAX];
};

static struct bcl_device *bcl_perph;
static struct power_supply bcl_psy;
static const char bcl_psy_name[] = "fg_adc";
static bool calibration_done;
static DEFINE_MUTEX(bcl_access_mutex);
static DEFINE_MUTEX(bcl_enable_mutex);

@@ -185,7 +192,8 @@ static void convert_vbat_to_adc_val(int *val)
	if (!bcl_perph)
		return;
	perph_data = &bcl_perph->param[BCL_PARAM_VOLTAGE];
	*val = (*val * 100 / (100 + perph_data->gain_factor_num
	*val = (*val * 100
		/ (100 + (perph_data->gain_factor_num * perph_data->gain)
		* BCL_CONSTANT_NUM
		/ perph_data->gain_factor_den))
		/ perph_data->scaling_factor;
@@ -200,7 +208,7 @@ static void convert_adc_to_vbat_val(int *val)
		return;
	perph_data = &bcl_perph->param[BCL_PARAM_VOLTAGE];
	*val = (*val * perph_data->scaling_factor)
		* (100 + perph_data->gain_factor_num
		* (100 + (perph_data->gain_factor_num * perph_data->gain)
		* BCL_CONSTANT_NUM  / perph_data->gain_factor_den)
		/ 100;
	return;
@@ -213,9 +221,10 @@ static void convert_ibat_to_adc_val(int *val)
	if (!bcl_perph)
		return;
	perph_data = &bcl_perph->param[BCL_PARAM_CURRENT];
	*val = (*val * 100 / (100 + perph_data->gain_factor_num
	*val = (*val * 100
		/ (100 + (perph_data->gain_factor_num * perph_data->gain)
		* BCL_CONSTANT_NUM / perph_data->gain_factor_den)
		- perph_data->offset_factor_num
		- (perph_data->offset_factor_num * perph_data->offset)
		/ perph_data->offset_factor_den)
		/  perph_data->scaling_factor;
	return;
@@ -229,9 +238,9 @@ static void convert_adc_to_ibat_val(int *val)
		return;
	perph_data = &bcl_perph->param[BCL_PARAM_CURRENT];
	*val = (*val * perph_data->scaling_factor
		+ perph_data->offset_factor_num
		+ (perph_data->offset_factor_num * perph_data->offset)
		/ perph_data->offset_factor_den)
		* (100 + perph_data->gain_factor_num
		* (100 + (perph_data->gain_factor_num * perph_data->gain)
		* BCL_CONSTANT_NUM / perph_data->gain_factor_den) / 100;
	return;
}
@@ -702,7 +711,6 @@ static int bcl_get_devicetree_data(struct spmi_device *spmi)
{
	int ret = 0, irq_num = 0, temp_val = 0;
	struct resource *resource = NULL;
	int8_t i_src = 0, val = 0;
	char *key = NULL;
	const __be32 *prop = NULL;
	struct device_node *dev_node = spmi->dev.of_node;
@@ -784,38 +792,89 @@ static int bcl_get_devicetree_data(struct spmi_device *spmi)
	READ_OPTIONAL_PROP(dev_node, key, temp_val, ret,
		bcl_perph->param[BCL_PARAM_CURRENT].inhibit_derating_ua);

bcl_dev_exit:
	return ret;
}

static int bcl_calibrate(void)
{
	int ret = 0;
	int8_t i_src = 0, val = 0;

	ret = bcl_read_register(BCL_I_SENSE_SRC, &i_src);
	if (ret) {
		pr_err("Error reading current sense reg. err:%d\n", ret);
		goto bcl_dev_exit;
		goto bcl_cal_exit;
	}

	ret = bcl_read_register((i_src & 0x01) ? BCL_I_GAIN_RSENSE
		: BCL_I_GAIN_BATFET, &val);
	if (ret) {
		pr_err("Error reading %s current gain. err:%d\n",
			(i_src & 0x01) ? "rsense" : "batfet", ret);
		goto bcl_dev_exit;
		goto bcl_cal_exit;
	}
	bcl_perph->param[BCL_PARAM_CURRENT].gain_factor_num *= val;
	bcl_perph->param[BCL_PARAM_CURRENT].gain = val;
	ret = bcl_read_register((i_src & 0x01) ? BCL_I_OFFSET_RSENSE
		: BCL_I_OFFSET_BATFET, &val);
	if (ret) {
		pr_err("Error reading %s current offset. err:%d\n",
			(i_src & 0x01) ? "rsense" : "batfet", ret);
		goto bcl_dev_exit;
		goto bcl_cal_exit;
	}
	bcl_perph->param[BCL_PARAM_CURRENT].offset_factor_num *= val;
	bcl_perph->param[BCL_PARAM_CURRENT].offset = val;
	ret = bcl_read_register(BCL_V_GAIN_BAT, &val);
	if (ret) {
		pr_err("Error reading vbat offset. err:%d\n", ret);
		goto bcl_dev_exit;
		goto bcl_cal_exit;
	}
	bcl_perph->param[BCL_PARAM_VOLTAGE].gain_factor_num *= val;
	bcl_perph->param[BCL_PARAM_VOLTAGE].gain = val;

bcl_dev_exit:
	if (((i_src & 0x01) != bcl_perph->i_src)
		&& (bcl_perph->enabled)) {
		bcl_set_low_vbat(bcl_perph->param[BCL_PARAM_VOLTAGE]
				.low_trip);
		bcl_set_high_ibat(bcl_perph->param[BCL_PARAM_CURRENT]
				.high_trip);
		bcl_perph->i_src = i_src;
	}

bcl_cal_exit:
	return ret;
}

static void power_supply_callback(struct power_supply *psy)
{
	static struct power_supply *bms_psy;
	int ret = 0;

	if (calibration_done)
		return;

	if (!bms_psy)
		bms_psy = power_supply_get_by_name("bms");
	if (bms_psy) {
		calibration_done = true;
		ret = bcl_calibrate();
		if (ret)
			pr_err("Could not read calibration values. err:%d",
				ret);
	}
}

static int bcl_psy_get_property(struct power_supply *psy,
				enum power_supply_property prop,
				union power_supply_propval *val)
{
	return 0;
}
static int bcl_psy_set_property(struct power_supply *psy,
				enum power_supply_property prop,
				const union power_supply_propval *val)
{
	return -EINVAL;
}

static int bcl_update_data(void)
{
	int ret = 0;
@@ -904,6 +963,23 @@ static int bcl_probe(struct spmi_device *spmi)
		pr_err("Device tree data fetch error. err:%d", ret);
		goto bcl_probe_exit;
	}
	ret = bcl_calibrate();
	if (ret) {
		pr_debug("Could not read calibration values. err:%d", ret);
		goto bcl_probe_exit;
	}
	bcl_psy.name = bcl_psy_name;
	bcl_psy.type = POWER_SUPPLY_TYPE_BMS;
	bcl_psy.get_property     = bcl_psy_get_property;
	bcl_psy.set_property     = bcl_psy_set_property;
	bcl_psy.num_properties   = 0;
	bcl_psy.external_power_changed = power_supply_callback;
	ret = power_supply_register(&spmi->dev, &bcl_psy);
	if (ret < 0) {
		pr_err("Unable to register bcl_psy rc = %d\n", ret);
		return ret;
	}

	bcl_perph->bcl_isr_wq = alloc_workqueue("bcl_isr_wq", WQ_HIGHPRI, 0);
	if (!bcl_perph->bcl_isr_wq) {
		pr_err("Alloc work queue failed\n");
+2 −1
Original line number Diff line number Diff line
@@ -370,7 +370,8 @@ static const struct of_device_id fg_match_table[] = {

static char *fg_supplicants[] = {
	"battery",
	"bcl"
	"bcl",
	"fg_adc"
};

#define DEBUG_PRINT_BUFFER_SIZE 64