Loading Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt +6 −0 Original line number Diff line number Diff line Loading @@ -458,6 +458,12 @@ First Level Node - FG Gen3 device Value type: <u32> Definition: The delay in ms for FG to enable BMD after reading RID. - qcom,fg-use-sw-esr Usage: optional Value type: <empty> Definition: A boolean property when defined uses software based ESR during charging. ========================================================== Second Level Nodes - Peripherals managed by FG Gen3 driver ========================================================== Loading drivers/power/supply/qcom/fg-core.h +17 −0 Original line number Diff line number Diff line Loading @@ -24,9 +24,11 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/alarmtimer.h> #include <linux/power_supply.h> #include <linux/regmap.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/string_helpers.h> #include <linux/types.h> #include <linux/uaccess.h> Loading @@ -51,6 +53,7 @@ #define SRAM_WRITE "fg_sram_write" #define PROFILE_LOAD "fg_profile_load" #define TTF_PRIMING "fg_ttf_priming" #define FG_ESR_VOTER "fg_esr_voter" /* Delta BSOC irq votable reasons */ #define DELTA_BSOC_IRQ_VOTER "fg_delta_bsoc_irq" Loading Loading @@ -107,6 +110,11 @@ enum fg_debug_flag { FG_TTF = BIT(8), /* Show time to full */ }; enum awake_reasons { FG_SW_ESR_WAKE = BIT(0), FG_STATUS_NOTIFY_WAKE = BIT(1), }; /* SRAM access */ enum sram_access_flags { FG_IMA_DEFAULT = 0, Loading Loading @@ -273,6 +281,7 @@ struct fg_dt_props { bool hold_soc_while_full; bool linearize_soc; bool auto_recharge_soc; bool use_esr_sw; int cutoff_volt_mv; int empty_volt_mv; int vbatt_low_thr_mv; Loading Loading @@ -440,17 +449,21 @@ struct fg_chip { struct fg_cyc_ctr_data cyc_ctr; struct notifier_block nb; struct fg_cap_learning cl; struct alarm esr_sw_timer; struct ttf ttf; struct mutex bus_lock; struct mutex sram_rw_lock; struct mutex charge_full_lock; struct mutex qnovo_esr_ctrl_lock; spinlock_t awake_lock; spinlock_t suspend_lock; u32 batt_soc_base; u32 batt_info_base; u32 mem_if_base; u32 rradc_base; u32 wa_flags; u32 esr_wakeup_ms; u32 awake_status; int batt_id_ohms; int ki_coeff_full_soc; int charge_status; Loading Loading @@ -482,6 +495,7 @@ struct fg_chip { bool esr_flt_cold_temp_en; bool slope_limit_en; bool use_ima_single_mode; bool usb_present; bool use_dma; bool qnovo_enable; bool suspended; Loading @@ -489,6 +503,7 @@ struct fg_chip { struct completion soc_ready; struct delayed_work profile_load_work; struct work_struct status_change_work; struct work_struct esr_sw_work; struct delayed_work ttf_work; struct delayed_work sram_dump_work; struct delayed_work pl_enable_work; Loading Loading @@ -561,4 +576,6 @@ extern int fg_circ_buf_avg(struct fg_circ_buf *buf, int *avg); extern int fg_circ_buf_median(struct fg_circ_buf *buf, int *median); extern int fg_lerp(const struct fg_pt *pts, size_t tablesize, s32 input, s32 *output); void fg_stay_awake(struct fg_chip *chip, int awake_reason); void fg_relax(struct fg_chip *chip, int awake_reason); #endif drivers/power/supply/qcom/fg-util.c +25 −1 Original line number Diff line number Diff line /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * 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 Loading Loading @@ -999,3 +999,27 @@ int fg_debugfs_create(struct fg_chip *chip) debugfs_remove_recursive(chip->dfs_root); return -ENOMEM; } void fg_stay_awake(struct fg_chip *chip, int awake_reason) { spin_lock(&chip->awake_lock); if (!chip->awake_status) pm_stay_awake(chip->dev); chip->awake_status |= awake_reason; spin_unlock(&chip->awake_lock); } void fg_relax(struct fg_chip *chip, int awake_reason) { spin_lock(&chip->awake_lock); chip->awake_status &= ~awake_reason; if (!chip->awake_status) pm_relax(chip->dev); spin_unlock(&chip->awake_lock); } drivers/power/supply/qcom/qpnp-fg-gen3.c +178 −3 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ #include <linux/ktime.h> #include <linux/of.h> #include <linux/of_irq.h> #include <linux/spinlock.h> #include <linux/alarmtimer.h> #include <linux/of_platform.h> #include <linux/of_batterydata.h> #include <linux/platform_device.h> Loading Loading @@ -2762,6 +2764,142 @@ static const char *fg_get_cycle_count(struct fg_chip *chip) return buf; } #define ESR_SW_FCC_UA 100000 /* 100mA */ #define ESR_EXTRACTION_ENABLE_MASK BIT(0) static void fg_esr_sw_work(struct work_struct *work) { struct fg_chip *chip = container_of(work, struct fg_chip, esr_sw_work); union power_supply_propval pval = {0, }; int rc, esr_uohms = 0; vote(chip->awake_votable, FG_ESR_VOTER, true, 0); /* * Enable ESR extraction just before we reduce the FCC * to make sure that FG extracts the ESR. Disable ESR * extraction after FCC reduction is complete to prevent * any further HW pulses. */ rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD, ESR_EXTRACTION_ENABLE_OFFSET, ESR_EXTRACTION_ENABLE_MASK, 0x1, FG_IMA_DEFAULT); if (rc < 0) { pr_err("Failed to enable ESR extraction rc=%d\n", rc); goto done; } /* delay for 1 FG cycle to complete */ msleep(1500); /* for FCC to 100mA */ pval.intval = ESR_SW_FCC_UA; rc = power_supply_set_property(chip->batt_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, &pval); if (rc < 0) { pr_err("Failed to set FCC to 100mA rc=%d\n", rc); goto done; } /* delay for ESR readings */ msleep(3000); /* FCC to 0 (removes vote) */ pval.intval = 0; rc = power_supply_set_property(chip->batt_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, &pval); if (rc < 0) { pr_err("Failed to remove FCC vote rc=%d\n", rc); goto done; } fg_get_sram_prop(chip, FG_SRAM_ESR, &esr_uohms); fg_dbg(chip, FG_STATUS, "SW ESR done ESR=%d\n", esr_uohms); /* restart the alarm timer */ alarm_start_relative(&chip->esr_sw_timer, ms_to_ktime(chip->esr_wakeup_ms)); done: rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD, ESR_EXTRACTION_ENABLE_OFFSET, ESR_EXTRACTION_ENABLE_MASK, 0x0, FG_IMA_DEFAULT); if (rc < 0) pr_err("Failed to disable ESR extraction rc=%d\n", rc); vote(chip->awake_votable, FG_ESR_VOTER, false, 0); fg_relax(chip, FG_SW_ESR_WAKE); } static enum alarmtimer_restart fg_esr_sw_timer(struct alarm *alarm, ktime_t now) { struct fg_chip *chip = container_of(alarm, struct fg_chip, esr_sw_timer); if (!chip->usb_present) return ALARMTIMER_NORESTART; fg_stay_awake(chip, FG_SW_ESR_WAKE); schedule_work(&chip->esr_sw_work); return ALARMTIMER_NORESTART; } static int fg_config_esr_sw(struct fg_chip *chip) { int rc; union power_supply_propval prop = {0, }; if (!chip->dt.use_esr_sw) return 0; if (!usb_psy_initialized(chip)) return 0; rc = power_supply_get_property(chip->usb_psy, POWER_SUPPLY_PROP_PRESENT, &prop); if (rc < 0) { pr_err("Error in reading usb-status rc = %d\n", rc); return rc; } if (chip->usb_present != prop.intval) { chip->usb_present = prop.intval; fg_dbg(chip, FG_STATUS, "USB status changed=%d\n", chip->usb_present); /* cancel any pending work */ alarm_cancel(&chip->esr_sw_timer); cancel_work_sync(&chip->esr_sw_work); if (chip->usb_present) { /* disable ESR extraction across the charging cycle */ rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD, ESR_EXTRACTION_ENABLE_OFFSET, ESR_EXTRACTION_ENABLE_MASK, 0x0, FG_IMA_DEFAULT); if (rc < 0) return rc; /* wake up early for the first ESR on insertion */ alarm_start_relative(&chip->esr_sw_timer, ms_to_ktime(chip->esr_wakeup_ms / 2)); } else { /* enable ESR extraction on removal */ rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD, ESR_EXTRACTION_ENABLE_OFFSET, ESR_EXTRACTION_ENABLE_MASK, 0x1, FG_IMA_DEFAULT); if (rc < 0) return rc; } } return 0; } static void status_change_work(struct work_struct *work) { struct fg_chip *chip = container_of(work, Loading @@ -2779,6 +2917,10 @@ static void status_change_work(struct work_struct *work) goto out; } rc = fg_config_esr_sw(chip); if (rc < 0) pr_err("Failed to config SW ESR rc=%d\n", rc); rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_STATUS, &prop); if (rc < 0) { Loading Loading @@ -2844,7 +2986,7 @@ static void status_change_work(struct work_struct *work) out: fg_dbg(chip, FG_STATUS, "charge_status:%d charge_type:%d charge_done:%d\n", chip->charge_status, chip->charge_type, chip->charge_done); pm_relax(chip->dev); fg_relax(chip, FG_STATUS_NOTIFY_WAKE); } static int fg_bp_params_config(struct fg_chip *chip) Loading Loading @@ -3165,7 +3307,7 @@ static void profile_load_work(struct work_struct *work) schedule_delayed_work(&chip->pl_enable_work, msecs_to_jiffies(5000)); vote(chip->awake_votable, PROFILE_LOAD, false, 0); if (!work_pending(&chip->status_change_work)) { pm_stay_awake(chip->dev); fg_stay_awake(chip, FG_STATUS_NOTIFY_WAKE); schedule_work(&chip->status_change_work); } } Loading Loading @@ -4083,7 +4225,7 @@ static int fg_notifier_cb(struct notifier_block *nb, * We cannot vote for awake votable here as that takes * a mutex lock and this is executed in an atomic context. */ pm_stay_awake(chip->dev); fg_stay_awake(chip, FG_STATUS_NOTIFY_WAKE); schedule_work(&chip->status_change_work); } Loading Loading @@ -4421,6 +4563,18 @@ static int fg_hw_init(struct fg_chip *chip) } } if (chip->dt.use_esr_sw) { /* Enable ESR extraction explicitly */ rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD, ESR_EXTRACTION_ENABLE_OFFSET, ESR_EXTRACTION_ENABLE_MASK, 0x1, FG_IMA_DEFAULT); if (rc < 0) { pr_err("Error in enabling ESR extraction rc=%d\n", rc); return rc; } } return 0; } Loading Loading @@ -5358,6 +5512,8 @@ static int fg_parse_dt(struct fg_chip *chip) chip->dt.bmd_en_delay_ms = temp; } chip->dt.use_esr_sw = of_property_read_bool(node, "qcom,fg-use-sw-esr"); return 0; } Loading Loading @@ -5506,12 +5662,14 @@ static int fg_gen3_probe(struct platform_device *pdev) mutex_init(&chip->ttf.lock); mutex_init(&chip->charge_full_lock); mutex_init(&chip->qnovo_esr_ctrl_lock); spin_lock_init(&chip->awake_lock); spin_lock_init(&chip->suspend_lock); init_completion(&chip->soc_update); init_completion(&chip->soc_ready); INIT_DELAYED_WORK(&chip->profile_load_work, profile_load_work); INIT_DELAYED_WORK(&chip->pl_enable_work, pl_enable_work); INIT_WORK(&chip->status_change_work, status_change_work); INIT_WORK(&chip->esr_sw_work, fg_esr_sw_work); INIT_DELAYED_WORK(&chip->ttf_work, ttf_work); INIT_DELAYED_WORK(&chip->sram_dump_work, sram_dump_work); INIT_WORK(&chip->esr_filter_work, esr_filter_work); Loading @@ -5534,6 +5692,23 @@ static int fg_gen3_probe(struct platform_device *pdev) goto exit; } if (chip->dt.use_esr_sw) { if (alarmtimer_get_rtcdev()) { alarm_init(&chip->esr_sw_timer, ALARM_BOOTTIME, fg_esr_sw_timer); } else { pr_err("Failed to get esw_sw alarm-timer\n"); /* RTC always registers, hence defer until it passes */ rc = -EPROBE_DEFER; goto exit; } if (chip->dt.esr_timer_charging[TIMER_MAX] != -EINVAL) chip->esr_wakeup_ms = chip->dt.esr_timer_charging[TIMER_MAX] * 1460; else chip->esr_wakeup_ms = 140000; /* 140 seconds */ } /* Register the power supply */ fg_psy_cfg.drv_data = chip; fg_psy_cfg.of_node = NULL; Loading Loading
Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt +6 −0 Original line number Diff line number Diff line Loading @@ -458,6 +458,12 @@ First Level Node - FG Gen3 device Value type: <u32> Definition: The delay in ms for FG to enable BMD after reading RID. - qcom,fg-use-sw-esr Usage: optional Value type: <empty> Definition: A boolean property when defined uses software based ESR during charging. ========================================================== Second Level Nodes - Peripherals managed by FG Gen3 driver ========================================================== Loading
drivers/power/supply/qcom/fg-core.h +17 −0 Original line number Diff line number Diff line Loading @@ -24,9 +24,11 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/alarmtimer.h> #include <linux/power_supply.h> #include <linux/regmap.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/string_helpers.h> #include <linux/types.h> #include <linux/uaccess.h> Loading @@ -51,6 +53,7 @@ #define SRAM_WRITE "fg_sram_write" #define PROFILE_LOAD "fg_profile_load" #define TTF_PRIMING "fg_ttf_priming" #define FG_ESR_VOTER "fg_esr_voter" /* Delta BSOC irq votable reasons */ #define DELTA_BSOC_IRQ_VOTER "fg_delta_bsoc_irq" Loading Loading @@ -107,6 +110,11 @@ enum fg_debug_flag { FG_TTF = BIT(8), /* Show time to full */ }; enum awake_reasons { FG_SW_ESR_WAKE = BIT(0), FG_STATUS_NOTIFY_WAKE = BIT(1), }; /* SRAM access */ enum sram_access_flags { FG_IMA_DEFAULT = 0, Loading Loading @@ -273,6 +281,7 @@ struct fg_dt_props { bool hold_soc_while_full; bool linearize_soc; bool auto_recharge_soc; bool use_esr_sw; int cutoff_volt_mv; int empty_volt_mv; int vbatt_low_thr_mv; Loading Loading @@ -440,17 +449,21 @@ struct fg_chip { struct fg_cyc_ctr_data cyc_ctr; struct notifier_block nb; struct fg_cap_learning cl; struct alarm esr_sw_timer; struct ttf ttf; struct mutex bus_lock; struct mutex sram_rw_lock; struct mutex charge_full_lock; struct mutex qnovo_esr_ctrl_lock; spinlock_t awake_lock; spinlock_t suspend_lock; u32 batt_soc_base; u32 batt_info_base; u32 mem_if_base; u32 rradc_base; u32 wa_flags; u32 esr_wakeup_ms; u32 awake_status; int batt_id_ohms; int ki_coeff_full_soc; int charge_status; Loading Loading @@ -482,6 +495,7 @@ struct fg_chip { bool esr_flt_cold_temp_en; bool slope_limit_en; bool use_ima_single_mode; bool usb_present; bool use_dma; bool qnovo_enable; bool suspended; Loading @@ -489,6 +503,7 @@ struct fg_chip { struct completion soc_ready; struct delayed_work profile_load_work; struct work_struct status_change_work; struct work_struct esr_sw_work; struct delayed_work ttf_work; struct delayed_work sram_dump_work; struct delayed_work pl_enable_work; Loading Loading @@ -561,4 +576,6 @@ extern int fg_circ_buf_avg(struct fg_circ_buf *buf, int *avg); extern int fg_circ_buf_median(struct fg_circ_buf *buf, int *median); extern int fg_lerp(const struct fg_pt *pts, size_t tablesize, s32 input, s32 *output); void fg_stay_awake(struct fg_chip *chip, int awake_reason); void fg_relax(struct fg_chip *chip, int awake_reason); #endif
drivers/power/supply/qcom/fg-util.c +25 −1 Original line number Diff line number Diff line /* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * 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 Loading Loading @@ -999,3 +999,27 @@ int fg_debugfs_create(struct fg_chip *chip) debugfs_remove_recursive(chip->dfs_root); return -ENOMEM; } void fg_stay_awake(struct fg_chip *chip, int awake_reason) { spin_lock(&chip->awake_lock); if (!chip->awake_status) pm_stay_awake(chip->dev); chip->awake_status |= awake_reason; spin_unlock(&chip->awake_lock); } void fg_relax(struct fg_chip *chip, int awake_reason) { spin_lock(&chip->awake_lock); chip->awake_status &= ~awake_reason; if (!chip->awake_status) pm_relax(chip->dev); spin_unlock(&chip->awake_lock); }
drivers/power/supply/qcom/qpnp-fg-gen3.c +178 −3 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ #include <linux/ktime.h> #include <linux/of.h> #include <linux/of_irq.h> #include <linux/spinlock.h> #include <linux/alarmtimer.h> #include <linux/of_platform.h> #include <linux/of_batterydata.h> #include <linux/platform_device.h> Loading Loading @@ -2762,6 +2764,142 @@ static const char *fg_get_cycle_count(struct fg_chip *chip) return buf; } #define ESR_SW_FCC_UA 100000 /* 100mA */ #define ESR_EXTRACTION_ENABLE_MASK BIT(0) static void fg_esr_sw_work(struct work_struct *work) { struct fg_chip *chip = container_of(work, struct fg_chip, esr_sw_work); union power_supply_propval pval = {0, }; int rc, esr_uohms = 0; vote(chip->awake_votable, FG_ESR_VOTER, true, 0); /* * Enable ESR extraction just before we reduce the FCC * to make sure that FG extracts the ESR. Disable ESR * extraction after FCC reduction is complete to prevent * any further HW pulses. */ rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD, ESR_EXTRACTION_ENABLE_OFFSET, ESR_EXTRACTION_ENABLE_MASK, 0x1, FG_IMA_DEFAULT); if (rc < 0) { pr_err("Failed to enable ESR extraction rc=%d\n", rc); goto done; } /* delay for 1 FG cycle to complete */ msleep(1500); /* for FCC to 100mA */ pval.intval = ESR_SW_FCC_UA; rc = power_supply_set_property(chip->batt_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, &pval); if (rc < 0) { pr_err("Failed to set FCC to 100mA rc=%d\n", rc); goto done; } /* delay for ESR readings */ msleep(3000); /* FCC to 0 (removes vote) */ pval.intval = 0; rc = power_supply_set_property(chip->batt_psy, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, &pval); if (rc < 0) { pr_err("Failed to remove FCC vote rc=%d\n", rc); goto done; } fg_get_sram_prop(chip, FG_SRAM_ESR, &esr_uohms); fg_dbg(chip, FG_STATUS, "SW ESR done ESR=%d\n", esr_uohms); /* restart the alarm timer */ alarm_start_relative(&chip->esr_sw_timer, ms_to_ktime(chip->esr_wakeup_ms)); done: rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD, ESR_EXTRACTION_ENABLE_OFFSET, ESR_EXTRACTION_ENABLE_MASK, 0x0, FG_IMA_DEFAULT); if (rc < 0) pr_err("Failed to disable ESR extraction rc=%d\n", rc); vote(chip->awake_votable, FG_ESR_VOTER, false, 0); fg_relax(chip, FG_SW_ESR_WAKE); } static enum alarmtimer_restart fg_esr_sw_timer(struct alarm *alarm, ktime_t now) { struct fg_chip *chip = container_of(alarm, struct fg_chip, esr_sw_timer); if (!chip->usb_present) return ALARMTIMER_NORESTART; fg_stay_awake(chip, FG_SW_ESR_WAKE); schedule_work(&chip->esr_sw_work); return ALARMTIMER_NORESTART; } static int fg_config_esr_sw(struct fg_chip *chip) { int rc; union power_supply_propval prop = {0, }; if (!chip->dt.use_esr_sw) return 0; if (!usb_psy_initialized(chip)) return 0; rc = power_supply_get_property(chip->usb_psy, POWER_SUPPLY_PROP_PRESENT, &prop); if (rc < 0) { pr_err("Error in reading usb-status rc = %d\n", rc); return rc; } if (chip->usb_present != prop.intval) { chip->usb_present = prop.intval; fg_dbg(chip, FG_STATUS, "USB status changed=%d\n", chip->usb_present); /* cancel any pending work */ alarm_cancel(&chip->esr_sw_timer); cancel_work_sync(&chip->esr_sw_work); if (chip->usb_present) { /* disable ESR extraction across the charging cycle */ rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD, ESR_EXTRACTION_ENABLE_OFFSET, ESR_EXTRACTION_ENABLE_MASK, 0x0, FG_IMA_DEFAULT); if (rc < 0) return rc; /* wake up early for the first ESR on insertion */ alarm_start_relative(&chip->esr_sw_timer, ms_to_ktime(chip->esr_wakeup_ms / 2)); } else { /* enable ESR extraction on removal */ rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD, ESR_EXTRACTION_ENABLE_OFFSET, ESR_EXTRACTION_ENABLE_MASK, 0x1, FG_IMA_DEFAULT); if (rc < 0) return rc; } } return 0; } static void status_change_work(struct work_struct *work) { struct fg_chip *chip = container_of(work, Loading @@ -2779,6 +2917,10 @@ static void status_change_work(struct work_struct *work) goto out; } rc = fg_config_esr_sw(chip); if (rc < 0) pr_err("Failed to config SW ESR rc=%d\n", rc); rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_STATUS, &prop); if (rc < 0) { Loading Loading @@ -2844,7 +2986,7 @@ static void status_change_work(struct work_struct *work) out: fg_dbg(chip, FG_STATUS, "charge_status:%d charge_type:%d charge_done:%d\n", chip->charge_status, chip->charge_type, chip->charge_done); pm_relax(chip->dev); fg_relax(chip, FG_STATUS_NOTIFY_WAKE); } static int fg_bp_params_config(struct fg_chip *chip) Loading Loading @@ -3165,7 +3307,7 @@ static void profile_load_work(struct work_struct *work) schedule_delayed_work(&chip->pl_enable_work, msecs_to_jiffies(5000)); vote(chip->awake_votable, PROFILE_LOAD, false, 0); if (!work_pending(&chip->status_change_work)) { pm_stay_awake(chip->dev); fg_stay_awake(chip, FG_STATUS_NOTIFY_WAKE); schedule_work(&chip->status_change_work); } } Loading Loading @@ -4083,7 +4225,7 @@ static int fg_notifier_cb(struct notifier_block *nb, * We cannot vote for awake votable here as that takes * a mutex lock and this is executed in an atomic context. */ pm_stay_awake(chip->dev); fg_stay_awake(chip, FG_STATUS_NOTIFY_WAKE); schedule_work(&chip->status_change_work); } Loading Loading @@ -4421,6 +4563,18 @@ static int fg_hw_init(struct fg_chip *chip) } } if (chip->dt.use_esr_sw) { /* Enable ESR extraction explicitly */ rc = fg_sram_masked_write(chip, ESR_EXTRACTION_ENABLE_WORD, ESR_EXTRACTION_ENABLE_OFFSET, ESR_EXTRACTION_ENABLE_MASK, 0x1, FG_IMA_DEFAULT); if (rc < 0) { pr_err("Error in enabling ESR extraction rc=%d\n", rc); return rc; } } return 0; } Loading Loading @@ -5358,6 +5512,8 @@ static int fg_parse_dt(struct fg_chip *chip) chip->dt.bmd_en_delay_ms = temp; } chip->dt.use_esr_sw = of_property_read_bool(node, "qcom,fg-use-sw-esr"); return 0; } Loading Loading @@ -5506,12 +5662,14 @@ static int fg_gen3_probe(struct platform_device *pdev) mutex_init(&chip->ttf.lock); mutex_init(&chip->charge_full_lock); mutex_init(&chip->qnovo_esr_ctrl_lock); spin_lock_init(&chip->awake_lock); spin_lock_init(&chip->suspend_lock); init_completion(&chip->soc_update); init_completion(&chip->soc_ready); INIT_DELAYED_WORK(&chip->profile_load_work, profile_load_work); INIT_DELAYED_WORK(&chip->pl_enable_work, pl_enable_work); INIT_WORK(&chip->status_change_work, status_change_work); INIT_WORK(&chip->esr_sw_work, fg_esr_sw_work); INIT_DELAYED_WORK(&chip->ttf_work, ttf_work); INIT_DELAYED_WORK(&chip->sram_dump_work, sram_dump_work); INIT_WORK(&chip->esr_filter_work, esr_filter_work); Loading @@ -5534,6 +5692,23 @@ static int fg_gen3_probe(struct platform_device *pdev) goto exit; } if (chip->dt.use_esr_sw) { if (alarmtimer_get_rtcdev()) { alarm_init(&chip->esr_sw_timer, ALARM_BOOTTIME, fg_esr_sw_timer); } else { pr_err("Failed to get esw_sw alarm-timer\n"); /* RTC always registers, hence defer until it passes */ rc = -EPROBE_DEFER; goto exit; } if (chip->dt.esr_timer_charging[TIMER_MAX] != -EINVAL) chip->esr_wakeup_ms = chip->dt.esr_timer_charging[TIMER_MAX] * 1460; else chip->esr_wakeup_ms = 140000; /* 140 seconds */ } /* Register the power supply */ fg_psy_cfg.drv_data = chip; fg_psy_cfg.of_node = NULL; Loading