drivers: power: supply: import xiaomi changes
Signed-off-by: UtsavBalar1231 <utsavbalar1231@gmail.com>
This commit is contained in:
@@ -610,6 +610,11 @@ config CHARGER_RT9455
|
||||
help
|
||||
Say Y to enable support for Richtek RT9455 battery charger.
|
||||
|
||||
config CHARGER_NU1618
|
||||
tristate "nuvolta nu1618 wireless charger driver"
|
||||
help
|
||||
say y here to enable support for nu1618 charger driver.
|
||||
|
||||
source "drivers/power/supply/qcom/Kconfig"
|
||||
|
||||
endif # POWER_SUPPLY
|
||||
|
||||
@@ -82,4 +82,5 @@ obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o
|
||||
obj-$(CONFIG_CHARGER_TPS65217) += tps65217_charger.o
|
||||
obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
|
||||
obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o
|
||||
obj-$(CONFIG_CHARGER_NU1618) += rx1618.o
|
||||
obj-$(CONFIG_ARCH_QCOM) += qcom/
|
||||
|
||||
@@ -354,7 +354,7 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data)
|
||||
unsigned int *count = data;
|
||||
|
||||
(*count)++;
|
||||
if (psy->desc->type != POWER_SUPPLY_TYPE_BATTERY)
|
||||
if ((psy->desc->type != POWER_SUPPLY_TYPE_BATTERY) && (psy->desc->type != POWER_SUPPLY_TYPE_BMS))
|
||||
if (!psy->desc->get_property(psy, POWER_SUPPLY_PROP_ONLINE,
|
||||
&ret))
|
||||
return ret.intval;
|
||||
|
||||
@@ -113,6 +113,8 @@ static void power_supply_remove_bat_triggers(struct power_supply *psy)
|
||||
|
||||
static void power_supply_update_gen_leds(struct power_supply *psy)
|
||||
{
|
||||
/* xiaomi project don't support this feature, return skip this feature*/
|
||||
#if 0
|
||||
union power_supply_propval online;
|
||||
|
||||
if (power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online))
|
||||
@@ -124,6 +126,7 @@ static void power_supply_update_gen_leds(struct power_supply *psy)
|
||||
led_trigger_event(psy->online_trig, LED_FULL);
|
||||
else
|
||||
led_trigger_event(psy->online_trig, LED_OFF);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int power_supply_create_gen_triggers(struct power_supply *psy)
|
||||
|
||||
@@ -46,7 +46,7 @@ static const char * const power_supply_type_text[] = {
|
||||
"USB_PD", "USB_PD_DRP", "BrickID",
|
||||
"USB_HVDCP", "USB_HVDCP_3", "USB_HVDCP_3P5", "Wireless", "USB_FLOAT",
|
||||
"BMS", "Parallel", "Main", "Wipower", "USB_C_UFP", "USB_C_DFP",
|
||||
"Charge_Pump",
|
||||
"Charge_Pump","ZIMI_CAR_POWER"
|
||||
};
|
||||
|
||||
static const char * const power_supply_status_text[] = {
|
||||
@@ -164,6 +164,21 @@ static ssize_t power_supply_show_property(struct device *dev,
|
||||
|
||||
if (off == POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT)
|
||||
return sprintf(buf, "%lld\n", value.int64val);
|
||||
else if (off == POWER_SUPPLY_PROP_WIRELESS_VERSION)
|
||||
return scnprintf(buf, PAGE_SIZE, "0x%x\n",
|
||||
value.intval);
|
||||
else if (off == POWER_SUPPLY_PROP_WIRELESS_WAKELOCK)
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n",
|
||||
value.intval);
|
||||
else if (off == POWER_SUPPLY_PROP_SIGNAL_STRENGTH)
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n",
|
||||
value.intval);
|
||||
else if (off == POWER_SUPPLY_PROP_WIRELESS_CP_EN)
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n",
|
||||
value.intval);
|
||||
else if (off == POWER_SUPPLY_PROP_TYPE_RECHECK)
|
||||
return scnprintf(buf, PAGE_SIZE, "0x%x\n",
|
||||
value.intval);
|
||||
else
|
||||
return sprintf(buf, "%d\n", value.intval);
|
||||
}
|
||||
@@ -295,6 +310,8 @@ static struct device_attribute power_supply_attrs[] = {
|
||||
POWER_SUPPLY_ATTR(charge_enabled),
|
||||
POWER_SUPPLY_ATTR(set_ship_mode),
|
||||
POWER_SUPPLY_ATTR(real_type),
|
||||
POWER_SUPPLY_ATTR(hvdcp3_type),
|
||||
POWER_SUPPLY_ATTR(quick_charge_type),
|
||||
POWER_SUPPLY_ATTR(charge_now_raw),
|
||||
POWER_SUPPLY_ATTR(charge_now_error),
|
||||
POWER_SUPPLY_ATTR(capacity_raw),
|
||||
@@ -349,6 +366,7 @@ static struct device_attribute power_supply_attrs[] = {
|
||||
POWER_SUPPLY_ATTR(typec_src_rp),
|
||||
POWER_SUPPLY_ATTR(pd_allowed),
|
||||
POWER_SUPPLY_ATTR(pd_active),
|
||||
POWER_SUPPLY_ATTR(pd_authentication),
|
||||
POWER_SUPPLY_ATTR(pd_in_hard_reset),
|
||||
POWER_SUPPLY_ATTR(pd_current_max),
|
||||
POWER_SUPPLY_ATTR(pd_usb_suspend_supported),
|
||||
@@ -372,9 +390,16 @@ static struct device_attribute power_supply_attrs[] = {
|
||||
POWER_SUPPLY_ATTR(pd_voltage_max),
|
||||
POWER_SUPPLY_ATTR(pd_voltage_min),
|
||||
POWER_SUPPLY_ATTR(sdp_current_max),
|
||||
POWER_SUPPLY_ATTR(dc_thermal_levels),
|
||||
POWER_SUPPLY_ATTR(connector_type),
|
||||
POWER_SUPPLY_ATTR(parallel_batfet_mode),
|
||||
POWER_SUPPLY_ATTR(parallel_fcc_max),
|
||||
POWER_SUPPLY_ATTR(wireless_version),
|
||||
POWER_SUPPLY_ATTR(signal_strength),
|
||||
POWER_SUPPLY_ATTR(wireless_cp_en),
|
||||
POWER_SUPPLY_ATTR(wireless_power_good_en),
|
||||
POWER_SUPPLY_ATTR(wireless_wakelock),
|
||||
POWER_SUPPLY_ATTR(tx_adapter),
|
||||
POWER_SUPPLY_ATTR(min_icl),
|
||||
POWER_SUPPLY_ATTR(moisture_detected),
|
||||
POWER_SUPPLY_ATTR(batt_profile_version),
|
||||
@@ -390,6 +415,9 @@ static struct device_attribute power_supply_attrs[] = {
|
||||
POWER_SUPPLY_ATTR(force_recharge),
|
||||
POWER_SUPPLY_ATTR(fcc_stepper_enable),
|
||||
POWER_SUPPLY_ATTR(toggle_stat),
|
||||
POWER_SUPPLY_ATTR(type_recheck),
|
||||
POWER_SUPPLY_ATTR(liquid_detection),
|
||||
POWER_SUPPLY_ATTR(dynamic_fv_enabled),
|
||||
POWER_SUPPLY_ATTR(main_fcc_max),
|
||||
POWER_SUPPLY_ATTR(fg_reset),
|
||||
POWER_SUPPLY_ATTR(qc_opti_disable),
|
||||
|
||||
@@ -48,6 +48,17 @@ config SMB1355_SLAVE_CHARGER
|
||||
The driver reports the charger status via the power supply framework.
|
||||
A charger status change triggers an IRQ via the device STAT pin.
|
||||
|
||||
config IDT_P9220
|
||||
tristate "idtp9220 wireless Charger"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y to include support for idtp9220 wireless Charger.
|
||||
idtp9220 is a wireless battery charger.
|
||||
The driver supports charger enable/disable.
|
||||
The driver reports the charger status via the power supply framework.
|
||||
The driver controls idtp9220 via I2C and
|
||||
supports device-tree interface.
|
||||
|
||||
config QPNP_SMB2
|
||||
tristate "SMB2 Battery Charger"
|
||||
depends on MFD_SPMI_PMIC
|
||||
|
||||
@@ -9,6 +9,7 @@ obj-$(CONFIG_QPNP_QNOVO) += qpnp-qnovo.o battery.o
|
||||
obj-$(CONFIG_QPNP_QNOVO5) += qpnp-qnovo5.o battery.o
|
||||
obj-$(CONFIG_QPNP_SMB5) += step-chg-jeita.o battery.o qpnp-smb5.o smb5-lib.o pmic-voter.o storm-watch.o schgm-flash.o
|
||||
obj-$(CONFIG_SMB1390_CHARGE_PUMP) += smb1390-charger.o pmic-voter.o
|
||||
obj-$(CONFIG_IDT_P9220) += idtp9220.o
|
||||
obj-$(CONFIG_SMB1390_CHARGE_PUMP_PSY) += smb1390-charger-psy.o pmic-voter.o
|
||||
obj-$(CONFIG_SMB1398_CHARGER) += smb1398-charger.o pmic-voter.o
|
||||
obj-$(CONFIG_SMB358_CHARGER) += smb358-charger.o
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2019 XiaoMi, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -1314,6 +1315,27 @@ static int usb_icl_vote_callback(struct votable *votable, void *data,
|
||||
|
||||
vote(chip->pl_disable_votable, ICL_CHANGE_VOTER, false, 0);
|
||||
|
||||
if (!chip->usb_psy)
|
||||
chip->usb_psy = power_supply_get_by_name("usb");
|
||||
if (!chip->usb_psy) {
|
||||
pr_err("Couldn't get usb psy\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rc = power_supply_get_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_SMB_EN_REASON, &pval);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't get cp reason rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (chip->cp_ilim_votable) {
|
||||
if (pval.intval != POWER_SUPPLY_CP_WIRELESS)
|
||||
vote(chip->cp_ilim_votable, ICL_CHANGE_VOTER, true, icl_ua);
|
||||
else
|
||||
vote(chip->cp_ilim_votable, ICL_CHANGE_VOTER, false, 0);
|
||||
}
|
||||
|
||||
/* Configure ILIM based on AICL result only if input mode is USBMID */
|
||||
if (cp_get_parallel_mode(chip, PARALLEL_INPUT_MODE)
|
||||
== POWER_SUPPLY_PL_USBMID_USBMID)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2019 XiaoMi, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -277,7 +278,28 @@ int get_cycle_counts(struct cycle_counter *counter, const char **buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* set_cycle_count -
|
||||
* @counter: Cycle counter object
|
||||
* @value: The cycle count value to be set
|
||||
*
|
||||
* Get average cycle count for all buckets
|
||||
*
|
||||
*/
|
||||
int set_cycle_count(struct cycle_counter *counter, u16 count)
|
||||
{
|
||||
int rc, id;
|
||||
|
||||
for (id = 0; id < BUCKET_COUNT; id++) {
|
||||
rc = counter->store_count(counter->data, &count, id, 2);
|
||||
if (rc < 0)
|
||||
pr_err("failed to clear cycle counter rc=%d\n", rc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cycle_count_init -
|
||||
* @counter: Cycle counter object
|
||||
*
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2019 XiaoMi, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -157,6 +158,7 @@ void cycle_count_update(struct cycle_counter *counter, int batt_soc,
|
||||
int charge_status, bool charge_done, bool input_present);
|
||||
int get_cycle_count(struct cycle_counter *counter, int *count);
|
||||
int get_cycle_counts(struct cycle_counter *counter, const char **buf);
|
||||
int set_cycle_count(struct cycle_counter *counter, u16 count);
|
||||
int cycle_count_init(struct cycle_counter *counter);
|
||||
void cap_learning_abort(struct cap_learning *cl);
|
||||
void cap_learning_update(struct cap_learning *cl, int batt_temp,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2019 XiaoMi, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -92,12 +93,22 @@
|
||||
|
||||
#define FULL_CAPACITY 100
|
||||
#define FULL_SOC_RAW 255
|
||||
#define FULL_SOC_REPORT_THR 250
|
||||
|
||||
#define DEBUG_BATT_SOC 67
|
||||
#define BATT_MISS_SOC 50
|
||||
#define ESR_SOH_SOC 50
|
||||
#define EMPTY_SOC 0
|
||||
|
||||
#define VBAT_RESTART_FG_EMPTY_UV 3700000
|
||||
#define TEMP_THR_RESTART_FG 150
|
||||
#define RESTART_FG_START_WORK_MS 1000
|
||||
#define RESTART_FG_WORK_MS 2000
|
||||
#define EMPTY_REPORT_SOC 1
|
||||
|
||||
#define VBAT_CRITICAL_LOW_THR 2800
|
||||
#define EMPTY_DEBOUNCE_TIME_COUNT_MAX 5
|
||||
|
||||
enum prof_load_status {
|
||||
PROFILE_MISSING,
|
||||
PROFILE_LOADED,
|
||||
@@ -333,6 +344,7 @@ struct fg_batt_props {
|
||||
int float_volt_uv;
|
||||
int vbatt_full_mv;
|
||||
int fastchg_curr_ma;
|
||||
int nom_cap_uah;
|
||||
int *therm_coeffs;
|
||||
int therm_ctr_offset;
|
||||
int therm_pull_up_kohms;
|
||||
@@ -480,6 +492,8 @@ struct fg_dev {
|
||||
int last_recharge_volt_mv;
|
||||
int delta_temp_irq_count;
|
||||
enum esr_filter_status esr_flt_sts;
|
||||
int vbatt_full_volt_uv;
|
||||
int vbat_critical_low_count;
|
||||
bool profile_available;
|
||||
enum prof_load_status profile_load_status;
|
||||
bool battery_missing;
|
||||
@@ -490,8 +504,11 @@ struct fg_dev {
|
||||
bool use_ima_single_mode;
|
||||
bool usb_present;
|
||||
bool twm_state;
|
||||
bool report_full;
|
||||
bool use_dma;
|
||||
bool qnovo_enable;
|
||||
bool empty_restart_fg;
|
||||
bool input_present;
|
||||
enum fg_version version;
|
||||
bool suspended;
|
||||
struct completion soc_update;
|
||||
@@ -503,6 +520,8 @@ struct fg_dev {
|
||||
struct work_struct esr_filter_work;
|
||||
struct alarm esr_filter_alarm;
|
||||
ktime_t last_delta_temp_time;
|
||||
struct delayed_work empty_restart_fg_work;
|
||||
struct delayed_work soc_work;
|
||||
};
|
||||
|
||||
/* Debugfs data structures are below */
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2019 XiaoMi, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -407,7 +408,9 @@ void fg_notify_charger(struct fg_dev *fg)
|
||||
}
|
||||
}
|
||||
|
||||
if (fg->bp.fastchg_curr_ma > 0) {
|
||||
fg_dbg(fg, FG_STATUS, "Notified charger on float voltage and FCC\n");
|
||||
|
||||
/*if (fg->bp.fastchg_curr_ma > 0) {
|
||||
prop.intval = fg->bp.fastchg_curr_ma * 1000;
|
||||
rc = power_supply_set_property(fg->batt_psy,
|
||||
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
|
||||
@@ -417,7 +420,7 @@ void fg_notify_charger(struct fg_dev *fg)
|
||||
rc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
bool batt_psy_initialized(struct fg_dev *fg)
|
||||
@@ -867,6 +870,8 @@ wait:
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
if (fg->empty_restart_fg)
|
||||
fg->empty_restart_fg = false;
|
||||
fg->fg_restarting = false;
|
||||
return rc;
|
||||
}
|
||||
@@ -916,10 +921,17 @@ int fg_get_msoc(struct fg_dev *fg, int *msoc)
|
||||
* of the values 1-254 will be scaled to 1-99. DIV_ROUND_UP will not
|
||||
* be suitable here as it rounds up any value higher than 252 to 100.
|
||||
*/
|
||||
if (*msoc == FULL_SOC_RAW)
|
||||
if ((*msoc >= FULL_SOC_REPORT_THR - 2)
|
||||
&& (*msoc < FULL_SOC_RAW) && fg->report_full) {
|
||||
*msoc = DIV_ROUND_CLOSEST(*msoc * FULL_CAPACITY, FULL_SOC_RAW) + 1;
|
||||
if (*msoc >= FULL_CAPACITY)
|
||||
*msoc = FULL_CAPACITY;
|
||||
} else if (*msoc == FULL_SOC_RAW)
|
||||
*msoc = 100;
|
||||
else if (*msoc == 0)
|
||||
*msoc = 0;
|
||||
else if (*msoc >= FULL_SOC_REPORT_THR - 4 && *msoc <= FULL_SOC_REPORT_THR - 3 && fg->report_full)
|
||||
*msoc = DIV_ROUND_CLOSEST(*msoc * FULL_CAPACITY, FULL_SOC_RAW);
|
||||
else
|
||||
*msoc = DIV_ROUND_CLOSEST((*msoc - 1) * (FULL_CAPACITY - 2),
|
||||
FULL_SOC_RAW - 2) + 1;
|
||||
|
||||
2201
drivers/power/supply/qcom/idtp9220.c
Normal file
2201
drivers/power/supply/qcom/idtp9220.c
Normal file
File diff suppressed because it is too large
Load Diff
1266
drivers/power/supply/qcom/idtp9220.h
Normal file
1266
drivers/power/supply/qcom/idtp9220.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2015-2017, 2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2019 XiaoMi, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -487,8 +488,15 @@ int vote(struct votable *votable, const char *client_str, bool enabled, int val)
|
||||
*/
|
||||
if (!votable->voted_on
|
||||
|| (effective_result != votable->effective_result)) {
|
||||
if (strcmp(votable->name, "FG_WS") != 0) {
|
||||
pr_info("%s: current vote is now %d voted by %s,%d, previous voted %d\n",
|
||||
votable->name, effective_result,
|
||||
get_client_str(votable, effective_id),
|
||||
effective_id, votable->effective_result);
|
||||
}
|
||||
votable->effective_client_id = effective_id;
|
||||
votable->effective_result = effective_result;
|
||||
|
||||
pr_debug("%s: effective vote is now %d voted by %s,%d\n",
|
||||
votable->name, effective_result,
|
||||
get_client_str(votable, effective_id),
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <linux/qpnp/qpnp-pbs.h>
|
||||
#include <linux/qpnp/qpnp-revid.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include "fg-core.h"
|
||||
#include "fg-reg.h"
|
||||
#include "fg-alg.h"
|
||||
@@ -280,6 +281,7 @@ struct fg_gen4_chip {
|
||||
struct votable *parallel_current_en_votable;
|
||||
struct votable *mem_attn_irq_en_votable;
|
||||
struct work_struct esr_calib_work;
|
||||
struct work_struct vbat_sync_work;
|
||||
struct work_struct soc_scale_work;
|
||||
struct alarm esr_fast_cal_timer;
|
||||
struct alarm soc_scale_alarm_timer;
|
||||
@@ -332,7 +334,7 @@ struct bias_config {
|
||||
int bias_kohms;
|
||||
};
|
||||
|
||||
static int fg_gen4_debug_mask;
|
||||
static int fg_gen4_debug_mask = FG_STATUS | FG_IRQ;
|
||||
module_param_named(
|
||||
debug_mask, fg_gen4_debug_mask, int, 0600
|
||||
);
|
||||
@@ -917,6 +919,18 @@ static int fg_gen4_get_prop_capacity(struct fg_dev *fg, int *val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = fg_get_msoc(fg, &msoc);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if (fg->empty_restart_fg && (msoc == 0))
|
||||
msoc = EMPTY_REPORT_SOC;
|
||||
|
||||
if (chip->dt.linearize_soc && fg->delta_soc > 0)
|
||||
*val = fg->maint_soc;
|
||||
else
|
||||
*val = msoc;
|
||||
|
||||
if (chip->soc_scale_mode) {
|
||||
mutex_lock(&chip->soc_scale_lock);
|
||||
*val = chip->soc_scale_msoc;
|
||||
@@ -1770,6 +1784,13 @@ static int fg_gen4_get_batt_profile(struct fg_dev *fg)
|
||||
fg->bp.vbatt_full_mv = -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(profile_node, "qcom,nom-batt-capacity-mah",
|
||||
&fg->bp.nom_cap_uah);
|
||||
if (rc < 0) {
|
||||
pr_err("battery nominal capacity unavailable, rc:%d\n", rc);
|
||||
fg->bp.nom_cap_uah = -EINVAL;
|
||||
}
|
||||
|
||||
if (of_find_property(profile_node, "qcom,therm-coefficients", &len)) {
|
||||
len /= sizeof(u32);
|
||||
if (len == BATT_THERM_NUM_COEFFS) {
|
||||
@@ -2738,6 +2759,8 @@ static int fg_gen4_adjust_recharge_soc(struct fg_gen4_chip *chip)
|
||||
if (is_input_present(fg)) {
|
||||
if (fg->charge_done) {
|
||||
if (!fg->recharge_soc_adjusted) {
|
||||
if (fg->health == POWER_SUPPLY_HEALTH_GOOD)
|
||||
return 0;
|
||||
/* Get raw monotonic SOC for calculation */
|
||||
rc = fg_get_msoc(fg, &msoc);
|
||||
if (rc < 0) {
|
||||
@@ -3407,6 +3430,7 @@ static irqreturn_t fg_vbatt_low_irq_handler(int irq, void *data)
|
||||
int rc, vbatt_mv, msoc_raw;
|
||||
s64 time_us;
|
||||
|
||||
schedule_work(&chip->vbat_sync_work);
|
||||
rc = fg_get_battery_voltage(fg, &vbatt_mv);
|
||||
if (rc < 0)
|
||||
return IRQ_HANDLED;
|
||||
@@ -3435,6 +3459,20 @@ static irqreturn_t fg_vbatt_low_irq_handler(int irq, void *data)
|
||||
|
||||
if (vbatt_mv < chip->dt.cutoff_volt_mv) {
|
||||
if (chip->dt.rapid_soc_dec_en) {
|
||||
/*
|
||||
* Set vbat_low debounce window to avoid shutdown in low temperature and high
|
||||
* current scene, we set the counter to maxium 5, if fg_vbatt_low_irq trigger
|
||||
* exceed 5 times, decrease soc to 0% very rapidly.
|
||||
*/
|
||||
fg->vbat_critical_low_count++;
|
||||
if (fg->vbat_critical_low_count < EMPTY_DEBOUNCE_TIME_COUNT_MAX
|
||||
&& vbatt_mv > VBAT_CRITICAL_LOW_THR) {
|
||||
pr_info("fg->vbat_critical_low_count:%d\n",
|
||||
fg->vbat_critical_low_count);
|
||||
if (batt_psy_initialized(fg))
|
||||
power_supply_changed(fg->batt_psy);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
/*
|
||||
* Set this flag so that slope limiter coefficient
|
||||
* cannot be configured during rapid SOC decrease.
|
||||
@@ -3581,6 +3619,29 @@ static irqreturn_t fg_delta_bsoc_irq_handler(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static bool fg_is_input_suspend(struct fg_dev *fg)
|
||||
{
|
||||
int rc = 0;
|
||||
union power_supply_propval prop = {0, };
|
||||
int input_suspend = 0;
|
||||
|
||||
if (fg->batt_psy) {
|
||||
rc = power_supply_get_property(fg->batt_psy,
|
||||
POWER_SUPPLY_PROP_INPUT_SUSPEND,
|
||||
&prop);
|
||||
if (rc < 0) {
|
||||
pr_err("Error in getting input suspend property, rc=%d\n", rc);
|
||||
return false;
|
||||
}
|
||||
input_suspend = prop.intval;
|
||||
}
|
||||
|
||||
if (input_suspend == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
#define CENTI_FULL_SOC 10000
|
||||
static irqreturn_t fg_delta_msoc_irq_handler(int irq, void *data)
|
||||
{
|
||||
@@ -3589,6 +3650,7 @@ static irqreturn_t fg_delta_msoc_irq_handler(int irq, void *data)
|
||||
int rc, batt_soc, batt_temp, msoc_raw;
|
||||
bool input_present = is_input_present(fg);
|
||||
u32 batt_soc_cp;
|
||||
bool input_suspend = false;
|
||||
|
||||
rc = fg_get_msoc_raw(fg, &msoc_raw);
|
||||
if (!rc)
|
||||
@@ -3597,12 +3659,15 @@ static irqreturn_t fg_delta_msoc_irq_handler(int irq, void *data)
|
||||
|
||||
get_batt_psy_props(fg);
|
||||
|
||||
input_suspend = fg_is_input_suspend(fg);
|
||||
|
||||
rc = fg_get_sram_prop(fg, FG_SRAM_BATT_SOC, &batt_soc);
|
||||
if (rc < 0)
|
||||
pr_err("Failed to read battery soc rc: %d\n", rc);
|
||||
else
|
||||
cycle_count_update(chip->counter, (u32)batt_soc >> 24,
|
||||
fg->charge_status, fg->charge_done, input_present);
|
||||
fg->charge_status, fg->charge_done,
|
||||
(input_present & (!input_suspend)));
|
||||
|
||||
rc = fg_gen4_get_battery_temp(fg, &batt_temp);
|
||||
if (rc < 0) {
|
||||
@@ -4037,6 +4102,8 @@ static void pl_current_en_work(struct work_struct *work)
|
||||
return;
|
||||
|
||||
vote(chip->parallel_current_en_votable, FG_PARALLEL_EN_VOTER, en, 0);
|
||||
|
||||
vote(chip->mem_attn_irq_en_votable, MEM_ATTN_IRQ_VOTER, false, 0);
|
||||
}
|
||||
|
||||
static void pl_enable_work(struct work_struct *work)
|
||||
@@ -4053,14 +4120,21 @@ static void pl_enable_work(struct work_struct *work)
|
||||
vote(fg->awake_votable, ESR_FCC_VOTER, false, 0);
|
||||
}
|
||||
|
||||
static void vbat_sync_work(struct work_struct *work)
|
||||
{
|
||||
pr_err("sys_sync:vbat_sync_work\n");
|
||||
sys_sync();
|
||||
}
|
||||
|
||||
static void status_change_work(struct work_struct *work)
|
||||
{
|
||||
struct fg_dev *fg = container_of(work,
|
||||
struct fg_dev, status_change_work);
|
||||
struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg);
|
||||
int rc, batt_soc, batt_temp;
|
||||
int rc, batt_soc, batt_temp, msoc_raw;
|
||||
bool input_present, qnovo_en;
|
||||
u32 batt_soc_cp;
|
||||
bool input_suspend = false;
|
||||
|
||||
if (fg->battery_missing) {
|
||||
pm_relax(fg->dev);
|
||||
@@ -4085,6 +4159,16 @@ static void status_change_work(struct work_struct *work)
|
||||
|
||||
get_batt_psy_props(fg);
|
||||
|
||||
if (fg->charge_done && !fg->report_full) {
|
||||
fg->report_full = true;
|
||||
} else if (!fg->charge_done && fg->report_full) {
|
||||
rc = fg_get_msoc_raw(fg, &msoc_raw);
|
||||
if (rc < 0)
|
||||
pr_err("Error in getting msoc, rc=%d\n", rc);
|
||||
if (msoc_raw < FULL_SOC_REPORT_THR - 4)
|
||||
fg->report_full = false;
|
||||
}
|
||||
|
||||
rc = fg_get_sram_prop(fg, FG_SRAM_BATT_SOC, &batt_soc);
|
||||
if (rc < 0) {
|
||||
pr_err("Failed to read battery soc rc: %d\n", rc);
|
||||
@@ -4098,9 +4182,12 @@ static void status_change_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
input_present = is_input_present(fg);
|
||||
fg->input_present = input_present;
|
||||
input_suspend = fg_is_input_suspend(fg);
|
||||
qnovo_en = is_qnovo_en(fg);
|
||||
cycle_count_update(chip->counter, (u32)batt_soc >> 24,
|
||||
fg->charge_status, fg->charge_done, input_present);
|
||||
fg->charge_status, fg->charge_done,
|
||||
(input_present & (!input_suspend)));
|
||||
|
||||
batt_soc_cp = div64_u64((u64)(u32)batt_soc * CENTI_FULL_SOC,
|
||||
BATT_SOC_32BIT);
|
||||
@@ -4401,9 +4488,13 @@ static int fg_psy_get_property(struct power_supply *psy,
|
||||
pval->intval = (int)temp;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
|
||||
rc = fg_gen4_get_nominal_capacity(chip, &temp);
|
||||
if (!rc)
|
||||
pval->intval = (int)temp;
|
||||
if (-EINVAL != fg->bp.nom_cap_uah) {
|
||||
pval->intval = fg->bp.nom_cap_uah * 1000;
|
||||
} else {
|
||||
rc = fg_gen4_get_nominal_capacity(chip, &temp);
|
||||
if (!rc)
|
||||
pval->intval = (int)temp;
|
||||
}
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CHARGE_COUNTER:
|
||||
rc = fg_gen4_get_charge_counter(chip, &pval->intval);
|
||||
@@ -4537,6 +4628,10 @@ static int fg_psy_set_property(struct power_supply *psy,
|
||||
if (chip->sp)
|
||||
soh_profile_update(chip->sp, chip->soh);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CYCLE_COUNT:
|
||||
rc = set_cycle_count(chip->counter, pval->intval);
|
||||
pr_info("Cycle count is modified to %d by userspace\n", pval->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CLEAR_SOH:
|
||||
if (chip->first_profile_load && !pval->intval) {
|
||||
fg_dbg(fg, FG_STATUS, "Clearing first profile load bit\n");
|
||||
@@ -4560,6 +4655,11 @@ static int fg_psy_set_property(struct power_supply *psy,
|
||||
chip->batt_age_level = pval->intval;
|
||||
schedule_delayed_work(&fg->profile_load_work, 0);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
|
||||
if (fg->vbatt_full_volt_uv != pval->intval)
|
||||
rc = fg_set_constant_chg_voltage(fg, pval->intval);
|
||||
fg->vbatt_full_volt_uv = pval->intval;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CALIBRATE:
|
||||
rc = fg_gen4_set_calibrate_level(chip, pval->intval);
|
||||
break;
|
||||
@@ -4580,8 +4680,10 @@ static int fg_property_is_writeable(struct power_supply *psy,
|
||||
case POWER_SUPPLY_PROP_ESR_ACTUAL:
|
||||
case POWER_SUPPLY_PROP_ESR_NOMINAL:
|
||||
case POWER_SUPPLY_PROP_SOH:
|
||||
case POWER_SUPPLY_PROP_CYCLE_COUNT:
|
||||
case POWER_SUPPLY_PROP_CLEAR_SOH:
|
||||
case POWER_SUPPLY_PROP_BATT_AGE_LEVEL:
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
|
||||
case POWER_SUPPLY_PROP_CALIBRATE:
|
||||
return 1;
|
||||
default:
|
||||
@@ -4614,6 +4716,7 @@ static enum power_supply_property fg_psy_props[] = {
|
||||
POWER_SUPPLY_PROP_CHARGE_FULL,
|
||||
POWER_SUPPLY_PROP_CHARGE_COUNTER,
|
||||
POWER_SUPPLY_PROP_CHARGE_COUNTER_SHADOW,
|
||||
POWER_SUPPLY_PROP_CYCLE_COUNT,
|
||||
POWER_SUPPLY_PROP_CYCLE_COUNTS,
|
||||
POWER_SUPPLY_PROP_SOC_REPORTING_READY,
|
||||
POWER_SUPPLY_PROP_CLEAR_SOH,
|
||||
@@ -4745,6 +4848,7 @@ static int fg_parallel_current_en_cb(struct votable *votable, void *data,
|
||||
return rc;
|
||||
|
||||
val = enable ? SMB_MEASURE_EN_BIT : 0;
|
||||
|
||||
mask = SMB_MEASURE_EN_BIT;
|
||||
rc = fg_masked_write(fg, BATT_INFO_FG_CNV_CHAR_CFG(fg), mask, val);
|
||||
if (rc < 0)
|
||||
@@ -4754,6 +4858,8 @@ static int fg_parallel_current_en_cb(struct votable *votable, void *data,
|
||||
vote(chip->mem_attn_irq_en_votable, MEM_ATTN_IRQ_VOTER, false, 0);
|
||||
fg_dbg(fg, FG_STATUS, "Parallel current summing: %d\n", enable);
|
||||
|
||||
/*vote(chip->mem_attn_irq_en_votable, MEM_ATTN_IRQ_VOTER, false, 0);*/
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -5612,7 +5718,7 @@ static int fg_gen4_parse_nvmem_dt(struct fg_gen4_chip *chip)
|
||||
#define DEFAULT_CL_MAX_LIM_DECIPERC 0
|
||||
#define DEFAULT_CL_DELTA_BATT_SOC 10
|
||||
#define BTEMP_DELTA_LOW 0
|
||||
#define BTEMP_DELTA_HIGH 3
|
||||
#define BTEMP_DELTA_HIGH 10
|
||||
#define DEFAULT_ESR_PULSE_THRESH_MA 47
|
||||
#define DEFAULT_ESR_MEAS_CURR_MA 120
|
||||
#define DEFAULT_SCALE_VBATT_THR_MV 3400
|
||||
@@ -5946,6 +6052,116 @@ static int fg_gen4_parse_dt(struct fg_gen4_chip *chip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SOC_WORK_MS 20000
|
||||
static void soc_work_fn(struct work_struct *work)
|
||||
{
|
||||
struct fg_dev *fg = container_of(work,
|
||||
struct fg_dev, soc_work.work);
|
||||
struct fg_gen4_chip *chip = container_of(fg,
|
||||
struct fg_gen4_chip, fg);
|
||||
int msoc = 0, soc = 0, curr_ua = 0, volt_uv = 0, temp = 0;
|
||||
int esr_uohms = 0;
|
||||
int cycle_count;
|
||||
int rc;
|
||||
static int prev_soc = -EINVAL;
|
||||
|
||||
rc = fg_gen4_get_prop_capacity(fg, &soc);
|
||||
if (rc < 0)
|
||||
pr_err("Error in getting capacity, rc=%d\n", rc);
|
||||
|
||||
rc = fg_get_msoc_raw(fg, &msoc);
|
||||
if (rc < 0)
|
||||
pr_err("Error in getting msoc, rc=%d\n", rc);
|
||||
|
||||
rc = fg_get_battery_resistance(fg, &esr_uohms);
|
||||
if (rc < 0)
|
||||
pr_err("Error in getting esr_uohms, rc=%d\n", rc);
|
||||
|
||||
fg_get_battery_current(fg, &curr_ua);
|
||||
if (rc < 0)
|
||||
pr_err("failed to get current, rc=%d\n", rc);
|
||||
|
||||
rc = fg_get_battery_voltage(fg, &volt_uv);
|
||||
if (rc < 0)
|
||||
pr_err("failed to get voltage, rc=%d\n", rc);
|
||||
|
||||
rc = fg_gen4_get_battery_temp(fg, &temp);
|
||||
if (rc < 0)
|
||||
pr_err("Error in getting batt_temp, rc=%d\n", rc);
|
||||
|
||||
rc = get_cycle_count(chip->counter, &cycle_count);
|
||||
if (rc < 0)
|
||||
pr_err("failed to get cycle count, rc=%d\n", rc);
|
||||
|
||||
pr_info("adjust_soc: s %d r %d i %d v %d t %d cc %d m 0x%02x\n",
|
||||
soc,
|
||||
esr_uohms,
|
||||
curr_ua/1000,
|
||||
volt_uv/1000,
|
||||
temp,
|
||||
cycle_count,
|
||||
msoc);
|
||||
|
||||
if (temp < 450 && fg->last_batt_temp >= 450) {
|
||||
/* follow the way that fg_notifier_cb use wake lock */
|
||||
pm_stay_awake(fg->dev);
|
||||
schedule_work(&fg->status_change_work);
|
||||
}
|
||||
|
||||
fg->last_batt_temp = temp;
|
||||
|
||||
/* if soc changes, report power supply changed uevent */
|
||||
if (soc != prev_soc) {
|
||||
if (fg->batt_psy)
|
||||
power_supply_changed(fg->batt_psy);
|
||||
prev_soc = soc;
|
||||
}
|
||||
|
||||
schedule_delayed_work(
|
||||
&fg->soc_work,
|
||||
msecs_to_jiffies(SOC_WORK_MS));
|
||||
}
|
||||
|
||||
static void empty_restart_fg_work(struct work_struct *work)
|
||||
{
|
||||
struct fg_dev *fg = container_of(work, struct fg_dev,
|
||||
empty_restart_fg_work.work);
|
||||
union power_supply_propval prop = {0, };
|
||||
int usb_present = 0;
|
||||
int rc;
|
||||
|
||||
if (usb_psy_initialized(fg)) {
|
||||
rc = power_supply_get_property(fg->usb_psy,
|
||||
POWER_SUPPLY_PROP_PRESENT, &prop);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't read usb present prop rc=%d\n", rc);
|
||||
return;
|
||||
}
|
||||
usb_present = prop.intval;
|
||||
}
|
||||
|
||||
/* only when usb is absent, restart fg */
|
||||
if (!usb_present) {
|
||||
if (fg->profile_load_status == PROFILE_LOADED) {
|
||||
pr_info("soc empty after cold to warm, need to restart fg\n");
|
||||
fg->empty_restart_fg = true;
|
||||
rc = fg_restart(fg, SOC_READY_WAIT_TIME_MS);
|
||||
if (rc < 0) {
|
||||
pr_err("Error in restarting FG, rc=%d\n", rc);
|
||||
fg->empty_restart_fg = false;
|
||||
return;
|
||||
}
|
||||
pr_info("FG restart done\n");
|
||||
if (batt_psy_initialized(fg))
|
||||
power_supply_changed(fg->batt_psy);
|
||||
} else {
|
||||
schedule_delayed_work(
|
||||
&fg->empty_restart_fg_work,
|
||||
msecs_to_jiffies(RESTART_FG_WORK_MS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fg_gen4_cleanup(struct fg_gen4_chip *chip)
|
||||
{
|
||||
struct fg_dev *fg = &chip->fg;
|
||||
@@ -5957,7 +6173,9 @@ static void fg_gen4_cleanup(struct fg_gen4_chip *chip)
|
||||
fg_gen4_exit_soc_scale(chip);
|
||||
|
||||
cancel_delayed_work_sync(&fg->profile_load_work);
|
||||
cancel_delayed_work_sync(&fg->empty_restart_fg_work);
|
||||
cancel_delayed_work_sync(&fg->sram_dump_work);
|
||||
cancel_delayed_work_sync(&fg->soc_work);
|
||||
cancel_work_sync(&chip->pl_current_en_work);
|
||||
|
||||
power_supply_unreg_notifier(&fg->nb);
|
||||
@@ -5981,6 +6199,35 @@ static void fg_gen4_cleanup(struct fg_gen4_chip *chip)
|
||||
dev_set_drvdata(fg->dev, NULL);
|
||||
}
|
||||
|
||||
#define IBAT_OLD_WORD 317
|
||||
#define IBAT_OLD_OFFSET 0
|
||||
#define BATT_CURRENT_NUMR 488281
|
||||
#define BATT_CURRENT_DENR 1000
|
||||
int fg_get_batt_isense(struct fg_dev *fg, int *val)
|
||||
{
|
||||
int rc;
|
||||
u8 buf[2];
|
||||
int64_t temp = 0;
|
||||
|
||||
rc = fg_sram_read(fg, IBAT_OLD_WORD, IBAT_OLD_OFFSET, buf, 2,
|
||||
FG_IMA_DEFAULT);
|
||||
if (rc < 0) {
|
||||
pr_err("Error in reading %04x[%d] rc=%d\n", IBAT_OLD_WORD,
|
||||
IBAT_OLD_OFFSET, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
temp = buf[0] | buf[1] << 8;
|
||||
|
||||
/* Sign bit is bit 15 */
|
||||
temp = sign_extend32(temp, 15);
|
||||
*val = div_s64((s64)temp * BATT_CURRENT_NUMR, BATT_CURRENT_DENR);
|
||||
pr_info("read batt isense: %d[%d]%d\n",
|
||||
(*val)/10, *val, (*val)/1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fg_gen4_post_init(struct fg_gen4_chip *chip)
|
||||
{
|
||||
int i;
|
||||
@@ -6030,6 +6277,8 @@ static int fg_gen4_probe(struct platform_device *pdev)
|
||||
chip->ki_coeff_full_soc[0] = -EINVAL;
|
||||
chip->ki_coeff_full_soc[1] = -EINVAL;
|
||||
chip->esr_soh_cycle_count = -EINVAL;
|
||||
fg->vbat_critical_low_count = 0;
|
||||
fg->vbatt_full_volt_uv = 0;
|
||||
chip->calib_level = -EINVAL;
|
||||
fg->regmap = dev_get_regmap(fg->dev->parent, NULL);
|
||||
if (!fg->regmap) {
|
||||
@@ -6047,9 +6296,12 @@ static int fg_gen4_probe(struct platform_device *pdev)
|
||||
init_completion(&chip->mem_attn);
|
||||
INIT_WORK(&fg->status_change_work, status_change_work);
|
||||
INIT_WORK(&chip->esr_calib_work, esr_calib_work);
|
||||
INIT_WORK(&chip->vbat_sync_work, vbat_sync_work);
|
||||
INIT_WORK(&chip->soc_scale_work, soc_scale_work);
|
||||
INIT_DELAYED_WORK(&fg->profile_load_work, profile_load_work);
|
||||
INIT_DELAYED_WORK(&fg->sram_dump_work, sram_dump_work);
|
||||
INIT_DELAYED_WORK(&fg->soc_work, soc_work_fn);
|
||||
INIT_DELAYED_WORK(&fg->empty_restart_fg_work, empty_restart_fg_work);
|
||||
INIT_DELAYED_WORK(&chip->pl_enable_work, pl_enable_work);
|
||||
INIT_WORK(&chip->pl_current_en_work, pl_current_en_work);
|
||||
|
||||
@@ -6226,6 +6478,12 @@ static int fg_gen4_probe(struct platform_device *pdev)
|
||||
if (!fg->battery_missing)
|
||||
schedule_delayed_work(&fg->profile_load_work, 0);
|
||||
|
||||
schedule_delayed_work(&fg->soc_work, 0);
|
||||
|
||||
if ((volt_uv >= VBAT_RESTART_FG_EMPTY_UV)
|
||||
&& (msoc == 0) && (batt_temp >= TEMP_THR_RESTART_FG))
|
||||
schedule_delayed_work(&fg->empty_restart_fg_work,
|
||||
msecs_to_jiffies(RESTART_FG_START_WORK_MS));
|
||||
fg_gen4_post_init(chip);
|
||||
|
||||
pr_debug("FG GEN4 driver probed successfully\n");
|
||||
@@ -6247,7 +6505,7 @@ static void fg_gen4_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct fg_gen4_chip *chip = dev_get_drvdata(&pdev->dev);
|
||||
struct fg_dev *fg = &chip->fg;
|
||||
int rc, bsoc;
|
||||
int rc, bsoc, msoc;
|
||||
|
||||
fg_unregister_interrupts(fg, chip, FG_GEN4_IRQ_MAX);
|
||||
|
||||
@@ -6261,13 +6519,19 @@ static void fg_gen4_shutdown(struct platform_device *pdev)
|
||||
rc);
|
||||
}
|
||||
|
||||
rc = fg_gen4_get_prop_capacity(fg, &msoc);
|
||||
if (rc < 0) {
|
||||
pr_err("Error in getting capacity, rc=%d\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = fg_get_sram_prop(fg, FG_SRAM_BATT_SOC, &bsoc);
|
||||
if (rc < 0) {
|
||||
pr_err("Error in getting BATT_SOC, rc=%d\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fg->charge_full) {
|
||||
if (fg->charge_full || (msoc == 100)) {
|
||||
/* We need 2 most significant bytes here */
|
||||
bsoc = (u32)bsoc >> 16;
|
||||
|
||||
@@ -6291,6 +6555,7 @@ static int fg_gen4_suspend(struct device *dev)
|
||||
struct fg_gen4_chip *chip = dev_get_drvdata(dev);
|
||||
struct fg_dev *fg = &chip->fg;
|
||||
|
||||
cancel_delayed_work_sync(&fg->soc_work);
|
||||
cancel_delayed_work_sync(&chip->ttf->ttf_work);
|
||||
if (fg_sram_dump)
|
||||
cancel_delayed_work_sync(&fg->sram_dump_work);
|
||||
@@ -6301,11 +6566,18 @@ static int fg_gen4_resume(struct device *dev)
|
||||
{
|
||||
struct fg_gen4_chip *chip = dev_get_drvdata(dev);
|
||||
struct fg_dev *fg = &chip->fg;
|
||||
int val = 0;
|
||||
|
||||
if (!fg->input_present)
|
||||
fg_get_batt_isense(fg, &val);
|
||||
|
||||
schedule_delayed_work(
|
||||
&fg->soc_work, msecs_to_jiffies(SOC_WORK_MS));
|
||||
schedule_delayed_work(&chip->ttf->ttf_work, 0);
|
||||
if (fg_sram_dump)
|
||||
schedule_delayed_work(&fg->sram_dump_work,
|
||||
msecs_to_jiffies(fg_sram_dump_period_ms));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2019 XiaoMi, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -87,6 +88,7 @@
|
||||
#define ILIM_VOTER "ILIM_VOTER"
|
||||
#define FCC_VOTER "FCC_VOTER"
|
||||
#define ICL_VOTER "ICL_VOTER"
|
||||
#define ICL_CHANGE_VOTER "ICL_CHANGE_VOTER"
|
||||
#define TAPER_END_VOTER "TAPER_END_VOTER"
|
||||
#define WIRELESS_VOTER "WIRELESS_VOTER"
|
||||
#define SRC_VOTER "SRC_VOTER"
|
||||
@@ -139,6 +141,7 @@ struct smb1390 {
|
||||
int irqs[NUM_IRQS];
|
||||
bool status_change_running;
|
||||
bool taper_work_running;
|
||||
bool taper_early_trigger;
|
||||
struct smb1390_iio iio;
|
||||
int irq_status;
|
||||
int taper_entry_fv;
|
||||
@@ -343,6 +346,20 @@ static ssize_t stat2_show(struct class *c, struct class_attribute *attr,
|
||||
}
|
||||
static CLASS_ATTR_RO(stat2);
|
||||
|
||||
static ssize_t model_name_show(struct class *c, struct class_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct smb1390 *chip = container_of(c, struct smb1390, cp_class);
|
||||
int rc, val;
|
||||
|
||||
rc = smb1390_read(chip, CORE_STATUS1_REG, &val);
|
||||
if (rc < 0)
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", "unknown");
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", "smb1390");
|
||||
}
|
||||
static CLASS_ATTR_RO(model_name);
|
||||
|
||||
static ssize_t enable_show(struct class *c, struct class_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
@@ -469,6 +486,7 @@ static struct attribute *cp_class_attrs[] = {
|
||||
&class_attr_toggle_switcher.attr,
|
||||
&class_attr_die_temp.attr,
|
||||
&class_attr_isns.attr,
|
||||
&class_attr_model_name.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(cp_class);
|
||||
@@ -519,11 +537,11 @@ static int smb1390_ilim_vote_cb(struct votable *votable, void *data,
|
||||
}
|
||||
|
||||
/* ILIM less than 1A is not accurate; disable charging */
|
||||
if (ilim_uA < 1000000) {
|
||||
pr_debug("ILIM %duA is too low to allow charging\n", ilim_uA);
|
||||
if (ilim_uA < 900000) {
|
||||
pr_info("ILIM %duA is too low to allow charging\n", ilim_uA);
|
||||
vote(chip->disable_votable, ILIM_VOTER, true, 0);
|
||||
} else {
|
||||
pr_debug("setting ILIM to %duA\n", ilim_uA);
|
||||
pr_info("setting ILIM to %duA\n", ilim_uA);
|
||||
rc = smb1390_masked_write(chip, CORE_FTRIM_ILIM_REG,
|
||||
CFG_ILIM_MASK,
|
||||
DIV_ROUND_CLOSEST(ilim_uA - 500000, 100000));
|
||||
@@ -575,12 +593,17 @@ static int smb1390_notifier_cb(struct notifier_block *nb,
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
|
||||
#define TAPER_CAPACITY_THR 55
|
||||
#define TAPER_CAPCITY_DELTA 1
|
||||
#define BATT_COOL_THR 220
|
||||
static void smb1390_status_change_work(struct work_struct *work)
|
||||
{
|
||||
struct smb1390 *chip = container_of(work, struct smb1390,
|
||||
status_change_work);
|
||||
union power_supply_propval pval = {0, };
|
||||
int max_fcc_ma, rc;
|
||||
int capacity, batt_temp, charge_type;
|
||||
|
||||
if (!is_psy_voter_available(chip))
|
||||
goto out;
|
||||
@@ -612,6 +635,7 @@ static void smb1390_status_change_work(struct work_struct *work)
|
||||
*/
|
||||
if (pval.intval == POWER_SUPPLY_CP_WIRELESS) {
|
||||
vote(chip->ilim_votable, ICL_VOTER, false, 0);
|
||||
vote(chip->ilim_votable, ICL_CHANGE_VOTER, false, 0);
|
||||
rc = power_supply_get_property(chip->dc_psy,
|
||||
POWER_SUPPLY_PROP_CURRENT_MAX, &pval);
|
||||
if (rc < 0)
|
||||
@@ -650,6 +674,49 @@ static void smb1390_status_change_work(struct work_struct *work)
|
||||
if (get_effective_result(chip->disable_votable))
|
||||
goto out;
|
||||
|
||||
|
||||
rc = power_supply_get_property(chip->batt_psy,
|
||||
POWER_SUPPLY_PROP_CAPACITY, &pval);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't get batt capacity rc=%d\n", rc);
|
||||
goto out;
|
||||
}
|
||||
capacity = pval.intval;
|
||||
|
||||
rc = power_supply_get_property(chip->batt_psy,
|
||||
POWER_SUPPLY_PROP_TEMP, &pval);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't get batt temp rc=%d\n", rc);
|
||||
goto out;
|
||||
}
|
||||
batt_temp = pval.intval;
|
||||
|
||||
rc = power_supply_get_property(chip->batt_psy,
|
||||
POWER_SUPPLY_PROP_CHARGE_TYPE, &pval);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't get charge type rc=%d\n", rc);
|
||||
goto out;
|
||||
}
|
||||
charge_type = pval.intval;
|
||||
|
||||
pr_info("capacity:%d, batt_temp:%d, charge_type:%d\n",
|
||||
capacity, batt_temp, charge_type);
|
||||
|
||||
if ((capacity < TAPER_CAPACITY_THR)
|
||||
&& (batt_temp >= BATT_COOL_THR)
|
||||
&& (charge_type == POWER_SUPPLY_CHARGE_TYPE_FAST)
|
||||
&& chip->taper_early_trigger) {
|
||||
if (is_client_vote_enabled(chip->fcc_votable,
|
||||
CP_VOTER)) {
|
||||
/* reset cp_voter here */
|
||||
vote(chip->fcc_votable, CP_VOTER, false, 0);
|
||||
/* input current is always half the charge current */
|
||||
vote(chip->ilim_votable, FCC_VOTER, true,
|
||||
get_effective_result(chip->fcc_votable) / 2);
|
||||
chip->taper_early_trigger = false;
|
||||
}
|
||||
}
|
||||
|
||||
rc = power_supply_get_property(chip->batt_psy,
|
||||
POWER_SUPPLY_PROP_CHARGE_TYPE, &pval);
|
||||
if (rc < 0) {
|
||||
@@ -673,6 +740,7 @@ static void smb1390_status_change_work(struct work_struct *work)
|
||||
BATT_PROFILE_VOTER);
|
||||
vote(chip->fcc_votable, CP_VOTER,
|
||||
max_fcc_ma > 0 ? true : false, max_fcc_ma);
|
||||
chip->taper_early_trigger = false;
|
||||
vote(chip->disable_votable, SOC_LEVEL_VOTER, true, 0);
|
||||
}
|
||||
|
||||
@@ -686,12 +754,24 @@ static void smb1390_taper_work(struct work_struct *work)
|
||||
struct smb1390 *chip = container_of(work, struct smb1390, taper_work);
|
||||
union power_supply_propval pval = {0, };
|
||||
int rc, fcc_uA;
|
||||
int capacity;
|
||||
|
||||
if (!is_psy_voter_available(chip))
|
||||
goto out;
|
||||
|
||||
chip->taper_entry_fv = get_effective_result(chip->fv_votable);
|
||||
while (true) {
|
||||
rc = power_supply_get_property(chip->batt_psy,
|
||||
POWER_SUPPLY_PROP_CAPACITY, &pval);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't get batt capacity rc=%d\n", rc);
|
||||
goto out;
|
||||
}
|
||||
capacity = pval.intval;
|
||||
if ((capacity < (TAPER_CAPACITY_THR - TAPER_CAPCITY_DELTA))
|
||||
&& !chip->taper_early_trigger)
|
||||
chip->taper_early_trigger = true;
|
||||
|
||||
rc = power_supply_get_property(chip->batt_psy,
|
||||
POWER_SUPPLY_PROP_CHARGE_TYPE, &pval);
|
||||
if (rc < 0) {
|
||||
@@ -794,7 +874,7 @@ static void smb1390_destroy_votables(struct smb1390 *chip)
|
||||
|
||||
static int smb1390_init_hw(struct smb1390 *chip)
|
||||
{
|
||||
int rc;
|
||||
int rc, val;
|
||||
|
||||
/*
|
||||
* charge pump is initially disabled; this indirectly votes to allow
|
||||
@@ -820,6 +900,15 @@ static int smb1390_init_hw(struct smb1390 *chip)
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = smb1390_read(chip, 0x1032, &val);
|
||||
pr_err("default smb1390 400K 0x1032_REG: 0x%x\n", val);
|
||||
|
||||
rc = smb1390_masked_write(chip, 0x1032, 0x0F, 0x07);
|
||||
rc = smb1390_read(chip, 0x1032, &val);
|
||||
pr_err("modify smb1390 800K 0x1032_REG: 0x%x\n", val);
|
||||
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2019 XiaoMi, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -32,6 +33,7 @@ enum print_reason {
|
||||
PR_PARALLEL = BIT(3),
|
||||
PR_OTG = BIT(4),
|
||||
PR_WLS = BIT(5),
|
||||
PR_OEM = BIT(6),
|
||||
};
|
||||
|
||||
#define DEFAULT_VOTER "DEFAULT_VOTER"
|
||||
@@ -61,14 +63,25 @@ enum print_reason {
|
||||
#define OTG_DELAY_VOTER "OTG_DELAY_VOTER"
|
||||
#define USBIN_I_VOTER "USBIN_I_VOTER"
|
||||
#define WEAK_CHARGER_VOTER "WEAK_CHARGER_VOTER"
|
||||
#define OTG_VOTER "OTG_VOTER"
|
||||
#define PL_FCC_LOW_VOTER "PL_FCC_LOW_VOTER"
|
||||
#define WBC_VOTER "WBC_VOTER"
|
||||
#define HW_LIMIT_VOTER "HW_LIMIT_VOTER"
|
||||
#define CHG_AWAKE_VOTER "CHG_AWAKE_VOTER"
|
||||
#define DCIN_ADAPTER_VOTER "DCIN_ADAPTER_VOTER"
|
||||
#define DCIN_LIMIT_VOTER "DCIN_LIMIT_VOTER"
|
||||
#define PL_SMB_EN_VOTER "PL_SMB_EN_VOTER"
|
||||
#define FORCE_RECHARGE_VOTER "FORCE_RECHARGE_VOTER"
|
||||
#define LPD_VOTER "LPD_VOTER"
|
||||
#define DC_AWAKE_VOTER "DC_AWAKE_VOTER"
|
||||
#define DC_UV_AWAKE_VOTER "DC_UV_AWAKE_VOTER"
|
||||
#define CLASSA_QC_FCC_VOTER "CLASSA_QC_FCC_VOTER"
|
||||
#define QC_A_CP_ICL_MAX_VOTER "QC_A_CP_ICL_MAX_VOTER"
|
||||
#define JEITA_VOTER "JEITA_VOTER"
|
||||
#define FCC_STEPPER_VOTER "FCC_STEPPER_VOTER"
|
||||
#define SW_THERM_REGULATION_VOTER "SW_THERM_REGULATION_VOTER"
|
||||
#define LIQUID_DETECTION_VOTER "LIQUID_DETECTION_VOTER"
|
||||
#define QC2_UNSUPPORTED_VOTER "QC2_UNSUPPORTED_VOTER"
|
||||
#define JEITA_ARB_VOTER "JEITA_ARB_VOTER"
|
||||
#define MOISTURE_VOTER "MOISTURE_VOTER"
|
||||
#define HVDCP2_ICL_VOTER "HVDCP2_ICL_VOTER"
|
||||
@@ -86,10 +99,48 @@ enum print_reason {
|
||||
#define MAIN_FCC_VOTER "MAIN_FCC_VOTER"
|
||||
#define DCIN_AICL_VOTER "DCIN_AICL_VOTER"
|
||||
#define OVERHEAT_LIMIT_VOTER "OVERHEAT_LIMIT_VOTER"
|
||||
#define PD_VERIFED_VOTER "PD_VERIFED_VOTER"
|
||||
|
||||
#define BOOST_BACK_STORM_COUNT 3
|
||||
#define WEAK_CHG_STORM_COUNT 8
|
||||
|
||||
#define VOL_THR_FOR_QC_CLASS_AB 12300000
|
||||
#define COMP_FOR_LOW_RESISTANCE_CABLE 100000
|
||||
#define QC_CLASS_A_CURRENT_UA 3600000
|
||||
#define HVDCP_CLASS_A_MAX_UA 2500000
|
||||
#define HVDCP_CLASS_A_FOR_CP_UA 2000000
|
||||
#define MAX_PULSE 38
|
||||
#define MAX_PLUSE_COUNT_ALLOWED 30
|
||||
#define HIGH_NUM_PULSE_THR 12
|
||||
#define PD_UNVERIFED_CURRENT 3000000
|
||||
|
||||
/* thermal micros */
|
||||
#define MAX_TEMP_LEVEL 16
|
||||
/* percent of ICL compared to base 5V for different PD voltage_min voltage */
|
||||
#define PD_6P5V_PERCENT 85
|
||||
#define PD_7P5V_PERCENT 75
|
||||
#define PD_8P5V_PERCENT 70
|
||||
#define PD_9V_PERCENT 65
|
||||
#define PD_MICRO_5V 5000000
|
||||
#define PD_MICRO_5P9V 5900000
|
||||
#define PD_MICRO_6P5V 6500000
|
||||
#define PD_MICRO_7P5V 7500000
|
||||
#define PD_MICRO_8P5V 8500000
|
||||
#define PD_MICRO_9V 9000000
|
||||
#define ICL_LIMIT_LEVEL_THR 8
|
||||
|
||||
#define QC2_UNSUPPORTED_UA 1800000
|
||||
/* defined for HVDCP2 */
|
||||
#define HVDCP2_CURRENT_UA 1500000
|
||||
|
||||
/* defined for charger type recheck */
|
||||
#define CHARGER_RECHECK_DELAY_MS 30000
|
||||
#define TYPE_RECHECK_TIME_5S 5000
|
||||
#define TYPE_RECHECK_COUNT 3
|
||||
|
||||
/* defined for un_compliant Type-C cable */
|
||||
#define CC_UN_COMPLIANT_START_DELAY_MS 700
|
||||
|
||||
#define VBAT_TO_VRAW_ADC(v) div_u64((u64)v * 1000000UL, 194637UL)
|
||||
|
||||
#define ITERM_LIMITS_PMI632_MA 5000
|
||||
@@ -99,8 +150,8 @@ enum print_reason {
|
||||
#define SDP_100_MA 100000
|
||||
#define SDP_CURRENT_UA 500000
|
||||
#define CDP_CURRENT_UA 1500000
|
||||
#define DCP_CURRENT_UA 1500000
|
||||
#define HVDCP_CURRENT_UA 3000000
|
||||
#define DCP_CURRENT_UA 1600000
|
||||
#define HVDCP_CURRENT_UA 2800000
|
||||
#define TYPEC_DEFAULT_CURRENT_UA 900000
|
||||
#define TYPEC_MEDIUM_CURRENT_UA 1500000
|
||||
#define TYPEC_HIGH_CURRENT_UA 3000000
|
||||
@@ -108,6 +159,24 @@ enum print_reason {
|
||||
#define DCIN_ICL_MAX_UA 1500000
|
||||
#define DCIN_ICL_STEP_UA 100000
|
||||
|
||||
/*DCIN ICL*/
|
||||
#define PSNS_CURRENT_SAMPLE_RATE 1053
|
||||
#define PSNS_CURRENT_SAMPLE_RESIS 392
|
||||
#define PSNS_COMP_UV_FOR_HIGH_THERMAL 40000
|
||||
|
||||
/* cutoff voltage threshold */
|
||||
#define CUTOFF_VOL_THR 3400000
|
||||
|
||||
#define RSBU_K_300K_UV 3000000
|
||||
|
||||
#define RECHARGE_SOC_THR 99
|
||||
|
||||
enum hvdcp3_type {
|
||||
HVDCP3_NONE = 0,
|
||||
HVDCP3_CLASSA_18W,
|
||||
HVDCP3_CLASSB_27W,
|
||||
};
|
||||
|
||||
#define ROLE_REVERSAL_DELAY_MS 2000
|
||||
|
||||
enum smb_mode {
|
||||
@@ -376,6 +445,8 @@ struct smb_iio {
|
||||
struct iio_channel *die_temp_chan;
|
||||
struct iio_channel *skin_temp_chan;
|
||||
struct iio_channel *smb_temp_chan;
|
||||
struct iio_channel *hw_version_gpio5;
|
||||
struct iio_channel *project_gpio6;
|
||||
};
|
||||
|
||||
struct smb_charger {
|
||||
@@ -392,6 +463,9 @@ struct smb_charger {
|
||||
int otg_delay_ms;
|
||||
int *weak_chg_icl_ua;
|
||||
bool pd_not_supported;
|
||||
bool init_once;
|
||||
bool support_liquid;
|
||||
bool dynamic_fv_enabled;
|
||||
|
||||
/* locks */
|
||||
struct mutex smb_lock;
|
||||
@@ -408,11 +482,17 @@ struct smb_charger {
|
||||
struct power_supply *usb_psy;
|
||||
struct power_supply *dc_psy;
|
||||
struct power_supply *bms_psy;
|
||||
struct power_supply_desc usb_psy_desc;
|
||||
struct power_supply *usb_main_psy;
|
||||
struct power_supply *usb_port_psy;
|
||||
struct power_supply *wls_psy;
|
||||
struct power_supply *idtp_psy;
|
||||
struct power_supply *wip_psy;
|
||||
struct power_supply *wireless_psy;
|
||||
struct power_supply *wls_chip_psy;
|
||||
struct power_supply *cp_psy;
|
||||
enum power_supply_type real_charger_type;
|
||||
enum power_supply_type wireless_charger_type;
|
||||
|
||||
/* dual role class */
|
||||
struct dual_role_phy_instance *dual_role;
|
||||
@@ -438,6 +518,7 @@ struct smb_charger {
|
||||
struct votable *fcc_main_votable;
|
||||
struct votable *fv_votable;
|
||||
struct votable *usb_icl_votable;
|
||||
struct votable *dc_icl_votable;
|
||||
struct votable *awake_votable;
|
||||
struct votable *pl_disable_votable;
|
||||
struct votable *chg_disable_votable;
|
||||
@@ -456,16 +537,22 @@ struct smb_charger {
|
||||
struct work_struct moisture_protection_work;
|
||||
struct work_struct chg_termination_work;
|
||||
struct work_struct dcin_aicl_work;
|
||||
struct work_struct lpd_disable_chg_work;
|
||||
struct delayed_work ps_change_timeout_work;
|
||||
struct delayed_work clear_hdc_work;
|
||||
struct delayed_work icl_change_work;
|
||||
struct delayed_work pl_enable_work;
|
||||
struct delayed_work uusb_otg_work;
|
||||
struct delayed_work bb_removal_work;
|
||||
struct delayed_work raise_qc3_vbus_work;
|
||||
struct delayed_work lpd_ra_open_work;
|
||||
struct delayed_work lpd_detach_work;
|
||||
struct delayed_work charger_type_recheck;
|
||||
struct delayed_work cc_un_compliant_charge_work;
|
||||
struct delayed_work reg_work;
|
||||
struct delayed_work thermal_regulation_work;
|
||||
struct delayed_work usbov_dbc_work;
|
||||
struct delayed_work dc_plug_out_delay_work;
|
||||
struct delayed_work role_reversal_check;
|
||||
struct delayed_work pr_swap_detach_work;
|
||||
struct delayed_work pr_lock_clear_work;
|
||||
@@ -488,10 +575,13 @@ struct smb_charger {
|
||||
int voltage_min_uv;
|
||||
int voltage_max_uv;
|
||||
int pd_active;
|
||||
int pd_verifed;
|
||||
bool pd_hard_reset;
|
||||
bool pr_lock_in_progress;
|
||||
bool pr_swap_in_progress;
|
||||
bool early_usb_attach;
|
||||
bool early_dc_attach;
|
||||
bool batt_temp_irq_enabled;
|
||||
bool ok_to_pd;
|
||||
bool typec_legacy;
|
||||
bool typec_irq_en;
|
||||
@@ -502,13 +592,34 @@ struct smb_charger {
|
||||
int boost_threshold_ua;
|
||||
int system_temp_level;
|
||||
int thermal_levels;
|
||||
int lpd_levels;
|
||||
int dc_temp_level;
|
||||
int dc_thermal_levels;
|
||||
#ifdef CONFIG_THERMAL
|
||||
int *thermal_mitigation_dcp;
|
||||
int *thermal_mitigation_qc2;
|
||||
int *thermal_mitigation_pd_base;
|
||||
int *thermal_mitigation_icl;
|
||||
int *thermal_fcc_qc3_normal;
|
||||
int *thermal_fcc_qc3_cp;
|
||||
int *thermal_fcc_qc3_classb_cp;
|
||||
int *thermal_fcc_pps_cp;
|
||||
int *thermal_mitigation_dc;
|
||||
int *lpd_hwversion;
|
||||
int *thermal_mitigation_epp;
|
||||
int *thermal_mitigation_bpp_qc3;
|
||||
int *thermal_mitigation_bpp_qc2;
|
||||
int *thermal_mitigation_bpp;
|
||||
#else
|
||||
int *thermal_mitigation;
|
||||
#endif
|
||||
int dcp_icl_ua;
|
||||
int fake_capacity;
|
||||
int fake_batt_status;
|
||||
bool step_chg_enabled;
|
||||
bool sw_jeita_enabled;
|
||||
bool typec_legacy_use_rp_icl;
|
||||
bool lpd_enabled;
|
||||
bool is_hdc;
|
||||
bool chg_done;
|
||||
int connector_type;
|
||||
@@ -538,6 +649,7 @@ struct smb_charger {
|
||||
enum lpd_stage lpd_stage;
|
||||
bool lpd_disabled;
|
||||
enum lpd_reason lpd_reason;
|
||||
bool lpd_status;
|
||||
bool fcc_stepper_enable;
|
||||
int die_temp;
|
||||
int smb_temp;
|
||||
@@ -545,6 +657,7 @@ struct smb_charger {
|
||||
int connector_temp;
|
||||
int thermal_status;
|
||||
int main_fcc_max;
|
||||
bool report_usb_absent;
|
||||
u32 jeita_soft_thlds[2];
|
||||
u32 jeita_soft_hys_thlds[2];
|
||||
int jeita_soft_fcc[2];
|
||||
@@ -582,6 +695,8 @@ struct smb_charger {
|
||||
int qc2_max_pulses;
|
||||
enum qc2_non_comp_voltage qc2_unsupported_voltage;
|
||||
bool dbc_usbov;
|
||||
bool fake_usb_insertion;
|
||||
bool qc2_unsupported;
|
||||
|
||||
/* extcon for VBUS / ID notification to USB for uUSB */
|
||||
struct extcon_dev *extcon;
|
||||
@@ -595,6 +710,13 @@ struct smb_charger {
|
||||
|
||||
int die_health;
|
||||
int connector_health;
|
||||
/* raise qc3 vbus flag */
|
||||
bool qc_class_ab;
|
||||
bool is_qc_class_a;
|
||||
bool is_qc_class_b;
|
||||
bool raise_vbus_to_detect;
|
||||
bool detect_low_power_qc3_charger;
|
||||
bool high_vbus_detected;
|
||||
|
||||
/* flash */
|
||||
u32 flash_derating_soc;
|
||||
@@ -608,6 +730,31 @@ struct smb_charger {
|
||||
int dcin_uv_count;
|
||||
ktime_t dcin_uv_last_time;
|
||||
int last_wls_vout;
|
||||
int flag_dc_present;
|
||||
int power_good_en;
|
||||
int fake_dc_on;
|
||||
int fake_dc_flag;
|
||||
int last_batt_stat;
|
||||
/* charger type recheck */
|
||||
int recheck_charger;
|
||||
int precheck_charger_type;
|
||||
/* workarounds */
|
||||
bool cc_un_compliant_detected;
|
||||
bool snk_debug_acc_detected;
|
||||
bool support_wireless;
|
||||
};
|
||||
|
||||
enum quick_charge_type {
|
||||
QUICK_CHARGE_NORMAL = 0,
|
||||
QUICK_CHARGE_FAST,
|
||||
QUICK_CHARGE_FLASH,
|
||||
QUICK_CHARGE_TURBE,
|
||||
QUICK_CHARGE_MAX,
|
||||
};
|
||||
|
||||
struct quick_charge {
|
||||
enum power_supply_type adap_type;
|
||||
enum quick_charge_type adap_cap;
|
||||
};
|
||||
|
||||
int smblib_read(struct smb_charger *chg, u16 addr, u8 *val);
|
||||
@@ -626,6 +773,8 @@ int smblib_set_charge_param(struct smb_charger *chg,
|
||||
int smblib_set_usb_suspend(struct smb_charger *chg, bool suspend);
|
||||
int smblib_set_dc_suspend(struct smb_charger *chg, bool suspend);
|
||||
|
||||
int smblib_change_psns_to_curr(struct smb_charger *chg, int uv);
|
||||
|
||||
int smblib_mapping_soc_from_field_value(struct smb_chg_param *param,
|
||||
int val_u, u8 *val_raw);
|
||||
int smblib_mapping_cc_delta_to_field_value(struct smb_chg_param *param,
|
||||
@@ -647,6 +796,7 @@ int smblib_vconn_regulator_disable(struct regulator_dev *rdev);
|
||||
int smblib_vconn_regulator_is_enabled(struct regulator_dev *rdev);
|
||||
|
||||
irqreturn_t default_irq_handler(int irq, void *data);
|
||||
irqreturn_t dcin_uv_handler(int irq, void *data);
|
||||
irqreturn_t smb_en_irq_handler(int irq, void *data);
|
||||
irqreturn_t chg_state_change_irq_handler(int irq, void *data);
|
||||
irqreturn_t batt_temp_changed_irq_handler(int irq, void *data);
|
||||
@@ -685,6 +835,8 @@ int smblib_get_prop_system_temp_level(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
int smblib_get_prop_system_temp_level_max(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
int smblib_get_prop_dc_temp_level(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
int smblib_get_prop_input_current_limited(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
int smblib_get_prop_batt_iterm(struct smb_charger *chg,
|
||||
@@ -697,6 +849,8 @@ int smblib_set_prop_batt_status(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_set_prop_system_temp_level(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_set_prop_dc_temp_level(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_set_prop_input_current_limited(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
|
||||
@@ -716,6 +870,8 @@ int smblib_get_prop_voltage_wls_output(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
int smblib_set_prop_voltage_wls_output(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_get_prop_wireless_version(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
int smblib_set_prop_dc_reset(struct smb_charger *chg);
|
||||
int smblib_get_prop_usb_present(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
@@ -807,6 +963,23 @@ int smblib_configure_hvdcp_apsd(struct smb_charger *chg, bool enable);
|
||||
int smblib_icl_override(struct smb_charger *chg, enum icl_override_mode mode);
|
||||
enum alarmtimer_restart smblib_lpd_recheck_timer(struct alarm *alarm,
|
||||
ktime_t time);
|
||||
int smblib_set_prop_wireless_wakelock(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
|
||||
int smblib_set_prop_type_recheck(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_get_prop_type_recheck(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
int smblib_get_quick_charge_type(struct smb_charger *chg);
|
||||
int smblib_set_wirless_cp_enable(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_set_wirless_power_good_enable(struct smb_charger *chg,
|
||||
const union power_supply_propval *val);
|
||||
int smblib_get_prop_liquid_status(struct smb_charger *chg,
|
||||
union power_supply_propval *val);
|
||||
|
||||
bool smblib_support_liquid_feature(struct smb_charger *chg);
|
||||
|
||||
int smblib_toggle_smb_en(struct smb_charger *chg, int toggle);
|
||||
void smblib_hvdcp_detect_enable(struct smb_charger *chg, bool enable);
|
||||
void smblib_hvdcp_exit_config(struct smb_charger *chg);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2019 XiaoMi, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -317,6 +318,10 @@ enum {
|
||||
|
||||
#define USBIN_5V_AICL_THRESHOLD_REG (USBIN_BASE + 0x81)
|
||||
#define USBIN_CONT_AICL_THRESHOLD_REG (USBIN_BASE + 0x84)
|
||||
|
||||
#define TYPE_C_CFG_REG (USBIN_BASE + 0x58)
|
||||
#define APSD_START_ON_CC_BIT BIT(7)
|
||||
|
||||
/********************************
|
||||
* DCIN Peripheral Registers *
|
||||
********************************/
|
||||
@@ -327,6 +332,12 @@ enum {
|
||||
#define DCIN_CMD_IL_REG (DCIN_BASE + 0x40)
|
||||
#define DCIN_SUSPEND_BIT BIT(0)
|
||||
#define DCIN_EN_OVERRIDE_BIT BIT(1)
|
||||
#define DCIN_EN_BIT BIT(2)
|
||||
|
||||
#define DCIN_CMD_PULLDOWN_REG (DCIN_BASE + 0x45)
|
||||
#define DCIN_PULLDOWN_EN_BIT BIT(0)
|
||||
#define DCIN_MID_PULLDOWN_BIT BIT(1)
|
||||
|
||||
#define DCIN_EN_MASK GENMASK(2, 1)
|
||||
|
||||
#define DCIN_CMD_PON_REG (DCIN_BASE + 0x45)
|
||||
@@ -349,6 +360,9 @@ enum {
|
||||
#define SNK_RP_3P0_BIT BIT(1)
|
||||
#define SNK_RP_SHORT_BIT BIT(0)
|
||||
|
||||
#define TYPE_C_SNK_DEBUG_ACC_STATUS_REG (TYPEC_BASE + 0x07)
|
||||
#define SNK_DEBUG_ACC_RPSTD_PRSTD_BIT BIT(0)
|
||||
|
||||
#define TYPE_C_SRC_STATUS_REG (TYPEC_BASE + 0x08)
|
||||
#define DETECTED_SNK_TYPE_MASK GENMASK(4, 0)
|
||||
#define SRC_HIGH_BATT_BIT BIT(5)
|
||||
@@ -400,6 +414,10 @@ enum {
|
||||
#define TYPEC_CCOUT_VALUE_BIT BIT(1)
|
||||
#define TYPEC_CCOUT_SRC_BIT BIT(0)
|
||||
|
||||
#define TYPE_C_DEBUG_ACC_SNK_CFG (TYPEC_BASE + 0x4A)
|
||||
#define TYPEC_DEBUG_ACC_SNK_SEL_ICL BIT(2)
|
||||
#define TYPEC_DEBUG_ACC_SNK_DIS_AICL BIT(3)
|
||||
|
||||
#define DEBUG_ACCESS_SRC_CFG_REG (TYPEC_BASE + 0x4C)
|
||||
#define EN_UNORIENTED_DEBUG_ACCESS_SRC_BIT BIT(0)
|
||||
|
||||
@@ -515,6 +533,7 @@ enum {
|
||||
#define WATCHDOG_TRIGGER_AFP_EN_BIT BIT(7)
|
||||
#define BARK_WDOG_INT_EN_BIT BIT(6)
|
||||
#define WDOG_TIMER_EN_ON_PLUGIN_BIT BIT(1)
|
||||
#define WDOG_TIMER_EN_BIT BIT(0)
|
||||
|
||||
#define SNARL_BARK_BITE_WD_CFG_REG (MISC_BASE + 0x53)
|
||||
#define BITE_WDOG_DISABLE_CHARGING_CFG_BIT BIT(7)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2019 XiaoMi, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -22,6 +23,7 @@
|
||||
|
||||
#define STEP_CHG_VOTER "STEP_CHG_VOTER"
|
||||
#define JEITA_VOTER "JEITA_VOTER"
|
||||
#define DYNAMIC_FV_VOTER "DYNAMIC_FV_VOTER"
|
||||
|
||||
#define is_between(left, right, value) \
|
||||
(((left) >= (right) && (left) >= (value) \
|
||||
@@ -44,16 +46,24 @@ struct jeita_fv_cfg {
|
||||
struct range_data fv_cfg[MAX_STEP_CHG_ENTRIES];
|
||||
};
|
||||
|
||||
struct dynamic_fv_cfg {
|
||||
char *prop_name;
|
||||
struct range_data fv_cfg[MAX_STEP_CHG_ENTRIES];
|
||||
};
|
||||
|
||||
struct step_chg_info {
|
||||
struct device *dev;
|
||||
ktime_t step_last_update_time;
|
||||
ktime_t jeita_last_update_time;
|
||||
ktime_t dynamic_fv_last_update_time;
|
||||
bool step_chg_enable;
|
||||
bool sw_jeita_enable;
|
||||
bool dynamic_fv_enable;
|
||||
bool jeita_arb_en;
|
||||
bool config_is_read;
|
||||
bool step_chg_cfg_valid;
|
||||
bool sw_jeita_cfg_valid;
|
||||
bool dynamic_fv_cfg_valid;
|
||||
bool soc_based_step_chg;
|
||||
bool ocv_based_step_chg;
|
||||
bool vbat_avg_based_step_chg;
|
||||
@@ -61,16 +71,19 @@ struct step_chg_info {
|
||||
bool taper_fcc;
|
||||
int jeita_fcc_index;
|
||||
int jeita_fv_index;
|
||||
int dynamic_fv_index;
|
||||
int step_index;
|
||||
int get_config_retry_count;
|
||||
|
||||
struct step_chg_cfg *step_chg_config;
|
||||
struct jeita_fcc_cfg *jeita_fcc_config;
|
||||
struct jeita_fv_cfg *jeita_fv_config;
|
||||
struct dynamic_fv_cfg *dynamic_fv_config;
|
||||
|
||||
struct votable *fcc_votable;
|
||||
struct votable *fv_votable;
|
||||
struct votable *usb_icl_votable;
|
||||
struct votable *dc_suspend_votable;
|
||||
struct wakeup_source *step_chg_ws;
|
||||
struct power_supply *batt_psy;
|
||||
struct power_supply *bms_psy;
|
||||
@@ -360,6 +373,17 @@ static int get_step_chg_jeita_setting_from_profile(struct step_chg_info *chip)
|
||||
chip->sw_jeita_cfg_valid = false;
|
||||
}
|
||||
|
||||
chip->dynamic_fv_cfg_valid = true;
|
||||
rc = read_range_data_from_node(profile_node,
|
||||
"qcom,dynamic-fv-ranges",
|
||||
chip->dynamic_fv_config->fv_cfg,
|
||||
BATT_HOT_DECIDEGREE_MAX, max_fv_uv);
|
||||
if (rc < 0) {
|
||||
pr_debug("Read qcom,dynamic-fv-ranges failed from battery profile, rc=%d\n",
|
||||
rc);
|
||||
chip->dynamic_fv_cfg_valid = false;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -391,16 +415,20 @@ static void get_config_work(struct work_struct *work)
|
||||
chip->step_chg_config->fcc_cfg[i].high_threshold,
|
||||
chip->step_chg_config->fcc_cfg[i].value);
|
||||
for (i = 0; i < MAX_STEP_CHG_ENTRIES; i++)
|
||||
pr_debug("jeita-fcc-cfg: %ddecidegree ~ %ddecidegre, %duA\n",
|
||||
pr_info("jeita-fcc-cfg: %ddecidegree ~ %ddecidegre, %duA\n",
|
||||
chip->jeita_fcc_config->fcc_cfg[i].low_threshold,
|
||||
chip->jeita_fcc_config->fcc_cfg[i].high_threshold,
|
||||
chip->jeita_fcc_config->fcc_cfg[i].value);
|
||||
for (i = 0; i < MAX_STEP_CHG_ENTRIES; i++)
|
||||
pr_debug("jeita-fv-cfg: %ddecidegree ~ %ddecidegre, %duV\n",
|
||||
pr_info("jeita-fv-cfg: %ddecidegree ~ %ddecidegre, %duV\n",
|
||||
chip->jeita_fv_config->fv_cfg[i].low_threshold,
|
||||
chip->jeita_fv_config->fv_cfg[i].high_threshold,
|
||||
chip->jeita_fv_config->fv_cfg[i].value);
|
||||
|
||||
for (i = 0; i < MAX_STEP_CHG_ENTRIES; i++)
|
||||
pr_info("dynamic-fv-cfg: %d(count) ~ %d(count), %duV\n",
|
||||
chip->dynamic_fv_config->fv_cfg[i].low_threshold,
|
||||
chip->dynamic_fv_config->fv_cfg[i].high_threshold,
|
||||
chip->dynamic_fv_config->fv_cfg[i].value);
|
||||
return;
|
||||
|
||||
reschedule:
|
||||
@@ -417,6 +445,14 @@ static int get_val(struct range_data *range, int hysteresis, int current_index,
|
||||
|
||||
*new_index = -EINVAL;
|
||||
|
||||
/*
|
||||
* As battery temperature may be below 0, range.xxx is a unsigned int, but battery
|
||||
* temperature is a signed int, so cannot compare them when battery temp is below 0,
|
||||
* we treat it as 0 degree when the parameter threshold(battery temp) is below 0.
|
||||
*/
|
||||
if (threshold < 0)
|
||||
threshold = 0;
|
||||
|
||||
/*
|
||||
* If the threshold is lesser than the minimum allowed range,
|
||||
* return -ENODATA.
|
||||
@@ -456,6 +492,14 @@ static int get_val(struct range_data *range, int hysteresis, int current_index,
|
||||
*val = range[*new_index].value;
|
||||
}
|
||||
|
||||
if (threshold < range[0].low_threshold) {
|
||||
*new_index = 0;
|
||||
*val = range[*new_index].value;
|
||||
} else if (threshold > range[MAX_STEP_CHG_ENTRIES - 1].low_threshold) {
|
||||
*new_index = MAX_STEP_CHG_ENTRIES - 1;
|
||||
*val = range[*new_index].value;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we don't have a current_index return this
|
||||
* newfound value. There is no hysterisis from out of range
|
||||
@@ -614,7 +658,86 @@ update_time:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define JEITA_SUSPEND_HYST_UV 50000
|
||||
static int handle_dynamic_fv(struct step_chg_info *chip)
|
||||
{
|
||||
union power_supply_propval pval = {0, };
|
||||
int rc = 0, fv_uv, cycle_count;
|
||||
u64 elapsed_us;
|
||||
int batt_vol = 0;
|
||||
|
||||
rc = power_supply_get_property(chip->batt_psy,
|
||||
POWER_SUPPLY_PROP_DYNAMIC_FV_ENABLED, &pval);
|
||||
if (rc < 0)
|
||||
chip->dynamic_fv_enable = 0;
|
||||
else
|
||||
chip->dynamic_fv_enable = pval.intval;
|
||||
|
||||
if (!chip->dynamic_fv_enable || !chip->dynamic_fv_cfg_valid) {
|
||||
/*need recovery some setting*/
|
||||
if (chip->fv_votable)
|
||||
vote(chip->fv_votable, DYNAMIC_FV_VOTER, false, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
elapsed_us = ktime_us_delta(ktime_get(), chip->dynamic_fv_last_update_time);
|
||||
/* skip processing, event too early */
|
||||
if (elapsed_us < STEP_CHG_HYSTERISIS_DELAY_US)
|
||||
return 0;
|
||||
|
||||
rc = power_supply_get_property(chip->bms_psy,
|
||||
POWER_SUPPLY_PROP_CYCLE_COUNT, &pval);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't read %s property rc=%d\n",
|
||||
chip->dynamic_fv_config->prop_name, rc);
|
||||
return rc;
|
||||
}
|
||||
cycle_count = pval.intval;
|
||||
|
||||
rc = get_val(chip->dynamic_fv_config->fv_cfg,
|
||||
0,
|
||||
chip->dynamic_fv_index,
|
||||
cycle_count,
|
||||
&chip->dynamic_fv_index,
|
||||
&fv_uv);
|
||||
if (rc < 0) {
|
||||
/* remove the vote if no step-based fv is found */
|
||||
if (chip->fv_votable)
|
||||
vote(chip->fv_votable, DYNAMIC_FV_VOTER, false, 0);
|
||||
goto update_time;
|
||||
}
|
||||
|
||||
power_supply_get_property(chip->batt_psy,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW, &pval);
|
||||
batt_vol = pval.intval;
|
||||
if (batt_vol >= fv_uv) {
|
||||
goto update_time;
|
||||
}
|
||||
|
||||
chip->fv_votable = find_votable("FV");
|
||||
if (!chip->fv_votable)
|
||||
goto update_time;
|
||||
|
||||
vote(chip->fv_votable, DYNAMIC_FV_VOTER, true, fv_uv);
|
||||
|
||||
/*set battery full voltage to FLOAT VOLTAGE - 10mV*/
|
||||
pval.intval = fv_uv - 10000;
|
||||
rc = power_supply_set_property(chip->bms_psy,
|
||||
POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, &pval);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't set CONSTANT VOLTAGE property rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pr_debug("%s:cycle_count:%d,Batt_full:%d,fv:%d,\n",
|
||||
__func__, cycle_count, pval.intval, fv_uv);
|
||||
|
||||
update_time:
|
||||
chip->dynamic_fv_last_update_time = ktime_get();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set JEITA_SUSPEND_HYST_UV to 70mV to avoid recharge frequently when jeita warm */
|
||||
#define JEITA_SUSPEND_HYST_UV 70000
|
||||
static int handle_jeita(struct step_chg_info *chip)
|
||||
{
|
||||
union power_supply_propval pval = {0, };
|
||||
@@ -635,6 +758,8 @@ static int handle_jeita(struct step_chg_info *chip)
|
||||
vote(chip->fv_votable, JEITA_VOTER, false, 0);
|
||||
if (chip->usb_icl_votable)
|
||||
vote(chip->usb_icl_votable, JEITA_VOTER, false, 0);
|
||||
if (chip->dc_suspend_votable)
|
||||
vote(chip->dc_suspend_votable, JEITA_VOTER, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -692,6 +817,12 @@ static int handle_jeita(struct step_chg_info *chip)
|
||||
if (!chip->usb_icl_votable)
|
||||
goto set_jeita_fv;
|
||||
|
||||
if (!chip->dc_suspend_votable)
|
||||
chip->dc_suspend_votable = find_votable("DC_SUSPEND");
|
||||
|
||||
if (!chip->dc_suspend_votable)
|
||||
goto set_jeita_fv;
|
||||
|
||||
/*
|
||||
* If JEITA float voltage is same as max-vfloat of battery then
|
||||
* skip any further VBAT specific checks.
|
||||
@@ -700,20 +831,27 @@ static int handle_jeita(struct step_chg_info *chip)
|
||||
POWER_SUPPLY_PROP_VOLTAGE_MAX, &pval);
|
||||
if (rc || (pval.intval == fv_uv)) {
|
||||
vote(chip->usb_icl_votable, JEITA_VOTER, false, 0);
|
||||
vote(chip->dc_suspend_votable, JEITA_VOTER, 0, 0);
|
||||
goto set_jeita_fv;
|
||||
}
|
||||
|
||||
pr_info("%s = %d FCC = %duA FV = %duV\n",
|
||||
chip->jeita_fcc_config->param.prop_name, pval.intval, fcc_ua, fv_uv);
|
||||
/*
|
||||
* Suspend USB input path if battery voltage is above
|
||||
* JEITA VFLOAT threshold.
|
||||
*/
|
||||
if (chip->jeita_arb_en && fv_uv > 0) {
|
||||
/* if (chip->jeita_arb_en && fv_uv > 0) { */
|
||||
if (fv_uv > 0) {
|
||||
rc = power_supply_get_property(chip->batt_psy,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW, &pval);
|
||||
if (!rc && (pval.intval > fv_uv))
|
||||
if (!rc && (pval.intval > fv_uv)) {
|
||||
vote(chip->usb_icl_votable, JEITA_VOTER, true, 0);
|
||||
else if (pval.intval < (fv_uv - JEITA_SUSPEND_HYST_UV))
|
||||
vote(chip->dc_suspend_votable, JEITA_VOTER, 1, 0);
|
||||
} else if (pval.intval < (fv_uv - JEITA_SUSPEND_HYST_UV)) {
|
||||
vote(chip->usb_icl_votable, JEITA_VOTER, false, 0);
|
||||
vote(chip->dc_suspend_votable, JEITA_VOTER, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
set_jeita_fv:
|
||||
@@ -744,6 +882,7 @@ static int handle_battery_insertion(struct step_chg_info *chip)
|
||||
if (chip->batt_missing) {
|
||||
chip->step_chg_cfg_valid = false;
|
||||
chip->sw_jeita_cfg_valid = false;
|
||||
chip->dynamic_fv_cfg_valid = false;
|
||||
chip->get_config_retry_count = 0;
|
||||
} else {
|
||||
/*
|
||||
@@ -775,6 +914,10 @@ static void status_change_work(struct work_struct *work)
|
||||
if (rc < 0)
|
||||
pr_err("Couldn't handle sw jeita rc = %d\n", rc);
|
||||
|
||||
rc = handle_dynamic_fv(chip);
|
||||
if (rc < 0)
|
||||
pr_err("Couldn't handle sw dynamic fv rc = %d\n", rc);
|
||||
|
||||
rc = handle_step_chg_config(chip);
|
||||
if (rc < 0)
|
||||
pr_err("Couldn't handle step rc = %d\n", rc);
|
||||
@@ -860,6 +1003,7 @@ int qcom_step_chg_init(struct device *dev,
|
||||
chip->step_index = -EINVAL;
|
||||
chip->jeita_fcc_index = -EINVAL;
|
||||
chip->jeita_fv_index = -EINVAL;
|
||||
chip->dynamic_fv_index = -EINVAL;
|
||||
|
||||
chip->step_chg_config = devm_kzalloc(dev,
|
||||
sizeof(struct step_chg_cfg), GFP_KERNEL);
|
||||
@@ -874,16 +1018,18 @@ int qcom_step_chg_init(struct device *dev,
|
||||
sizeof(struct jeita_fcc_cfg), GFP_KERNEL);
|
||||
chip->jeita_fv_config = devm_kzalloc(dev,
|
||||
sizeof(struct jeita_fv_cfg), GFP_KERNEL);
|
||||
if (!chip->jeita_fcc_config || !chip->jeita_fv_config)
|
||||
chip->dynamic_fv_config = devm_kzalloc(dev,
|
||||
sizeof(struct dynamic_fv_cfg), GFP_KERNEL);
|
||||
if (!chip->jeita_fcc_config || !chip->jeita_fv_config || !chip->dynamic_fv_config)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->jeita_fcc_config->param.psy_prop = POWER_SUPPLY_PROP_TEMP;
|
||||
chip->jeita_fcc_config->param.prop_name = "BATT_TEMP";
|
||||
chip->jeita_fcc_config->param.hysteresis = 10;
|
||||
chip->jeita_fcc_config->param.hysteresis = 5;
|
||||
chip->jeita_fv_config->param.psy_prop = POWER_SUPPLY_PROP_TEMP;
|
||||
chip->jeita_fv_config->param.prop_name = "BATT_TEMP";
|
||||
chip->jeita_fv_config->param.hysteresis = 10;
|
||||
|
||||
chip->jeita_fv_config->param.hysteresis = 5;
|
||||
chip->dynamic_fv_config->prop_name = "BATT_CYCLE_COUNT";
|
||||
INIT_DELAYED_WORK(&chip->status_change_work, status_change_work);
|
||||
INIT_DELAYED_WORK(&chip->get_config_work, get_config_work);
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (C) 2019 XiaoMi, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -13,7 +14,7 @@
|
||||
#ifndef __STEP_CHG_H__
|
||||
#define __STEP_CHG_H__
|
||||
|
||||
#define MAX_STEP_CHG_ENTRIES 8
|
||||
#define MAX_STEP_CHG_ENTRIES 5
|
||||
|
||||
struct step_chg_jeita_param {
|
||||
u32 psy_prop;
|
||||
|
||||
1550
drivers/power/supply/rx1618.c
Normal file
1550
drivers/power/supply/rx1618.c
Normal file
File diff suppressed because it is too large
Load Diff
31
drivers/power/supply/rx1618.h
Normal file
31
drivers/power/supply/rx1618.h
Normal file
File diff suppressed because one or more lines are too long
@@ -231,6 +231,8 @@ enum power_supply_property {
|
||||
POWER_SUPPLY_PROP_CHARGE_ENABLED,
|
||||
POWER_SUPPLY_PROP_SET_SHIP_MODE,
|
||||
POWER_SUPPLY_PROP_REAL_TYPE,
|
||||
POWER_SUPPLY_PROP_HVDCP3_TYPE,
|
||||
POWER_SUPPLY_PROP_QUICK_CHARGE_TYPE,
|
||||
POWER_SUPPLY_PROP_CHARGE_NOW_RAW,
|
||||
POWER_SUPPLY_PROP_CHARGE_NOW_ERROR,
|
||||
POWER_SUPPLY_PROP_CAPACITY_RAW,
|
||||
@@ -285,6 +287,7 @@ enum power_supply_property {
|
||||
POWER_SUPPLY_PROP_TYPEC_SRC_RP,
|
||||
POWER_SUPPLY_PROP_PD_ALLOWED,
|
||||
POWER_SUPPLY_PROP_PD_ACTIVE,
|
||||
POWER_SUPPLY_PROP_PD_AUTHENTICATION,
|
||||
POWER_SUPPLY_PROP_PD_IN_HARD_RESET,
|
||||
POWER_SUPPLY_PROP_PD_CURRENT_MAX,
|
||||
POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED,
|
||||
@@ -308,9 +311,16 @@ enum power_supply_property {
|
||||
POWER_SUPPLY_PROP_PD_VOLTAGE_MAX,
|
||||
POWER_SUPPLY_PROP_PD_VOLTAGE_MIN,
|
||||
POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
|
||||
POWER_SUPPLY_PROP_DC_THERMAL_LEVELS,
|
||||
POWER_SUPPLY_PROP_CONNECTOR_TYPE,
|
||||
POWER_SUPPLY_PROP_PARALLEL_BATFET_MODE,
|
||||
POWER_SUPPLY_PROP_PARALLEL_FCC_MAX,
|
||||
POWER_SUPPLY_PROP_WIRELESS_VERSION,
|
||||
POWER_SUPPLY_PROP_SIGNAL_STRENGTH,
|
||||
POWER_SUPPLY_PROP_WIRELESS_CP_EN,
|
||||
POWER_SUPPLY_PROP_WIRELESS_POWER_GOOD_EN,
|
||||
POWER_SUPPLY_PROP_WIRELESS_WAKELOCK,
|
||||
POWER_SUPPLY_PROP_TX_ADAPTER,
|
||||
POWER_SUPPLY_PROP_MIN_ICL,
|
||||
POWER_SUPPLY_PROP_MOISTURE_DETECTED,
|
||||
POWER_SUPPLY_PROP_BATT_PROFILE_VERSION,
|
||||
@@ -326,6 +336,9 @@ enum power_supply_property {
|
||||
POWER_SUPPLY_PROP_FORCE_RECHARGE,
|
||||
POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE,
|
||||
POWER_SUPPLY_PROP_TOGGLE_STAT,
|
||||
POWER_SUPPLY_PROP_TYPE_RECHECK,
|
||||
POWER_SUPPLY_PROP_LIQUID_DETECTION,
|
||||
POWER_SUPPLY_PROP_DYNAMIC_FV_ENABLED,
|
||||
POWER_SUPPLY_PROP_MAIN_FCC_MAX,
|
||||
POWER_SUPPLY_PROP_FG_RESET,
|
||||
POWER_SUPPLY_PROP_QC_OPTI_DISABLE,
|
||||
@@ -394,6 +407,7 @@ enum power_supply_type {
|
||||
POWER_SUPPLY_TYPE_UFP, /* Type-C UFP */
|
||||
POWER_SUPPLY_TYPE_DFP, /* Type-C DFP */
|
||||
POWER_SUPPLY_TYPE_CHARGE_PUMP, /* Charge Pump */
|
||||
POWER_SUPPLY_TYPE_ZIMI_CAR_POWER, /* Zimi Car chargr */
|
||||
};
|
||||
|
||||
/* Indicates USB Type-C CC connection status */
|
||||
|
||||
Reference in New Issue
Block a user