Merge "qpnp-fg-gen3: add support to configure ki coefficients during discharge"

This commit is contained in:
Linux Build Service Account 2016-10-13 19:11:32 -07:00 committed by Gerrit - the friendly Code Review server
commit 580442d0a6
3 changed files with 200 additions and 0 deletions

View file

@ -222,6 +222,36 @@ First Level Node - FG Gen3 device
Definition: A boolean property that when defined holds SOC at 100% when
the battery is full.
- qcom,ki-coeff-soc-dischg:
Usage: optional
Value type: <prop-encoded-array>
Definition: Array of monotonic SOC threshold values to change the ki
coefficient for medium discharge current during discharge.
This should be defined in the ascending order and in the
range of 0-100. Array limit is set to 3.
- qcom,ki-coeff-med-dischg:
Usage: optional
Value type: <prop-encoded-array>
Definition: Array of ki coefficient values for medium discharge current
during discharge. These values will be applied when the
monotonic SOC goes below the SOC threshold specified under
qcom,ki-coeff-soc-dischg. Array limit is set to 3. This
property should be specified if qcom,ki-coeff-soc-dischg
is specified to make it fully functional. Value has no
unit. Allowed range is 0 to 62200 in micro units.
- qcom,ki-coeff-hi-dischg:
Usage: optional
Value type: <prop-encoded-array>
Definition: Array of ki coefficient values for high discharge current
during discharge. These values will be applied when the
monotonic SOC goes below the SOC threshold specified under
qcom,ki-coeff-soc-dischg. Array limit is set to 3. This
property should be specified if qcom,ki-coeff-soc-dischg
is specified to make it fully functional. Value has no
unit. Allowed range is 0 to 62200 in micro units.
==========================================================
Second Level Nodes - Peripherals managed by FG Gen3 driver
==========================================================
@ -252,6 +282,9 @@ pmicobalt_fg: qpnp,fg {
qcom,pmic-revid = <&pmicobalt_revid>;
io-channels = <&pmicobalt_rradc 3>;
io-channel-names = "rradc_batt_id";
qcom,ki-coeff-soc-dischg = <30 60 90>;
qcom,ki-coeff-med-dischg = <800 1000 1400>;
qcom,ki-coeff-hi-dischg = <1200 1500 2100>;
status = "okay";
qcom,fg-batt-soc@4000 {

View file

@ -61,6 +61,9 @@
#define BUCKET_COUNT 8
#define BUCKET_SOC_PCT (256 / BUCKET_COUNT)
#define KI_COEFF_MAX 62200
#define KI_COEFF_SOC_LEVELS 3
/* Debug flag definitions */
enum fg_debug_flag {
FG_IRQ = BIT(0), /* Show interrupts */
@ -139,6 +142,8 @@ enum fg_sram_param_id {
FG_SRAM_CHG_TERM_CURR,
FG_SRAM_DELTA_SOC_THR,
FG_SRAM_RECHARGE_SOC_THR,
FG_SRAM_KI_COEFF_MED_DISCHG,
FG_SRAM_KI_COEFF_HI_DISCHG,
FG_SRAM_MAX,
};
@ -198,6 +203,9 @@ struct fg_dt_props {
int cl_min_cap_limit;
int jeita_hyst_temp;
int batt_temp_delta;
int ki_coeff_soc[KI_COEFF_SOC_LEVELS];
int ki_coeff_med_dischg[KI_COEFF_SOC_LEVELS];
int ki_coeff_hi_dischg[KI_COEFF_SOC_LEVELS];
};
/* parameters from battery profile */
@ -275,6 +283,7 @@ struct fg_chip {
bool fg_restarting;
bool charge_full;
bool recharge_soc_adjusted;
bool ki_coeff_dischg_en;
struct completion soc_update;
struct completion soc_ready;
struct delayed_work profile_load_work;

View file

@ -36,6 +36,12 @@
#define SYS_TERM_CURR_OFFSET 0
#define VBATT_FULL_WORD 7
#define VBATT_FULL_OFFSET 0
#define KI_COEFF_MED_DISCHG_WORD 9
#define KI_COEFF_MED_DISCHG_OFFSET 3
#define KI_COEFF_HI_DISCHG_WORD 10
#define KI_COEFF_HI_DISCHG_OFFSET 0
#define KI_COEFF_LOW_DISCHG_WORD 10
#define KI_COEFF_LOW_DISCHG_OFFSET 2
#define DELTA_SOC_THR_WORD 12
#define DELTA_SOC_THR_OFFSET 3
#define RECHARGE_SOC_THR_WORD 14
@ -88,6 +94,12 @@
#define ALG_FLAGS_OFFSET 1
/* v2 SRAM address and offset in ascending order */
#define KI_COEFF_LOW_DISCHG_v2_WORD 9
#define KI_COEFF_LOW_DISCHG_v2_OFFSET 3
#define KI_COEFF_MED_DISCHG_v2_WORD 10
#define KI_COEFF_MED_DISCHG_v2_OFFSET 0
#define KI_COEFF_HI_DISCHG_v2_WORD 10
#define KI_COEFF_HI_DISCHG_v2_OFFSET 1
#define DELTA_SOC_THR_v2_WORD 13
#define DELTA_SOC_THR_v2_OFFSET 0
#define RECHARGE_SOC_THR_v2_WORD 14
@ -173,6 +185,12 @@ static struct fg_sram_param pmicobalt_v1_sram_params[] = {
ESR_TIMER_CHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
PARAM(ESR_TIMER_CHG_INIT, ESR_TIMER_CHG_INIT_WORD,
ESR_TIMER_CHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
PARAM(KI_COEFF_MED_DISCHG, KI_COEFF_MED_DISCHG_WORD,
KI_COEFF_MED_DISCHG_OFFSET, 1, 1000, 244141, 0,
fg_encode_default, NULL),
PARAM(KI_COEFF_HI_DISCHG, KI_COEFF_HI_DISCHG_WORD,
KI_COEFF_HI_DISCHG_OFFSET, 1, 1000, 244141, 0,
fg_encode_default, NULL),
};
static struct fg_sram_param pmicobalt_v2_sram_params[] = {
@ -222,6 +240,12 @@ static struct fg_sram_param pmicobalt_v2_sram_params[] = {
ESR_TIMER_CHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
PARAM(ESR_TIMER_CHG_INIT, ESR_TIMER_CHG_INIT_WORD,
ESR_TIMER_CHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
PARAM(KI_COEFF_MED_DISCHG, KI_COEFF_MED_DISCHG_v2_WORD,
KI_COEFF_MED_DISCHG_v2_OFFSET, 1, 1000, 244141, 0,
fg_encode_default, NULL),
PARAM(KI_COEFF_HI_DISCHG, KI_COEFF_HI_DISCHG_v2_WORD,
KI_COEFF_HI_DISCHG_v2_OFFSET, 1, 1000, 244141, 0,
fg_encode_default, NULL),
};
static struct fg_alg_flag pmicobalt_v1_alg_flags[] = {
@ -1124,6 +1148,60 @@ out:
mutex_unlock(&chip->cl.lock);
}
#define KI_COEFF_MED_DISCHG_DEFAULT 1500
#define KI_COEFF_HI_DISCHG_DEFAULT 2200
static int fg_adjust_ki_coeff_dischg(struct fg_chip *chip)
{
int rc, i, msoc;
int ki_coeff_med = KI_COEFF_MED_DISCHG_DEFAULT;
int ki_coeff_hi = KI_COEFF_HI_DISCHG_DEFAULT;
u8 val;
if (!chip->ki_coeff_dischg_en)
return 0;
rc = fg_get_prop_capacity(chip, &msoc);
if (rc < 0) {
pr_err("Error in getting capacity, rc=%d\n", rc);
return rc;
}
if (chip->status == POWER_SUPPLY_STATUS_DISCHARGING) {
for (i = KI_COEFF_SOC_LEVELS - 1; i >= 0; i--) {
if (msoc < chip->dt.ki_coeff_soc[i]) {
ki_coeff_med = chip->dt.ki_coeff_med_dischg[i];
ki_coeff_hi = chip->dt.ki_coeff_hi_dischg[i];
}
}
}
fg_encode(chip->sp, FG_SRAM_KI_COEFF_MED_DISCHG, ki_coeff_med, &val);
rc = fg_sram_write(chip,
chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_word,
chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_byte, &val,
chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].len,
FG_IMA_DEFAULT);
if (rc < 0) {
pr_err("Error in writing ki_coeff_med, rc=%d\n", rc);
return rc;
}
fg_encode(chip->sp, FG_SRAM_KI_COEFF_HI_DISCHG, ki_coeff_hi, &val);
rc = fg_sram_write(chip,
chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_word,
chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_byte, &val,
chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].len,
FG_IMA_DEFAULT);
if (rc < 0) {
pr_err("Error in writing ki_coeff_hi, rc=%d\n", rc);
return rc;
}
fg_dbg(chip, FG_STATUS, "Wrote ki_coeff_med %d ki_coeff_hi %d\n",
ki_coeff_med, ki_coeff_hi);
return 0;
}
static int fg_charge_full_update(struct fg_chip *chip)
{
union power_supply_propval prop = {0, };
@ -1298,6 +1376,7 @@ static void status_change_work(struct work_struct *work)
schedule_work(&chip->cycle_count_work);
fg_cap_learning_update(chip);
rc = fg_charge_full_update(chip);
if (rc < 0)
pr_err("Error in charge_full_update, rc=%d\n", rc);
@ -1306,6 +1385,9 @@ static void status_change_work(struct work_struct *work)
if (rc < 0)
pr_err("Error in adjusting recharge_soc, rc=%d\n", rc);
rc = fg_adjust_ki_coeff_dischg(chip);
if (rc < 0)
pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
out:
pm_relax(chip->dev);
}
@ -2138,6 +2220,10 @@ static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data)
if (rc < 0)
pr_err("Error in charge_full_update, rc=%d\n", rc);
rc = fg_adjust_ki_coeff_dischg(chip);
if (rc < 0)
pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
return IRQ_HANDLED;
}
@ -2298,6 +2384,73 @@ static int fg_register_interrupts(struct fg_chip *chip)
return 0;
}
static int fg_parse_ki_coefficients(struct fg_chip *chip)
{
struct device_node *node = chip->dev->of_node;
int rc, i;
rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-soc-dischg",
sizeof(u32));
if (rc != KI_COEFF_SOC_LEVELS)
return 0;
rc = of_property_read_u32_array(node, "qcom,ki-coeff-soc-dischg",
chip->dt.ki_coeff_soc, KI_COEFF_SOC_LEVELS);
if (rc < 0) {
pr_err("Error in reading ki-coeff-soc-dischg, rc=%d\n",
rc);
return rc;
}
rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-med-dischg",
sizeof(u32));
if (rc != KI_COEFF_SOC_LEVELS)
return 0;
rc = of_property_read_u32_array(node, "qcom,ki-coeff-med-dischg",
chip->dt.ki_coeff_med_dischg, KI_COEFF_SOC_LEVELS);
if (rc < 0) {
pr_err("Error in reading ki-coeff-med-dischg, rc=%d\n",
rc);
return rc;
}
rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-hi-dischg",
sizeof(u32));
if (rc != KI_COEFF_SOC_LEVELS)
return 0;
rc = of_property_read_u32_array(node, "qcom,ki-coeff-hi-dischg",
chip->dt.ki_coeff_hi_dischg, KI_COEFF_SOC_LEVELS);
if (rc < 0) {
pr_err("Error in reading ki-coeff-hi-dischg, rc=%d\n",
rc);
return rc;
}
for (i = 0; i < KI_COEFF_SOC_LEVELS; i++) {
if (chip->dt.ki_coeff_soc[i] < 0 ||
chip->dt.ki_coeff_soc[i] > FULL_CAPACITY) {
pr_err("Error in ki_coeff_soc_dischg values\n");
return -EINVAL;
}
if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
pr_err("Error in ki_coeff_med_dischg values\n");
return -EINVAL;
}
if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
pr_err("Error in ki_coeff_med_dischg values\n");
return -EINVAL;
}
}
chip->ki_coeff_dischg_en = true;
return 0;
}
#define DEFAULT_CUTOFF_VOLT_MV 3200
#define DEFAULT_EMPTY_VOLT_MV 3100
#define DEFAULT_CHG_TERM_CURR_MA 100
@ -2562,6 +2715,11 @@ static int fg_parse_dt(struct fg_chip *chip)
chip->dt.hold_soc_while_full = of_property_read_bool(node,
"qcom,hold-soc-while-full");
rc = fg_parse_ki_coefficients(chip);
if (rc < 0)
pr_err("Error in parsing Ki coefficients, rc=%d\n", rc);
return 0;
}