From d0ce77308fc03efcc1b02ff26c8bbf5608f8e5f4 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Tue, 4 Apr 2017 16:10:35 -0700 Subject: [PATCH] qpnp-fg-gen3: Move getting battery id and profile to profile_load_work Workaround to re-enable BMD while getting battery id was required when driver is probing. This was done to mitigate driver probe failures because of failed SRAM access. Getting battery_id from RR_ADC driver itself takes ~200ms and re-enabling BMD takes 200ms which increases driver probe time. With the recent changes in reading batt_id channel from RR_ADC driver, re-enabling BMD is not required anymore when the driver probes. Hence move getting battery_id and battery profile to profile_load_work. This way, there won't be any delay when the driver probes. CRs-Fixed: 2062261 Change-Id: Ifeb361e0f82fca65f9570fd1f425c7360445d01f Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qcom/fg-core.h | 6 +- drivers/power/supply/qcom/qpnp-fg-gen3.c | 90 +++++++++++++++--------- 2 files changed, 63 insertions(+), 33 deletions(-) diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index 18736547d422..947108c1410e 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -51,9 +51,12 @@ #define PROFILE_LOAD "fg_profile_load" #define DELTA_SOC "fg_delta_soc" -/* Delta BSOC votable reasons */ +/* Delta BSOC irq votable reasons */ #define DELTA_BSOC_IRQ_VOTER "fg_delta_bsoc_irq" +/* Battery missing irq votable reasons */ +#define BATT_MISS_IRQ_VOTER "fg_batt_miss_irq" + #define DEBUG_PRINT_BUFFER_SIZE 64 /* 3 byte address + 1 space character */ #define ADDR_LEN 4 @@ -361,6 +364,7 @@ struct fg_chip { struct fg_irq_info *irqs; struct votable *awake_votable; struct votable *delta_bsoc_irq_en_votable; + struct votable *batt_miss_irq_en_votable; struct fg_sram_param *sp; struct fg_alg_flag *alg_flags; int *debug_mask; diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c index 81cd4b89ddbf..e3c85ab705c4 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen3.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c @@ -904,6 +904,7 @@ out: return ret; } + vote(chip->batt_miss_irq_en_votable, BATT_MISS_IRQ_VOTER, true, 0); return rc; } @@ -1103,6 +1104,25 @@ static void fg_notify_charger(struct fg_chip *chip) fg_dbg(chip, FG_STATUS, "Notified charger on float voltage and FCC\n"); } +static int fg_batt_miss_irq_en_cb(struct votable *votable, void *data, + int enable, const char *client) +{ + struct fg_chip *chip = data; + + if (!chip->irqs[BATT_MISSING_IRQ].irq) + return 0; + + if (enable) { + enable_irq(chip->irqs[BATT_MISSING_IRQ].irq); + enable_irq_wake(chip->irqs[BATT_MISSING_IRQ].irq); + } else { + disable_irq_wake(chip->irqs[BATT_MISSING_IRQ].irq); + disable_irq(chip->irqs[BATT_MISSING_IRQ].irq); + } + + return 0; +} + static int fg_delta_bsoc_irq_en_cb(struct votable *votable, void *data, int enable, const char *client) { @@ -2514,6 +2534,23 @@ static void profile_load_work(struct work_struct *work) int rc; vote(chip->awake_votable, PROFILE_LOAD, true, 0); + + rc = fg_get_batt_id(chip); + if (rc < 0) { + pr_err("Error in getting battery id, rc:%d\n", rc); + goto out; + } + + rc = fg_get_batt_profile(chip); + if (rc < 0) { + pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n", + chip->batt_id_ohms / 1000, rc); + goto out; + } + + if (!chip->profile_available) + goto out; + if (!is_profile_load_required(chip)) goto done; @@ -2578,9 +2615,9 @@ done: batt_psy_initialized(chip); fg_notify_charger(chip); chip->profile_loaded = true; - chip->soc_reporting_ready = true; fg_dbg(chip, FG_STATUS, "profile loaded successfully"); out: + chip->soc_reporting_ready = true; vote(chip->awake_votable, PROFILE_LOAD, false, 0); } @@ -3565,20 +3602,6 @@ static irqreturn_t fg_batt_missing_irq_handler(int irq, void *data) return IRQ_HANDLED; } - rc = fg_get_batt_id(chip); - if (rc < 0) { - chip->soc_reporting_ready = true; - pr_err("Error in getting battery id, rc:%d\n", rc); - return IRQ_HANDLED; - } - - rc = fg_get_batt_profile(chip); - if (rc < 0) { - chip->soc_reporting_ready = true; - pr_err("Error in getting battery profile, rc:%d\n", rc); - return IRQ_HANDLED; - } - clear_battery_profile(chip); schedule_delayed_work(&chip->profile_load_work, 0); @@ -4345,6 +4368,9 @@ static void fg_cleanup(struct fg_chip *chip) if (chip->delta_bsoc_irq_en_votable) destroy_votable(chip->delta_bsoc_irq_en_votable); + if (chip->batt_miss_irq_en_votable) + destroy_votable(chip->batt_miss_irq_en_votable); + if (chip->batt_id_chan) iio_channel_release(chip->batt_id_chan); @@ -4402,6 +4428,7 @@ static int fg_gen3_probe(struct platform_device *pdev) chip); if (IS_ERR(chip->awake_votable)) { rc = PTR_ERR(chip->awake_votable); + chip->awake_votable = NULL; goto exit; } @@ -4410,6 +4437,16 @@ static int fg_gen3_probe(struct platform_device *pdev) fg_delta_bsoc_irq_en_cb, chip); if (IS_ERR(chip->delta_bsoc_irq_en_votable)) { rc = PTR_ERR(chip->delta_bsoc_irq_en_votable); + chip->delta_bsoc_irq_en_votable = NULL; + goto exit; + } + + chip->batt_miss_irq_en_votable = create_votable("FG_BATT_MISS_IRQ", + VOTE_SET_ANY, + fg_batt_miss_irq_en_cb, chip); + if (IS_ERR(chip->batt_miss_irq_en_votable)) { + rc = PTR_ERR(chip->batt_miss_irq_en_votable); + chip->batt_miss_irq_en_votable = NULL; goto exit; } @@ -4434,19 +4471,6 @@ static int fg_gen3_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&chip->batt_avg_work, batt_avg_work); INIT_DELAYED_WORK(&chip->sram_dump_work, sram_dump_work); - rc = fg_get_batt_id(chip); - if (rc < 0) { - pr_err("Error in getting battery id, rc:%d\n", rc); - goto exit; - } - - rc = fg_get_batt_profile(chip); - if (rc < 0) { - chip->soc_reporting_ready = true; - pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n", - chip->batt_id_ohms / 1000, rc); - } - rc = fg_memif_init(chip); if (rc < 0) { dev_err(chip->dev, "Error in initializing FG_MEMIF, rc:%d\n", @@ -4490,13 +4514,16 @@ static int fg_gen3_probe(struct platform_device *pdev) goto exit; } - /* Keep SOC_UPDATE irq disabled until we require it */ + /* Keep SOC_UPDATE_IRQ disabled until we require it */ if (fg_irqs[SOC_UPDATE_IRQ].irq) disable_irq_nosync(fg_irqs[SOC_UPDATE_IRQ].irq); - /* Keep BSOC_DELTA_IRQ irq disabled until we require it */ + /* Keep BSOC_DELTA_IRQ disabled until we require it */ vote(chip->delta_bsoc_irq_en_votable, DELTA_BSOC_IRQ_VOTER, false, 0); + /* Keep BATT_MISSING_IRQ disabled until we require it */ + vote(chip->batt_miss_irq_en_votable, BATT_MISS_IRQ_VOTER, false, 0); + rc = fg_debugfs_create(chip); if (rc < 0) { dev_err(chip->dev, "Error in creating debugfs entries, rc:%d\n", @@ -4520,8 +4547,7 @@ static int fg_gen3_probe(struct platform_device *pdev) } device_init_wakeup(chip->dev, true); - if (chip->profile_available) - schedule_delayed_work(&chip->profile_load_work, 0); + schedule_delayed_work(&chip->profile_load_work, 0); pr_debug("FG GEN3 driver probed successfully\n"); return 0;