From: Michel JAOUEN <michel.jao...@stericsson.com> Add dedicated test functions for HATS framework. This patch allows validating fuel gauge HW IP in all possible modes supported by HW. Services are accessible through DebugFS interface.
Signed-off-by: Lee Jones <lee.jo...@linaro.org> Signed-off-by: Loic Pallardy <loic.palla...@stericsson.com> Reviewed-by: Michel JAOUEN <michel.jao...@stericsson.com> Reviewed-by: Marcus COOPER <marcus.xm.coo...@stericsson.com> Reviewed-by: Jonas ABERG <jonas.ab...@stericsson.com> Tested-by: Michel JAOUEN <michel.jao...@stericsson.com> Tested-by: Jonas ABERG <jonas.ab...@stericsson.com> --- drivers/power/Kconfig | 10 + drivers/power/Makefile | 1 + drivers/power/ab8500_fg.c | 271 +++-------- drivers/power/ab8500_fg.h | 242 ++++++++++ drivers/power/ab8500_fg_deepdebug.c | 823 ++++++++++++++++++++++++++++++++++ include/linux/mfd/abx500/ab8500-bm.h | 164 +++++++ 6 files changed, 1297 insertions(+), 214 deletions(-) create mode 100644 drivers/power/ab8500_fg.h create mode 100644 drivers/power/ab8500_fg_deepdebug.c diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index b9de00d..16b4869 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -346,6 +346,15 @@ config AB8500_BM help Say Y to include support for AB8500 battery management. +config AB8500_BM_DEEP_DEBUG + bool "AB8500 Battery Management Deep Debug" + depends on (AB8500_BM && DEEP_DEBUG) + default y + help + Say Y to include support for Deep Debug interface + for battery management. + If unsure, say N. + config CHARGER_PM2301 bool "PM2301 Battery Charger Driver" depends on AB8500_BM @@ -356,6 +365,7 @@ config CHARGER_PM2301 config PM2XXX_DEEP_DEBUG bool "PM2XXX Deep Debug" depends on DEEP_DEBUG && CHARGER_PM2301 + default n help Deep Debug interface provides an access to all registers. It allows to read or write directly a register. diff --git a/drivers/power/Makefile b/drivers/power/Makefile index ef1e79c..476668d 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o +obj-$(CONFIG_AB8500_BM_DEEP_DEBUG) += ab8500_fg_deepdebug.o obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c index a0cbbd3..238eeee 100644 --- a/drivers/power/ab8500_fg.c +++ b/drivers/power/ab8500_fg.c @@ -33,25 +33,12 @@ #include <linux/mfd/abx500/ab8500-bm.h> #include <linux/mfd/abx500/ab8500-gpadc.h> #include <linux/kernel.h> +#include "ab8500_fg.h" -#define MILLI_TO_MICRO 1000 -#define FG_LSB_IN_MA 1627 -#define QLSB_NANO_AMP_HOURS_X10 1129 -#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 +char *charge_state[] = { + "CHARGE_INIT", + "CHARGE_READOUT", +}; #define interpolate(x, x1, y1, x2, y2) \ ((y1) + ((((y2) - (y1)) * ((x) - (x1))) / ((x2) - (x1)))); @@ -59,186 +46,6 @@ #define to_ab8500_fg_device_info(x) container_of((x), \ struct ab8500_fg, fg_psy); -/** - * 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]; - __kernel_time_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); /** @@ -470,7 +277,7 @@ static void ab8500_fg_fill_cap_sample(struct ab8500_fg *di, int sample) * Enable/Disable coulomb counter. * On failure returns negative value. */ -static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable) +int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable) { int ret = 0; mutex_lock(&di->cc_lock); @@ -483,11 +290,13 @@ static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable) 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; + if (!di->test.enable) { + 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, @@ -1403,7 +1212,7 @@ static void ab8500_fg_check_capacity_limits(struct ab8500_fg *di, bool init) } } -static void ab8500_fg_charge_state_to(struct ab8500_fg *di, +void ab8500_fg_charge_state_to(struct ab8500_fg *di, enum ab8500_fg_charge_state new_state) { dev_dbg(di->dev, "Charge state from %d [%s] to %d [%s]\n", @@ -1991,12 +1800,17 @@ 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); + + if (di->test.enable) + complete(&di->test.cceoc_complete); + else { + 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; } @@ -2011,8 +1825,31 @@ static irqreturn_t ab8500_fg_cc_data_end_handler(int irq, void *_di) static irqreturn_t ab8500_fg_cc_int_calib_handler(int irq, void *_di) { struct ab8500_fg *di = _di; - di->calib_state = AB8500_FG_CALIB_END; - queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); + + if (di->test.enable) { + complete(&di->test.cc_int_calib_complete); + } else { + di->calib_state = AB8500_FG_CALIB_END; + queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0); + } + return IRQ_HANDLED; +} + +/** + * ab8500_fg_cceoc_handler() - end of conversion isr. + * @irq: interrupt number + * @_di: pointer to the ab8500_fg structure + * + * Returns IRQ status(IRQ_HANDLED) + */ + +static irqreturn_t ab8500_fg_cceoc_handler(int irq, void *_di) +{ + struct ab8500_fg *di = _di; + + if (di->test.enable) + complete(&di->test.cceoc_complete); + return IRQ_HANDLED; } @@ -2027,7 +1864,10 @@ static irqreturn_t ab8500_fg_cc_convend_handler(int irq, void *_di) { struct ab8500_fg *di = _di; - queue_work(di->fg_wq, &di->fg_acc_cur_work); + if (di->test.enable) + complete(&di->test.nconv_accu_complete); + else + queue_work(di->fg_wq, &di->fg_acc_cur_work); return IRQ_HANDLED; } @@ -2613,6 +2453,7 @@ static struct ab8500_fg_interrupts ab8500_fg_irq[] = { {"LOW_BAT_F", ab8500_fg_lowbatf_handler}, {"CC_INT_CALIB", ab8500_fg_cc_int_calib_handler}, {"CCEOC", ab8500_fg_cc_data_end_handler}, + {"CCEOC", ab8500_fg_cceoc_handler}, }; static char *supply_interface[] = { @@ -2676,6 +2517,8 @@ static int ab8500_fg_probe(struct platform_device *pdev) ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_INIT); ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_INIT); + ab8500_fg_test_init(di); + /* Create a work queue for running the FG algorithm */ di->fg_wq = create_singlethread_workqueue("ab8500_fg_wq"); if (di->fg_wq == NULL) { diff --git a/drivers/power/ab8500_fg.h b/drivers/power/ab8500_fg.h new file mode 100644 index 0000000..946840b --- /dev/null +++ b/drivers/power/ab8500_fg.h @@ -0,0 +1,242 @@ +/* + * 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.pals...@stericsson.com> + * Author: Karl Komierowski <karl.komierow...@stericsson.com> + */ + +#define MILLI_TO_MICRO 1000 +#define FG_LSB_IN_MA 1627 +#define QLSB_NANO_AMP_HOURS_X10 1129 +#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 + +/** + * 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, +}; + +enum ab8500_fg_charge_state { + AB8500_FG_CHARGE_INIT, + AB8500_FG_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]; + __kernel_time_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_test - ab8500 FG device information in test mode + * @enable: true if fg in test mode else false + * @cc_int_offset: offset for internal calibration + * @cc_soft_offset: offset for software calibration + * @cc_sample_conv: sample read + * @cc_sample_conv_calib_uA: sample converted in uA + * @cceoc_complete: pointer to the struct completion, to indicate + * the completion of internal calibration and + * one sample reading + * @nconv_accu_complete: pointer to the struct completion, to indicate + * the completion of sample to accumulate + * @cc_int_calib_complete: pointer to the struct completion, to indicate + * the completion of internal calibration + * @lock: Mutex for locking the CC + */ +struct ab8500_fg_test { + bool enable; + u8 cc_int_offset; + u8 cc_soft_offset; + u16 cc_sample_conv; + int cc_sample_conv_calib_uA; + struct completion cceoc_complete; + struct completion nconv_accu_complete; + struct completion cc_int_calib_complete; + struct mutex lock; +}; + +/** + * 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; +}; + +extern char *discharge_state[]; +extern char *charge_state[]; + +int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable); +void ab8500_fg_charge_state_to(struct ab8500_fg *di, + enum ab8500_fg_charge_state new_state); +void ab8500_fg_discharge_state_to(struct ab8500_fg *di, + enum ab8500_fg_charge_state new_state); +/* test initialization */ +#ifdef CONFIG_AB8500_BM_DEEP_DEBUG +void ab8500_fg_test_init(struct ab8500_fg *di); +#else +void ab8500_fg_test_init(struct ab8500_fg *di) {return; } +#endif diff --git a/drivers/power/ab8500_fg_deepdebug.c b/drivers/power/ab8500_fg_deepdebug.c new file mode 100644 index 0000000..8845de6 --- /dev/null +++ b/drivers/power/ab8500_fg_deepdebug.c @@ -0,0 +1,823 @@ +/* + * Copyright (C) ST-Ericsson AB 2012 + * + * Battery Management Deep debug support + * + * Note: Deep debug features are needed to perform the + * HW validation of the platform + * + * License Terms: GNU General Public License v2 + * Author: Cedric Madianga <cedric.madia...@stericsson.com> + */ + +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/power_supply.h> +#include <linux/mfd/ab8500.h> +#include <linux/mfd/abx500.h> +#include <linux/mfd/abx500/ab8500-bm.h> +#include <linux/delay.h> +#include <linux/time.h> + +#include "ab8500_fg.h" + +/* Exposure to the debugfs interface for test purpose only */ + +/** + * ab8500_fg_test_algorithm_en() - enable or disable gas gauge test mode + * @di: pointer to the ab8500_fg structure + * @enable: enable/disable gas gaude test mode + * + * Return 0 or error code + * Only used for test purpose + */ +int ab8500_fg_test_algorithm_en(struct ab8500_fg *di, bool enable) +{ + int ret = 0; + + if (enable) { + /* Set coulomb counter in test mode. */ + dev_dbg(di->dev, "Try to put gas gauge in test mode\n"); + cancel_delayed_work_sync(&di->fg_periodic_work); + if (di->flags.fg_enabled) { + ret = ab8500_fg_coulomb_counter(di, false); + if (ret) + return ret; + } + di->test.enable = true; + dev_dbg(di->dev, "Gas gauge in test mode\n"); + } else { + /* Set coulomb counter in normal mode. */ + dev_dbg(di->dev, "Try to put gas gauge in normal mode\n"); + if (di->flags.fg_enabled) { + ret = ab8500_fg_coulomb_counter(di, false); + if (ret) + return ret; + } + + di->init_capacity = true; + ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_INIT); + ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_INIT); + + di->flags.batt_unknown = true; + di->flags.batt_id_received = false; + + di->test.enable = false; + ab8500_fg_coulomb_counter(di, true); + + di->flags.calibrate = true; + di->calib_state = AB8500_FG_CALIB_INIT; + dev_dbg(di->dev, "Gas gauge in normal mode\n"); + } + + return ret; +} + +/** + * ab8500_fg_is_test_is_algorithm_en() - + * Return 1 if fg algorithm is enable 0 else + * @di: pointer to the ab8500_fg structure + * + * Only used for test purpose + */ +bool ab8500_fg_test_is_algorithm_en(struct ab8500_fg *di) +{ + return di->test.enable; +} + +/** + * ab8500_fg_test_en() - enable coulomb counter + * @di: pointer to the ab8500_fg structure + * @enable: enable/disable + * + * Return 0 or error code on failure + * Only used for test purpose + */ + +int ab8500_fg_test_en(struct ab8500_fg *di, bool enable) +{ + return ab8500_fg_coulomb_counter(di, enable); +} + +/** + * ab8500_fg_test_is_en() - Return 1 if fg is enabled 0 else + * @di: pointer to the ab8500_fg structure + * + * Only used for test purpose + */ +bool ab8500_fg_test_is_en(struct ab8500_fg *di) +{ + return di->flags.fg_enabled; +} + +/** + * ab8500_fg_test_set_cc_int_n_avg() - set number of conversion to average for + * internal calibration + * @di: pointer to the ab8500_fg structure + * @val: number of conversion to average + * + * Return 0 or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_set_cc_int_n_avg(struct ab8500_fg *di, u8 val) +{ + int ret; + u8 cc_int_n_avg = 0; + + switch (val) { + case 4: + cc_int_n_avg = CC_INT_CAL_SAMPLES_4; + break; + case 8: + cc_int_n_avg = CC_INT_CAL_SAMPLES_8; + break; + case 16: + cc_int_n_avg = CC_INT_CAL_SAMPLES_16; + break; + default: + dev_err(di->dev, + "incorrect sample values\n" + "correct sample values should be 4, 8 or 16\n"); + } + + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, + CC_INT_CAL_N_AVG_MASK, cc_int_n_avg); + if (ret < 0) + dev_err(di->dev, + "set number of conversion to average failed\n"); + + return ret; +} + +/** + * ab8500_fg_test_get_cc_int_n_avg() - get number of conversion to average for + * internal calibration + * @di: pointer to the ab8500_fg structure + * + * Return number of conversion to average or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_get_cc_int_n_avg(struct ab8500_fg *di) +{ + int ret; + u8 val = 0; + + ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, + AB8500_GASG_CC_CTRL_REG, &val); + if (ret < 0) { + dev_err(di->dev, + "get number of conversion to average failed\n"); + return ret; + } + + switch (val & CC_INT_CAL_N_AVG_MASK) { + case CC_INT_CAL_SAMPLES_4: + ret = 4; + break; + case CC_INT_CAL_SAMPLES_8: + ret = 8; + break; + case CC_INT_CAL_SAMPLES_16: + ret = 16; + break; + case CC_INT_CAL_N_AVG_MASK: + ret = 16; + break; + default: + dev_err(di->dev, + "incorrect val read in AB8500_GASG_CC_CTRL_REG"); + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * ab8500_fg_test_int_calib() - launch internal calibration + * @di: pointer to the ab8500_fg structure + * + * Return result of calibration or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_int_calib(struct ab8500_fg *di) +{ + int ret; + u8 val; + + mutex_lock(&di->test.lock); + dev_dbg(di->dev, "Internal calibration ongoing...\n"); + + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, + CC_INTAVGOFFSET_ENA, CC_INTAVGOFFSET_ENA); + if (ret < 0) { + dev_err(di->dev, + "enabling offset average computation failed\n"); + goto err; + } + + /* wait for completion of calibration */ + if (!wait_for_completion_timeout(&di->test.cc_int_calib_complete, + 5*HZ)) { + dev_err(di->dev, + "timeout: didn't receive CCIntCalib interrupt\n"); + ret = -EINVAL; + goto err; + } + + ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, + AB8500_GASG_CC_CNTR_AVGOFF_REG, &val); + if (ret < 0) + goto err; + + di->test.cc_int_offset = val; + dev_dbg(di->dev, "Internal Calibration done...\n"); + mutex_unlock(&di->test.lock); + + return di->test.cc_int_offset; + +err: + mutex_unlock(&di->test.lock); + dev_err(di->dev, "Internal calibration failure\n"); + return ret; +} + +/** + * ab8500_fg_test_soft_calib() - launch software calibration + * @di: pointer to the ab8500_fg structure + * + * Return result of calibration or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_soft_calib(struct ab8500_fg *di) +{ + int ret; + u8 low_data, high_data; + + mutex_lock(&di->test.lock); + dev_dbg(di->dev, "Software calibration ongoing...\n"); + + /* Set ADconverter in calibration mode */ + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, + CC_CALIB, CC_CALIB); + if (ret < 0) { + dev_err(di->dev, + "set ADconverter in calibration mode failed\n"); + goto err; + } + + /* wait for completion of calibration */ + if (!wait_for_completion_timeout(&di->test.cceoc_complete, 1*HZ)) { + dev_err(di->dev, + "timeout: didn't receive CCEOC interrupt\n"); + ret = -EINVAL; + goto err; + } + + if (!wait_for_completion_timeout(&di->test.cceoc_complete, 1*HZ)) { + dev_err(di->dev, + "timeout: didn't receive CCEOC interrupt\n"); + ret = -EINVAL; + goto err; + } + + /* Don't set ADConverter in calibration mode */ + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, + CC_CALIB, 0x00); + if (ret < 0) { + dev_err(di->dev, "stopping calibration mode failed\n"); + goto err; + } + + /* Transfer sample and accumulator values */ + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, + READ_REQ, READ_REQ); + if (ret < 0) { + dev_err(di->dev, "transfer accumulator data failed\n"); + goto err; + } + + /* Retrieve sample conversion */ + ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, + AB8500_GASG_CC_SMPL_CNVL_REG, &low_data); + if (ret < 0) { + dev_err(di->dev, "read low byte sample conversion failed\n"); + goto err; + } + + ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, + AB8500_GASG_CC_SMPL_CNVH_REG, &high_data); + if (ret < 0) { + dev_err(di->dev, "read high byte sample conversion failed\n"); + goto err; + } + + di->test.cc_soft_offset = (high_data << 8) | low_data; + dev_dbg(di->dev, "Software Calibration done...\n"); + mutex_unlock(&di->test.lock); + + return di->test.cc_soft_offset; + +err: + mutex_unlock(&di->test.lock); + dev_err(di->dev, "Software calibration failure\n"); + return ret; +} + +/** + * ab8500_fg_test_set_cc_soft_offset() - set software offset into register + * @di: pointer to the ab8500_fg structure + * @enable: manual offset to be stored + * + * Return 0 or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_set_cc_soft_offset(struct ab8500_fg *di, u8 val) +{ + int ret; + + ret = abx500_set_register_interruptible(di->dev, AB8500_GAS_GAUGE, + AB8500_GASG_CC_OFFSET_REG, val); + if (ret < 0) + dev_err(di->dev, + "set software offset failed\n"); + else + di->test.cc_soft_offset = val; + return ret; +} + +/** + * ab8500_fg_test_get_cc_soft_offset() - get software offset into register + * @di: pointer to the ab8500_fg structure + * @enable: manual offset to be stored + * + * Return software offset or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_get_cc_soft_offset(struct ab8500_fg *di, u8 *val) +{ + int ret; + + ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, + AB8500_GASG_CC_OFFSET_REG, val); + if (ret < 0) + dev_err(di->dev, + "get software offset failed\n"); + else + di->test.cc_soft_offset = *val; + + return ret; +} + +/** + * ab8500_fg_test_set_rst_accu_sample_counter() - set reset accumulator + * sample counter bit + * @di: pointer to the ab8500_fg structure + * @enable: enable/disable reset acc + * + * Return 0 or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_set_rst_accu_sample_counter(struct ab8500_fg *di, + bool enable) +{ + int ret; + u8 val = 0; + + if (enable) + val = RESET_ACCU; + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, + RESET_ACCU, val); + if (ret < 0) + dev_err(di->dev, + "set accumulator sample counter reset bit failed\n"); + + + return ret; +} + +/** + * ab8500_fg_test_get_rst_accu_sample_counter() - get reset accumulator + * sample counter bit + * @di: pointer to the ab8500_fg structure + * + * Return reset accumulator sample counter bit or error code + * Only used for test purpose + */ +int ab8500_fg_test_get_rst_accu_sample_counter(struct ab8500_fg *di) +{ + u8 val = 0; + int ret; + + ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, + AB8500_GASG_CC_CTRL_REG, &val); + if (ret < 0) { + dev_err(di->dev, + "get accumulator sample counter reset bit failed\n"); + return ret; + } + + if (val & RESET_ACCU) + ret = 1; + else + ret = 0; + return ret; +} + +/** + * ab8500_fg_test_set_cc_mux_offset() - set coumlomb counter offset + * @di: pointer to the ab8500_fg structure + * @enable: enable/disable offset + * + * Return 0 or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_set_cc_mux_offset(struct ab8500_fg *di, bool enable) +{ + int ret; + u8 val = 0; + + if (enable) + val = CC_MUXOFFSET; + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, + CC_MUXOFFSET, val); + if (ret < 0) + dev_err(di->dev, + "set mux offset failed\n"); + + return ret; +} + +/** + * ab8500_fg_test_get_cc_mux_offset() - get coulomb counter mux offset + * @di: pointer to the ab8500_fg structure + * + * Get mux offset or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_get_cc_mux_offset(struct ab8500_fg *di) +{ + u8 val = 0; + int ret; + + ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, + AB8500_GASG_CC_CTRL_REG, &val); + if (ret < 0) { + dev_err(di->dev, + "get mux offset failed\n"); + return ret; + } + + if (val & CC_MUXOFFSET) + ret = 1; + else + ret = 0; + return ret; +} + +/** + * ab8500_fg_test_read_sample() - read one sample + * @di: pointer to the ab8500_fg structure + * + * Return sample or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_read_sample(struct ab8500_fg *di) +{ + int ret; + u8 low_data, high_data; + + mutex_lock(&di->test.lock); + dev_dbg(di->dev, "Sample reading ongoing...\n"); + + /* wait for completion of calibration */ + if (!wait_for_completion_timeout(&di->test.cceoc_complete, 1*HZ)) { + dev_err(di->dev, + "timeout: didn't receive CCEOC interrupt\n"); + ret = -EINVAL; + goto err; + } + + if (!wait_for_completion_timeout(&di->test.cceoc_complete, 1*HZ)) { + dev_err(di->dev, + "timeout: didn't receive CCEOC interrupt\n"); + ret = -EINVAL; + goto err; + } + + /* Transfer sample and accumulator values */ + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, + READ_REQ, READ_REQ); + if (ret < 0) { + dev_err(di->dev, "transfer accumulator data failed\n"); + goto err; + } + + /* Retrieve sample conversion */ + ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, + AB8500_GASG_CC_SMPL_CNVL_REG, &low_data); + if (ret < 0) { + dev_err(di->dev, "read low byte sample conversion failed\n"); + goto err; + } + + ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, + AB8500_GASG_CC_SMPL_CNVH_REG, &high_data); + if (ret < 0) { + dev_err(di->dev, "read high byte sample conversion failed\n"); + goto err; + } + + di->test.cc_sample_conv = (high_data << 8) | low_data; + + dev_dbg(di->dev, "Sample reading done...\n"); + mutex_unlock(&di->test.lock); + + return di->test.cc_sample_conv; + +err: + mutex_unlock(&di->test.lock); + dev_err(di->dev, "Sample reading failure\n"); + return ret; +} + +/** + * ab8500_fg_test_sample_calibrate() - compute sample calibrated data + * @di: pointer to the ab8500_fg structure + * @val: raw sample + * + * Return sample calibrated value + * Only used for test purpose + */ +int ab8500_fg_test_sample_calibrate(struct ab8500_fg *di, int val) +{ + int ret; + + ret = ab8500_fg_test_get_cc_mux_offset(di); + if (ret < 0) + return ret; + + if (ret) + return val - di->test.cc_int_offset; + else + return val - di->test.cc_soft_offset; +} + +/** + * ab8500_fg_test_sample_calibrate_to_uA() - convert sample calibrated data + * to nuAH + * @di: pointer to the ab8500_fg structure + * @val: calibrate sample + * + * Return sample calibrated value + * Only used for test purpose + */ +int ab8500_fg_test_sample_calibrate_to_uA(struct ab8500_fg *di, int val) +{ + di->test.cc_sample_conv_calib_uA = val * QLSB_NANO_AMP_HOURS_X10; + return di->test.cc_sample_conv_calib_uA; +} + +/** + * ab8500_fg_test_get_nconv_accu() - get number of conversion accumulated + * @di: pointer to the ab8500_fg structure + * + * Return umber of conversion accumulated or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_get_nconv_accu(struct ab8500_fg *di, u8 *val) +{ + int ret; + + ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, + AB8500_GASG_CC_NCOV_ACCU, val); + if (ret < 0) + dev_err(di->dev, + "get nb samples to be accumulated failed\n"); + + return ret; +} + +/** + * ab8500_fg_test_get_nconv_accu_to_uA() - get number of conversion accumulated + * in uA + * @di: pointer to the ab8500_fg structure + * + * Return umber of conversion accumulated or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_get_nconv_accu_to_uA(struct ab8500_fg *di, int val) +{ + return val * di->test.cc_sample_conv_calib_uA; +} + +/** + * ab8500_fg_test_set_rst_nconv_accu() - allows to reset the 21bits accumulator data + * @di: pointer to the ab8500_fg structure + * @enable: enable/disable to reset the 21bits accumulator data + * + * Return 0 or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_set_rst_nconv_accu(struct ab8500_fg *di, + bool enable) +{ + int ret; + u8 val = 0; + + if (enable) + val = RESET_ACCU; + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB8500_GAS_GAUGE, AB8500_GASG_CC_NCOV_ACCU_CTRL, + RESET_ACCU, val); + if (ret < 0) + dev_err(di->dev, + "set accumulator reset bit failed\n"); + + return ret; +} + +/** + * ab8500_fg_test_get_rst_nconv_accu() - get staus of ResetNconvAccu bit + * @di: pointer to the ab8500_fg structure + * + * Return accumulator reset bit or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_get_rst_nconv_accu(struct ab8500_fg *di) +{ + u8 val = 0; + int ret; + + ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, + AB8500_GASG_CC_NCOV_ACCU_CTRL, &val); + if (ret < 0) { + dev_err(di->dev, + "get accumulator reset bit failedd\n"); + goto out; + } + + if (val & RESET_ACCU) + ret = 1; + else + ret = 0; +out: + return ret; +} + +/** + * ab8500_fg_test_set_nconv_accu_nb_sample() - set number of sample conversion + * to be accumulated in 21bits accumulator + * @di: pointer to the ab8500_fg structure + * @nb_sample: number of samples + * + * Return 0 or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_set_nconv_accu_nb_sample(struct ab8500_fg *di, u8 val) +{ + int ret; + + ret = abx500_set_register_interruptible(di->dev, + AB8500_GAS_GAUGE, AB8500_GASG_CC_NCOV_ACCU, val); + if (ret < 0) + dev_err(di->dev, + "set number of samples to accumulated failed\n"); + + return ret; +} + +/** + * ab8500_fg_test_get_nconv_accu_nb_sample() - get number of sample conversion + * to be accumulated in 21bits accumulator + * @di: pointer to the ab8500_fg structure + * + * Return number of samples to be accumulated or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_get_nconv_accu_nb_sample(struct ab8500_fg *di, u8 *val) +{ + int ret; + + ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, + AB8500_GASG_CC_NCOV_ACCU, val); + if (ret < 0) + dev_err(di->dev, + "get number of samples to accumulated failed\n"); + + return ret; +} + +/** + * ab8500_fg_test_read_nconv_accu_sample() - read of accumulator after N samples + * @di: pointer to the ab8500_fg structure + * + * Return sample or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_read_nconv_accu_sample(struct ab8500_fg *di) +{ + int ret; + int nb_sample; + u8 low_data, med_data, high_data; + + /* Get nb sample to average */ + ret = ab8500_fg_test_get_nconv_accu_nb_sample(di, &nb_sample); + if (ret < 0) + goto out; + + mutex_lock(&di->test.lock); + dev_dbg(di->dev, "N Samples reading ongoing...\n"); + + /* Launch measure */ + ret = abx500_mask_and_set_register_interruptible(di->dev, + AB8500_GAS_GAUGE, AB8500_GASG_CC_NCOV_ACCU_CTRL, + RD_NCONV_ACCU_REQ, RD_NCONV_ACCU_REQ); + if (ret < 0) { + dev_err(di->dev, + "launch measure failed\n"); + goto err; + } + + /* wait for completion of measure */ + if (!wait_for_completion_timeout(&di->test.nconv_accu_complete, + nb_sample*(HZ/4))) { + dev_err(di->dev, + "timeout: didn't receive NCONV_ACCU interrupt\n"); + ret = -EINVAL; + goto err; + } + + /* Retrieve samples */ + ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, + AB8500_GASG_CC_NCOV_ACCU_LOW, &low_data); + if (ret < 0) { + dev_err(di->dev, + "read low data failed\n"); + goto err; + } + + ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, + AB8500_GASG_CC_NCOV_ACCU_MED, &med_data); + if (ret < 0) { + dev_err(di->dev, + "read med data failed\n"); + goto err; + } + + ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE, + AB8500_GASG_CC_NCOV_ACCU_HIGH, &high_data); + if (ret < 0) { + dev_err(di->dev, + "read high data failed\n"); + goto err; + } + + dev_dbg(di->dev, "N Samples reading done...\n"); + mutex_unlock(&di->test.lock); + + return (high_data << 16) | (med_data << 8) | low_data; + +err: + mutex_unlock(&di->test.lock); + dev_err(di->dev, "Sample reading failure\n"); +out: + return ret; + +} + +/** + * ab8500_fg_test_read_nconv_accu_sample_to_uA - convert accu read in uA + * @di: pointer to the ab8500_fg structure + * @val: accu read + * + * Return sample or error code on failure + * Only used for test purpose + */ +int ab8500_fg_test_read_nconv_accu_sample_to_uA(struct ab8500_fg *di, int val) +{ + return val * QLSB_NANO_AMP_HOURS_X10; +} + +void __devinit ab8500_fg_test_init(struct ab8500_fg *di) +{ + /* Initialize objects need for test purpose. */ + di->test.enable = false; + di->test.cc_int_offset = 0; + di->test.cc_soft_offset = 0; + di->test.cc_sample_conv = 0; + di->test.cc_sample_conv_calib_uA = 0; + init_completion(&di->test.cceoc_complete); + init_completion(&di->test.nconv_accu_complete); + init_completion(&di->test.cc_int_calib_complete); + mutex_init(&di->test.lock); +} + diff --git a/include/linux/mfd/abx500/ab8500-bm.h b/include/linux/mfd/abx500/ab8500-bm.h index ec796c7..b800332 100644 --- a/include/linux/mfd/abx500/ab8500-bm.h +++ b/include/linux/mfd/abx500/ab8500-bm.h @@ -485,4 +485,168 @@ static inline int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res) } #endif + +#ifdef CONFIG_AB8500_BM_DEEP_DEBUG +int ab8500_fg_test_algorithm_en(struct ab8500_fg *di, bool enable); +bool ab8500_fg_test_is_algorithm_en(struct ab8500_fg *di); +int ab8500_fg_test_en(struct ab8500_fg *di, bool enable); +bool ab8500_fg_test_is_en(struct ab8500_fg *di); +int ab8500_fg_test_set_cc_int_n_avg(struct ab8500_fg *di, u8 val); +int ab8500_fg_test_get_cc_int_n_avg(struct ab8500_fg *di); +int ab8500_fg_test_int_calib(struct ab8500_fg *di); +int ab8500_fg_test_soft_calib(struct ab8500_fg *di); +int ab8500_fg_test_set_cc_soft_offset(struct ab8500_fg *di, u8 val); +int ab8500_fg_test_get_cc_soft_offset(struct ab8500_fg *di, u8 *val); +int ab8500_fg_test_set_rst_accu_sample_counter(struct ab8500_fg *di, + bool enable); +int ab8500_fg_test_get_rst_accu_sample_counter(struct ab8500_fg *di); +int ab8500_fg_test_set_cc_mux_offset(struct ab8500_fg *di, bool enable); +int ab8500_fg_test_get_cc_mux_offset(struct ab8500_fg *di); +int ab8500_fg_test_read_sample(struct ab8500_fg *di); +int ab8500_fg_test_sample_calibrate(struct ab8500_fg *di, int val); +int ab8500_fg_test_sample_calibrate_to_uA(struct ab8500_fg *di, int val); +int ab8500_fg_test_get_nconv_accu(struct ab8500_fg *di, u8 *val); +int ab8500_fg_test_get_nconv_accu_to_uA(struct ab8500_fg *di, int val); +int ab8500_fg_test_set_rst_nconv_accu(struct ab8500_fg *di, + bool enable); +int ab8500_fg_test_get_rst_nconv_accu(struct ab8500_fg *di); +int ab8500_fg_test_set_nconv_accu_nb_sample(struct ab8500_fg *di, u8 val); +int ab8500_fg_test_get_nconv_accu_nb_sample(struct ab8500_fg *di, u8 *val); +int ab8500_fg_test_read_nconv_accu_sample(struct ab8500_fg *di); +int ab8500_fg_test_read_nconv_accu_sample_to_uA(struct ab8500_fg *di, int val); +#else +static inline int ab8500_fg_test_algorithm_en(struct ab8500_fg *di, bool enable) +{ + return -ENODEV; +} + +static inline bool ab8500_fg_test_is_algorithm_en(struct ab8500_fg *di) +{ + return false; +} + +static inline int ab8500_fg_test_en(struct ab8500_fg *di, bool enable) +{ + return -ENODEV; +} + +static inline bool ab8500_fg_test_is_en(struct ab8500_fg *di) +{ + return false; +} + +static inline int ab8500_fg_test_set_cc_int_n_avg(struct ab8500_fg *di, u8 val) +{ + return 0; +} + +static inline int ab8500_fg_test_get_cc_int_n_avg(struct ab8500_fg *di) +{ + return 0; +} + +static inline int ab8500_fg_test_int_calib(struct ab8500_fg *di) +{ + return -ENODEV; +} + +static inline int ab8500_fg_test_soft_calib(struct ab8500_fg *di) +{ + return -ENODEV; +} + +static inline int ab8500_fg_test_set_cc_soft_offset(struct ab8500_fg *di, + u8 val) +{ + return 0; +} +static inline int ab8500_fg_test_get_cc_soft_offset(struct ab8500_fg *di) +{ + return 0; +} + +static inline int ab8500_fg_test_set_rst_accu_sample_counter(struct ab8500_fg + *di, bool enable) +{ + return 0; +} + +static inline int ab8500_fg_test_get_rst_accu_sample_counter(struct ab8500_fg + *di) +{ + return 0; +} + +static inline int ab8500_fg_test_set_cc_mux_offset(struct ab8500_fg *di, + bool enable) +{ + return 0; +} + +static inline int ab8500_fg_test_get_cc_mux_offset(struct ab8500_fg *di) +{ + return 0; +} + +static inline int ab8500_fg_test_read_sample(struct ab8500_fg *di) +{ + return -ENODEV; +} + +static inline int ab8500_fg_test_sample_calibrate(struct ab8500_fg *di, int val) +{ + return 0; +} + +static inline int ab8500_fg_test_sample_calibrate_to_uA(struct ab8500_fg *di, + int val) +{ + return 0; +} + +static inline int ab8500_fg_test_get_nconv_accu(struct ab8500_fg *di) +{ + return 0; +} + +static inline int ab8500_fg_test_get_nconv_accu_to_uA(struct ab8500_fg *di, + int val) +{ + return 0; +} + +static inline int ab8500_fg_test_set_rst_nconv_accu(struct ab8500_fg *di, + bool enable) +{ + return 0; +} + +static inline int ab8500_fg_test_get_rst_nconv_accu(struct ab8500_fg *di) +{ + return 0; +} + +static inline int ab8500_fg_test_set_nconv_accu_nb_sample(struct ab8500_fg *di, + u8 val) +{ + return 0; +} + +static inline int ab8500_fg_test_get_nconv_accu_nb_sample(struct ab8500_fg *di) +{ + return 0; +} + +static inline int ab8500_fg_test_read_nconv_accu_sample(struct ab8500_fg *di) +{ + return -ENODEV; +} + +static inline int ab8500_fg_test_read_nconv_accu_sample_to_uA(struct ab8500_fg + *di, int val) +{ + return 0; +} + +#endif #endif /* _AB8500_BM_H */ -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/