diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2016-12-19 00:45:05 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-12-19 00:45:05 -0800 |
commit | 70a39ffcf9b44bfc152f4b3fcd2c71234da256e8 (patch) | |
tree | 2eeafdbad91512de4d6f312e75d02775f20d15e8 /drivers/power | |
parent | 04d779afaa34b9bd8d6351658d80efa618ec4fdb (diff) | |
parent | d804378a310ada3631ac757de459342351c6213f (diff) |
Merge "smb138x-charger: enable the watchdog timer when parallel is enabled"
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/qcom-charger/smb-lib.c | 13 | ||||
-rw-r--r-- | drivers/power/qcom-charger/smb-lib.h | 1 | ||||
-rw-r--r-- | drivers/power/qcom-charger/smb-reg.h | 2 | ||||
-rw-r--r-- | drivers/power/qcom-charger/smb138x-charger.c | 110 |
4 files changed, 104 insertions, 22 deletions
diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c index 507704dd469a..987e8258d301 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -2949,6 +2949,19 @@ irqreturn_t smblib_handle_switcher_power_ok(int irq, void *data) return IRQ_HANDLED; } +irqreturn_t smblib_handle_wdog_bark(int irq, void *data) +{ + struct smb_irq_data *irq_data = data; + struct smb_charger *chg = irq_data->parent_data; + int rc; + + rc = smblib_write(chg, BARK_BITE_WDOG_PET_REG, BARK_BITE_WDOG_PET_BIT); + if (rc < 0) + smblib_err(chg, "Couldn't pet the dog rc=%d\n", rc); + + return IRQ_HANDLED; +} + /*************** * Work Queues * ***************/ diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h index b309095b04c1..001b62ad5b02 100644 --- a/drivers/power/qcom-charger/smb-lib.h +++ b/drivers/power/qcom-charger/smb-lib.h @@ -262,6 +262,7 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data); irqreturn_t smblib_handle_dc_plugin(int irq, void *data); irqreturn_t smblib_handle_high_duty_cycle(int irq, void *data); irqreturn_t smblib_handle_switcher_power_ok(int irq, void *data); +irqreturn_t smblib_handle_wdog_bark(int irq, void *data); int smblib_get_prop_input_suspend(struct smb_charger *chg, union power_supply_propval *val); diff --git a/drivers/power/qcom-charger/smb-reg.h b/drivers/power/qcom-charger/smb-reg.h index c2a2b0c86d73..ed43051adab6 100644 --- a/drivers/power/qcom-charger/smb-reg.h +++ b/drivers/power/qcom-charger/smb-reg.h @@ -897,7 +897,7 @@ enum { #define BITE_WDOG_INT_EN_BIT BIT(5) #define SFT_AFTER_WDOG_IRQ_MASK GENMASK(4, 3) #define WDOG_IRQ_SFT_BIT BIT(2) -#define WDOG_OPTION_BIT BIT(1) +#define WDOG_TIMER_EN_ON_PLUGIN_BIT BIT(1) #define WDOG_TIMER_EN_BIT BIT(0) #define MISC_CFG_REG (MISC_BASE + 0x52) diff --git a/drivers/power/qcom-charger/smb138x-charger.c b/drivers/power/qcom-charger/smb138x-charger.c index 4255958de300..70d935e9d1df 100644 --- a/drivers/power/qcom-charger/smb138x-charger.c +++ b/drivers/power/qcom-charger/smb138x-charger.c @@ -192,11 +192,13 @@ static int smb138x_usb_get_prop(struct power_supply *psy, pr_err("get prop %d is not supported\n", prop); return -EINVAL; } + if (rc < 0) { pr_debug("Couldn't get prop %d rc = %d\n", prop, rc); return -ENODATA; } - return 0; + + return rc; } static int smb138x_usb_set_prop(struct power_supply *psy, @@ -319,11 +321,13 @@ static int smb138x_batt_get_prop(struct power_supply *psy, pr_err("batt power supply get prop %d not supported\n", prop); return -EINVAL; } + if (rc < 0) { pr_debug("Couldn't get prop %d rc = %d\n", prop, rc); return -ENODATA; } - return 0; + + return rc; } static int smb138x_batt_set_prop(struct power_supply *psy, @@ -457,11 +461,37 @@ static int smb138x_parallel_get_prop(struct power_supply *psy, prop); return -EINVAL; } + if (rc < 0) { pr_debug("Couldn't get prop %d rc = %d\n", prop, rc); return -ENODATA; } - return 0; + + return rc; +} + +static int smb138x_set_parallel_suspend(struct smb138x *chip, bool suspend) +{ + struct smb_charger *chg = &chip->chg; + int rc = 0; + + rc = smblib_masked_write(chg, WD_CFG_REG, WDOG_TIMER_EN_BIT, + suspend ? 0 : WDOG_TIMER_EN_BIT); + if (rc < 0) { + pr_err("Couldn't %s watchdog rc=%d\n", + suspend ? "disable" : "enable", rc); + suspend = true; + } + + rc = smblib_masked_write(chg, USBIN_CMD_IL_REG, USBIN_SUSPEND_BIT, + suspend ? USBIN_SUSPEND_BIT : 0); + if (rc < 0) { + pr_err("Couldn't %s parallel charger rc=%d\n", + suspend ? "suspend" : "resume", rc); + return rc; + } + + return rc; } static int smb138x_parallel_set_prop(struct power_supply *psy, @@ -474,7 +504,7 @@ static int smb138x_parallel_set_prop(struct power_supply *psy, switch (prop) { case POWER_SUPPLY_PROP_INPUT_SUSPEND: - rc = smblib_set_usb_suspend(chg, val->intval); + rc = smb138x_set_parallel_suspend(chip, (bool)val->intval); break; case POWER_SUPPLY_PROP_VOLTAGE_MAX: rc = smblib_set_charge_param(chg, &chg->param.fv, val->intval); @@ -620,7 +650,7 @@ static int smb138x_init_vconn_regulator(struct smb138x *chip) static int smb138x_init_hw(struct smb138x *chip) { struct smb_charger *chg = &chip->chg; - int rc; + int rc = 0; /* votes must be cast before configuring software control */ vote(chg->usb_suspend_votable, @@ -772,6 +802,7 @@ static int smb138x_determine_initial_status(struct smb138x *chip) struct smb138x_irq_info { const char *name; const irq_handler_t handler; + const bool wake; const struct storm_watch storm_data; }; @@ -908,7 +939,8 @@ static const struct smb138x_irq_info smb138x_irqs[] = { }, { .name = "wdog-bark", - .handler = smblib_handle_debug, + .handler = smblib_handle_wdog_bark, + .wake = true, }, { .name = "aicl-fail", @@ -953,7 +985,7 @@ static int smb138x_request_interrupt(struct smb138x *chip, const char *irq_name) { struct smb_charger *chg = &chip->chg; - int rc, irq, irq_index; + int rc = 0, irq, irq_index; struct smb_irq_data *irq_data; irq = of_irq_get_byname(node, irq_name); @@ -968,6 +1000,9 @@ static int smb138x_request_interrupt(struct smb138x *chip, return irq_index; } + if (!smb138x_irqs[irq_index].handler) + return 0; + irq_data = devm_kzalloc(chg->dev, sizeof(*irq_data), GFP_KERNEL); if (!irq_data) return -ENOMEM; @@ -984,6 +1019,9 @@ static int smb138x_request_interrupt(struct smb138x *chip, return rc; } + if (smb138x_irqs[irq_index].wake) + enable_irq_wake(irq); + return rc; } @@ -1001,7 +1039,7 @@ static int smb138x_request_interrupts(struct smb138x *chip) prop, name) { rc = smb138x_request_interrupt(chip, child, name); if (rc < 0) { - pr_err("Coudn't request interrupt %s rc=%d\n", + pr_err("Couldn't request interrupt %s rc=%d\n", name, rc); return rc; } @@ -1092,7 +1130,7 @@ static int smb138x_slave_probe(struct smb138x *chip) rc = smblib_init(chg); if (rc < 0) { pr_err("Couldn't initialize smblib rc=%d\n", rc); - return rc; + goto cleanup; } if (chip->wa_flags & OOB_COMP_WA_BIT) { @@ -1102,7 +1140,7 @@ static int smb138x_slave_probe(struct smb138x *chip) if (rc < 0) { dev_err(chg->dev, "Couldn't configure the oob comp threh rc = %d\n", rc); - return rc; + goto cleanup; } rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG6, @@ -1110,22 +1148,41 @@ static int smb138x_slave_probe(struct smb138x *chip) if (rc < 0) { dev_err(chg->dev, "Couldn't configure the sdcdc cfg 6 reg rc = %d\n", rc); - return rc; + goto cleanup; } } - /* suspend usb input */ - rc = smblib_set_usb_suspend(chg, true); + /* enable watchdog bark and bite interrupts, and disable the watchdog */ + rc = smblib_masked_write(chg, WD_CFG_REG, WDOG_TIMER_EN_BIT + | WDOG_TIMER_EN_ON_PLUGIN_BIT | BITE_WDOG_INT_EN_BIT + | BARK_WDOG_INT_EN_BIT, + BITE_WDOG_INT_EN_BIT | BARK_WDOG_INT_EN_BIT); if (rc < 0) { - pr_err("Couldn't suspend USB input rc=%d\n", rc); - return rc; + pr_err("Couldn't configure the watchdog rc=%d\n", rc); + goto cleanup; + } + + /* disable charging when watchdog bites */ + rc = smblib_masked_write(chg, SNARL_BARK_BITE_WD_CFG_REG, + BITE_WDOG_DISABLE_CHARGING_CFG_BIT, + BITE_WDOG_DISABLE_CHARGING_CFG_BIT); + if (rc < 0) { + pr_err("Couldn't configure the watchdog bite rc=%d\n", rc); + goto cleanup; + } + + /* suspend parallel charging */ + rc = smb138x_set_parallel_suspend(chip, true); + if (rc < 0) { + pr_err("Couldn't suspend parallel charging rc=%d\n", rc); + goto cleanup; } /* initialize FCC to 0 */ rc = smblib_set_charge_param(chg, &chg->param.fcc, 0); if (rc < 0) { pr_err("Couldn't set 0 FCC rc=%d\n", rc); - return rc; + goto cleanup; } /* enable the charging path */ @@ -1134,7 +1191,7 @@ static int smb138x_slave_probe(struct smb138x *chip) CHARGING_ENABLE_CMD_BIT); if (rc < 0) { dev_err(chg->dev, "Couldn't enable charging rc=%d\n", rc); - return rc; + goto cleanup; } /* configure charge enable for software control; active high */ @@ -1143,7 +1200,7 @@ static int smb138x_slave_probe(struct smb138x *chip) if (rc < 0) { dev_err(chg->dev, "Couldn't configure charge enable source rc=%d\n", rc); - return rc; + goto cleanup; } /* enable parallel current sensing */ @@ -1152,17 +1209,28 @@ static int smb138x_slave_probe(struct smb138x *chip) if (rc < 0) { dev_err(chg->dev, "Couldn't enable parallel current sensing rc=%d\n", rc); - return rc; + goto cleanup; } - /* keep at the end of probe, ready to serve before notifying others */ rc = smb138x_init_parallel_psy(chip); if (rc < 0) { pr_err("Couldn't initialize parallel psy rc=%d\n", rc); - return rc; + goto cleanup; + } + + rc = smb138x_request_interrupts(chip); + if (rc < 0) { + pr_err("Couldn't request interrupts rc=%d\n", rc); + goto cleanup; } return rc; + +cleanup: + smblib_deinit(chg); + if (chip->parallel_psy) + power_supply_unregister(chip->parallel_psy); + return rc; } static const struct of_device_id match_table[] = { |