diff --git a/drivers/power/qcom-charger/pmic-voter.c b/drivers/power/qcom-charger/pmic-voter.c index 4254b5f2110a..943f4e22bde9 100644 --- a/drivers/power/qcom-charger/pmic-voter.c +++ b/drivers/power/qcom-charger/pmic-voter.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015 The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016 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 @@ -10,6 +10,7 @@ * GNU General Public License for more details. */ +#include #include #include #include @@ -20,15 +21,21 @@ #define NUM_MAX_CLIENTS 8 +static DEFINE_SPINLOCK(votable_list_slock); +static LIST_HEAD(votable_list); + +static struct dentry *debug_root; + struct client_vote { - int state; + bool enabled; int value; }; struct votable { + const char *name; + struct list_head list; struct client_vote votes[NUM_MAX_CLIENTS]; struct device *dev; - const char *name; int num_clients; int type; int effective_client_id; @@ -37,53 +44,84 @@ struct votable { struct mutex vote_lock; int (*callback)(struct device *dev, int effective_result, - int effective_client, - int last_result, - int last_client); + const char *effective_client); + char *client_strs[NUM_MAX_CLIENTS]; + struct dentry *ent; }; -static int vote_set_any(struct votable *votable) +static void vote_set_any(struct votable *votable, int client_id, + int *eff_res, int *eff_id) { int i; - for (i = 0; i < votable->num_clients; i++) - if (votable->votes[i].state == 1) - return 1; - return 0; + for (i = 0; i < votable->num_clients && votable->client_strs[i]; i++) + *eff_res |= votable->votes[i].enabled; + + *eff_id = client_id; } -static int vote_min(struct votable *votable) +static void vote_min(struct votable *votable, int client_id, + int *eff_res, int *eff_id) +{ + int i; + + *eff_res = INT_MAX; + *eff_id = -EINVAL; + for (i = 0; i < votable->num_clients && votable->client_strs[i]; i++) { + if (votable->votes[i].enabled + && *eff_res > votable->votes[i].value) { + *eff_res = votable->votes[i].value; + *eff_id = i; + } + } +} + +static void vote_max(struct votable *votable, int client_id, + int *eff_res, int *eff_id) +{ + int i; + + *eff_res = INT_MIN; + *eff_id = -EINVAL; + for (i = 0; i < votable->num_clients && votable->client_strs[i]; i++) { + if (votable->votes[i].enabled && + *eff_res < votable->votes[i].value) { + *eff_res = votable->votes[i].value; + *eff_id = i; + } + } +} + +static int get_client_id(struct votable *votable, const char *client_str) { - int min_vote = INT_MAX; - int client_index = -EINVAL; int i; for (i = 0; i < votable->num_clients; i++) { - if (votable->votes[i].state == 1 && - min_vote > votable->votes[i].value) { - min_vote = votable->votes[i].value; - client_index = i; - } + if (votable->client_strs[i] + && (strcmp(votable->client_strs[i], client_str) == 0)) + return i; } - return client_index; + /* new client */ + for (i = 0; i < votable->num_clients; i++) { + if (!votable->client_strs[i]) { + votable->client_strs[i] + = devm_kstrdup(votable->dev, + client_str, GFP_KERNEL); + if (!votable->client_strs[i]) + return -ENOMEM; + return i; + } + } + return -EINVAL; } -static int vote_max(struct votable *votable) +static char *get_client_str(struct votable *votable, int client_id) { - int max_vote = INT_MIN; - int client_index = -EINVAL; - int i; + if (client_id == -EINVAL) + return NULL; - for (i = 0; i < votable->num_clients; i++) { - if (votable->votes[i].state == 1 && - max_vote < votable->votes[i].value) { - max_vote = votable->votes[i].value; - client_index = i; - } - } - - return client_index; + return votable->client_strs[client_id]; } void lock_votable(struct votable *votable) @@ -96,30 +134,26 @@ void unlock_votable(struct votable *votable) mutex_unlock(&votable->vote_lock); } -int get_client_vote(struct votable *votable, int client_id) +int get_client_vote_locked(struct votable *votable, const char *client_str) { - int value; + int client_id = get_client_id(votable, client_str); - lock_votable(votable); - value = get_client_vote_locked(votable, client_id); - unlock_votable(votable); - return value; -} + if (client_id < 0) + return votable->default_result; -int get_client_vote_locked(struct votable *votable, int client_id) -{ - if (votable->votes[client_id].state < 0) + if ((votable->type != VOTE_SET_ANY) + && !votable->votes[client_id].enabled) return votable->default_result; return votable->votes[client_id].value; } -int get_effective_result(struct votable *votable) +int get_client_vote(struct votable *votable, const char *client_str) { int value; lock_votable(votable); - value = get_effective_result_locked(votable); + value = get_client_vote_locked(votable, client_str); unlock_votable(votable); return value; } @@ -132,60 +166,73 @@ int get_effective_result_locked(struct votable *votable) return votable->effective_result; } -int get_effective_client_id(struct votable *votable) +int get_effective_result(struct votable *votable) { - int id; + int value; lock_votable(votable); - id = get_effective_client_id_locked(votable); + value = get_effective_result_locked(votable); unlock_votable(votable); - return id; + return value; } -int get_effective_client_id_locked(struct votable *votable) +const char *get_effective_client_locked(struct votable *votable) { - return votable->effective_client_id; + return get_client_str(votable, votable->effective_client_id); } -int vote(struct votable *votable, int client_id, bool state, int val) +const char *get_effective_client(struct votable *votable) { - int effective_id = - EINVAL; + const char *client_str; + + lock_votable(votable); + client_str = get_effective_client_locked(votable); + unlock_votable(votable); + return client_str; +} + +int vote(struct votable *votable, const char *client_str, bool enabled, int val) +{ + int effective_id = -EINVAL; int effective_result; + int client_id; int rc = 0; lock_votable(votable); - if (votable->votes[client_id].state == state && - votable->votes[client_id].value == val) { - pr_debug("%s: votes unchanged; skipping\n", votable->name); + client_id = get_client_id(votable, client_str); + if (client_id < 0) { + rc = client_id; goto out; } - votable->votes[client_id].state = state; + if (votable->votes[client_id].enabled == enabled && + votable->votes[client_id].value == val) { + pr_debug("%s: %s,%d same vote %s of %d\n", + votable->name, + client_str, client_id, + enabled ? "on" : "off", + val); + goto out; + } + + votable->votes[client_id].enabled = enabled; votable->votes[client_id].value = val; - pr_debug("%s: %d voting for %d - %s\n", - votable->name, - client_id, val, state ? "on" : "off"); + pr_debug("%s: %s,%d voting %s of %d\n", + votable->name, + client_str, client_id, enabled ? "on" : "off", val); switch (votable->type) { case VOTE_MIN: - effective_id = vote_min(votable); + vote_min(votable, client_id, &effective_result, &effective_id); break; case VOTE_MAX: - effective_id = vote_max(votable); + vote_max(votable, client_id, &effective_result, &effective_id); break; case VOTE_SET_ANY: - votable->votes[client_id].value = state; - effective_result = vote_set_any(votable); - if (effective_result != votable->effective_result) { - votable->effective_client_id = client_id; - votable->effective_result = effective_result; - if (votable->callback) - rc = votable->callback(votable->dev, - effective_result, client_id, - state, client_id); - } - goto out; + vote_set_any(votable, client_id, + &effective_result, &effective_id); + break; } /* @@ -197,16 +244,16 @@ int vote(struct votable *votable, int client_id, bool state, int val) goto out; } - effective_result = votable->votes[effective_id].value; - if (effective_result != votable->effective_result) { votable->effective_client_id = effective_id; votable->effective_result = effective_result; - pr_debug("%s: effective vote is now %d voted by %d\n", - votable->name, effective_result, effective_id); + pr_debug("%s: effective vote is now %d voted by %s,%d\n", + votable->name, effective_result, + get_client_str(votable, effective_id), + effective_id); if (votable->callback) rc = votable->callback(votable->dev, effective_result, - effective_id, val, client_id); + get_client_str(votable, effective_id)); } out: @@ -214,37 +261,134 @@ out: return rc; } +int rerun_election(struct votable *votable) +{ + int rc = 0; + + lock_votable(votable); + if (votable->callback) + rc = votable->callback(votable->dev, + votable->effective_result, + get_client_str(votable, votable->effective_client_id)); + unlock_votable(votable); + return rc; +} + +struct votable *find_votable(const char *name) +{ + unsigned long flags; + struct votable *v; + bool found = false; + + spin_lock_irqsave(&votable_list_slock, flags); + if (list_empty(&votable_list)) + goto out; + + list_for_each_entry(v, &votable_list, list) { + if (strcmp(v->name, name) == 0) { + found = true; + break; + } + } +out: + spin_unlock_irqrestore(&votable_list_slock, flags); + + if (found) + return v; + else + return NULL; +} + +static int show_votable_clients(struct seq_file *m, void *data) +{ + struct votable *votable = m->private; + int i; + char *type_str = "Unkonwn"; + + lock_votable(votable); + + seq_puts(m, "Clients:\n"); + for (i = 0; i < votable->num_clients; i++) { + if (votable->client_strs[i]) { + seq_printf(m, "%-15s:\t\ten=%d\t\tv=%d\n", + votable->client_strs[i], + votable->votes[i].enabled, + votable->votes[i].value); + } + } + + switch (votable->type) { + case VOTE_MIN: + type_str = "Min"; + break; + case VOTE_MAX: + type_str = "Max"; + break; + case VOTE_SET_ANY: + type_str = "Set_any"; + break; + } + + seq_printf(m, "Type: %s\n", type_str); + seq_puts(m, "Effective:\n"); + seq_printf(m, "%-15s:\t\tv=%d\n", + get_effective_client_locked(votable), + get_effective_result_locked(votable)); + unlock_votable(votable); + + return 0; +} + +static int votable_debugfs_open(struct inode *inode, struct file *file) +{ + struct votable *votable = inode->i_private; + + return single_open(file, show_votable_clients, votable); +} + +static const struct file_operations votable_debugfs_ops = { + .owner = THIS_MODULE, + .open = votable_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + struct votable *create_votable(struct device *dev, const char *name, int votable_type, - int num_clients, int default_result, int (*callback)(struct device *dev, - int effective_result, - int effective_client, - int last_result, - int last_client) + int effective_result, + const char *effective_client) ) { - int i; struct votable *votable; + unsigned long flags; + + votable = find_votable(name); + if (votable) + return ERR_PTR(-EEXIST); + + if (debug_root == NULL) { + debug_root = debugfs_create_dir("pmic-votable", NULL); + if (!debug_root) { + dev_err(dev, "Couldn't create debug dir\n"); + return ERR_PTR(-ENOMEM); + } + } if (votable_type >= NUM_VOTABLE_TYPES) { dev_err(dev, "Invalid votable_type specified for voter\n"); return ERR_PTR(-EINVAL); } - if (num_clients > NUM_MAX_CLIENTS) { - dev_err(dev, "Invalid num_clients specified for voter\n"); - return ERR_PTR(-EINVAL); - } - votable = devm_kzalloc(dev, sizeof(struct votable), GFP_KERNEL); if (!votable) return ERR_PTR(-ENOMEM); votable->dev = dev; votable->name = name; - votable->num_clients = num_clients; + votable->num_clients = NUM_MAX_CLIENTS; votable->callback = callback; votable->type = votable_type; votable->default_result = default_result; @@ -257,8 +401,30 @@ struct votable *create_votable(struct device *dev, const char *name, votable->effective_result = -EINVAL; votable->effective_client_id = -EINVAL; - for (i = 0; i < votable->num_clients; i++) - votable->votes[i].state = -EINVAL; + spin_lock_irqsave(&votable_list_slock, flags); + list_add(&votable->list, &votable_list); + spin_unlock_irqrestore(&votable_list_slock, flags); + + votable->ent = debugfs_create_file(name, S_IFREG | S_IRUGO, + debug_root, votable, + &votable_debugfs_ops); + if (!votable->ent) { + dev_err(dev, "Couldn't create %s debug file\n", name); + devm_kfree(dev, votable); + return ERR_PTR(-EEXIST); + } return votable; } + +void destroy_votable(struct device *dev, struct votable *votable) +{ + unsigned long flags; + + /* only disengage from list, mem will be freed with dev release */ + spin_lock_irqsave(&votable_list_slock, flags); + list_del(&votable->list); + spin_unlock_irqrestore(&votable_list_slock, flags); + + debugfs_remove(votable->ent); +} diff --git a/drivers/power/qcom-charger/pmic-voter.h b/drivers/power/qcom-charger/pmic-voter.h index 30cfecad4287..6882c84b7cd6 100644 --- a/drivers/power/qcom-charger/pmic-voter.h +++ b/drivers/power/qcom-charger/pmic-voter.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015 The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016 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 @@ -24,23 +24,23 @@ enum votable_type { NUM_VOTABLE_TYPES, }; -int get_client_vote(struct votable *votable, int client_id); -int get_client_vote_locked(struct votable *votable, int client_id); +int get_client_vote(struct votable *votable, const char *client_str); +int get_client_vote_locked(struct votable *votable, const char *client_str); int get_effective_result(struct votable *votable); int get_effective_result_locked(struct votable *votable); -int get_effective_client_id(struct votable *votable); -int get_effective_client_id_locked(struct votable *votable); -int vote(struct votable *votable, int client_id, bool state, int val); +const char *get_effective_client(struct votable *votable); +const char *get_effective_client_locked(struct votable *votable); +int vote(struct votable *votable, const char *client_str, bool state, int val); +int rerun_election(struct votable *votable); +struct votable *find_votable(const char *name); struct votable *create_votable(struct device *dev, const char *name, - int votable_type, int num_clients, - int default_result, + int votable_type, int default_result, int (*callback)(struct device *dev, int effective_result, - int effective_client, - int last_result, - int last_client) + const char *effective_client) ); +void destroy_votable(struct device *dev, struct votable *votable); void lock_votable(struct votable *votable); -void unlock_votable(struct votable *votable); +void unlock_votable(struct votable *votable); #endif /* __PMIC_VOTER_H */ diff --git a/drivers/power/qcom-charger/qpnp-smbcharger.c b/drivers/power/qcom-charger/qpnp-smbcharger.c index fbb163908c03..4fd4e7a6bcf2 100644 --- a/drivers/power/qcom-charger/qpnp-smbcharger.c +++ b/drivers/power/qcom-charger/qpnp-smbcharger.c @@ -338,96 +338,79 @@ enum wake_reason { PM_DETECT_HVDCP = BIT(4), }; -enum fcc_voters { - ESR_PULSE_FCC_VOTER, - BATT_TYPE_FCC_VOTER, - RESTRICTED_CHG_FCC_VOTER, - NUM_FCC_VOTER, -}; +/* fcc_voters */ +#define ESR_PULSE_FCC_VOTER "ESR_PULSE_FCC_VOTER" +#define BATT_TYPE_FCC_VOTER "BATT_TYPE_FCC_VOTER" +#define RESTRICTED_CHG_FCC_VOTER "RESTRICTED_CHG_FCC_VOTER" -enum icl_voters { - PSY_ICL_VOTER, - THERMAL_ICL_VOTER, - HVDCP_ICL_VOTER, - USER_ICL_VOTER, - WEAK_CHARGER_ICL_VOTER, - SW_AICL_ICL_VOTER, - CHG_SUSPEND_WORKAROUND_ICL_VOTER, - NUM_ICL_VOTER, -}; +/* ICL VOTERS */ +#define PSY_ICL_VOTER "PSY_ICL_VOTER" +#define THERMAL_ICL_VOTER "THERMAL_ICL_VOTER" +#define HVDCP_ICL_VOTER "HVDCP_ICL_VOTER" +#define USER_ICL_VOTER "USER_ICL_VOTER" +#define WEAK_CHARGER_ICL_VOTER "WEAK_CHARGER_ICL_VOTER" +#define SW_AICL_ICL_VOTER "SW_AICL_ICL_VOTER" +#define CHG_SUSPEND_WORKAROUND_ICL_VOTER "CHG_SUSPEND_WORKAROUND_ICL_VOTER" -enum enable_voters { - /* userspace has suspended charging altogether */ - USER_EN_VOTER, - /* - * this specific path has been suspended through the power supply - * framework - */ - POWER_SUPPLY_EN_VOTER, - /* - * the usb driver has suspended this path by setting a current limit - * of < 2MA - */ - USB_EN_VOTER, - /* - * when a wireless charger comes online, - * the dc path is suspended for a second - */ - WIRELESS_EN_VOTER, - /* - * the thermal daemon can suspend a charge path when the system - * temperature levels rise - */ - THERMAL_EN_VOTER, - /* - * an external OTG supply is being used, suspend charge path so the - * charger does not accidentally try to charge from the external supply. - */ - OTG_EN_VOTER, - /* - * the charger is very weak, do not draw any current from it - */ - WEAK_CHARGER_EN_VOTER, - /* - * fake battery voter, if battery id-resistance around 7.5 Kohm - */ - FAKE_BATTERY_EN_VOTER, - NUM_EN_VOTERS, -}; +/* USB SUSPEND VOTERS */ +/* userspace has suspended charging altogether */ +#define USER_EN_VOTER "USER_EN_VOTER" +/* + * this specific path has been suspended through the power supply + * framework + */ +#define POWER_SUPPLY_EN_VOTER "POWER_SUPPLY_EN_VOTER" +/* + * the usb driver has suspended this path by setting a current limit + * of < 2MA + */ +#define USB_EN_VOTER "USB_EN_VOTER" +/* + * the thermal daemon can suspend a charge path when the system + * temperature levels rise + */ +#define THERMAL_EN_VOTER "THERMAL_EN_VOTER" +/* + * an external OTG supply is being used, suspend charge path so the + * charger does not accidentally try to charge from the external supply. + */ +#define OTG_EN_VOTER "OTG_EN_VOTER" +/* + * the charger is very weak, do not draw any current from it + */ +#define WEAK_CHARGER_EN_VOTER "WEAK_CHARGER_EN_VOTER" +/* + * fake battery voter, if battery id-resistance around 7.5 Kohm + */ +#define FAKE_BATTERY_EN_VOTER "FAKE_BATTERY_EN_VOTER" -enum battchg_enable_voters { +/* battchg_enable_voters */ /* userspace has disabled battery charging */ - BATTCHG_USER_EN_VOTER, +#define BATTCHG_USER_EN_VOTER "BATTCHG_USER_EN_VOTER" /* battery charging disabled while loading battery profiles */ - BATTCHG_UNKNOWN_BATTERY_EN_VOTER, - NUM_BATTCHG_EN_VOTERS, -}; +#define BATTCHG_UNKNOWN_BATTERY_EN_VOTER "BATTCHG_UNKNOWN_BATTERY_EN_VOTER" -enum hw_aicl_rerun_enable_indirect_voters { - /* enabled via device tree */ - DEFAULT_CONFIG_HW_AICL_VOTER, - /* Varb workaround voter */ - VARB_WORKAROUND_VOTER, - /* SHUTDOWN workaround voter */ - SHUTDOWN_WORKAROUND_VOTER, - NUM_HW_AICL_RERUN_ENABLE_INDIRECT_VOTERS, -}; +/* hw_aicl_rerun_enable_indirect_voters */ +/* enabled via device tree */ +#define DEFAULT_CONFIG_HW_AICL_VOTER "DEFAULT_CONFIG_HW_AICL_VOTER" +/* Varb workaround voter */ +#define VARB_WORKAROUND_VOTER "VARB_WORKAROUND_VOTER" +/* SHUTDOWN workaround voter */ +#define SHUTDOWN_WORKAROUND_VOTER "SHUTDOWN_WORKAROUND_VOTER" -enum hw_aicl_rerun_disable_voters { - /* the results from enabling clients */ - HW_AICL_RERUN_ENABLE_INDIRECT_VOTER, - /* Weak charger voter */ - WEAK_CHARGER_HW_AICL_VOTER, - NUM_HW_AICL_DISABLE_VOTERS, -}; +/* hw_aicl_rerun_disable_voters */ +/* the results from enabling clients */ +#define HW_AICL_RERUN_ENABLE_INDIRECT_VOTER \ + "HW_AICL_RERUN_ENABLE_INDIRECT_VOTER" +/* Weak charger voter */ +#define WEAK_CHARGER_HW_AICL_VOTER "WEAK_CHARGER_HW_AICL_VOTER" -enum aicl_short_deglitch_voters { - /* Varb workaround voter */ - VARB_WORKAROUND_SHORT_DEGLITCH_VOTER, - /* QC 2.0 */ - HVDCP_SHORT_DEGLITCH_VOTER, - NUM_HW_SHORT_DEGLITCH_VOTERS, -}; +/* aicl_short_deglitch_voters */ +/* Varb workaround voter */ +#define VARB_WORKAROUND_SHORT_DEGLITCH_VOTER \ + "VARB_WRKARND_SHORT_DEGLITCH_VOTER" +/* QC 2.0 */ +#define HVDCP_SHORT_DEGLITCH_VOTER "HVDCP_SHORT_DEGLITCH_VOTER" static const unsigned int smbchg_extcon_cable[] = { EXTCON_USB, @@ -2136,7 +2119,8 @@ static bool smbchg_is_parallel_usb_ok(struct smbchg_chip *chip, ktime_t kt_since_last_disable; u8 reg; int fcc_ma = get_effective_result_locked(chip->fcc_votable); - int fcc_voter_id = get_effective_client_id_locked(chip->fcc_votable); + const char *fcc_voter + = get_effective_client_locked(chip->fcc_votable); int usb_icl_ma = get_effective_result_locked(chip->usb_icl_votable); if (!parallel_psy || !smbchg_parallel_en @@ -2216,11 +2200,13 @@ static bool smbchg_is_parallel_usb_ok(struct smbchg_chip *chip, return false; } + if (!fcc_voter) + return false; /* * Suspend the parallel charger if the charging current is < 1800 mA * and is not because of an ESR pulse. */ - if (fcc_voter_id != ESR_PULSE_FCC_VOTER + if ((strcmp(fcc_voter, ESR_PULSE_FCC_VOTER) == 0) && fcc_ma < PARALLEL_CHG_THRESHOLD_CURRENT) { pr_smb(PR_STATUS, "FCC %d lower than %d\n", fcc_ma, @@ -2325,8 +2311,7 @@ static void smbchg_parallel_usb_check_ok(struct smbchg_chip *chip) } static int charging_suspend_vote_cb(struct device *dev, int suspend, - int client, int last_suspend, - int last_client) + const char *client) { int rc; struct smbchg_chip *chip = dev_get_drvdata(dev); @@ -2342,8 +2327,7 @@ static int charging_suspend_vote_cb(struct device *dev, int suspend, } static int usb_suspend_vote_cb(struct device *dev, int suspend, - int client, int last_suspend, - int last_client) + const char *client) { int rc; struct smbchg_chip *chip = dev_get_drvdata(dev); @@ -2352,17 +2336,17 @@ static int usb_suspend_vote_cb(struct device *dev, int suspend, if (rc < 0) return rc; - if (client == THERMAL_EN_VOTER || client == POWER_SUPPLY_EN_VOTER || - client == USER_EN_VOTER || - client == FAKE_BATTERY_EN_VOTER) + if ((strcmp(client, THERMAL_EN_VOTER) == 0) + || (strcmp(client, POWER_SUPPLY_EN_VOTER) == 0) + || (strcmp(client, USER_EN_VOTER) == 0) + || (strcmp(client, FAKE_BATTERY_EN_VOTER) == 0)) smbchg_parallel_usb_check_ok(chip); return rc; } static int dc_suspend_vote_cb(struct device *dev, int suspend, - int client, int last_suspend, - int last_client) + const char *client) { int rc; struct smbchg_chip *chip = dev_get_drvdata(dev); @@ -2379,9 +2363,7 @@ static int dc_suspend_vote_cb(struct device *dev, int suspend, static int set_fastchg_current_vote_cb(struct device *dev, int fcc_ma, - int client, - int last_fcc_ma, - int last_client) + const char *client) { struct smbchg_chip *chip = dev_get_drvdata(dev); int rc; @@ -2667,9 +2649,7 @@ DEFINE_SIMPLE_ATTRIBUTE(force_dcin_icl_ops, NULL, */ static int set_dc_current_limit_vote_cb(struct device *dev, int icl_ma, - int client, - int last_icl_ma, - int last_client) + const char *client) { struct smbchg_chip *chip = dev_get_drvdata(dev); @@ -2682,17 +2662,19 @@ static int set_dc_current_limit_vote_cb(struct device *dev, */ static int set_usb_current_limit_vote_cb(struct device *dev, int icl_ma, - int client, - int last_icl_ma, - int last_client) + const char *client) { struct smbchg_chip *chip = dev_get_drvdata(dev); - int rc, aicl_ma, effective_id; + int rc, aicl_ma; + const char *effective_id; - effective_id = get_effective_client_id_locked(chip->usb_icl_votable); + effective_id = get_effective_client_locked(chip->usb_icl_votable); + + if (!effective_id) + return 0; /* disable parallel charging if HVDCP is voting for 300mA */ - if (effective_id == HVDCP_ICL_VOTER) + if (strcmp(effective_id, HVDCP_ICL_VOTER) == 0) smbchg_parallel_usb_disable(chip); if (chip->parallel.current_max_ma == 0) { @@ -2704,7 +2686,7 @@ static int set_usb_current_limit_vote_cb(struct device *dev, } /* skip the aicl rerun if hvdcp icl voter is active */ - if (effective_id == HVDCP_ICL_VOTER) + if (strcmp(effective_id, HVDCP_ICL_VOTER) == 0) return 0; aicl_ma = smbchg_get_aicl_level_ma(chip); @@ -3268,8 +3250,7 @@ static void smbchg_soc_changed(struct smbchg_chip *chip) static int smbchg_hw_aicl_rerun_enable_indirect_cb(struct device *dev, int enable, - int client, int last_enable, - int last_client) + const char *client) { int rc = 0; struct smbchg_chip *chip = dev_get_drvdata(dev); @@ -3289,8 +3270,7 @@ static int smbchg_hw_aicl_rerun_enable_indirect_cb(struct device *dev, } static int smbchg_hw_aicl_rerun_disable_cb(struct device *dev, int disable, - int client, int last_disable, - int last_client) + const char *client) { int rc = 0; struct smbchg_chip *chip = dev_get_drvdata(dev); @@ -3305,8 +3285,7 @@ static int smbchg_hw_aicl_rerun_disable_cb(struct device *dev, int disable, } static int smbchg_aicl_deglitch_config_cb(struct device *dev, int shorter, - int client, int last_result, - int last_client) + const char *client) { int rc = 0; struct smbchg_chip *chip = dev_get_drvdata(dev); @@ -7943,64 +7922,64 @@ static int smbchg_probe(struct platform_device *pdev) } chip->fcc_votable = create_votable(&pdev->dev, - "SMBCHG: fcc", - VOTE_MIN, NUM_FCC_VOTER, 2000, + "BATT_FCC", + VOTE_MIN, 2000, set_fastchg_current_vote_cb); if (IS_ERR(chip->fcc_votable)) return PTR_ERR(chip->fcc_votable); chip->usb_icl_votable = create_votable(&pdev->dev, - "SMBCHG: usb_icl", - VOTE_MIN, NUM_ICL_VOTER, 3000, + "USB_ICL", + VOTE_MIN, 3000, set_usb_current_limit_vote_cb); if (IS_ERR(chip->usb_icl_votable)) return PTR_ERR(chip->usb_icl_votable); chip->dc_icl_votable = create_votable(&pdev->dev, - "SMBCHG: dcl_icl", - VOTE_MIN, NUM_ICL_VOTER, 3000, + "DCIN_ICL", + VOTE_MIN, 3000, set_dc_current_limit_vote_cb); if (IS_ERR(chip->dc_icl_votable)) return PTR_ERR(chip->dc_icl_votable); chip->usb_suspend_votable = create_votable(&pdev->dev, - "SMBCHG: usb_suspend", - VOTE_SET_ANY, NUM_EN_VOTERS, 0, + "USB_SUSPEND", + VOTE_SET_ANY, 0, usb_suspend_vote_cb); if (IS_ERR(chip->usb_suspend_votable)) return PTR_ERR(chip->usb_suspend_votable); chip->dc_suspend_votable = create_votable(&pdev->dev, - "SMBCHG: dc_suspend", - VOTE_SET_ANY, NUM_EN_VOTERS, 0, + "DC_SUSPEND", + VOTE_SET_ANY, 0, dc_suspend_vote_cb); if (IS_ERR(chip->dc_suspend_votable)) return PTR_ERR(chip->dc_suspend_votable); chip->battchg_suspend_votable = create_votable(&pdev->dev, - "SMBCHG: battchg_suspend", - VOTE_SET_ANY, NUM_BATTCHG_EN_VOTERS, 0, + "BATTCHG_SUSPEND", + VOTE_SET_ANY, 0, charging_suspend_vote_cb); if (IS_ERR(chip->battchg_suspend_votable)) return PTR_ERR(chip->battchg_suspend_votable); chip->hw_aicl_rerun_disable_votable = create_votable(&pdev->dev, - "SMBCHG: hwaicl_disable", - VOTE_SET_ANY, NUM_HW_AICL_DISABLE_VOTERS, 0, + "HWAICL_DISABLE", + VOTE_SET_ANY, 0, smbchg_hw_aicl_rerun_disable_cb); if (IS_ERR(chip->hw_aicl_rerun_disable_votable)) return PTR_ERR(chip->hw_aicl_rerun_disable_votable); chip->hw_aicl_rerun_enable_indirect_votable = create_votable(&pdev->dev, - "SMBCHG: hwaicl_enable_indirect", - VOTE_SET_ANY, NUM_HW_AICL_RERUN_ENABLE_INDIRECT_VOTERS, - 0, smbchg_hw_aicl_rerun_enable_indirect_cb); + "HWAICL_ENABLE_INDIRECT", + VOTE_SET_ANY, 0, + smbchg_hw_aicl_rerun_enable_indirect_cb); if (IS_ERR(chip->hw_aicl_rerun_enable_indirect_votable)) return PTR_ERR(chip->hw_aicl_rerun_enable_indirect_votable); chip->aicl_deglitch_short_votable = create_votable(&pdev->dev, - "SMBCHG: hwaicl_short_deglitch", - VOTE_SET_ANY, NUM_HW_SHORT_DEGLITCH_VOTERS, 0, + "HWAICL_SHORT_DEGLITCH", + VOTE_SET_ANY, 0, smbchg_aicl_deglitch_config_cb); if (IS_ERR(chip->aicl_deglitch_short_votable)) return PTR_ERR(chip->aicl_deglitch_short_votable); @@ -8217,7 +8196,7 @@ static int smbchg_remove(struct platform_device *pdev) static void smbchg_shutdown(struct platform_device *pdev) { struct smbchg_chip *chip = dev_get_drvdata(&pdev->dev); - int i, rc; + int rc; if (!(chip->wa_flags & SMBCHG_RESTART_WA)) return; @@ -8256,8 +8235,10 @@ static void smbchg_shutdown(struct platform_device *pdev) disable_irq(chip->wdog_timeout_irq); /* remove all votes for short deglitch */ - for (i = 0; i < NUM_HW_SHORT_DEGLITCH_VOTERS; i++) - vote(chip->aicl_deglitch_short_votable, i, false, 0); + vote(chip->aicl_deglitch_short_votable, + VARB_WORKAROUND_SHORT_DEGLITCH_VOTER, false, 0); + vote(chip->aicl_deglitch_short_votable, + HVDCP_SHORT_DEGLITCH_VOTER, false, 0); /* vote to ensure AICL rerun is enabled */ rc = vote(chip->hw_aicl_rerun_enable_indirect_votable, diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c index 263b8b3bd672..a72d4a82270b 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -299,24 +299,24 @@ static int smblib_detach_usb(struct smb_charger *chg) * VOTABLE CALLBACKS * *********************/ -int smblib_usb_suspend_vote_callback(struct device *dev, - int suspend, int client, int last_suspend, int last_client) +static int smblib_usb_suspend_vote_callback(struct device *dev, + int suspend, const char *client) { struct smb_charger *chg = dev_get_drvdata(dev); return smblib_set_usb_suspend(chg, suspend); } -int smblib_dc_suspend_vote_callback(struct device *dev, - int suspend, int client, int last_suspend, int last_client) +static int smblib_dc_suspend_vote_callback(struct device *dev, + int suspend, const char *client) { struct smb_charger *chg = dev_get_drvdata(dev); return smblib_set_dc_suspend(chg, suspend); } -int smblib_fcc_vote_callback(struct device *dev, - int fcc_ua, int client, int last_fcc_ua, int last_client) +static int smblib_fcc_vote_callback(struct device *dev, + int fcc_ua, const char *client) { struct smb_charger *chg = dev_get_drvdata(dev); int rc = 0; @@ -325,8 +325,8 @@ int smblib_fcc_vote_callback(struct device *dev, return rc; } -int smblib_fv_vote_callback(struct device *dev, - int fv_uv, int client, int last_fv_uv, int last_client) +static int smblib_fv_vote_callback(struct device *dev, + int fv_uv, const char *client) { struct smb_charger *chg = dev_get_drvdata(dev); int rc = 0; @@ -337,8 +337,8 @@ int smblib_fv_vote_callback(struct device *dev, #define USBIN_25MA 25000 #define USBIN_100MA 100000 -int smblib_usb_icl_vote_callback(struct device *dev, - int icl_ua, int client, int last_icl_ua, int last_client) +static int smblib_usb_icl_vote_callback(struct device *dev, + int icl_ua, const char *client) { struct smb_charger *chg = dev_get_drvdata(dev); int rc = 0; @@ -372,8 +372,8 @@ suspend: return rc; } -int smblib_dc_icl_vote_callback(struct device *dev, - int icl_ua, int client, int last_icl_ua, int last_client) +static int smblib_dc_icl_vote_callback(struct device *dev, + int icl_ua, const char *client) { struct smb_charger *chg = dev_get_drvdata(dev); int rc = 0; @@ -1295,7 +1295,7 @@ int smblib_init(struct smb_charger *chg) chg->usb_suspend_votable = create_votable(chg->dev, "INPUT_SUSPEND", VOTE_SET_ANY, - NUM_VOTERS, 0, + 0, smblib_usb_suspend_vote_callback); if (IS_ERR(chg->usb_suspend_votable)) { rc = PTR_ERR(chg->usb_suspend_votable); @@ -1304,7 +1304,7 @@ int smblib_init(struct smb_charger *chg) chg->dc_suspend_votable = create_votable(chg->dev, "DC_SUSPEND", VOTE_SET_ANY, - NUM_VOTERS, 0, + 0, smblib_dc_suspend_vote_callback); if (IS_ERR(chg->dc_suspend_votable)) { rc = PTR_ERR(chg->dc_suspend_votable); @@ -1313,7 +1313,7 @@ int smblib_init(struct smb_charger *chg) chg->fcc_votable = create_votable(chg->dev, "FCC", VOTE_MAX, - NUM_VOTERS, SMB_DEFAULT_FCC_UA, + SMB_DEFAULT_FCC_UA, smblib_fcc_vote_callback); if (IS_ERR(chg->fcc_votable)) { rc = PTR_ERR(chg->fcc_votable); @@ -1322,7 +1322,7 @@ int smblib_init(struct smb_charger *chg) chg->fv_votable = create_votable(chg->dev, "FV", VOTE_MAX, - NUM_VOTERS, SMB_DEFAULT_FV_UV, + SMB_DEFAULT_FV_UV, smblib_fv_vote_callback); if (IS_ERR(chg->fv_votable)) { rc = PTR_ERR(chg->fv_votable); @@ -1331,7 +1331,7 @@ int smblib_init(struct smb_charger *chg) chg->usb_icl_votable = create_votable(chg->dev, "USB_ICL", VOTE_MIN, - NUM_VOTERS, SMB_DEFAULT_ICL_UA, + SMB_DEFAULT_ICL_UA, smblib_usb_icl_vote_callback); if (IS_ERR(chg->usb_icl_votable)) { rc = PTR_ERR(chg->usb_icl_votable); @@ -1340,7 +1340,7 @@ int smblib_init(struct smb_charger *chg) chg->dc_icl_votable = create_votable(chg->dev, "DC_ICL", VOTE_MIN, - NUM_VOTERS, SMB_DEFAULT_ICL_UA, + SMB_DEFAULT_ICL_UA, smblib_dc_icl_vote_callback); if (IS_ERR(chg->dc_icl_votable)) { rc = PTR_ERR(chg->dc_icl_votable); @@ -1349,7 +1349,7 @@ int smblib_init(struct smb_charger *chg) chg->pd_allowed_votable = create_votable(chg->dev, "PD_ALLOWED", VOTE_SET_ANY, - NUM_VOTERS, 0, NULL); + 0, NULL); if (IS_ERR(chg->pd_allowed_votable)) { rc = PTR_ERR(chg->pd_allowed_votable); return rc; diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h index a7e34552370e..5be7accb99a6 100644 --- a/drivers/power/qcom-charger/smb-lib.h +++ b/drivers/power/qcom-charger/smb-lib.h @@ -23,12 +23,9 @@ enum print_reason { PR_MISC = BIT(2), }; -enum smb_voters { - DEFAULT_VOTER = 0, - USER_VOTER, - PD_VOTER, - NUM_VOTERS, -}; +#define DEFAULT_VOTER "DEFAULT_VOTER" +#define USER_VOTER "USER_VOTER" +#define PD_VOTER "PD_VOTER" struct smb_regulator { struct regulator_dev *rdev; @@ -101,17 +98,6 @@ int smblib_write(struct smb_charger *chg, u16 addr, u8 val); int smblib_enable_charging(struct smb_charger *chg, bool enable); -int smblib_usb_suspend_vote_callback(struct device *dev, - int disable, int client, int last_disable, int last_client); -int smblib_dc_suspend_vote_callback(struct device *dev, - int disable, int client, int last_disable, int last_client); -int smblib_fcc_vote_callback(struct device *dev, - int fcc_ua, int client, int last_fcc_ua, int last_client); -int smblib_usb_icl_vote_callback(struct device *dev, - int icl_ua, int client, int last_icl_ua, int last_client); -int smblib_dc_icl_vote_callback(struct device *dev, - int icl_ua, int client, int last_icl_ua, int last_client); - int smblib_vbus_regulator_enable(struct regulator_dev *rdev); int smblib_vbus_regulator_disable(struct regulator_dev *rdev); int smblib_vbus_regulator_is_enabled(struct regulator_dev *rdev);