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

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
...@@ -374,13 +374,10 @@ static int ab8500_btemp_get_batctrl_res(struct ab8500_btemp *di) ...@@ -374,13 +374,10 @@ static int ab8500_btemp_get_batctrl_res(struct ab8500_btemp *di)
return ret; return ret;
} }
/* do {
* Since there is no interrupt when current measurement is done, msleep(20);
* loop for over 250ms (250ms is one sample conversion time } while (!ab8500_fg_inst_curr_started(di->fg));
* 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.
*/
i = 0; i = 0;
do { do {
......
...@@ -160,6 +160,7 @@ struct inst_curr_result_list { ...@@ -160,6 +160,7 @@ struct inst_curr_result_list {
* @recovery_cnt: Counter for recovery mode * @recovery_cnt: Counter for recovery mode
* @high_curr_cnt: Counter for high current mode * @high_curr_cnt: Counter for high current mode
* @init_cnt: Counter for init 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 * @recovery_needed: Indicate if recovery is needed
* @high_curr_mode: Indicate if we're in high current mode * @high_curr_mode: Indicate if we're in high current mode
* @init_capacity: Indicate if initial capacity measuring should be done * @init_capacity: Indicate if initial capacity measuring should be done
...@@ -167,6 +168,7 @@ struct inst_curr_result_list { ...@@ -167,6 +168,7 @@ struct inst_curr_result_list {
* @calib_state State during offset calibration * @calib_state State during offset calibration
* @discharge_state: Current discharge state * @discharge_state: Current discharge state
* @charge_state: Current charge 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 * @ab8500_fg_complete Completion struct used for the instant current reading
* @flags: Structure for information about events triggered * @flags: Structure for information about events triggered
* @bat_cap: Structure for battery capacity specific parameters * @bat_cap: Structure for battery capacity specific parameters
...@@ -199,6 +201,7 @@ struct ab8500_fg { ...@@ -199,6 +201,7 @@ struct ab8500_fg {
int recovery_cnt; int recovery_cnt;
int high_curr_cnt; int high_curr_cnt;
int init_cnt; int init_cnt;
int nbr_cceoc_irq_cnt;
bool recovery_needed; bool recovery_needed;
bool high_curr_mode; bool high_curr_mode;
bool init_capacity; bool init_capacity;
...@@ -206,6 +209,7 @@ struct ab8500_fg { ...@@ -206,6 +209,7 @@ struct ab8500_fg {
enum ab8500_fg_calibration_state calib_state; enum ab8500_fg_calibration_state calib_state;
enum ab8500_fg_discharge_state discharge_state; enum ab8500_fg_discharge_state discharge_state;
enum ab8500_fg_charge_state charge_state; enum ab8500_fg_charge_state charge_state;
struct completion ab8500_fg_started;
struct completion ab8500_fg_complete; struct completion ab8500_fg_complete;
struct ab8500_fg_flags flags; struct ab8500_fg_flags flags;
struct ab8500_fg_battery_capacity bat_cap; struct ab8500_fg_battery_capacity bat_cap;
...@@ -524,13 +528,14 @@ static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable) ...@@ -524,13 +528,14 @@ static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable)
* Note: This is part "one" and has to be called before * Note: This is part "one" and has to be called before
* ab8500_fg_inst_curr_finalize() * ab8500_fg_inst_curr_finalize()
*/ */
int ab8500_fg_inst_curr_start(struct ab8500_fg *di) int ab8500_fg_inst_curr_start(struct ab8500_fg *di)
{ {
u8 reg_val; u8 reg_val;
int ret; int ret;
mutex_lock(&di->cc_lock); mutex_lock(&di->cc_lock);
di->nbr_cceoc_irq_cnt = 0;
ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
AB8500_RTC_CC_CONF_REG, &reg_val); AB8500_RTC_CC_CONF_REG, &reg_val);
if (ret < 0) if (ret < 0)
...@@ -558,6 +563,7 @@ static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable) ...@@ -558,6 +563,7 @@ static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable)
} }
/* Return and WFI */ /* Return and WFI */
INIT_COMPLETION(di->ab8500_fg_started);
INIT_COMPLETION(di->ab8500_fg_complete); INIT_COMPLETION(di->ab8500_fg_complete);
enable_irq(di->irq); enable_irq(di->irq);
...@@ -568,6 +574,17 @@ static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable) ...@@ -568,6 +574,17 @@ static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable)
return ret; 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 * ab8500_fg_inst_curr_done() - check if fg conversion is done
* @di: pointer to the ab8500_fg structure * @di: pointer to the ab8500_fg structure
...@@ -596,13 +613,15 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res) ...@@ -596,13 +613,15 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res)
int timeout; int timeout;
if (!completion_done(&di->ab8500_fg_complete)) { 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); INS_CURR_TIMEOUT);
dev_dbg(di->dev, "Finalize time: %d ms\n", dev_dbg(di->dev, "Finalize time: %d ms\n",
((INS_CURR_TIMEOUT - timeout) * 1000) / HZ); ((INS_CURR_TIMEOUT - timeout) * 1000) / HZ);
if (!timeout) { if (!timeout) {
ret = -ETIME; ret = -ETIME;
disable_irq(di->irq); disable_irq(di->irq);
di->nbr_cceoc_irq_cnt = 0;
dev_err(di->dev, "completion timed out [%d]\n", dev_err(di->dev, "completion timed out [%d]\n",
__LINE__); __LINE__);
goto fail; goto fail;
...@@ -610,6 +629,7 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res) ...@@ -610,6 +629,7 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res)
} }
disable_irq(di->irq); disable_irq(di->irq);
di->nbr_cceoc_irq_cnt = 0;
ret = abx500_mask_and_set_register_interruptible(di->dev, ret = abx500_mask_and_set_register_interruptible(di->dev,
AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG,
...@@ -684,6 +704,7 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res) ...@@ -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 ab8500_fg_inst_curr_blocking(struct ab8500_fg *di)
{ {
int ret; int ret;
int timeout;
int res = 0; int res = 0;
ret = ab8500_fg_inst_curr_start(di); ret = ab8500_fg_inst_curr_start(di);
...@@ -692,13 +713,32 @@ int ab8500_fg_inst_curr_blocking(struct ab8500_fg *di) ...@@ -692,13 +713,32 @@ int ab8500_fg_inst_curr_blocking(struct ab8500_fg *di)
return 0; 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); ret = ab8500_fg_inst_curr_finalize(di, &res);
if (ret) { if (ret) {
dev_err(di->dev, "Failed to finalize fg_inst\n"); dev_err(di->dev, "Failed to finalize fg_inst\n");
return 0; return 0;
} }
dev_dbg(di->dev, "%s instant current: %d", __func__, res);
return 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) ...@@ -1523,8 +1563,6 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di)
case AB8500_FG_DISCHARGE_WAKEUP: case AB8500_FG_DISCHARGE_WAKEUP:
ab8500_fg_coulomb_counter(di, true); ab8500_fg_coulomb_counter(di, true);
di->inst_curr = ab8500_fg_inst_curr_blocking(di);
ab8500_fg_calc_cap_discharge_voltage(di, true); ab8500_fg_calc_cap_discharge_voltage(di, true);
di->fg_samples = SEC_TO_SAMPLE( di->fg_samples = SEC_TO_SAMPLE(
...@@ -1641,8 +1679,6 @@ static void ab8500_fg_periodic_work(struct work_struct *work) ...@@ -1641,8 +1679,6 @@ static void ab8500_fg_periodic_work(struct work_struct *work)
fg_periodic_work.work); fg_periodic_work.work);
if (di->init_capacity) { 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 */ /* Get an initial capacity calculation */
ab8500_fg_calc_cap_discharge_voltage(di, true); ab8500_fg_calc_cap_discharge_voltage(di, true);
ab8500_fg_check_capacity_limits(di, true); ab8500_fg_check_capacity_limits(di, true);
...@@ -1828,7 +1864,13 @@ static void ab8500_fg_instant_work(struct work_struct *work) ...@@ -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) static irqreturn_t ab8500_fg_cc_data_end_handler(int irq, void *_di)
{ {
struct ab8500_fg *di = _di; struct ab8500_fg *di = _di;
complete(&di->ab8500_fg_complete); 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; return IRQ_HANDLED;
} }
...@@ -2551,7 +2593,11 @@ static int ab8500_fg_probe(struct platform_device *pdev) ...@@ -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); di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer);
ab8500_fg_coulomb_counter(di, true); 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); init_completion(&di->ab8500_fg_complete);
/* Register interrupts */ /* Register interrupts */
...@@ -2571,6 +2617,7 @@ static int ab8500_fg_probe(struct platform_device *pdev) ...@@ -2571,6 +2617,7 @@ static int ab8500_fg_probe(struct platform_device *pdev)
} }
di->irq = platform_get_irq_byname(pdev, "CCEOC"); di->irq = platform_get_irq_byname(pdev, "CCEOC");
disable_irq(di->irq); disable_irq(di->irq);
di->nbr_cceoc_irq_cnt = 0;
platform_set_drvdata(pdev, di); platform_set_drvdata(pdev, di);
......
...@@ -431,11 +431,18 @@ struct ab8500_fg *ab8500_fg_get(void); ...@@ -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_blocking(struct ab8500_fg *dev);
int ab8500_fg_inst_curr_start(struct ab8500_fg *di); 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_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); int ab8500_fg_inst_curr_done(struct ab8500_fg *di);
#else #else
int ab8500_fg_inst_curr_started(struct ab8500_fg *di)
{
return 0;
}
int ab8500_fg_inst_curr_done(struct ab8500_fg *di) int ab8500_fg_inst_curr_done(struct ab8500_fg *di)
{ {
return 0;
} }
static void ab8500_fg_reinit(void) static void ab8500_fg_reinit(void)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment