^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) ST-Ericsson AB 2012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Main and Back-up battery management driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Note: Backup battery management is required in case of Li-Ion battery and not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * for capacitive battery. HREF boards have capacitive battery and hence backup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * battery management is not used and the supported code is available in this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Author:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Johan Palsson <johan.palsson@stericsson.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Karl Komierowski <karl.komierowski@stericsson.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Arun R Murthy <arun.murthy@stericsson.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/power_supply.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/kobject.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/time64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/mfd/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/mfd/abx500.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/mfd/abx500/ab8500.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/mfd/abx500/ab8500-bm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/iio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define MILLI_TO_MICRO 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define FG_LSB_IN_MA 1627
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define QLSB_NANO_AMP_HOURS_X10 1071
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define INS_CURR_TIMEOUT (3 * HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define SEC_TO_SAMPLE(S) (S * 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define NBR_AVG_SAMPLES 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define LOW_BAT_CHECK_INTERVAL (HZ / 16) /* 62.5 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define VALID_CAPACITY_SEC (45 * 60) /* 45 minutes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define BATT_OK_MIN 2360 /* mV */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define BATT_OK_INCREMENT 50 /* mV */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define BATT_OK_MAX_NR_INCREMENTS 0xE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* FG constants */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define BATT_OVV 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define interpolate(x, x1, y1, x2, y2) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) ((y1) + ((((y2) - (y1)) * ((x) - (x1))) / ((x2) - (x1))));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * struct ab8500_fg_interrupts - ab8500 fg interupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * @name: name of the interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * @isr function pointer to the isr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct ab8500_fg_interrupts {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) irqreturn_t (*isr)(int irq, void *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) enum ab8500_fg_discharge_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) AB8500_FG_DISCHARGE_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) AB8500_FG_DISCHARGE_INITMEASURING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) AB8500_FG_DISCHARGE_INIT_RECOVERY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) AB8500_FG_DISCHARGE_RECOVERY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) AB8500_FG_DISCHARGE_READOUT_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) AB8500_FG_DISCHARGE_READOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) AB8500_FG_DISCHARGE_WAKEUP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static char *discharge_state[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) "DISCHARGE_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) "DISCHARGE_INITMEASURING",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) "DISCHARGE_INIT_RECOVERY",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) "DISCHARGE_RECOVERY",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) "DISCHARGE_READOUT_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) "DISCHARGE_READOUT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) "DISCHARGE_WAKEUP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) enum ab8500_fg_charge_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) AB8500_FG_CHARGE_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) AB8500_FG_CHARGE_READOUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static char *charge_state[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) "CHARGE_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) "CHARGE_READOUT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) enum ab8500_fg_calibration_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) AB8500_FG_CALIB_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) AB8500_FG_CALIB_WAIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) AB8500_FG_CALIB_END,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct ab8500_fg_avg_cap {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) int avg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int samples[NBR_AVG_SAMPLES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) time64_t time_stamps[NBR_AVG_SAMPLES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) int nbr_samples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) int sum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct ab8500_fg_cap_scaling {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) bool enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int cap_to_scale[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int disable_cap_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int scaled_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct ab8500_fg_battery_capacity {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int max_mah_design;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int max_mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int permille;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) int prev_mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int prev_percent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int prev_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int user_mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct ab8500_fg_cap_scaling cap_scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct ab8500_fg_flags {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) bool fg_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) bool conv_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) bool charging;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) bool fully_charged;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) bool force_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) bool low_bat_delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) bool low_bat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) bool bat_ovv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) bool batt_unknown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) bool calibrate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) bool user_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) bool batt_id_received;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct inst_curr_result_list {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int *result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * struct ab8500_fg - ab8500 FG device information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * @dev: Pointer to the structure device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * @node: a list of AB8500 FGs, hence prepared for reentrance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * @irq holds the CCEOC interrupt number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * @vbat: Battery voltage in mV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * @vbat_nom: Nominal battery voltage in mV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * @inst_curr: Instantenous battery current in mA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * @avg_curr: Average battery current in mA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * @bat_temp battery temperature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * @fg_samples: Number of samples used in the FG accumulation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * @accu_charge: Accumulated charge from the last conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * @recovery_cnt: Counter for recovery mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * @high_curr_cnt: Counter for high current mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * @init_cnt: Counter for init mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * @low_bat_cnt Counter for number of consecutive low battery measures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * @nbr_cceoc_irq_cnt Counter for number of CCEOC irqs received since enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * @recovery_needed: Indicate if recovery is needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * @high_curr_mode: Indicate if we're in high current mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * @init_capacity: Indicate if initial capacity measuring should be done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * @turn_off_fg: True if fg was off before current measurement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * @calib_state State during offset calibration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * @discharge_state: Current discharge state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * @charge_state: Current charge state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * @ab8500_fg_started Completion struct used for the instant current start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * @ab8500_fg_complete Completion struct used for the instant current reading
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * @flags: Structure for information about events triggered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * @bat_cap: Structure for battery capacity specific parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * @avg_cap: Average capacity filter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * @parent: Pointer to the struct ab8500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * @main_bat_v: ADC channel for the main battery voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * @bm: Platform specific battery management information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * @fg_psy: Structure that holds the FG specific battery properties
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * @fg_wq: Work queue for running the FG algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * @fg_periodic_work: Work to run the FG algorithm periodically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * @fg_low_bat_work: Work to check low bat condition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * @fg_reinit_work Work used to reset and reinitialise the FG algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * @fg_work: Work to run the FG algorithm instantly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * @fg_acc_cur_work: Work to read the FG accumulator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * @fg_check_hw_failure_work: Work for checking HW state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * @cc_lock: Mutex for locking the CC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * @fg_kobject: Structure of type kobject
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct ab8500_fg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct list_head node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int vbat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) int vbat_nom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) int inst_curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) int avg_curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) int bat_temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) int fg_samples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) int accu_charge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) int recovery_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) int high_curr_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) int init_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) int low_bat_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) int nbr_cceoc_irq_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) bool recovery_needed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) bool high_curr_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) bool init_capacity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) bool turn_off_fg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) enum ab8500_fg_calibration_state calib_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) enum ab8500_fg_discharge_state discharge_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) enum ab8500_fg_charge_state charge_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct completion ab8500_fg_started;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct completion ab8500_fg_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct ab8500_fg_flags flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct ab8500_fg_battery_capacity bat_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct ab8500_fg_avg_cap avg_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct ab8500 *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct iio_channel *main_bat_v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct abx500_bm_data *bm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct power_supply *fg_psy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct workqueue_struct *fg_wq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct delayed_work fg_periodic_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct delayed_work fg_low_bat_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct delayed_work fg_reinit_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct work_struct fg_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct work_struct fg_acc_cur_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct delayed_work fg_check_hw_failure_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) struct mutex cc_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) struct kobject fg_kobject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static LIST_HEAD(ab8500_fg_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * ab8500_fg_get() - returns a reference to the primary AB8500 fuel gauge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * (i.e. the first fuel gauge in the instance list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct ab8500_fg *ab8500_fg_get(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return list_first_entry_or_null(&ab8500_fg_list, struct ab8500_fg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* Main battery properties */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static enum power_supply_property ab8500_fg_props[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) POWER_SUPPLY_PROP_VOLTAGE_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) POWER_SUPPLY_PROP_CURRENT_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) POWER_SUPPLY_PROP_CURRENT_AVG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) POWER_SUPPLY_PROP_ENERGY_FULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) POWER_SUPPLY_PROP_ENERGY_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) POWER_SUPPLY_PROP_CHARGE_FULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) POWER_SUPPLY_PROP_CHARGE_NOW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) POWER_SUPPLY_PROP_CAPACITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) POWER_SUPPLY_PROP_CAPACITY_LEVEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * This array maps the raw hex value to lowbat voltage used by the AB8500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * Values taken from the UM0836
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static int ab8500_fg_lowbat_voltage_map[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 2300 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 2325 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 2350 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 2375 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 2400 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 2425 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 2450 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 2475 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 2500 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 2525 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 2550 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 2575 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 2600 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 2625 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 2650 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 2675 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 2700 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 2725 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 2750 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 2775 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 2800 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 2825 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 2850 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 2875 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 2900 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 2925 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 2950 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 2975 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 3000 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 3025 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 3050 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 3075 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 3100 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 3125 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 3150 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 3175 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 3200 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 3225 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 3250 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 3275 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 3300 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 3325 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 3350 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 3375 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 3400 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 3425 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 3450 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 3475 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 3500 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 3525 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 3550 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 3575 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 3600 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 3625 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 3650 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 3675 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 3700 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 3725 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 3750 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 3775 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 3800 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 3825 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 3850 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 3850 ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) static u8 ab8500_volt_to_regval(int voltage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (voltage < ab8500_fg_lowbat_voltage_map[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) for (i = 0; i < ARRAY_SIZE(ab8500_fg_lowbat_voltage_map); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (voltage < ab8500_fg_lowbat_voltage_map[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return (u8) i - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /* If not captured above, return index of last element */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return (u8) ARRAY_SIZE(ab8500_fg_lowbat_voltage_map) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * ab8500_fg_is_low_curr() - Low or high current mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * @curr: the current to base or our decision on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * Low current mode if the current consumption is below a certain threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) static int ab8500_fg_is_low_curr(struct ab8500_fg *di, int curr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * We want to know if we're in low current mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (curr > -di->bm->fg_params->high_curr_threshold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * ab8500_fg_add_cap_sample() - Add capacity to average filter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * @sample: the capacity in mAh to add to the filter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * A capacity is added to the filter and a new mean capacity is calculated and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static int ab8500_fg_add_cap_sample(struct ab8500_fg *di, int sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) time64_t now = ktime_get_boottime_seconds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct ab8500_fg_avg_cap *avg = &di->avg_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) avg->sum += sample - avg->samples[avg->pos];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) avg->samples[avg->pos] = sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) avg->time_stamps[avg->pos] = now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) avg->pos++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (avg->pos == NBR_AVG_SAMPLES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) avg->pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (avg->nbr_samples < NBR_AVG_SAMPLES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) avg->nbr_samples++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * Check the time stamp for each sample. If too old,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * replace with latest sample
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) } while (now - VALID_CAPACITY_SEC > avg->time_stamps[avg->pos]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) avg->avg = avg->sum / avg->nbr_samples;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return avg->avg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * ab8500_fg_clear_cap_samples() - Clear average filter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * The capacity filter is is reset to zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) static void ab8500_fg_clear_cap_samples(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct ab8500_fg_avg_cap *avg = &di->avg_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) avg->pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) avg->nbr_samples = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) avg->sum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) avg->avg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) for (i = 0; i < NBR_AVG_SAMPLES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) avg->samples[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) avg->time_stamps[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * ab8500_fg_fill_cap_sample() - Fill average filter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) * @sample: the capacity in mAh to fill the filter with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) * The capacity filter is filled with a capacity in mAh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static void ab8500_fg_fill_cap_sample(struct ab8500_fg *di, int sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) time64_t now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct ab8500_fg_avg_cap *avg = &di->avg_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) now = ktime_get_boottime_seconds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) for (i = 0; i < NBR_AVG_SAMPLES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) avg->samples[i] = sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) avg->time_stamps[i] = now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) avg->pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) avg->nbr_samples = NBR_AVG_SAMPLES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) avg->sum = sample * NBR_AVG_SAMPLES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) avg->avg = sample;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * ab8500_fg_coulomb_counter() - enable coulomb counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * @enable: enable/disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) * Enable/Disable coulomb counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) * On failure returns negative value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) mutex_lock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /* To be able to reprogram the number of samples, we have to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * first stop the CC and then enable it again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) AB8500_RTC_CC_CONF_REG, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) goto cc_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* Program the samples */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) ret = abx500_set_register_interruptible(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) AB8500_GAS_GAUGE, AB8500_GASG_CC_NCOV_ACCU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) di->fg_samples);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) goto cc_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) /* Start the CC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) AB8500_RTC_CC_CONF_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) (CC_DEEP_SLEEP_ENA | CC_PWR_UP_ENA));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) goto cc_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) di->flags.fg_enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* Clear any pending read requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) ret = abx500_mask_and_set_register_interruptible(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) (RESET_ACCU | READ_REQ), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) goto cc_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) ret = abx500_set_register_interruptible(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) AB8500_GAS_GAUGE, AB8500_GASG_CC_NCOV_ACCU_CTRL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) goto cc_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /* Stop the CC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) AB8500_RTC_CC_CONF_REG, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) goto cc_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) di->flags.fg_enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) dev_dbg(di->dev, " CC enabled: %d Samples: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) enable, di->fg_samples);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) mutex_unlock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) cc_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) dev_err(di->dev, "%s Enabling coulomb counter failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) mutex_unlock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * ab8500_fg_inst_curr_start() - start battery instantaneous current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) * Returns 0 or error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) * Note: This is part "one" and has to be called before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * ab8500_fg_inst_curr_finalize()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) int ab8500_fg_inst_curr_start(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) u8 reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) mutex_lock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) di->nbr_cceoc_irq_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) AB8500_RTC_CC_CONF_REG, ®_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (!(reg_val & CC_PWR_UP_ENA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) dev_dbg(di->dev, "%s Enable FG\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) di->turn_off_fg = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) /* Program the samples */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) ret = abx500_set_register_interruptible(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) AB8500_GAS_GAUGE, AB8500_GASG_CC_NCOV_ACCU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) SEC_TO_SAMPLE(10));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /* Start the CC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) AB8500_RTC_CC_CONF_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) (CC_DEEP_SLEEP_ENA | CC_PWR_UP_ENA));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) di->turn_off_fg = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) /* Return and WFI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) reinit_completion(&di->ab8500_fg_started);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) reinit_completion(&di->ab8500_fg_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) enable_irq(di->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) /* Note: cc_lock is still locked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) mutex_unlock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * ab8500_fg_inst_curr_started() - check if fg conversion has started
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * Returns 1 if conversion started, 0 if still waiting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) int ab8500_fg_inst_curr_started(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return completion_done(&di->ab8500_fg_started);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) * ab8500_fg_inst_curr_done() - check if fg conversion is done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) * Returns 1 if conversion done, 0 if still waiting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) int ab8500_fg_inst_curr_done(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return completion_done(&di->ab8500_fg_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * ab8500_fg_inst_curr_finalize() - battery instantaneous current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) * @res: battery instantenous current(on success)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * Returns 0 or an error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) * Note: This is part "two" and has to be called at earliest 250 ms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) * after ab8500_fg_inst_curr_start()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) u8 low, high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (!completion_done(&di->ab8500_fg_complete)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) timeout = wait_for_completion_timeout(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) &di->ab8500_fg_complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) INS_CURR_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) dev_dbg(di->dev, "Finalize time: %d ms\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) jiffies_to_msecs(INS_CURR_TIMEOUT - timeout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (!timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) ret = -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) disable_irq(di->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) di->nbr_cceoc_irq_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) dev_err(di->dev, "completion timed out [%d]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) disable_irq(di->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) di->nbr_cceoc_irq_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) ret = abx500_mask_and_set_register_interruptible(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) READ_REQ, READ_REQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) /* 100uS between read request and read is needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) usleep_range(100, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) /* Read CC Sample conversion value Low and high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) AB8500_GASG_CC_SMPL_CNVL_REG, &low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) AB8500_GASG_CC_SMPL_CNVH_REG, &high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) * negative value for Discharging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) * convert 2's complement into decimal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if (high & 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) val = (low | (high << 8) | 0xFFFFE000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) val = (low | (high << 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) * Convert to unit value in mA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) * Full scale input voltage is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * 63.160mV => LSB = 63.160mV/(4096*res) = 1.542mA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * Given a 250ms conversion cycle time the LSB corresponds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * to 107.1 nAh. Convert to current by dividing by the conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * time in hours (250ms = 1 / (3600 * 4)h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * 107.1nAh assumes 10mOhm, but fg_res is in 0.1mOhm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) val = (val * QLSB_NANO_AMP_HOURS_X10 * 36 * 4) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) (1000 * di->bm->fg_res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (di->turn_off_fg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) dev_dbg(di->dev, "%s Disable FG\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* Clear any pending read requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) ret = abx500_set_register_interruptible(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) /* Stop the CC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) AB8500_RTC_CC_CONF_REG, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) mutex_unlock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) (*res) = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) mutex_unlock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * ab8500_fg_inst_curr_blocking() - battery instantaneous current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * @res: battery instantenous current(on success)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) * Returns 0 else error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) int ab8500_fg_inst_curr_blocking(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) int res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) ret = ab8500_fg_inst_curr_start(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) dev_err(di->dev, "Failed to initialize fg_inst\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) /* Wait for CC to actually start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (!completion_done(&di->ab8500_fg_started)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) timeout = wait_for_completion_timeout(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) &di->ab8500_fg_started,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) INS_CURR_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) dev_dbg(di->dev, "Start time: %d ms\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) jiffies_to_msecs(INS_CURR_TIMEOUT - timeout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (!timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) ret = -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) dev_err(di->dev, "completion timed out [%d]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) ret = ab8500_fg_inst_curr_finalize(di, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) dev_err(di->dev, "Failed to finalize fg_inst\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) dev_dbg(di->dev, "%s instant current: %d", __func__, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) disable_irq(di->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) mutex_unlock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) * ab8500_fg_acc_cur_work() - average battery current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) * @work: pointer to the work_struct structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * Updated the average battery current obtained from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) * coulomb counter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) static void ab8500_fg_acc_cur_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) u8 low, med, high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) struct ab8500_fg *di = container_of(work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) struct ab8500_fg, fg_acc_cur_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) mutex_lock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) ret = abx500_set_register_interruptible(di->dev, AB8500_GAS_GAUGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) AB8500_GASG_CC_NCOV_ACCU_CTRL, RD_NCONV_ACCU_REQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) AB8500_GASG_CC_NCOV_ACCU_LOW, &low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) AB8500_GASG_CC_NCOV_ACCU_MED, &med);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) ret = abx500_get_register_interruptible(di->dev, AB8500_GAS_GAUGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) AB8500_GASG_CC_NCOV_ACCU_HIGH, &high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) /* Check for sign bit in case of negative value, 2's complement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (high & 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) val = (low | (med << 8) | (high << 16) | 0xFFE00000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) val = (low | (med << 8) | (high << 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) * Convert to uAh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * Given a 250ms conversion cycle time the LSB corresponds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * to 112.9 nAh.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) di->accu_charge = (val * QLSB_NANO_AMP_HOURS_X10) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) (100 * di->bm->fg_res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * Convert to unit value in mA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * by dividing by the conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * time in hours (= samples / (3600 * 4)h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * and multiply with 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) di->avg_curr = (val * QLSB_NANO_AMP_HOURS_X10 * 36) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) (1000 * di->bm->fg_res * (di->fg_samples / 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) di->flags.conv_done = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) mutex_unlock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) queue_work(di->fg_wq, &di->fg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) dev_dbg(di->dev, "fg_res: %d, fg_samples: %d, gasg: %d, accu_charge: %d \n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) di->bm->fg_res, di->fg_samples, val, di->accu_charge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) dev_err(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) "Failed to read or write gas gauge registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) mutex_unlock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) queue_work(di->fg_wq, &di->fg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) * ab8500_fg_bat_voltage() - get battery voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) * Returns battery voltage(on success) else error code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) static int ab8500_fg_bat_voltage(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) int vbat, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) static int prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) ret = iio_read_channel_processed(di->main_bat_v, &vbat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) dev_err(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) "%s ADC conversion failed, using previous value\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) prev = vbat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) return vbat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * ab8500_fg_volt_to_capacity() - Voltage based capacity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * @voltage: The voltage to convert to a capacity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) * Returns battery capacity in per mille based on voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) static int ab8500_fg_volt_to_capacity(struct ab8500_fg *di, int voltage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) int i, tbl_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) const struct abx500_v_to_cap *tbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) int cap = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) tbl = di->bm->bat_type[di->bm->batt_id].v_to_cap_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) tbl_size = di->bm->bat_type[di->bm->batt_id].n_v_cap_tbl_elements;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) for (i = 0; i < tbl_size; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (voltage > tbl[i].voltage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if ((i > 0) && (i < tbl_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) cap = interpolate(voltage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) tbl[i].voltage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) tbl[i].capacity * 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) tbl[i-1].voltage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) tbl[i-1].capacity * 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) } else if (i == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) cap = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) cap = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) dev_dbg(di->dev, "%s Vbat: %d, Cap: %d per mille",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) __func__, voltage, cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * ab8500_fg_uncomp_volt_to_capacity() - Uncompensated voltage based capacity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) * Returns battery capacity based on battery voltage that is not compensated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) * for the voltage drop due to the load
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) static int ab8500_fg_uncomp_volt_to_capacity(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) di->vbat = ab8500_fg_bat_voltage(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) return ab8500_fg_volt_to_capacity(di, di->vbat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) * ab8500_fg_battery_resistance() - Returns the battery inner resistance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * Returns battery inner resistance added with the fuel gauge resistor value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) * to get the total resistance in the whole link from gnd to bat+ node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) static int ab8500_fg_battery_resistance(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) int i, tbl_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) const struct batres_vs_temp *tbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) int resist = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) tbl = di->bm->bat_type[di->bm->batt_id].batres_tbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) tbl_size = di->bm->bat_type[di->bm->batt_id].n_batres_tbl_elements;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) for (i = 0; i < tbl_size; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (di->bat_temp / 10 > tbl[i].temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if ((i > 0) && (i < tbl_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) resist = interpolate(di->bat_temp / 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) tbl[i].temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) tbl[i].resist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) tbl[i-1].temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) tbl[i-1].resist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) } else if (i == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) resist = tbl[0].resist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) resist = tbl[tbl_size - 1].resist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) dev_dbg(di->dev, "%s Temp: %d battery internal resistance: %d"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) " fg resistance %d, total: %d (mOhm)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) __func__, di->bat_temp, resist, di->bm->fg_res / 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) (di->bm->fg_res / 10) + resist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) /* fg_res variable is in 0.1mOhm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) resist += di->bm->fg_res / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) return resist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) * ab8500_fg_load_comp_volt_to_capacity() - Load compensated voltage based capacity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) * Returns battery capacity based on battery voltage that is load compensated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) * for the voltage drop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) static int ab8500_fg_load_comp_volt_to_capacity(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) int vbat_comp, res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) int vbat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) ab8500_fg_inst_curr_start(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) vbat += ab8500_fg_bat_voltage(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) usleep_range(5000, 6000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) } while (!ab8500_fg_inst_curr_done(di));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) ab8500_fg_inst_curr_finalize(di, &di->inst_curr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) di->vbat = vbat / i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) res = ab8500_fg_battery_resistance(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) /* Use Ohms law to get the load compensated voltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) vbat_comp = di->vbat - (di->inst_curr * res) / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) dev_dbg(di->dev, "%s Measured Vbat: %dmV,Compensated Vbat %dmV, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) "R: %dmOhm, Current: %dmA Vbat Samples: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) __func__, di->vbat, vbat_comp, res, di->inst_curr, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return ab8500_fg_volt_to_capacity(di, vbat_comp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) * ab8500_fg_convert_mah_to_permille() - Capacity in mAh to permille
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) * @cap_mah: capacity in mAh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) * Converts capacity in mAh to capacity in permille
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) static int ab8500_fg_convert_mah_to_permille(struct ab8500_fg *di, int cap_mah)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) return (cap_mah * 1000) / di->bat_cap.max_mah_design;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) * ab8500_fg_convert_permille_to_mah() - Capacity in permille to mAh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) * @cap_pm: capacity in permille
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) * Converts capacity in permille to capacity in mAh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) static int ab8500_fg_convert_permille_to_mah(struct ab8500_fg *di, int cap_pm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) return cap_pm * di->bat_cap.max_mah_design / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) * ab8500_fg_convert_mah_to_uwh() - Capacity in mAh to uWh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) * @cap_mah: capacity in mAh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * Converts capacity in mAh to capacity in uWh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) static int ab8500_fg_convert_mah_to_uwh(struct ab8500_fg *di, int cap_mah)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) u64 div_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) u32 div_rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) div_res = ((u64) cap_mah) * ((u64) di->vbat_nom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) div_rem = do_div(div_res, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) /* Make sure to round upwards if necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (div_rem >= 1000 / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) div_res++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) return (int) div_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) * ab8500_fg_calc_cap_charging() - Calculate remaining capacity while charging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) * Return the capacity in mAh based on previous calculated capcity and the FG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) * accumulator register value. The filter is filled with this capacity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) static int ab8500_fg_calc_cap_charging(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) dev_dbg(di->dev, "%s cap_mah %d accu_charge %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) di->bat_cap.mah,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) di->accu_charge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) /* Capacity should not be less than 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (di->bat_cap.mah + di->accu_charge > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) di->bat_cap.mah += di->accu_charge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) di->bat_cap.mah = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) * We force capacity to 100% once when the algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) * reports that it's full.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (di->bat_cap.mah >= di->bat_cap.max_mah_design ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) di->flags.force_full) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) di->bat_cap.mah = di->bat_cap.max_mah_design;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) ab8500_fg_fill_cap_sample(di, di->bat_cap.mah);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) di->bat_cap.permille =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) ab8500_fg_convert_mah_to_permille(di, di->bat_cap.mah);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) /* We need to update battery voltage and inst current when charging */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) di->vbat = ab8500_fg_bat_voltage(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) di->inst_curr = ab8500_fg_inst_curr_blocking(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) return di->bat_cap.mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) * ab8500_fg_calc_cap_discharge_voltage() - Capacity in discharge with voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) * @comp: if voltage should be load compensated before capacity calc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) * Return the capacity in mAh based on the battery voltage. The voltage can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) * either be load compensated or not. This value is added to the filter and a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) * new mean value is calculated and returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) static int ab8500_fg_calc_cap_discharge_voltage(struct ab8500_fg *di, bool comp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) int permille, mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) if (comp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) permille = ab8500_fg_load_comp_volt_to_capacity(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) permille = ab8500_fg_uncomp_volt_to_capacity(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) mah = ab8500_fg_convert_permille_to_mah(di, permille);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) di->bat_cap.mah = ab8500_fg_add_cap_sample(di, mah);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) di->bat_cap.permille =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) ab8500_fg_convert_mah_to_permille(di, di->bat_cap.mah);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) return di->bat_cap.mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) * ab8500_fg_calc_cap_discharge_fg() - Capacity in discharge with FG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) * Return the capacity in mAh based on previous calculated capcity and the FG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) * accumulator register value. This value is added to the filter and a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) * new mean value is calculated and returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) static int ab8500_fg_calc_cap_discharge_fg(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) int permille_volt, permille;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) dev_dbg(di->dev, "%s cap_mah %d accu_charge %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) di->bat_cap.mah,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) di->accu_charge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) /* Capacity should not be less than 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) if (di->bat_cap.mah + di->accu_charge > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) di->bat_cap.mah += di->accu_charge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) di->bat_cap.mah = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) if (di->bat_cap.mah >= di->bat_cap.max_mah_design)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) di->bat_cap.mah = di->bat_cap.max_mah_design;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) * Check against voltage based capacity. It can not be lower
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) * than what the uncompensated voltage says
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) permille = ab8500_fg_convert_mah_to_permille(di, di->bat_cap.mah);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) permille_volt = ab8500_fg_uncomp_volt_to_capacity(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (permille < permille_volt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) di->bat_cap.permille = permille_volt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) di->bat_cap.mah = ab8500_fg_convert_permille_to_mah(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) di->bat_cap.permille);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) dev_dbg(di->dev, "%s voltage based: perm %d perm_volt %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) permille,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) permille_volt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) ab8500_fg_fill_cap_sample(di, di->bat_cap.mah);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) ab8500_fg_fill_cap_sample(di, di->bat_cap.mah);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) di->bat_cap.permille =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) ab8500_fg_convert_mah_to_permille(di, di->bat_cap.mah);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) return di->bat_cap.mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) * ab8500_fg_capacity_level() - Get the battery capacity level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) * Get the battery capacity level based on the capacity in percent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) static int ab8500_fg_capacity_level(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) int ret, percent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) percent = DIV_ROUND_CLOSEST(di->bat_cap.permille, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) if (percent <= di->bm->cap_levels->critical ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) di->flags.low_bat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) ret = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) else if (percent <= di->bm->cap_levels->low)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) ret = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) else if (percent <= di->bm->cap_levels->normal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) ret = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) else if (percent <= di->bm->cap_levels->high)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) ret = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) ret = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) * ab8500_fg_calculate_scaled_capacity() - Capacity scaling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) * Calculates the capacity to be shown to upper layers. Scales the capacity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) * to have 100% as a reference from the actual capacity upon removal of charger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) * when charging is in maintenance mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) static int ab8500_fg_calculate_scaled_capacity(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) struct ab8500_fg_cap_scaling *cs = &di->bat_cap.cap_scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) int capacity = di->bat_cap.prev_percent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (!cs->enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) return capacity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) * As long as we are in fully charge mode scale the capacity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) * to show 100%.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) if (di->flags.fully_charged) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) cs->cap_to_scale[0] = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) cs->cap_to_scale[1] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) max(capacity, di->bm->fg_params->maint_thres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) dev_dbg(di->dev, "Scale cap with %d/%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) cs->cap_to_scale[0], cs->cap_to_scale[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) /* Calculates the scaled capacity. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if ((cs->cap_to_scale[0] != cs->cap_to_scale[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) && (cs->cap_to_scale[1] > 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) capacity = min(100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) DIV_ROUND_CLOSEST(di->bat_cap.prev_percent *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) cs->cap_to_scale[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) cs->cap_to_scale[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) if (di->flags.charging) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) if (capacity < cs->disable_cap_level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) cs->disable_cap_level = capacity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) dev_dbg(di->dev, "Cap to stop scale lowered %d%%\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) cs->disable_cap_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) } else if (!di->flags.fully_charged) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) if (di->bat_cap.prev_percent >=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) cs->disable_cap_level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) dev_dbg(di->dev, "Disabling scaled capacity\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) cs->enable = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) capacity = di->bat_cap.prev_percent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) dev_dbg(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) "Waiting in cap to level %d%%\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) cs->disable_cap_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) capacity = cs->disable_cap_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) return capacity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) * ab8500_fg_update_cap_scalers() - Capacity scaling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) * To be called when state change from charge<->discharge to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) * the capacity scalers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) static void ab8500_fg_update_cap_scalers(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) struct ab8500_fg_cap_scaling *cs = &di->bat_cap.cap_scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) if (!cs->enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) if (di->flags.charging) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) di->bat_cap.cap_scale.disable_cap_level =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) di->bat_cap.cap_scale.scaled_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) dev_dbg(di->dev, "Cap to stop scale at charge %d%%\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) di->bat_cap.cap_scale.disable_cap_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) if (cs->scaled_cap != 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) cs->cap_to_scale[0] = cs->scaled_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) cs->cap_to_scale[1] = di->bat_cap.prev_percent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) cs->cap_to_scale[0] = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) cs->cap_to_scale[1] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) max(di->bat_cap.prev_percent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) di->bm->fg_params->maint_thres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) dev_dbg(di->dev, "Cap to scale at discharge %d/%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) cs->cap_to_scale[0], cs->cap_to_scale[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) * ab8500_fg_check_capacity_limits() - Check if capacity has changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) * @init: capacity is allowed to go up in init mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) * Check if capacity or capacity limit has changed and notify the system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) * about it using the power_supply framework
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) static void ab8500_fg_check_capacity_limits(struct ab8500_fg *di, bool init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) bool changed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) int percent = DIV_ROUND_CLOSEST(di->bat_cap.permille, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) di->bat_cap.level = ab8500_fg_capacity_level(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) if (di->bat_cap.level != di->bat_cap.prev_level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) * We do not allow reported capacity level to go up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) * unless we're charging or if we're in init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (!(!di->flags.charging && di->bat_cap.level >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) di->bat_cap.prev_level) || init) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) dev_dbg(di->dev, "level changed from %d to %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) di->bat_cap.prev_level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) di->bat_cap.level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) di->bat_cap.prev_level = di->bat_cap.level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) dev_dbg(di->dev, "level not allowed to go up "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) "since no charger is connected: %d to %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) di->bat_cap.prev_level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) di->bat_cap.level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) * If we have received the LOW_BAT IRQ, set capacity to 0 to initiate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) * shutdown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) if (di->flags.low_bat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) dev_dbg(di->dev, "Battery low, set capacity to 0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) di->bat_cap.prev_percent = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) di->bat_cap.permille = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) percent = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) di->bat_cap.prev_mah = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) di->bat_cap.mah = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) } else if (di->flags.fully_charged) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) * We report 100% if algorithm reported fully charged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) * and show 100% during maintenance charging (scaling).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) if (di->flags.force_full) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) di->bat_cap.prev_percent = percent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) di->bat_cap.prev_mah = di->bat_cap.mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (!di->bat_cap.cap_scale.enable &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) di->bm->capacity_scaling) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) di->bat_cap.cap_scale.enable = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) di->bat_cap.cap_scale.cap_to_scale[0] = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) di->bat_cap.cap_scale.cap_to_scale[1] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) di->bat_cap.prev_percent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) di->bat_cap.cap_scale.disable_cap_level = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) } else if (di->bat_cap.prev_percent != percent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) dev_dbg(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) "battery reported full "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) "but capacity dropping: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) percent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) di->bat_cap.prev_percent = percent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) di->bat_cap.prev_mah = di->bat_cap.mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) } else if (di->bat_cap.prev_percent != percent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) if (percent == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) * We will not report 0% unless we've got
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) * the LOW_BAT IRQ, no matter what the FG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) * algorithm says.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) di->bat_cap.prev_percent = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) percent = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) } else if (!(!di->flags.charging &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) percent > di->bat_cap.prev_percent) || init) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) * We do not allow reported capacity to go up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) * unless we're charging or if we're in init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) dev_dbg(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) "capacity changed from %d to %d (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) di->bat_cap.prev_percent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) percent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) di->bat_cap.permille);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) di->bat_cap.prev_percent = percent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) di->bat_cap.prev_mah = di->bat_cap.mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) dev_dbg(di->dev, "capacity not allowed to go up since "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) "no charger is connected: %d to %d (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) di->bat_cap.prev_percent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) percent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) di->bat_cap.permille);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) if (changed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) if (di->bm->capacity_scaling) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) di->bat_cap.cap_scale.scaled_cap =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) ab8500_fg_calculate_scaled_capacity(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) dev_info(di->dev, "capacity=%d (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) di->bat_cap.prev_percent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) di->bat_cap.cap_scale.scaled_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) power_supply_changed(di->fg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) if (di->flags.fully_charged && di->flags.force_full) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) dev_dbg(di->dev, "Battery full, notifying.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) di->flags.force_full = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) sysfs_notify(&di->fg_kobject, NULL, "charge_full");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) sysfs_notify(&di->fg_kobject, NULL, "charge_now");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) static void ab8500_fg_charge_state_to(struct ab8500_fg *di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) enum ab8500_fg_charge_state new_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) dev_dbg(di->dev, "Charge state from %d [%s] to %d [%s]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) di->charge_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) charge_state[di->charge_state],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) new_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) charge_state[new_state]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) di->charge_state = new_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) static void ab8500_fg_discharge_state_to(struct ab8500_fg *di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) enum ab8500_fg_discharge_state new_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) dev_dbg(di->dev, "Discharge state from %d [%s] to %d [%s]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) di->discharge_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) discharge_state[di->discharge_state],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) new_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) discharge_state[new_state]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) di->discharge_state = new_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) * ab8500_fg_algorithm_charging() - FG algorithm for when charging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) * Battery capacity calculation state machine for when we're charging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) static void ab8500_fg_algorithm_charging(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) * If we change to discharge mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) * we should start with recovery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (di->discharge_state != AB8500_FG_DISCHARGE_INIT_RECOVERY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) ab8500_fg_discharge_state_to(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) AB8500_FG_DISCHARGE_INIT_RECOVERY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) switch (di->charge_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) case AB8500_FG_CHARGE_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) di->fg_samples = SEC_TO_SAMPLE(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) di->bm->fg_params->accu_charging);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) ab8500_fg_coulomb_counter(di, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_READOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) case AB8500_FG_CHARGE_READOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) * Read the FG and calculate the new capacity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) mutex_lock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) if (!di->flags.conv_done && !di->flags.force_full) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) /* Wasn't the CC IRQ that got us here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) mutex_unlock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) dev_dbg(di->dev, "%s CC conv not done\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) di->flags.conv_done = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) mutex_unlock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) ab8500_fg_calc_cap_charging(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) /* Check capacity limits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) ab8500_fg_check_capacity_limits(di, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) static void force_capacity(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) int cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) ab8500_fg_clear_cap_samples(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) cap = di->bat_cap.user_mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) if (cap > di->bat_cap.max_mah_design) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) dev_dbg(di->dev, "Remaining cap %d can't be bigger than total"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) " %d\n", cap, di->bat_cap.max_mah_design);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) cap = di->bat_cap.max_mah_design;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) ab8500_fg_fill_cap_sample(di, di->bat_cap.user_mah);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) di->bat_cap.permille = ab8500_fg_convert_mah_to_permille(di, cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) di->bat_cap.mah = cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) ab8500_fg_check_capacity_limits(di, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) static bool check_sysfs_capacity(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) int cap, lower, upper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) int cap_permille;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) cap = di->bat_cap.user_mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) cap_permille = ab8500_fg_convert_mah_to_permille(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) di->bat_cap.user_mah);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) lower = di->bat_cap.permille - di->bm->fg_params->user_cap_limit * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) upper = di->bat_cap.permille + di->bm->fg_params->user_cap_limit * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) if (lower < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) lower = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) /* 1000 is permille, -> 100 percent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) if (upper > 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) upper = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) dev_dbg(di->dev, "Capacity limits:"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) " (Lower: %d User: %d Upper: %d) [user: %d, was: %d]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) lower, cap_permille, upper, cap, di->bat_cap.mah);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) /* If within limits, use the saved capacity and exit estimation...*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) if (cap_permille > lower && cap_permille < upper) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) dev_dbg(di->dev, "OK! Using users cap %d uAh now\n", cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) force_capacity(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) dev_dbg(di->dev, "Capacity from user out of limits, ignoring");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) * ab8500_fg_algorithm_discharging() - FG algorithm for when discharging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) * Battery capacity calculation state machine for when we're discharging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) int sleep_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) /* If we change to charge mode we should start with init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) if (di->charge_state != AB8500_FG_CHARGE_INIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) switch (di->discharge_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) case AB8500_FG_DISCHARGE_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) /* We use the FG IRQ to work on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) di->init_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) ab8500_fg_coulomb_counter(di, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) ab8500_fg_discharge_state_to(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) AB8500_FG_DISCHARGE_INITMEASURING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) case AB8500_FG_DISCHARGE_INITMEASURING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) * Discard a number of samples during startup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) * After that, use compensated voltage for a few
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) * samples to get an initial capacity.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) * Then go to READOUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) sleep_time = di->bm->fg_params->init_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) /* Discard the first [x] seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) if (di->init_cnt > di->bm->fg_params->init_discard_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) ab8500_fg_calc_cap_discharge_voltage(di, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) ab8500_fg_check_capacity_limits(di, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) di->init_cnt += sleep_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) if (di->init_cnt > di->bm->fg_params->init_total_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) ab8500_fg_discharge_state_to(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) AB8500_FG_DISCHARGE_READOUT_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) case AB8500_FG_DISCHARGE_INIT_RECOVERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) di->recovery_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) di->recovery_needed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) ab8500_fg_discharge_state_to(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) AB8500_FG_DISCHARGE_RECOVERY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) case AB8500_FG_DISCHARGE_RECOVERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) sleep_time = di->bm->fg_params->recovery_sleep_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) * We should check the power consumption
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) * If low, go to READOUT (after x min) or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) * RECOVERY_SLEEP if time left.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) * If high, go to READOUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) di->inst_curr = ab8500_fg_inst_curr_blocking(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) if (ab8500_fg_is_low_curr(di, di->inst_curr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) if (di->recovery_cnt >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) di->bm->fg_params->recovery_total_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) di->fg_samples = SEC_TO_SAMPLE(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) di->bm->fg_params->accu_high_curr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) ab8500_fg_coulomb_counter(di, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) ab8500_fg_discharge_state_to(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) AB8500_FG_DISCHARGE_READOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) di->recovery_needed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) queue_delayed_work(di->fg_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) &di->fg_periodic_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) sleep_time * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) di->recovery_cnt += sleep_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) di->fg_samples = SEC_TO_SAMPLE(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) di->bm->fg_params->accu_high_curr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) ab8500_fg_coulomb_counter(di, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) ab8500_fg_discharge_state_to(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) AB8500_FG_DISCHARGE_READOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) case AB8500_FG_DISCHARGE_READOUT_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) di->fg_samples = SEC_TO_SAMPLE(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) di->bm->fg_params->accu_high_curr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) ab8500_fg_coulomb_counter(di, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) ab8500_fg_discharge_state_to(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) AB8500_FG_DISCHARGE_READOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) case AB8500_FG_DISCHARGE_READOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) di->inst_curr = ab8500_fg_inst_curr_blocking(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) if (ab8500_fg_is_low_curr(di, di->inst_curr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) /* Detect mode change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) if (di->high_curr_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) di->high_curr_mode = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) di->high_curr_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) if (di->recovery_needed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) ab8500_fg_discharge_state_to(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) AB8500_FG_DISCHARGE_INIT_RECOVERY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) queue_delayed_work(di->fg_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) &di->fg_periodic_work, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) ab8500_fg_calc_cap_discharge_voltage(di, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) mutex_lock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) if (!di->flags.conv_done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) /* Wasn't the CC IRQ that got us here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) mutex_unlock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) dev_dbg(di->dev, "%s CC conv not done\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) di->flags.conv_done = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) mutex_unlock(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) /* Detect mode change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) if (!di->high_curr_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) di->high_curr_mode = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) di->high_curr_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) di->high_curr_cnt +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) di->bm->fg_params->accu_high_curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) if (di->high_curr_cnt >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) di->bm->fg_params->high_curr_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) di->recovery_needed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) ab8500_fg_calc_cap_discharge_fg(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) ab8500_fg_check_capacity_limits(di, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) case AB8500_FG_DISCHARGE_WAKEUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) ab8500_fg_calc_cap_discharge_voltage(di, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) di->fg_samples = SEC_TO_SAMPLE(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) di->bm->fg_params->accu_high_curr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) ab8500_fg_coulomb_counter(di, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) ab8500_fg_discharge_state_to(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) AB8500_FG_DISCHARGE_READOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) ab8500_fg_check_capacity_limits(di, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) * ab8500_fg_algorithm_calibrate() - Internal columb counter offset calibration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) static void ab8500_fg_algorithm_calibrate(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) switch (di->calib_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) case AB8500_FG_CALIB_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) dev_dbg(di->dev, "Calibration ongoing...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) ret = abx500_mask_and_set_register_interruptible(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) CC_INT_CAL_N_AVG_MASK, CC_INT_CAL_SAMPLES_8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) ret = abx500_mask_and_set_register_interruptible(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) CC_INTAVGOFFSET_ENA, CC_INTAVGOFFSET_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) di->calib_state = AB8500_FG_CALIB_WAIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) case AB8500_FG_CALIB_END:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) ret = abx500_mask_and_set_register_interruptible(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) CC_MUXOFFSET, CC_MUXOFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) di->flags.calibrate = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) dev_dbg(di->dev, "Calibration done...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) case AB8500_FG_CALIB_WAIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) dev_dbg(di->dev, "Calibration WFI\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) /* Something went wrong, don't calibrate then */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) dev_err(di->dev, "failed to calibrate the CC\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) di->flags.calibrate = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) di->calib_state = AB8500_FG_CALIB_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) * ab8500_fg_algorithm() - Entry point for the FG algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) * Entry point for the battery capacity calculation state machine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) static void ab8500_fg_algorithm(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) if (di->flags.calibrate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) ab8500_fg_algorithm_calibrate(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) if (di->flags.charging)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) ab8500_fg_algorithm_charging(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) ab8500_fg_algorithm_discharging(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) dev_dbg(di->dev, "[FG_DATA] %d %d %d %d %d %d %d %d %d %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) "%d %d %d %d %d %d %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) di->bat_cap.max_mah_design,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) di->bat_cap.max_mah,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) di->bat_cap.mah,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) di->bat_cap.permille,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) di->bat_cap.level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) di->bat_cap.prev_mah,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) di->bat_cap.prev_percent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) di->bat_cap.prev_level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) di->vbat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) di->inst_curr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) di->avg_curr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) di->accu_charge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) di->flags.charging,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) di->charge_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) di->discharge_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) di->high_curr_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) di->recovery_needed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) * ab8500_fg_periodic_work() - Run the FG state machine periodically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) * @work: pointer to the work_struct structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) * Work queue function for periodic work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) static void ab8500_fg_periodic_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) struct ab8500_fg *di = container_of(work, struct ab8500_fg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) fg_periodic_work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) if (di->init_capacity) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) /* Get an initial capacity calculation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) ab8500_fg_calc_cap_discharge_voltage(di, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) ab8500_fg_check_capacity_limits(di, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) di->init_capacity = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) } else if (di->flags.user_cap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) if (check_sysfs_capacity(di)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) ab8500_fg_check_capacity_limits(di, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) if (di->flags.charging)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) ab8500_fg_charge_state_to(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) AB8500_FG_CHARGE_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) ab8500_fg_discharge_state_to(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) AB8500_FG_DISCHARGE_READOUT_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) di->flags.user_cap = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) ab8500_fg_algorithm(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) * ab8500_fg_check_hw_failure_work() - Check OVV_BAT condition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) * @work: pointer to the work_struct structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) * Work queue function for checking the OVV_BAT condition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) static void ab8500_fg_check_hw_failure_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) u8 reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) struct ab8500_fg *di = container_of(work, struct ab8500_fg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) fg_check_hw_failure_work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) * If we have had a battery over-voltage situation,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) * check ovv-bit to see if it should be reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) ret = abx500_get_register_interruptible(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) AB8500_CHARGER, AB8500_CH_STAT_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) ®_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) dev_err(di->dev, "%s ab8500 read failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) if ((reg_value & BATT_OVV) == BATT_OVV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) if (!di->flags.bat_ovv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) dev_dbg(di->dev, "Battery OVV\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) di->flags.bat_ovv = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) power_supply_changed(di->fg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) /* Not yet recovered from ovv, reschedule this test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) queue_delayed_work(di->fg_wq, &di->fg_check_hw_failure_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) dev_dbg(di->dev, "Battery recovered from OVV\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) di->flags.bat_ovv = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) power_supply_changed(di->fg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) * ab8500_fg_low_bat_work() - Check LOW_BAT condition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) * @work: pointer to the work_struct structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) * Work queue function for checking the LOW_BAT condition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) static void ab8500_fg_low_bat_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) int vbat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) struct ab8500_fg *di = container_of(work, struct ab8500_fg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) fg_low_bat_work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) vbat = ab8500_fg_bat_voltage(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) /* Check if LOW_BAT still fulfilled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) if (vbat < di->bm->fg_params->lowbat_threshold) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) /* Is it time to shut down? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) if (di->low_bat_cnt < 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) di->flags.low_bat = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) dev_warn(di->dev, "Shut down pending...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) * Else we need to re-schedule this check to be able to detect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) * if the voltage increases again during charging or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) * due to decreasing load.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) di->low_bat_cnt--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) dev_warn(di->dev, "Battery voltage still LOW\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) queue_delayed_work(di->fg_wq, &di->fg_low_bat_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) round_jiffies(LOW_BAT_CHECK_INTERVAL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) di->flags.low_bat_delay = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) di->low_bat_cnt = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) dev_warn(di->dev, "Battery voltage OK again\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) /* This is needed to dispatch LOW_BAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) ab8500_fg_check_capacity_limits(di, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) * ab8500_fg_battok_calc - calculate the bit pattern corresponding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) * to the target voltage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) * @target: target voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) * Returns bit pattern closest to the target voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) * valid return values are 0-14. (0-BATT_OK_MAX_NR_INCREMENTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) static int ab8500_fg_battok_calc(struct ab8500_fg *di, int target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) if (target > BATT_OK_MIN +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) (BATT_OK_INCREMENT * BATT_OK_MAX_NR_INCREMENTS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) return BATT_OK_MAX_NR_INCREMENTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) if (target < BATT_OK_MIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) return (target - BATT_OK_MIN) / BATT_OK_INCREMENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) * ab8500_fg_battok_init_hw_register - init battok levels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) static int ab8500_fg_battok_init_hw_register(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) int selected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) int sel0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) int sel1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) int cbp_sel0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) int cbp_sel1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) int new_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) sel0 = di->bm->fg_params->battok_falling_th_sel0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) sel1 = di->bm->fg_params->battok_raising_th_sel1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) cbp_sel0 = ab8500_fg_battok_calc(di, sel0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) cbp_sel1 = ab8500_fg_battok_calc(di, sel1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) selected = BATT_OK_MIN + cbp_sel0 * BATT_OK_INCREMENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) if (selected != sel0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) dev_warn(di->dev, "Invalid voltage step:%d, using %d %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) sel0, selected, cbp_sel0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) selected = BATT_OK_MIN + cbp_sel1 * BATT_OK_INCREMENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) if (selected != sel1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) dev_warn(di->dev, "Invalid voltage step:%d, using %d %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) sel1, selected, cbp_sel1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) new_val = cbp_sel0 | (cbp_sel1 << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) dev_dbg(di->dev, "using: %x %d %d\n", new_val, cbp_sel0, cbp_sel1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) ret = abx500_set_register_interruptible(di->dev, AB8500_SYS_CTRL2_BLOCK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) AB8500_BATT_OK_REG, new_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) * ab8500_fg_instant_work() - Run the FG state machine instantly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) * @work: pointer to the work_struct structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) * Work queue function for instant work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) static void ab8500_fg_instant_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) struct ab8500_fg *di = container_of(work, struct ab8500_fg, fg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) ab8500_fg_algorithm(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) * ab8500_fg_cc_data_end_handler() - end of data conversion isr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) * @irq: interrupt number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) * @_di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) * Returns IRQ status(IRQ_HANDLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) static irqreturn_t ab8500_fg_cc_data_end_handler(int irq, void *_di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) struct ab8500_fg *di = _di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) if (!di->nbr_cceoc_irq_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) di->nbr_cceoc_irq_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) complete(&di->ab8500_fg_started);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) di->nbr_cceoc_irq_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) complete(&di->ab8500_fg_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) * ab8500_fg_cc_int_calib_handler () - end of calibration isr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) * @irq: interrupt number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) * @_di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) * Returns IRQ status(IRQ_HANDLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) static irqreturn_t ab8500_fg_cc_int_calib_handler(int irq, void *_di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) struct ab8500_fg *di = _di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) di->calib_state = AB8500_FG_CALIB_END;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) * ab8500_fg_cc_convend_handler() - isr to get battery avg current.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) * @irq: interrupt number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) * @_di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) * Returns IRQ status(IRQ_HANDLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) static irqreturn_t ab8500_fg_cc_convend_handler(int irq, void *_di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) struct ab8500_fg *di = _di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) queue_work(di->fg_wq, &di->fg_acc_cur_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) * ab8500_fg_batt_ovv_handler() - Battery OVV occured
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) * @irq: interrupt number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) * @_di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) * Returns IRQ status(IRQ_HANDLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) static irqreturn_t ab8500_fg_batt_ovv_handler(int irq, void *_di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) struct ab8500_fg *di = _di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) dev_dbg(di->dev, "Battery OVV\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) /* Schedule a new HW failure check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) queue_delayed_work(di->fg_wq, &di->fg_check_hw_failure_work, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) * ab8500_fg_lowbatf_handler() - Battery voltage is below LOW threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) * @irq: interrupt number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) * @_di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) * Returns IRQ status(IRQ_HANDLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) static irqreturn_t ab8500_fg_lowbatf_handler(int irq, void *_di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) struct ab8500_fg *di = _di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) /* Initiate handling in ab8500_fg_low_bat_work() if not already initiated. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) if (!di->flags.low_bat_delay) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) dev_warn(di->dev, "Battery voltage is below LOW threshold\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) di->flags.low_bat_delay = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) * Start a timer to check LOW_BAT again after some time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) * This is done to avoid shutdown on single voltage dips
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) queue_delayed_work(di->fg_wq, &di->fg_low_bat_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) round_jiffies(LOW_BAT_CHECK_INTERVAL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) * ab8500_fg_get_property() - get the fg properties
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) * @psy: pointer to the power_supply structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) * @psp: pointer to the power_supply_property structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) * @val: pointer to the power_supply_propval union
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) * This function gets called when an application tries to get the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) * fg properties by reading the sysfs files.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) * voltage_now: battery voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) * current_now: battery instant current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) * current_avg: battery average current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) * charge_full_design: capacity where battery is considered full
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) * charge_now: battery capacity in nAh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) * capacity: capacity in percent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) * capacity_level: capacity level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) * Returns error code in case of failure else 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) static int ab8500_fg_get_property(struct power_supply *psy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) enum power_supply_property psp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) union power_supply_propval *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) struct ab8500_fg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) * If battery is identified as unknown and charging of unknown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) * batteries is disabled, we always report 100% capacity and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) * capacity level UNKNOWN, since we can't calculate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) * remaining capacity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) switch (psp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) case POWER_SUPPLY_PROP_VOLTAGE_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) if (di->flags.bat_ovv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) val->intval = BATT_OVV_VALUE * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) val->intval = di->vbat * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) case POWER_SUPPLY_PROP_CURRENT_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) val->intval = di->inst_curr * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) case POWER_SUPPLY_PROP_CURRENT_AVG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) val->intval = di->avg_curr * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) val->intval = ab8500_fg_convert_mah_to_uwh(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) di->bat_cap.max_mah_design);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) case POWER_SUPPLY_PROP_ENERGY_FULL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) val->intval = ab8500_fg_convert_mah_to_uwh(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) di->bat_cap.max_mah);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) case POWER_SUPPLY_PROP_ENERGY_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) if (di->flags.batt_unknown && !di->bm->chg_unknown_bat &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) di->flags.batt_id_received)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) val->intval = ab8500_fg_convert_mah_to_uwh(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) di->bat_cap.max_mah);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) val->intval = ab8500_fg_convert_mah_to_uwh(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) di->bat_cap.prev_mah);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) val->intval = di->bat_cap.max_mah_design;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) case POWER_SUPPLY_PROP_CHARGE_FULL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) val->intval = di->bat_cap.max_mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) case POWER_SUPPLY_PROP_CHARGE_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) if (di->flags.batt_unknown && !di->bm->chg_unknown_bat &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) di->flags.batt_id_received)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) val->intval = di->bat_cap.max_mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) val->intval = di->bat_cap.prev_mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) case POWER_SUPPLY_PROP_CAPACITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) if (di->flags.batt_unknown && !di->bm->chg_unknown_bat &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) di->flags.batt_id_received)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) val->intval = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) val->intval = di->bat_cap.prev_percent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) if (di->flags.batt_unknown && !di->bm->chg_unknown_bat &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) di->flags.batt_id_received)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) val->intval = di->bat_cap.prev_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) struct power_supply *psy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) struct power_supply *ext = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) const char **supplicants = (const char **)ext->supplied_to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) struct ab8500_fg *di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) union power_supply_propval ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) psy = (struct power_supply *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) * For all psy where the name of your driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) * appears in any supplied_to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) j = match_string(supplicants, ext->num_supplicants, psy->desc->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) if (j < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) /* Go through all properties for the psy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) for (j = 0; j < ext->desc->num_properties; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) enum power_supply_property prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) prop = ext->desc->properties[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) if (power_supply_get_property(ext, prop, &ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) switch (prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) case POWER_SUPPLY_PROP_STATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) switch (ext->desc->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) case POWER_SUPPLY_TYPE_BATTERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) switch (ret.intval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) case POWER_SUPPLY_STATUS_UNKNOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) case POWER_SUPPLY_STATUS_DISCHARGING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) case POWER_SUPPLY_STATUS_NOT_CHARGING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) if (!di->flags.charging)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) di->flags.charging = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) di->flags.fully_charged = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) if (di->bm->capacity_scaling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) ab8500_fg_update_cap_scalers(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) queue_work(di->fg_wq, &di->fg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) case POWER_SUPPLY_STATUS_FULL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) if (di->flags.fully_charged)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) di->flags.fully_charged = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) di->flags.force_full = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) /* Save current capacity as maximum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) di->bat_cap.max_mah = di->bat_cap.mah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) queue_work(di->fg_wq, &di->fg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) case POWER_SUPPLY_STATUS_CHARGING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) if (di->flags.charging &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) !di->flags.fully_charged)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) di->flags.charging = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) di->flags.fully_charged = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) if (di->bm->capacity_scaling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) ab8500_fg_update_cap_scalers(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) queue_work(di->fg_wq, &di->fg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) case POWER_SUPPLY_PROP_TECHNOLOGY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) switch (ext->desc->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) case POWER_SUPPLY_TYPE_BATTERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) if (!di->flags.batt_id_received &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) di->bm->batt_id != BATTERY_UNKNOWN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) const struct abx500_battery_type *b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) b = &(di->bm->bat_type[di->bm->batt_id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) di->flags.batt_id_received = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) di->bat_cap.max_mah_design =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) MILLI_TO_MICRO *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) b->charge_full_design;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) di->bat_cap.max_mah =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) di->bat_cap.max_mah_design;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) di->vbat_nom = b->nominal_voltage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) if (ret.intval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) di->flags.batt_unknown = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) di->flags.batt_unknown = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) case POWER_SUPPLY_PROP_TEMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) switch (ext->desc->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) case POWER_SUPPLY_TYPE_BATTERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) if (di->flags.batt_id_received)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) di->bat_temp = ret.intval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) * ab8500_fg_init_hw_registers() - Set up FG related registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) * @di: pointer to the ab8500_fg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) * Set up battery OVV, low battery voltage registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) static int ab8500_fg_init_hw_registers(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) /* Set VBAT OVV threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) ret = abx500_mask_and_set_register_interruptible(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) AB8500_CHARGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) AB8500_BATT_OVV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) BATT_OVV_TH_4P75,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) BATT_OVV_TH_4P75);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) dev_err(di->dev, "failed to set BATT_OVV\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) /* Enable VBAT OVV detection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) ret = abx500_mask_and_set_register_interruptible(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) AB8500_CHARGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) AB8500_BATT_OVV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) BATT_OVV_ENA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) BATT_OVV_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) dev_err(di->dev, "failed to enable BATT_OVV\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) /* Low Battery Voltage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) ret = abx500_set_register_interruptible(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) AB8500_SYS_CTRL2_BLOCK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) AB8500_LOW_BAT_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) ab8500_volt_to_regval(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) di->bm->fg_params->lowbat_threshold) << 1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) LOW_BAT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) dev_err(di->dev, "%s write failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) /* Battery OK threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) ret = ab8500_fg_battok_init_hw_register(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) dev_err(di->dev, "BattOk init write failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) if (is_ab8505(di->parent)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) AB8505_RTC_PCUT_MAX_TIME_REG, di->bm->fg_params->pcut_max_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_MAX_TIME_REG\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) AB8505_RTC_PCUT_FLAG_TIME_REG, di->bm->fg_params->pcut_flag_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_FLAG_TIME_REG\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) AB8505_RTC_PCUT_RESTART_REG, di->bm->fg_params->pcut_max_restart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_RESTART_REG\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) AB8505_RTC_PCUT_DEBOUNCE_REG, di->bm->fg_params->pcut_debounce_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_DEBOUNCE_REG\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) AB8505_RTC_PCUT_CTL_STATUS_REG, di->bm->fg_params->pcut_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) dev_err(di->dev, "%s write failed AB8505_RTC_PCUT_CTL_STATUS_REG\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) * ab8500_fg_external_power_changed() - callback for power supply changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) * @psy: pointer to the structure power_supply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) * This function is the entry point of the pointer external_power_changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) * of the structure power_supply.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) * This function gets executed when there is a change in any external power
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) * supply that this driver needs to be notified of.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) static void ab8500_fg_external_power_changed(struct power_supply *psy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) struct ab8500_fg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) class_for_each_device(power_supply_class, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) di->fg_psy, ab8500_fg_get_ext_psy_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) * ab8500_fg_reinit_work() - work to reset the FG algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) * @work: pointer to the work_struct structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) * Used to reset the current battery capacity to be able to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) * retrigger a new voltage base capacity calculation. For
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) * test and verification purpose.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) static void ab8500_fg_reinit_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) struct ab8500_fg *di = container_of(work, struct ab8500_fg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) fg_reinit_work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) if (!di->flags.calibrate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) dev_dbg(di->dev, "Resetting FG state machine to init.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) ab8500_fg_clear_cap_samples(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) ab8500_fg_calc_cap_discharge_voltage(di, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) dev_err(di->dev, "Residual offset calibration ongoing "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) "retrying..\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) /* Wait one second until next try*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) queue_delayed_work(di->fg_wq, &di->fg_reinit_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) round_jiffies(1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) /* Exposure to the sysfs interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) struct ab8500_fg_sysfs_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) struct attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) ssize_t (*show)(struct ab8500_fg *, char *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) ssize_t (*store)(struct ab8500_fg *, const char *, size_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) static ssize_t charge_full_show(struct ab8500_fg *di, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) return sprintf(buf, "%d\n", di->bat_cap.max_mah);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) static ssize_t charge_full_store(struct ab8500_fg *di, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) unsigned long charge_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) ret = kstrtoul(buf, 10, &charge_full);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) di->bat_cap.max_mah = (int) charge_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) static ssize_t charge_now_show(struct ab8500_fg *di, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) return sprintf(buf, "%d\n", di->bat_cap.prev_mah);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) static ssize_t charge_now_store(struct ab8500_fg *di, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) unsigned long charge_now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) ret = kstrtoul(buf, 10, &charge_now);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) di->bat_cap.user_mah = (int) charge_now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) di->flags.user_cap = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) static struct ab8500_fg_sysfs_entry charge_full_attr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) __ATTR(charge_full, 0644, charge_full_show, charge_full_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) static struct ab8500_fg_sysfs_entry charge_now_attr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) __ATTR(charge_now, 0644, charge_now_show, charge_now_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) ab8500_fg_show(struct kobject *kobj, struct attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) struct ab8500_fg_sysfs_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) struct ab8500_fg *di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) entry = container_of(attr, struct ab8500_fg_sysfs_entry, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) di = container_of(kobj, struct ab8500_fg, fg_kobject);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) if (!entry->show)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) return entry->show(di, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) ab8500_fg_store(struct kobject *kobj, struct attribute *attr, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) struct ab8500_fg_sysfs_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) struct ab8500_fg *di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) entry = container_of(attr, struct ab8500_fg_sysfs_entry, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) di = container_of(kobj, struct ab8500_fg, fg_kobject);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) if (!entry->store)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) return entry->store(di, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) static const struct sysfs_ops ab8500_fg_sysfs_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) .show = ab8500_fg_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) .store = ab8500_fg_store,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) static struct attribute *ab8500_fg_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) &charge_full_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) &charge_now_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) static struct kobj_type ab8500_fg_ktype = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) .sysfs_ops = &ab8500_fg_sysfs_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) .default_attrs = ab8500_fg_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) * ab8500_fg_sysfs_exit() - de-init of sysfs entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) * @di: pointer to the struct ab8500_chargalg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) * This function removes the entry in sysfs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) static void ab8500_fg_sysfs_exit(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) kobject_del(&di->fg_kobject);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) * ab8500_fg_sysfs_init() - init of sysfs entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) * @di: pointer to the struct ab8500_chargalg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) * This function adds an entry in sysfs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) * Returns error code in case of failure else 0(on success)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) static int ab8500_fg_sysfs_init(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) ret = kobject_init_and_add(&di->fg_kobject,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) &ab8500_fg_ktype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) NULL, "battery");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) kobject_put(&di->fg_kobject);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) dev_err(di->dev, "failed to create sysfs entry\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) static ssize_t ab8505_powercut_flagtime_read(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) u8 reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) struct power_supply *psy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) struct ab8500_fg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) AB8505_RTC_PCUT_FLAG_TIME_REG, ®_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) dev_err(dev, "Failed to read AB8505_RTC_PCUT_FLAG_TIME_REG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7F));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) static ssize_t ab8505_powercut_flagtime_write(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) int reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) struct power_supply *psy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) struct ab8500_fg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) if (kstrtoint(buf, 10, ®_value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) if (reg_value > 0x7F) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) dev_err(dev, "Incorrect parameter, echo 0 (1.98s) - 127 (15.625ms) for flagtime\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) AB8505_RTC_PCUT_FLAG_TIME_REG, (u8)reg_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) dev_err(dev, "Failed to set AB8505_RTC_PCUT_FLAG_TIME_REG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) static ssize_t ab8505_powercut_maxtime_read(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) u8 reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) struct power_supply *psy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) struct ab8500_fg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) AB8505_RTC_PCUT_MAX_TIME_REG, ®_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) dev_err(dev, "Failed to read AB8505_RTC_PCUT_MAX_TIME_REG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7F));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) static ssize_t ab8505_powercut_maxtime_write(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) int reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) struct power_supply *psy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) struct ab8500_fg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) if (kstrtoint(buf, 10, ®_value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) if (reg_value > 0x7F) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) dev_err(dev, "Incorrect parameter, echo 0 (0.0s) - 127 (1.98s) for maxtime\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) AB8505_RTC_PCUT_MAX_TIME_REG, (u8)reg_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) dev_err(dev, "Failed to set AB8505_RTC_PCUT_MAX_TIME_REG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) static ssize_t ab8505_powercut_restart_read(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) u8 reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) struct power_supply *psy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) struct ab8500_fg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) AB8505_RTC_PCUT_RESTART_REG, ®_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) dev_err(dev, "Failed to read AB8505_RTC_PCUT_RESTART_REG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0xF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) static ssize_t ab8505_powercut_restart_write(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) int reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) struct power_supply *psy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) struct ab8500_fg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) if (kstrtoint(buf, 10, ®_value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) if (reg_value > 0xF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) dev_err(dev, "Incorrect parameter, echo 0 - 15 for number of restart\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) AB8505_RTC_PCUT_RESTART_REG, (u8)reg_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) dev_err(dev, "Failed to set AB8505_RTC_PCUT_RESTART_REG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) static ssize_t ab8505_powercut_timer_read(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) u8 reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) struct power_supply *psy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) struct ab8500_fg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) AB8505_RTC_PCUT_TIME_REG, ®_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) dev_err(dev, "Failed to read AB8505_RTC_PCUT_TIME_REG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7F));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) static ssize_t ab8505_powercut_restart_counter_read(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) u8 reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) struct power_supply *psy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) struct ab8500_fg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) AB8505_RTC_PCUT_RESTART_REG, ®_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) dev_err(dev, "Failed to read AB8505_RTC_PCUT_RESTART_REG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0xF0) >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) static ssize_t ab8505_powercut_read(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) u8 reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) struct power_supply *psy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) struct ab8500_fg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) AB8505_RTC_PCUT_CTL_STATUS_REG, ®_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) static ssize_t ab8505_powercut_write(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) int reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) struct power_supply *psy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) struct ab8500_fg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) if (kstrtoint(buf, 10, ®_value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) if (reg_value > 0x1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) dev_err(dev, "Incorrect parameter, echo 0/1 to disable/enable Pcut feature\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) AB8505_RTC_PCUT_CTL_STATUS_REG, (u8)reg_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) dev_err(dev, "Failed to set AB8505_RTC_PCUT_CTL_STATUS_REG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) static ssize_t ab8505_powercut_flag_read(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) u8 reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) struct power_supply *psy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) struct ab8500_fg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) AB8505_RTC_PCUT_CTL_STATUS_REG, ®_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) dev_err(dev, "Failed to read AB8505_RTC_PCUT_CTL_STATUS_REG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) return scnprintf(buf, PAGE_SIZE, "%d\n", ((reg_value & 0x10) >> 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) static ssize_t ab8505_powercut_debounce_read(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) u8 reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) struct power_supply *psy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) struct ab8500_fg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) AB8505_RTC_PCUT_DEBOUNCE_REG, ®_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) dev_err(dev, "Failed to read AB8505_RTC_PCUT_DEBOUNCE_REG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) static ssize_t ab8505_powercut_debounce_write(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) int reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) struct power_supply *psy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) struct ab8500_fg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) if (kstrtoint(buf, 10, ®_value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) if (reg_value > 0x7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) dev_err(dev, "Incorrect parameter, echo 0 to 7 for debounce setting\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) ret = abx500_set_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) AB8505_RTC_PCUT_DEBOUNCE_REG, (u8)reg_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) dev_err(dev, "Failed to set AB8505_RTC_PCUT_DEBOUNCE_REG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) static ssize_t ab8505_powercut_enable_status_read(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) u8 reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) struct power_supply *psy = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) struct ab8500_fg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) ret = abx500_get_register_interruptible(di->dev, AB8500_RTC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) AB8505_RTC_PCUT_CTL_STATUS_REG, ®_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) dev_err(dev, "Failed to read AB8505_RTC_PCUT_CTL_STATUS_REG\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) return scnprintf(buf, PAGE_SIZE, "%d\n", ((reg_value & 0x20) >> 5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) static struct device_attribute ab8505_fg_sysfs_psy_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) __ATTR(powercut_flagtime, (S_IRUGO | S_IWUSR | S_IWGRP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) ab8505_powercut_flagtime_read, ab8505_powercut_flagtime_write),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) __ATTR(powercut_maxtime, (S_IRUGO | S_IWUSR | S_IWGRP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) ab8505_powercut_maxtime_read, ab8505_powercut_maxtime_write),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) __ATTR(powercut_restart_max, (S_IRUGO | S_IWUSR | S_IWGRP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) ab8505_powercut_restart_read, ab8505_powercut_restart_write),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) __ATTR(powercut_timer, S_IRUGO, ab8505_powercut_timer_read, NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) __ATTR(powercut_restart_counter, S_IRUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) ab8505_powercut_restart_counter_read, NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) __ATTR(powercut_enable, (S_IRUGO | S_IWUSR | S_IWGRP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) ab8505_powercut_read, ab8505_powercut_write),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) __ATTR(powercut_flag, S_IRUGO, ab8505_powercut_flag_read, NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) __ATTR(powercut_debounce_time, (S_IRUGO | S_IWUSR | S_IWGRP),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) ab8505_powercut_debounce_read, ab8505_powercut_debounce_write),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) __ATTR(powercut_enable_status, S_IRUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) ab8505_powercut_enable_status_read, NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) static int ab8500_fg_sysfs_psy_create_attrs(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) if (is_ab8505(di->parent)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) for (i = 0; i < ARRAY_SIZE(ab8505_fg_sysfs_psy_attrs); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) if (device_create_file(&di->fg_psy->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) &ab8505_fg_sysfs_psy_attrs[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) goto sysfs_psy_create_attrs_failed_ab8505;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) sysfs_psy_create_attrs_failed_ab8505:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) dev_err(&di->fg_psy->dev, "Failed creating sysfs psy attrs for ab8505.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) while (i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) device_remove_file(&di->fg_psy->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) &ab8505_fg_sysfs_psy_attrs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) static void ab8500_fg_sysfs_psy_remove_attrs(struct ab8500_fg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) if (is_ab8505(di->parent)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) for (i = 0; i < ARRAY_SIZE(ab8505_fg_sysfs_psy_attrs); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) (void)device_remove_file(&di->fg_psy->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) &ab8505_fg_sysfs_psy_attrs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) /* Exposure to the sysfs interface <<END>> */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) #if defined(CONFIG_PM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) static int ab8500_fg_resume(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) struct ab8500_fg *di = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) * Change state if we're not charging. If we're charging we will wake
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) * up on the FG IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) if (!di->flags.charging) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_WAKEUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) queue_work(di->fg_wq, &di->fg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) static int ab8500_fg_suspend(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) pm_message_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) struct ab8500_fg *di = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) flush_delayed_work(&di->fg_periodic_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) flush_work(&di->fg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) flush_work(&di->fg_acc_cur_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) flush_delayed_work(&di->fg_reinit_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) flush_delayed_work(&di->fg_low_bat_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) flush_delayed_work(&di->fg_check_hw_failure_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) * If the FG is enabled we will disable it before going to suspend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) * only if we're not charging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) if (di->flags.fg_enabled && !di->flags.charging)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) ab8500_fg_coulomb_counter(di, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) #define ab8500_fg_suspend NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) #define ab8500_fg_resume NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) static int ab8500_fg_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) struct ab8500_fg *di = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) list_del(&di->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) /* Disable coulomb counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) ret = ab8500_fg_coulomb_counter(di, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) dev_err(di->dev, "failed to disable coulomb counter\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) destroy_workqueue(di->fg_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) ab8500_fg_sysfs_exit(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) flush_scheduled_work();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) ab8500_fg_sysfs_psy_remove_attrs(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) power_supply_unregister(di->fg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) /* ab8500 fg driver interrupts and their respective isr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) static struct ab8500_fg_interrupts ab8500_fg_irq_th[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) {"NCONV_ACCU", ab8500_fg_cc_convend_handler},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) {"BATT_OVV", ab8500_fg_batt_ovv_handler},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) {"LOW_BAT_F", ab8500_fg_lowbatf_handler},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) {"CC_INT_CALIB", ab8500_fg_cc_int_calib_handler},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) static struct ab8500_fg_interrupts ab8500_fg_irq_bh[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) {"CCEOC", ab8500_fg_cc_data_end_handler},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) static char *supply_interface[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) "ab8500_chargalg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) "ab8500_usb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) static const struct power_supply_desc ab8500_fg_desc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) .name = "ab8500_fg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) .type = POWER_SUPPLY_TYPE_BATTERY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) .properties = ab8500_fg_props,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) .num_properties = ARRAY_SIZE(ab8500_fg_props),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) .get_property = ab8500_fg_get_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) .external_power_changed = ab8500_fg_external_power_changed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) static int ab8500_fg_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) struct abx500_bm_data *plat = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) struct power_supply_config psy_cfg = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) struct ab8500_fg *di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) int i, irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) if (!di) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) if (!plat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) dev_err(&pdev->dev, "no battery management data supplied\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) di->bm = plat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) if (np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) dev_err(&pdev->dev, "failed to get battery information\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) mutex_init(&di->cc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) /* get parent data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) di->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) di->parent = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) di->main_bat_v = devm_iio_channel_get(&pdev->dev, "main_bat_v");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) if (IS_ERR(di->main_bat_v)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) if (PTR_ERR(di->main_bat_v) == -ENODEV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) dev_err(&pdev->dev, "failed to get main battery ADC channel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) return PTR_ERR(di->main_bat_v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) psy_cfg.supplied_to = supply_interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) psy_cfg.drv_data = di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) di->bat_cap.max_mah_design = MILLI_TO_MICRO *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) di->bm->bat_type[di->bm->batt_id].charge_full_design;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) di->bat_cap.max_mah = di->bat_cap.max_mah_design;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) di->vbat_nom = di->bm->bat_type[di->bm->batt_id].nominal_voltage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) di->init_capacity = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) /* Create a work queue for running the FG algorithm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) di->fg_wq = alloc_ordered_workqueue("ab8500_fg_wq", WQ_MEM_RECLAIM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) if (di->fg_wq == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) dev_err(di->dev, "failed to create work queue\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) /* Init work for running the fg algorithm instantly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) INIT_WORK(&di->fg_work, ab8500_fg_instant_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) /* Init work for getting the battery accumulated current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) INIT_WORK(&di->fg_acc_cur_work, ab8500_fg_acc_cur_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) /* Init work for reinitialising the fg algorithm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) INIT_DEFERRABLE_WORK(&di->fg_reinit_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) ab8500_fg_reinit_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) /* Work delayed Queue to run the state machine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) INIT_DEFERRABLE_WORK(&di->fg_periodic_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) ab8500_fg_periodic_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) /* Work to check low battery condition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) INIT_DEFERRABLE_WORK(&di->fg_low_bat_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) ab8500_fg_low_bat_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) /* Init work for HW failure check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) INIT_DEFERRABLE_WORK(&di->fg_check_hw_failure_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) ab8500_fg_check_hw_failure_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) /* Reset battery low voltage flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) di->flags.low_bat = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) /* Initialize low battery counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) di->low_bat_cnt = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) /* Initialize OVV, and other registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) ret = ab8500_fg_init_hw_registers(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) dev_err(di->dev, "failed to initialize registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) goto free_inst_curr_wq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) /* Consider battery unknown until we're informed otherwise */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139) di->flags.batt_unknown = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) di->flags.batt_id_received = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) /* Register FG power supply class */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) di->fg_psy = power_supply_register(di->dev, &ab8500_fg_desc, &psy_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) if (IS_ERR(di->fg_psy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) dev_err(di->dev, "failed to register FG psy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) ret = PTR_ERR(di->fg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) goto free_inst_curr_wq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) ab8500_fg_coulomb_counter(di, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) * Initialize completion used to notify completion and start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) * of inst current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) init_completion(&di->ab8500_fg_started);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) init_completion(&di->ab8500_fg_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) /* Register primary interrupt handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161) for (i = 0; i < ARRAY_SIZE(ab8500_fg_irq_th); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) irq = platform_get_irq_byname(pdev, ab8500_fg_irq_th[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) if (irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) ret = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) goto free_irq_th;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) ret = request_irq(irq, ab8500_fg_irq_th[i].isr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) IRQF_SHARED | IRQF_NO_SUSPEND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) ab8500_fg_irq_th[i].name, di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) dev_err(di->dev, "failed to request %s IRQ %d: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) ab8500_fg_irq_th[i].name, irq, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) goto free_irq_th;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) dev_dbg(di->dev, "Requested %s IRQ %d: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) ab8500_fg_irq_th[i].name, irq, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) /* Register threaded interrupt handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) irq = platform_get_irq_byname(pdev, ab8500_fg_irq_bh[0].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) if (irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) ret = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) goto free_irq_th;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) ret = request_threaded_irq(irq, NULL, ab8500_fg_irq_bh[0].isr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) ab8500_fg_irq_bh[0].name, di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) dev_err(di->dev, "failed to request %s IRQ %d: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) ab8500_fg_irq_bh[0].name, irq, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) goto free_irq_th;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) dev_dbg(di->dev, "Requested %s IRQ %d: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) ab8500_fg_irq_bh[0].name, irq, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) di->irq = platform_get_irq_byname(pdev, "CCEOC");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) disable_irq(di->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) di->nbr_cceoc_irq_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) platform_set_drvdata(pdev, di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) ret = ab8500_fg_sysfs_init(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) dev_err(di->dev, "failed to create sysfs entry\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) goto free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) ret = ab8500_fg_sysfs_psy_create_attrs(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) dev_err(di->dev, "failed to create FG psy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) ab8500_fg_sysfs_exit(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) goto free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) /* Calibrate the fg first time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) di->flags.calibrate = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) di->calib_state = AB8500_FG_CALIB_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) /* Use room temp as default value until we get an update from driver. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) di->bat_temp = 210;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) /* Run the FG algorithm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) list_add_tail(&di->node, &ab8500_fg_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) free_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234) /* We also have to free all registered irqs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) irq = platform_get_irq_byname(pdev, ab8500_fg_irq_bh[0].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236) free_irq(irq, di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) free_irq_th:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) while (--i >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239) /* Last assignment of i from primary interrupt handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) irq = platform_get_irq_byname(pdev, ab8500_fg_irq_th[i].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241) free_irq(irq, di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) power_supply_unregister(di->fg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) free_inst_curr_wq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) destroy_workqueue(di->fg_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250) static const struct of_device_id ab8500_fg_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) { .compatible = "stericsson,ab8500-fg", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) MODULE_DEVICE_TABLE(of, ab8500_fg_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) static struct platform_driver ab8500_fg_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) .probe = ab8500_fg_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) .remove = ab8500_fg_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) .suspend = ab8500_fg_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) .resume = ab8500_fg_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) .name = "ab8500-fg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) .of_match_table = ab8500_fg_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267) static int __init ab8500_fg_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269) return platform_driver_register(&ab8500_fg_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) static void __exit ab8500_fg_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) platform_driver_unregister(&ab8500_fg_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) subsys_initcall_sync(ab8500_fg_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) module_exit(ab8500_fg_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281) MODULE_AUTHOR("Johan Palsson, Karl Komierowski");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) MODULE_ALIAS("platform:ab8500-fg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) MODULE_DESCRIPTION("AB8500 Fuel Gauge driver");