summaryrefslogtreecommitdiffstats
path: root/drivers/power/ab8500_fg.c
diff options
context:
space:
mode:
authorSebastian Reichel <sre@kernel.org>2016-06-17 13:54:32 +0200
committerSebastian Reichel <sre@kernel.org>2016-08-11 01:11:03 +0200
commit8c0984e5a75337df513047ec92a6c09d78e3e5cd (patch)
treea2fc0a0dd7c7c40d9379bdd1c2b279c0959d0e1f /drivers/power/ab8500_fg.c
parent29b4817d4018df78086157ea3a55c1d9424a7cfc (diff)
power: move power supply drivers to power/supply
This moves all power supply drivers from drivers/power/ to drivers/power/supply/. The intention is a cleaner source tree, since drivers/power/ also contains frameworks unrelated to power supply, like adaptive voltage scaling. Signed-off-by: Sebastian Reichel <sre@kernel.org>
Diffstat (limited to 'drivers/power/ab8500_fg.c')
-rw-r--r--drivers/power/ab8500_fg.c3272
1 files changed, 0 insertions, 3272 deletions
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c
deleted file mode 100644
index 5a36cf88578a..000000000000
--- a/drivers/power/ab8500_fg.c
+++ /dev/null
@@ -1,3272 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson AB 2012
- *
- * Main and Back-up battery management driver.
- *
- * Note: Backup battery management is required in case of Li-Ion battery and not
- * for capacitive battery. HREF boards have capacitive battery and hence backup
- * battery management is not used and the supported code is available in this
- * driver.
- *
- * License Terms: GNU General Public License v2
- * Author:
- * Johan Palsson <johan.palsson@stericsson.com>
- * Karl Komierowski <karl.komierowski@stericsson.com>
- * Arun R Murthy <arun.murthy@stericsson.com>
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/power_supply.h>
-#include <linux/kobject.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/time.h>
-#include <linux/time64.h>
-#include <linux/of.h>
-#include <linux/completion.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/abx500.h>
-#include <linux/mfd/abx500/ab8500.h>
-#include <linux/mfd/abx500/ab8500-bm.h>
-#include <linux/mfd/abx500/ab8500-gpadc.h>
-#include <linux/kernel.h>
-
-#define MILLI_TO_MICRO 1000
-#define FG_LSB_IN_MA 1627
-#define QLSB_NANO_AMP_HOURS_X10 1071
-#define INS_CURR_TIMEOUT (3 * HZ)
-
-#define SEC_TO_SAMPLE(S) (S * 4)
-
-#define NBR_AVG_SAMPLES 20
-
-#define LOW_BAT_CHECK_INTERVAL (HZ / 16) /* 62.5 ms */
-
-#define VALID_CAPACITY_SEC (45 * 60) /* 45 minutes */
-#define BATT_OK_MIN 2360 /* mV */
-#define BATT_OK_INCREMENT 50 /* mV */
-#define BATT_OK_MAX_NR_INCREMENTS 0xE
-
-/* FG constants */
-#define BATT_OVV 0x01
-
-#define interpolate(x, x1, y1, x2, y2) \
- ((y1) + ((((y2) - (y1)) * ((x) - (x1))) / ((x2) - (x1))));
-
-/**
- * struct ab8500_fg_interrupts - ab8500 fg interupts
- * @name: name of the interrupt
- * @isr function pointer to the isr
- */
-struct ab8500_fg_interrupts {
- char *name;
- irqreturn_t (*isr)(int irq, void *data);
-};
-
-enum ab8500_fg_discharge_state {
- AB8500_FG_DISCHARGE_INIT,
- AB8500_FG_DISCHARGE_INITMEASURING,
- AB8500_FG_DISCHARGE_INIT_RECOVERY,
- AB8500_FG_DISCHARGE_RECOVERY,
- AB8500_FG_DISCHARGE_READOUT_INIT,
- AB8500_FG_DISCHARGE_READOUT,
- AB8500_FG_DISCHARGE_WAKEUP,
-};
-
-static char *discharge_state[] = {
- "DISCHARGE_INIT",
- "DISCHARGE_INITMEASURING",
- "DISCHARGE_INIT_RECOVERY",
- "DISCHARGE_RECOVERY",
- "DISCHARGE_READOUT_INIT",
- "DISCHARGE_READOUT",
- "DISCHARGE_WAKEUP",
-};
-
-enum ab8500_fg_charge_state {
- AB8500_FG_CHARGE_INIT,
- AB8500_FG_CHARGE_READOUT,
-};
-
-static char *charge_state[] = {
- "CHARGE_INIT",
- "CHARGE_READOUT",
-};
-
-enum ab8500_fg_calibration_state {
- AB8500_FG_CALIB_INIT,
- AB8500_FG_CALIB_WAIT,
- AB8500_FG_CALIB_END,
-};
-
-struct ab8500_fg_avg_cap {
- int avg;
- int samples[NBR_AVG_SAMPLES];
- time64_t time_stamps[NBR_AVG_SAMPLES];
- int pos;
- int nbr_samples;
- int sum;
-};
-
-struct ab8500_fg_cap_scaling {
- bool enable;
- int cap_to_scale[2];
- int disable_cap_level;
- int scaled_cap;
-};
-
-struct ab8500_fg_battery_capacity {
- int max_mah_design;
- int max_mah;
- int mah;
- int permille;
- int level;
- int prev_mah;
- int prev_percent;
- int prev_level;
- int user_mah;
- struct ab8500_fg_cap_scaling cap_scale;
-};
-
-struct ab8500_fg_flags {
- bool fg_enabled;
- bool conv_done;
- bool charging;
- bool fully_charged;
- bool force_full;
- bool low_bat_delay;
- bool low_bat;
- bool bat_ovv;
- bool batt_unknown;
- bool calibrate;
- bool user_cap;
- bool batt_id_received;
-};
-
-struct inst_curr_result_list {
- struct list_head list;
- int *result;
-};
-
-/**
- * struct ab8500_fg - ab8500 FG device information
- * @dev: Pointer to the structure device
- * @node: a list of AB8500 FGs, hence prepared for reentrance
- * @irq holds the CCEOC interrupt number
- * @vbat: Battery voltage in mV
- * @vbat_nom: Nominal battery voltage in mV
- * @inst_curr: Instantenous battery current in mA
- * @avg_curr: Average battery current in mA
- * @bat_temp battery temperature
- * @fg_samples: Number of samples used in the FG accumulation
- * @accu_charge: Accumulated charge from the last conversion
- * @recovery_cnt: Counter for recovery mode
- * @high_curr_cnt: Counter for high current mode
- * @init_cnt: Counter for init mode
- * @low_bat_cnt Counter for number of consecutive low battery measures
- * @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
- * @turn_off_fg: True if fg was off before current measurement
- * @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
- * @avg_cap: Average capacity filter
- * @parent: Pointer to the struct ab8500
- * @gpadc: Pointer to the struct gpadc
- * @bm: Platform specific battery management information
- * @fg_psy: Structure that holds the FG specific battery properties
- * @fg_wq: Work queue for running the FG algorithm
- * @fg_periodic_work: Work to run the FG algorithm periodically
- * @fg_low_bat_work: Work to check low bat condition
- * @fg_reinit_work Work used to reset and reinitialise the FG algorithm
- * @fg_work: Work to run the FG algorithm instantly
- * @fg_acc_cur_work: Work to read the FG accumulator
- * @fg_check_hw_failure_work: Work for checking HW state
- * @cc_lock: Mutex for locking the CC
- * @fg_kobject: Structure of type kobject
- */
-struct ab8500_fg {
- struct device *dev;
- struct list_head node;
- int irq;
- int vbat;
- int vbat_nom;
- int inst_curr;
- int avg_curr;
- int bat_temp;
- int fg_samples;
- int accu_charge;
- int recovery_cnt;
- int high_curr_cnt;
- int init_cnt;
- int low_bat_cnt;
- int nbr_cceoc_irq_cnt;
- bool recovery_needed;
- bool high_curr_mode;
- bool init_capacity;
- bool turn_off_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;
- struct ab8500_fg_avg_cap avg_cap;
- struct ab8500 *parent;
- struct ab8500_gpadc *gpadc;
- struct abx500_bm_data *bm;
- struct power_supply *fg_psy;
- struct workqueue_struct *fg_wq;
- struct delayed_work fg_periodic_work;
- struct delayed_work fg_low_bat_work;
- struct delayed_work fg_reinit_work;
- struct work_struct fg_work;
- struct work_struct fg_acc_cur_work;
- struct delayed_work fg_check_hw_failure_work;
- struct mutex cc_lock;
- struct kobject fg_kobject;
-};
-static LIST_HEAD(ab8500_fg_list);
-
-/**
- * ab8500_fg_get() - returns a reference to the primary AB8500 fuel gauge
- * (i.e. the first fuel gauge in the instance list)
- */
-struct ab8500_fg *ab8500_fg_get(void)
-{
- struct ab8500_fg *fg;
-
- if (list_empty(&ab8500_fg_list))
- return NULL;
-
- fg = list_first_entry(&ab8500_fg_list, struct ab8500_fg, node);
- return fg;
-}
-
-/* Main battery properties */
-static enum power_supply_property ab8500_fg_props[] = {
- POWER_SUPPLY_PROP_VOLTAGE_NOW,
- POWER_SUPPLY_PROP_CURRENT_NOW,
- POWER_SUPPLY_PROP_CURRENT_AVG,
- POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
- POWER_SUPPLY_PROP_ENERGY_FULL,
- POWER_SUPPLY_PROP_ENERGY_NOW,
- POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
- POWER_SUPPLY_PROP_CHARGE_FULL,
- POWER_SUPPLY_PROP_CHARGE_NOW,
- POWER_SUPPLY_PROP_CAPACITY,
- POWER_SUPPLY_PROP_CAPACITY_LEVEL,
-};
-
-/*
- * This array maps the raw hex value to lowbat voltage used by the AB8500
- * Values taken from the UM0836
- */
-static int ab8500_fg_lowbat_voltage_map[] = {
- 2300 ,
- 2325 ,
- 2350 ,
- 2375 ,
- 2400 ,
- 2425 ,
- 2450 ,
- 2475 ,
- 2500 ,
- 2525 ,
- 2550 ,
- 2575 ,
- 2600 ,
- 2625 ,
- 2650 ,
- 2675 ,
- 2700 ,
- 2725 ,
- 2750 ,
- 2775 ,
- 2800 ,
- 2825 ,
- 2850 ,
- 2875 ,
- 2900 ,
- 2925 ,
- 2950 ,
- 2975 ,
- 3000 ,
- 3025 ,
- 3050 ,
- 3075 ,
- 3100 ,
- 3125 ,
- 3150 ,
- 3175 ,
- 3200 ,
- 3225 ,
- 3250 ,
- 3275 ,
- 3300 ,
- 3325 ,
- 3350 ,
- 3375 ,
- 3400 ,
- 3425 ,
- 3450 ,
- 3475 ,
- 3500 ,
- 3525 ,
- 3550 ,
- 3575 ,
- 3600 ,
- 3625 ,
- 3650 ,
- 3675 ,
- 3700 ,
- 3725 ,
- 3750 ,
- 3775 ,
- 3800 ,
- 3825 ,
- 3850 ,
- 3850 ,
-};
-
-static u8 ab8500_volt_to_regval(int voltage)
-{
- int i;
-
- if (voltage < ab8500_fg_lowbat_voltage_map[0])
- return 0;
-
- for (i = 0; i < ARRAY_SIZE(ab8500_fg_lowbat_voltage_map); i++) {
- if (voltage < ab8500_fg_lowbat_voltage_map[i])
- return (u8) i - 1;
- }
-
- /* If not captured above, return index of last element */
- return (u8) ARRAY_SIZE(ab8500_fg_lowbat_voltage_map) - 1;
-}
-
-/**
- * ab8500_fg_is_low_curr() - Low or high current mode
- * @di: pointer to the ab8500_fg structure
- * @curr: the current to base or our decision on
- *
- * Low current mode if the current consumption is below a certain threshold
- */
-static int ab8500_fg_is_low_curr(struct ab8500_fg *di, int curr)
-{
- /*
- * We want to know if we're in low current mode
- */
- if (curr > -di->bm->fg_params->high_curr_threshold)
- return true;
- else
- return false;
-}
-
-/**
- * ab8500_fg_add_cap_sample() - Add capacity to average filter
- * @di: pointer to the ab8500_fg structure
- * @sample: the capacity in mAh to add to the filter
- *
- * A capacity is added to the filter and a new mean capacity is calculated and
- * returned
- */
-static int ab8500_fg_add_cap_sample(struct ab8500_fg *di, int sample)
-{
- struct timespec64 ts64;
- struct ab8500_fg_avg_cap *avg = &di->avg_cap;
-
- getnstimeofday64(&ts64);
-
- do {
- avg->sum += sample - avg->samples[avg->pos];
- avg->samples[avg->pos] = sample;
- avg->time_stamps[avg->pos] = ts64.tv_sec;
- avg->pos++;
-
- if (avg->pos == NBR_AVG_SAMPLES)
- avg->pos = 0;
-
- if (avg->nbr_samples < NBR_AVG_SAMPLES)
- avg->nbr_samples++;
-
- /*
- * Check the time stamp for each sample. If too old,
- * replace with latest sample
- */
- } while (ts64.tv_sec - VALID_CAPACITY_SEC > avg->time_stamps[avg->pos]);
-
- avg->avg = avg->sum / avg->nbr_samples;
-
- return avg->avg;
-}
-
-/**
- * ab8500_fg_clear_cap_samples() - Clear average filter
- * @di: pointer to the ab8500_fg structure
- *
- * The capacity filter is is reset to zero.
- */
-static void ab8500_fg_clear_cap_samples(struct ab8500_fg *di)
-{
- int i;
- struct ab8500_fg_avg_cap *avg = &di->avg_cap;
-
- avg->pos = 0;
- avg->nbr_samples = 0;
- avg->sum = 0;
- avg->avg = 0;
-
- for (i = 0; i < NBR_AVG_SAMPLES; i++) {
- avg->samples[i] = 0;
- avg->time_stamps[i] = 0;
- }
-}
-
-/**
- * ab8500_fg_fill_cap_sample() - Fill average filter
- * @di: pointer to the ab8500_fg structure
- * @sample: the capacity in mAh to fill the filter with
- *
- * The capacity filter is filled with a capacity in mAh
- */
-static void ab8500_fg_fill_cap_sample(struct ab8500_fg *di, int sample)
-{
- int i;
- struct timespec64 ts64;
- struct ab8500_fg_avg_cap *avg = &di->avg_cap;
-
- getnstimeofday64(&ts64);
-
- for (i = 0; i < NBR_AVG_SAMPLES; i++) {
- avg->samples[i] = sample;
- avg->time_stamps[i] = ts64.tv_sec;
- }
-
- avg->pos = 0;
- avg->nbr_samples = NBR_AVG_SAMPLES;
- avg->sum = sample * NBR_AVG_SAMPLES;
- avg->avg = sample;
-}
-
-/**
- * ab8500_fg_coulomb_counter() - enable coulomb counter
- * @di: pointer to the ab8500_fg structure
- * @enable: enable/disable
- *
- * Enable/Disable coulomb counter.
- * On failure returns negative value.
- */
-static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable)
-{
- int ret = 0;
- mutex_lock(&di->cc_lock);
- if (enable) {
- /* To be able to reprogram the number of samples, we have to
- * first stop the CC and then enable it again */
- ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
- AB8500_RTC_CC_CONF_REG, 0x00);
- if (ret)
- goto cc_err;
-
- /* Program the samples */
- ret = abx500_set_register_interruptible(di->dev,
- AB8500_GAS_GAUGE, AB8500_GASG_CC_NCOV_ACCU,
- di->fg_samples);
- if (ret)
- goto cc_err;
-
- /* Start the CC */
- ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
- AB8500_RTC_CC_CONF_REG,
- (CC_DEEP_SLEEP_ENA | CC_PWR_UP_ENA));
- if (ret)
- goto cc_err;
-
- di->flags.fg_enabled = true;
- } else {
- /* Clear any pending read requests */
- ret = abx500_mask_and_set_register_interruptible(di->dev,
- AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG,
- (RESET_ACCU | READ_REQ), 0);
- if (ret)
- goto cc_err;
-
- ret = abx500_set_register_interruptible(di->dev,
- AB8500_GAS_GAUGE, AB8500_GASG_CC_NCOV_ACCU_CTRL, 0);
- if (ret)
- goto cc_err;
-
- /* Stop the CC */
- ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
- AB8500_RTC_CC_CONF_REG, 0);
- if (ret)
- goto cc_err;
-
- di->flags.fg_enabled = false;
-
- }
- dev_dbg(di->dev, " CC enabled: %d Samples: %d\n",
- enable, di->fg_samples);
-
- mutex_unlock(&di->cc_lock);
-
- return ret;
-cc_err:
- dev_err(di->dev, "%s Enabling coulomb counter failed\n", __func__);
- mutex_unlock(&di->cc_lock);
- return ret;
-}
-
-/**
- * ab8500_fg_inst_curr_start() - start battery instantaneous current
- * @di: pointer to the ab8500_fg structure
- *
- * Returns 0 or error code
- * Note: This is part "one" and has to be called before
- * ab8500_fg_inst_curr_finalize()
- */
-int ab8500_fg_inst_curr_start(struct ab8500_fg *di)
-{
- u8 reg_val;
- int ret;
-
- 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)
- goto fail;
-
- if (!(reg_val & CC_PWR_UP_ENA)) {
- dev_dbg(di->dev, "%s Enable FG\n", __func__);
- di->turn_off_fg = true;
-
- /* Program the samples */
- ret = abx500_set_register_interruptible(di->dev,
- AB8500_GAS_GAUGE, AB8500_GASG_CC_NCOV_ACCU,
- SEC_TO_SAMPLE(10));
- if (ret)
- goto fail;
-
- /* Start the CC */
- ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
- AB8500_RTC_CC_CONF_REG,
- (CC_DEEP_SLEEP_ENA | CC_PWR_UP_ENA));
- if (ret)
- goto fail;
- } else {
- di->turn_off_fg = false;
- }
-
- /* Return and WFI */
- reinit_completion(&di->ab8500_fg_started);
- reinit_completion(&di->ab8500_fg_complete);
- enable_irq(di->irq);
-
- /* Note: cc_lock is still locked */
- return 0;
-fail:
- mutex_unlock(&di->cc_lock);
- 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
- *
- * Returns 1 if conversion done, 0 if still waiting
- */
-int ab8500_fg_inst_curr_done(struct ab8500_fg *di)
-{
- return completion_done(&di->ab8500_fg_complete);
-}
-
-/**
- * ab8500_fg_inst_curr_finalize() - battery instantaneous current
- * @di: pointer to the ab8500_fg structure
- * @res: battery instantenous current(on success)
- *
- * Returns 0 or an error code
- * Note: This is part "two" and has to be called at earliest 250 ms
- * after ab8500_fg_inst_curr_start()
- */
-int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res)
-{
- u8 low, high;
- int val;
- int ret;
- unsigned long timeout;
-
- if (!completion_done(&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",
- jiffies_to_msecs(INS_CURR_TIMEOUT - timeout));
- 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;
- }
- }
-
- 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,
- READ_REQ, READ_REQ);
-
- /* 100uS between read request and read is needed */
- usleep_range(100, 100);
-
- /* Read CC Sample conversion value Low and high */
- ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE,
- AB8500_GASG_CC_SMPL_CNVL_REG, &low);
- if (ret < 0)
- goto fail;
-
- ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE,
- AB8500_GASG_CC_SMPL_CNVH_REG, &high);
- if (ret < 0)
- goto fail;
-
- /*
- * negative value for Discharging
- * convert 2's compliment into decimal
- */
- if (high & 0x10)
- val = (low | (high << 8) | 0xFFFFE000);
- else
- val = (low | (high << 8));
-
- /*
- * Convert to unit value in mA
- * Full scale input voltage is
- * 63.160mV => LSB = 63.160mV/(4096*res) = 1.542mA
- * Given a 250ms conversion cycle time the LSB corresponds
- * to 107.1 nAh. Convert to current by dividing by the conversion
- * time in hours (250ms = 1 / (3600 * 4)h)
- * 107.1nAh assumes 10mOhm, but fg_res is in 0.1mOhm
- */
- val = (val * QLSB_NANO_AMP_HOURS_X10 * 36 * 4) /
- (1000 * di->bm->fg_res);
-
- if (di->turn_off_fg) {
- dev_dbg(di->dev, "%s Disable FG\n", __func__);
-
- /* Clear any pending read requests */
- ret = abx500_set_register_interruptible(di->dev,
- AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, 0);
- if (ret)
- goto fail;
-
- /* Stop the CC */
- ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
- AB8500_RTC_CC_CONF_REG, 0);
- if (ret)
- goto fail;
- }
- mutex_unlock(&di->cc_lock);
- (*res) = val;
-
- return 0;
-fail:
- mutex_unlock(&di->cc_lock);
- return ret;
-}
-
-/**
- * ab8500_fg_inst_curr_blocking() - battery instantaneous current
- * @di: pointer to the ab8500_fg structure
- * @res: battery instantenous current(on success)
- *
- * Returns 0 else error code
- */
-int ab8500_fg_inst_curr_blocking(struct ab8500_fg *di)
-{
- int ret;
- unsigned long timeout;
- int res = 0;
-
- ret = ab8500_fg_inst_curr_start(di);
- if (ret) {
- dev_err(di->dev, "Failed to initialize fg_inst\n");
- 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",
- jiffies_to_msecs(INS_CURR_TIMEOUT - timeout));
- 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:
- disable_irq(di->irq);
- mutex_unlock(&di->cc_lock);
- return ret;
-}
-
-/**
- * ab8500_fg_acc_cur_work() - average battery current
- * @work: pointer to the work_struct structure
- *
- * Updated the average battery current obtained from the
- * coulomb counter.
- */
-static void ab8500_fg_acc_cur_work(struct work_struct *work)
-{
- int val;
- int ret;
- u8 low, med, high;
-
- struct ab8500_fg *di = container_of(work,
- struct ab8500_fg, fg_acc_cur_work);
-
- mutex_lock(&di->cc_lock);
- ret = abx500_set_register_interruptible(di->dev, AB8500_GAS_GAUGE,
- AB8500_GASG_CC_NCOV_ACCU_CTRL, RD_NCONV_ACCU_REQ);
- if (ret)
- goto exit;
-
- ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE,
- AB8500_GASG_CC_NCOV_ACCU_LOW, &low);
- if (ret < 0)
- goto exit;
-
- ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE,
- AB8500_GASG_CC_NCOV_ACCU_MED, &med);
- if (ret < 0)
- goto exit;
-
- ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE,
- AB8500_GASG_CC_NCOV_ACCU_HIGH, &high);
- if (ret < 0)
- goto exit;
-
- /* Check for sign bit in case of negative value, 2's compliment */
- if (high & 0x10)
- val = (low | (med << 8) | (high << 16) | 0xFFE00000);
- else
- val = (low | (med << 8) | (high << 16));
-
- /*
- * Convert to uAh
- * Given a 250ms conversion cycle time the LSB corresponds
- * to 112.9 nAh.
- * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm
- */
- di->accu_charge = (val * QLSB_NANO_AMP_HOURS_X10) /
- (100 * di->bm->fg_res);
-
- /*
- * Convert to unit value in mA
- * by dividing by the conversion
- * time in hours (= samples / (3600 * 4)h)
- * and multiply with 1000
- */
- di->avg_curr = (val * QLSB_NANO_AMP_HOURS_X10 * 36) /
- (1000 * di->bm->fg_res * (di->fg_samples / 4));
-
- di->flags.conv_done = true;
-
- mutex_unlock(&di->cc_lock);
-
- queue_work(di->fg_wq, &di->fg_work);
-
- dev_dbg(di->dev, "fg_res: %d, fg_samples: %d, gasg: %d, accu_charge: %d \n",
- di->bm->fg_res, di->fg_samples, val, di->accu_charge);
- return;
-exit:
- dev_err(di->dev,
- "Failed to read or write gas gauge registers\n");
- mutex_unlock(&di->cc_lock);
- queue_work(di->fg_wq, &di->fg_work);
-}
-
-/**
- * ab8500_fg_bat_voltage() - get battery voltage
- * @di: pointer to the ab8500_fg structure
- *
- * Returns battery voltage(on success) else error code
- */
-static int ab8500_fg_bat_voltage(struct ab8500_fg *di)
-{
- int vbat;
- static int prev;
-
- vbat = ab8500_gpadc_convert(di->gpadc, MAIN_BAT_V);
- if (vbat < 0) {
- dev_err(di->dev,
- "%s gpadc conversion failed, using previous value\n",
- __func__);
- return prev;
- }
-
- prev = vbat;
- return vbat;
-}
-
-/**
- * ab8500_fg_volt_to_capacity() - Voltage based capacity
- * @di: pointer to the ab8500_fg structure
- * @voltage: The voltage to convert to a capacity
- *
- * Returns battery capacity in per mille based on voltage
- */
-static int ab8500_fg_volt_to_capacity(struct ab8500_fg *di, int voltage)
-{
- int i, tbl_size;
- const struct abx500_v_to_cap *tbl;
- int cap = 0;
-
- tbl = di->bm->bat_type[di->bm->batt_id].v_to_cap_tbl,
- tbl_size = di->bm->bat_type[di->bm->batt_id].n_v_cap_tbl_elements;
-
- for (i = 0; i < tbl_size; ++i) {
- if (voltage > tbl[i].voltage)
- break;
- }
-
- if ((i > 0) && (i < tbl_size)) {
- cap = interpolate(voltage,
- tbl[i].voltage,
- tbl[i].capacity * 10,
- tbl[i-1].voltage,
- tbl[i-1].capacity * 10);
- } else if (i == 0) {
- cap = 1000;
- } else {
- cap = 0;
- }
-
- dev_dbg(di->dev, "%s Vbat: %d, Cap: %d per mille",
- __func__, voltage, cap);
-
- return cap;
-}
-
-/**
- * ab8500_fg_uncomp_volt_to_capacity() - Uncompensated voltage based capacity
- * @di: pointer to the ab8500_fg structure
- *
- * Returns battery capacity based on battery voltage that is not compensated
- * for the voltage drop due to the load
- */
-static int ab8500_fg_uncomp_volt_to_capacity(struct ab8500_fg *di)
-{
- di->vbat = ab8500_fg_bat_voltage(di);
- return ab8500_fg_volt_to_capacity(di, di->vbat);
-}
-
-/**
- * ab8500_fg_battery_resistance() - Returns the battery inner resistance
- * @di: pointer to the ab8500_fg structure
- *
- * Returns battery inner resistance added with the fuel gauge resistor value
- * to get the total resistance in the whole link from gnd to bat+ node.
- */
-static int ab8500_fg_battery_resistance(struct ab8500_fg *di)
-{
- int i, tbl_size;
- const struct batres_vs_temp *tbl;
- int resist = 0;
-
- tbl = di->bm->bat_type[di->bm->batt_id].batres_tbl;
- tbl_size = di->bm->bat_type[di->bm->batt_id].n_batres_tbl_elements;
-
- for (i = 0; i < tbl_size; ++i) {
- if (di->bat_temp / 10 > tbl[i].temp)
- break;
- }
-
- if ((i > 0) && (i < tbl_size)) {
- resist = interpolate(di->bat_temp / 10,
- tbl[i].temp,
- tbl[i].resist,
- tbl[i-1].temp,
- tbl[i-1].resist);
- } else if (i == 0) {
- resist = tbl[0].resist;
- } else {
- resist = tbl[tbl_size - 1].resist;
- }
-
- dev_dbg(di->dev, "%s Temp: %d battery internal resistance: %d"
- " fg resistance %d, total: %d (mOhm)\n",
- __func__, di->bat_temp, resist, di->bm->fg_res / 10,
- (di->bm->fg_res / 10) + resist);
-
- /* fg_res variable is in 0.1mOhm */
- resist += di->bm->fg_res / 10;
-
- return resist;
-}
-
-/**
- * ab8500_fg_load_comp_volt_to_capacity() - Load compensated voltage based capacity
- * @di: pointer to the ab8500_fg structure
- *
- * Returns battery capacity based on battery voltage that is load compensated
- * for the voltage drop
- */
-static int ab8500_fg_load_comp_volt_to_capacity(struct ab8500_fg *di)
-{
- int vbat_comp, res;
- int i = 0;
- int vbat = 0;
-
- ab8500_fg_inst_curr_start(di);
-
- do {
- vbat += ab8500_fg_bat_voltage(di);
- i++;
- usleep_range(5000, 6000);
- } while (!ab8500_fg_inst_curr_done(di));
-
- ab8500_fg_inst_curr_finalize(di, &di->inst_curr);
-
- di->vbat = vbat / i;
- res = ab8500_fg_battery_resistance(di);
-
- /* Use Ohms law to get the load compensated voltage */
- vbat_comp = di->vbat - (di->inst_curr * res) / 1000;
-
- dev_dbg(di->dev, "%s Measured Vbat: %dmV,Compensated Vbat %dmV, "
- "R: %dmOhm, Current: %dmA Vbat Samples: %d\n",
- __func__, di->vbat, vbat_comp, res, di->inst_curr, i);
-
- return ab8500_fg_volt_to_capacity(di, vbat_comp);
-}
-
-/**
- * ab8500_fg_convert_mah_to_permille() - Capacity in mAh to permille
- * @di: pointer to the ab8500_fg structure
- * @cap_mah: capacity in mAh
- *
- * Converts capacity in mAh to capacity in permille
- */
-static int ab8500_fg_convert_mah_to_permille(struct ab8500_fg *di, int cap_mah)
-{
- return (cap_mah * 1000) / di->bat_cap.max_mah_design;
-}
-
-/**
- * ab8500_fg_convert_permille_to_mah() - Capacity in permille to mAh
- * @di: pointer to the ab8500_fg structure
- * @cap_pm: capacity in permille
- *
- * Converts capacity in permille to capacity in mAh
- */
-static int ab8500_fg_convert_permille_to_mah(struct ab8500_fg *di, int cap_pm)
-{
- return cap_pm * di->bat_cap.max_mah_design / 1000;
-}
-
-/**
- * ab8500_fg_convert_mah_to_uwh() - Capacity in mAh to uWh
- * @di: pointer to the ab8500_fg structure
- * @cap_mah: capacity in mAh
- *
- * Converts capacity in mAh to capacity in uWh
- */
-static int ab8500_fg_convert_mah_to_uwh(struct ab8500_fg *di, int cap_mah)
-{
- u64 div_res;
- u32 div_rem;
-
- div_res = ((u64) cap_mah) * ((u64) di->vbat_nom);
- div_rem = do_div(div_res, 1000);
-
- /* Make sure to round upwards if necessary */
- if (div_rem >= 1000 / 2)
- div_res++;
-
- return (int) div_res;
-}
-
-/**
- * ab8500_fg_calc_cap_charging() - Calculate remaining capacity while charging
- * @di: pointer to the ab8500_fg structure
- *
- * Return the capacity in mAh based on previous calculated capcity and the FG
- * accumulator register value. The filter is filled with this capacity
- */
-static int ab8500_fg_calc_cap_charging(struct ab8500_fg *di)
-{
- dev_dbg(di->dev, "%s cap_mah %d accu_charge %d\n",
- __func__,
- di->bat_cap.mah,
- di->accu_charge);
-
- /* Capacity should not be less than 0 */
- if (di->bat_cap.mah + di->accu_charge > 0)
- di->bat_cap.mah += di->accu_charge;
- else
- di->bat_cap.mah = 0;
- /*
- * We force capacity to 100% once when the algorithm
- * reports that it's full.
- */
- if (di->bat_cap.mah >= di->bat_cap.max_mah_design ||
- di->flags.force_full) {
- di->bat_cap.mah = di->bat_cap.max_mah_design;
- }
-
- ab8500_fg_fill_cap_sample(di, di->bat_cap.mah);
- di->bat_cap.permille =
- ab8500_fg_convert_mah_to_permille(di, di->bat_cap.mah);
-
- /* We need to update battery voltage and inst current when charging */
- di->vbat = ab8500_fg_bat_voltage(di);
- di->inst_curr = ab8500_fg_inst_curr_blocking(di);
-
- return di->bat_cap.mah;
-}
-
-/**
- * ab8500_fg_calc_cap_discharge_voltage() - Capacity in discharge with voltage
- * @di: pointer to the ab8500_fg structure
- * @comp: if voltage should be load compensated before capacity calc
- *
- * Return the capacity in mAh based on the battery voltage. The voltage can
- * either be load compensated or not. This value is added to the filter and a
- * new mean value is calculated and returned.
- */
-static int ab8500_fg_calc_cap_discharge_voltage(struct ab8500_fg *di, bool comp)
-{
- int permille, mah;
-
- if (comp)
- permille = ab8500_fg_load_comp_volt_to_capacity(di);
- else
- permille = ab8500_fg_uncomp_volt_to_capacity(di);
-
- mah = ab8500_fg_convert_permille_to_mah(di, permille);
-
- di->bat_cap.mah = ab8500_fg_add_cap_sample(di, mah);
- di->bat_cap.permille =
- ab8500_fg_convert_mah_to_permille(di, di->bat_cap.mah);
-
- return di->bat_cap.mah;
-}
-
-/**
- * ab8500_fg_calc_cap_discharge_fg() - Capacity in discharge with FG
- * @di: pointer to the ab8500_fg structure
- *
- * Return the capacity in mAh based on previous calculated capcity and the FG
- * accumulator register value. This value is added to the filter and a
- * new mean value is calculated and returned.
- */
-static int ab8500_fg_calc_cap_discharge_fg(struct ab8500_fg *di)
-{
- int permille_volt, permille;
-
- dev_dbg(di->dev, "%s cap_mah %d accu_charge %d\n",
- __func__,
- di->bat_cap.mah,
- di->accu_charge);
-
- /* Capacity should not be less than 0 */
- if (di->bat_cap.mah + di->accu_charge > 0)
- di->bat_cap.mah += di->accu_charge;
- else
- di->bat_cap.mah = 0;
-
- if (di->bat_cap.mah >= di->bat_cap.max_mah_design)
- di->bat_cap.mah = di->bat_cap.max_mah_design;
-
- /*
- * Check against voltage based capacity. It can not be lower
- * than what the uncompensated voltage says
- */
- permille = ab8500_fg_convert_mah_to_permille(di, di->bat_cap.mah);
- permille_volt = ab8500_fg_uncomp_volt_to_capacity(di);
-
- if (permille < permille_volt) {
- di->bat_cap.permille = permille_volt;
- di->bat_cap.mah = ab8500_fg_convert_permille_to_mah(di,
- di->bat_cap.permille);
-
- dev_dbg(di->dev, "%s voltage based: perm %d perm_volt %d\n",
- __func__,
- permille,
- permille_volt);
-
- ab8500_fg_fill_cap_sample(di, di->bat_cap.mah);
- } else {
- ab8500_fg_fill_cap_sample(di, di->bat_cap.mah);
- di->bat_cap.permille =
- ab8500_fg_convert_mah_to_permille(di, di->bat_cap.mah);
- }
-
- return di->bat_cap.mah;
-}
-
-/**
- * ab8500_fg_capacity_level() - Get the battery capacity level
- * @di: pointer to the ab8500_fg structure
- *
- * Get the battery capacity level based on the capacity in percent
- */
-static int ab8500_fg_capacity_level(struct ab8500_fg *di)
-{
- int ret, percent;
-
- percent = DIV_ROUND_CLOSEST(di->bat_cap.permille, 10);
-
- if (percent <= di->bm->cap_levels->critical ||
- di->flags.low_bat)
- ret = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
- else if (percent <= di->bm->cap_levels->low)
- ret = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
- else if (percent <= di->bm->cap_levels->normal)
- ret = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
- else if (percent <= di->bm->cap_levels->high)
- ret = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
- else
- ret = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
-
- return ret;
-}
-
-/**
- * ab8500_fg_calculate_scaled_capacity() - Capacity scaling
- * @di: pointer to the ab8500_fg structure
- *
- * Calculates the capacity to be shown to upper layers. Scales the capacity
- * to have 100% as a reference from the actual capacity upon removal of charger
- * when charging is in maintenance mode.