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

Commit 3988a4df authored by Johan Bjornstedt's avatar Johan Bjornstedt Committed by Anton Vorontsov
Browse files

ab8500_bm: Skip first CCEOC irq for instant current



When enabling the CCEOC irq we might get false interrupt
from ab8500-driver due to the latched value will be saved
and interpreted as an IRQ when enabled

Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
Signed-off-by: default avatarJohan Bjornstedt <johan.bjornstedt@stericsson.com>
Signed-off-by: default avatarHenrik Solver <henrik.solver@stericsson.com>
Reviewed-by: default avatarKarl KOMIEROWSKI <karl.komierowski@stericsson.com>
Signed-off-by: default avatarAnton Vorontsov <anton@enomsg.org>
parent defbfa9c
Loading
Loading
Loading
Loading
+4 −7
Original line number Diff line number Diff line
@@ -374,13 +374,10 @@ static int ab8500_btemp_get_batctrl_res(struct ab8500_btemp *di)
		return ret;
	}

	/*
	 * Since there is no interrupt when current measurement is done,
	 * loop for over 250ms (250ms is one sample conversion time
	 * with 32.768 Khz RTC clock). Note that a stop time must be set
	 * since the ab8500_btemp_read_batctrl_voltage call can block and
	 * take an unknown amount of time to complete.
	 */
	do {
		msleep(20);
	} while (!ab8500_fg_inst_curr_started(di->fg));

	i = 0;

	do {
+55 −8
Original line number Diff line number Diff line
@@ -160,6 +160,7 @@ struct inst_curr_result_list {
 * @recovery_cnt:	Counter for recovery mode
 * @high_curr_cnt:	Counter for high current mode
 * @init_cnt:		Counter for init mode
 * @nbr_cceoc_irq_cnt	Counter for number of CCEOC irqs received since enabled
 * @recovery_needed:	Indicate if recovery is needed
 * @high_curr_mode:	Indicate if we're in high current mode
 * @init_capacity:	Indicate if initial capacity measuring should be done
@@ -167,6 +168,7 @@ struct inst_curr_result_list {
 * @calib_state		State during offset calibration
 * @discharge_state:	Current discharge state
 * @charge_state:	Current charge state
 * @ab8500_fg_started	Completion struct used for the instant current start
 * @ab8500_fg_complete	Completion struct used for the instant current reading
 * @flags:		Structure for information about events triggered
 * @bat_cap:		Structure for battery capacity specific parameters
@@ -199,6 +201,7 @@ struct ab8500_fg {
	int recovery_cnt;
	int high_curr_cnt;
	int init_cnt;
	int nbr_cceoc_irq_cnt;
	bool recovery_needed;
	bool high_curr_mode;
	bool init_capacity;
@@ -206,6 +209,7 @@ struct ab8500_fg {
	enum ab8500_fg_calibration_state calib_state;
	enum ab8500_fg_discharge_state discharge_state;
	enum ab8500_fg_charge_state charge_state;
	struct completion ab8500_fg_started;
	struct completion ab8500_fg_complete;
	struct ab8500_fg_flags flags;
	struct ab8500_fg_battery_capacity bat_cap;
@@ -531,6 +535,7 @@ static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable)

	mutex_lock(&di->cc_lock);

	di->nbr_cceoc_irq_cnt = 0;
	ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
		AB8500_RTC_CC_CONF_REG, &reg_val);
	if (ret < 0)
@@ -558,6 +563,7 @@ static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable)
	}

	/* Return and WFI */
	INIT_COMPLETION(di->ab8500_fg_started);
	INIT_COMPLETION(di->ab8500_fg_complete);
	enable_irq(di->irq);

@@ -568,6 +574,17 @@ static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable)
	return ret;
}

/**
 * ab8500_fg_inst_curr_started() - check if fg conversion has started
 * @di:         pointer to the ab8500_fg structure
 *
 * Returns 1 if conversion started, 0 if still waiting
 */
int ab8500_fg_inst_curr_started(struct ab8500_fg *di)
{
	return completion_done(&di->ab8500_fg_started);
}

/**
 * ab8500_fg_inst_curr_done() - check if fg conversion is done
 * @di:         pointer to the ab8500_fg structure
@@ -596,13 +613,15 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res)
	int timeout;

	if (!completion_done(&di->ab8500_fg_complete)) {
		timeout = wait_for_completion_timeout(&di->ab8500_fg_complete,
		timeout = wait_for_completion_timeout(
			&di->ab8500_fg_complete,
			INS_CURR_TIMEOUT);
		dev_dbg(di->dev, "Finalize time: %d ms\n",
			((INS_CURR_TIMEOUT - timeout) * 1000) / HZ);
		if (!timeout) {
			ret = -ETIME;
			disable_irq(di->irq);
			di->nbr_cceoc_irq_cnt = 0;
			dev_err(di->dev, "completion timed out [%d]\n",
				__LINE__);
			goto fail;
@@ -610,6 +629,7 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res)
	}

	disable_irq(di->irq);
	di->nbr_cceoc_irq_cnt = 0;

	ret = abx500_mask_and_set_register_interruptible(di->dev,
			AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG,
@@ -684,6 +704,7 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res)
int ab8500_fg_inst_curr_blocking(struct ab8500_fg *di)
{
	int ret;
	int timeout;
	int res = 0;

	ret = ab8500_fg_inst_curr_start(di);
@@ -692,13 +713,32 @@ int ab8500_fg_inst_curr_blocking(struct ab8500_fg *di)
		return 0;
	}

	/* Wait for CC to actually start */
	if (!completion_done(&di->ab8500_fg_started)) {
		timeout = wait_for_completion_timeout(
			&di->ab8500_fg_started,
			INS_CURR_TIMEOUT);
		dev_dbg(di->dev, "Start time: %d ms\n",
			((INS_CURR_TIMEOUT - timeout) * 1000) / HZ);
		if (!timeout) {
			ret = -ETIME;
			dev_err(di->dev, "completion timed out [%d]\n",
				__LINE__);
			goto fail;
		}
	}

	ret = ab8500_fg_inst_curr_finalize(di, &res);
	if (ret) {
		dev_err(di->dev, "Failed to finalize fg_inst\n");
		return 0;
	}

	dev_dbg(di->dev, "%s instant current: %d", __func__, res);
	return res;
fail:
	mutex_unlock(&di->cc_lock);
	return ret;
}

/**
@@ -1523,8 +1563,6 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di)

	case AB8500_FG_DISCHARGE_WAKEUP:
		ab8500_fg_coulomb_counter(di, true);
		di->inst_curr = ab8500_fg_inst_curr_blocking(di);

		ab8500_fg_calc_cap_discharge_voltage(di, true);

		di->fg_samples = SEC_TO_SAMPLE(
@@ -1641,8 +1679,6 @@ static void ab8500_fg_periodic_work(struct work_struct *work)
		fg_periodic_work.work);

	if (di->init_capacity) {
		/* A dummy read that will return 0 */
		di->inst_curr = ab8500_fg_inst_curr_blocking(di);
		/* Get an initial capacity calculation */
		ab8500_fg_calc_cap_discharge_voltage(di, true);
		ab8500_fg_check_capacity_limits(di, true);
@@ -1828,7 +1864,13 @@ static void ab8500_fg_instant_work(struct work_struct *work)
static irqreturn_t ab8500_fg_cc_data_end_handler(int irq, void *_di)
{
	struct ab8500_fg *di = _di;
	if (!di->nbr_cceoc_irq_cnt) {
		di->nbr_cceoc_irq_cnt++;
		complete(&di->ab8500_fg_started);
	} else {
		di->nbr_cceoc_irq_cnt = 0;
		complete(&di->ab8500_fg_complete);
	}
	return IRQ_HANDLED;
}

@@ -2551,7 +2593,11 @@ static int ab8500_fg_probe(struct platform_device *pdev)
	di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer);
	ab8500_fg_coulomb_counter(di, true);

	/* Initialize completion used to notify completion of inst current */
	/*
	 * Initialize completion used to notify completion and start
	 * of inst current
	 */
	init_completion(&di->ab8500_fg_started);
	init_completion(&di->ab8500_fg_complete);

	/* Register interrupts */
@@ -2571,6 +2617,7 @@ static int ab8500_fg_probe(struct platform_device *pdev)
	}
	di->irq = platform_get_irq_byname(pdev, "CCEOC");
	disable_irq(di->irq);
	di->nbr_cceoc_irq_cnt = 0;

	platform_set_drvdata(pdev, di);

+7 −0
Original line number Diff line number Diff line
@@ -431,11 +431,18 @@ struct ab8500_fg *ab8500_fg_get(void);
int ab8500_fg_inst_curr_blocking(struct ab8500_fg *dev);
int ab8500_fg_inst_curr_start(struct ab8500_fg *di);
int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res);
int ab8500_fg_inst_curr_started(struct ab8500_fg *di);
int ab8500_fg_inst_curr_done(struct ab8500_fg *di);

#else
int ab8500_fg_inst_curr_started(struct ab8500_fg *di)
{
	return 0;
}

int ab8500_fg_inst_curr_done(struct ab8500_fg *di)
{
	return 0;
}
static void ab8500_fg_reinit(void)
{