Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e6fbc72f authored by Abhijeet Dharmapurikar's avatar Abhijeet Dharmapurikar Committed by Ankit Sharma
Browse files

pmic-voter: disassociate device from votables



Currently the pmic votables need a device to be created.
Votables should be able to work on device less code. Remove
the need for device and instead use a void pointer to be passed
back to the callback.

CRs-Fixed: 1018090
Change-Id: If5dafbcc0d88596332b794ad5b6fdc1f9ff98a45
Signed-off-by: default avatarAbhijeet Dharmapurikar <adharmap@codeaurora.org>
parent 6bd558aa
Loading
Loading
Loading
Loading
+37 −22
Original line number Diff line number Diff line
@@ -15,7 +15,8 @@
#include <linux/errno.h>
#include <linux/bitops.h>
#include <linux/printk.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/string.h>

#include "pmic-voter.h"

@@ -35,13 +36,14 @@ struct votable {
	const char		*name;
	struct list_head	list;
	struct client_vote	votes[NUM_MAX_CLIENTS];
	struct device		*dev;
	int			num_clients;
	int			type;
	int			effective_client_id;
	int			effective_result;
	struct mutex		vote_lock;
	int			(*callback)(struct device *dev,
	void			*data;
	int			(*callback)(struct votable *votable,
						void *data,
						int effective_result,
						const char *effective_client);
	char			*client_strs[NUM_MAX_CLIENTS];
@@ -152,8 +154,7 @@ static int get_client_id(struct votable *votable, const char *client_str)
	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);
				= kstrdup(client_str, GFP_KERNEL);
			if (!votable->client_strs[i])
				return -ENOMEM;
			return i;
@@ -361,7 +362,8 @@ int vote(struct votable *votable, const char *client_str, bool enabled, int val)
			get_client_str(votable, effective_id),
			effective_id);
		if (votable->callback)
			rc = votable->callback(votable->dev, effective_result,
			rc = votable->callback(votable, votable->data,
					effective_result,
					get_client_str(votable, effective_id));
	}

@@ -377,7 +379,8 @@ int rerun_election(struct votable *votable)

	lock_votable(votable);
	if (votable->callback)
		rc = votable->callback(votable->dev,
		rc = votable->callback(votable,
				votable->data,
			votable->effective_result,
			get_client_str(votable, votable->effective_client_id));
	unlock_votable(votable);
@@ -466,12 +469,13 @@ static const struct file_operations votable_debugfs_ops = {
	.release	= single_release,
};

struct votable *create_votable(struct device *dev, const char *name,
struct votable *create_votable(const char *name,
				int votable_type,
					int (*callback)(struct device *dev,
				int (*callback)(struct votable *votable,
					void *data,
					int effective_result,
						const char *effective_client)
					)
					const char *effective_client),
				void *data)
{
	struct votable *votable;
	unsigned long flags;
@@ -483,25 +487,30 @@ struct votable *create_votable(struct device *dev, const char *name,
	if (debug_root == NULL) {
		debug_root = debugfs_create_dir("pmic-votable", NULL);
		if (!debug_root) {
			dev_err(dev, "Couldn't create debug dir\n");
			pr_err("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");
		pr_err("Invalid votable_type specified for voter\n");
		return ERR_PTR(-EINVAL);
	}

	votable = devm_kzalloc(dev, sizeof(struct votable), GFP_KERNEL);
	votable = kzalloc(sizeof(struct votable), GFP_KERNEL);
	if (!votable)
		return ERR_PTR(-ENOMEM);

	votable->dev = dev;
	votable->name = name;
	votable->name = kstrdup(name, GFP_KERNEL);
	if (!votable->name) {
		kfree(votable);
		return ERR_PTR(-ENOMEM);
	}

	votable->num_clients = NUM_MAX_CLIENTS;
	votable->callback = callback;
	votable->type = votable_type;
	votable->data = data;
	mutex_init(&votable->vote_lock);

	/*
@@ -521,22 +530,28 @@ struct votable *create_votable(struct device *dev, const char *name,
				  debug_root, votable,
				  &votable_debugfs_ops);
	if (!votable->ent) {
		dev_err(dev, "Couldn't create %s debug file\n", name);
		devm_kfree(dev, votable);
		pr_err("Couldn't create %s debug file\n", name);
		kfree(votable->name);
		kfree(votable);
		return ERR_PTR(-EEXIST);
	}

	return votable;
}

void destroy_votable(struct device *dev, struct votable *votable)
void destroy_votable(struct votable *votable)
{
	unsigned long flags;
	int i;

	/* 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);
	for (i = 0; i < votable->num_clients && votable->client_strs[i]; i++)
		kfree(votable->client_strs[i]);

	kfree(votable->name);
	kfree(votable);
}
+6 −5
Original line number Diff line number Diff line
@@ -33,13 +33,14 @@ 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,
struct votable *create_votable(const char *name,
				int votable_type,
				int (*callback)(struct device *dev,
				int (*callback)(struct votable *votable,
						void *data,
						int effective_result,
						const char *effective_client)
					);
void destroy_votable(struct device *dev, struct votable *votable);
						const char *effective_client),
				void *data);
void destroy_votable(struct votable *votable);
void lock_votable(struct votable *votable);
void unlock_votable(struct votable *votable);

+126 −72
Original line number Diff line number Diff line
@@ -2598,11 +2598,12 @@ static void smbchg_parallel_usb_check_ok(struct smbchg_chip *chip)
	schedule_delayed_work(&chip->parallel_en_work, 0);
}

static int charging_suspend_vote_cb(struct device *dev, int suspend,
static int charging_suspend_vote_cb(struct votable *votable, void *data,
						int suspend,
						const char *client)
{
	int rc;
	struct smbchg_chip *chip = dev_get_drvdata(dev);
	struct smbchg_chip *chip = data;

	if (suspend < 0) {
		pr_err("No voters\n");
@@ -2619,11 +2620,13 @@ static int charging_suspend_vote_cb(struct device *dev, int suspend,
	return rc;
}

static int usb_suspend_vote_cb(struct device *dev, int suspend,
static int usb_suspend_vote_cb(struct votable *votable,
						void *data,
						int suspend,
						const char *client)
{
	int rc;
	struct smbchg_chip *chip = dev_get_drvdata(dev);
	struct smbchg_chip *chip = data;

	if (suspend < 0) {
		pr_err("No voters\n");
@@ -2643,11 +2646,13 @@ static int usb_suspend_vote_cb(struct device *dev, int suspend,
	return rc;
}

static int dc_suspend_vote_cb(struct device *dev, int suspend,
static int dc_suspend_vote_cb(struct votable *votable,
						void *data,
						int suspend,
						const char *client)
{
	int rc;
	struct smbchg_chip *chip = dev_get_drvdata(dev);
	struct smbchg_chip *chip = data;

	if (suspend < 0) {
		pr_err("No voters\n");
@@ -2665,11 +2670,13 @@ static int dc_suspend_vote_cb(struct device *dev, int suspend,
}

#define HVDCP_EN_BIT			BIT(3)
static int smbchg_hvdcp_enable_cb(struct device *dev, int enable,
static int smbchg_hvdcp_enable_cb(struct votable *votable,
				void *data,
				int enable,
				const char *client)
{
	int rc = 0;
	struct smbchg_chip *chip = dev_get_drvdata(dev);
	struct smbchg_chip *chip = data;

	pr_err("smbchg_hvdcp_enable_cb  enable %d\n", enable);
	rc = smbchg_sec_masked_write(chip,
@@ -2682,11 +2689,12 @@ static int smbchg_hvdcp_enable_cb(struct device *dev, int enable,
	return rc;
}

static int set_fastchg_current_vote_cb(struct device *dev,
static int set_fastchg_current_vote_cb(struct votable *votable,
						void *data,
						int fcc_ma,
						const char *client)
{
	struct smbchg_chip *chip = dev_get_drvdata(dev);
	struct smbchg_chip *chip = data;
	int rc;

	if (fcc_ma < 0) {
@@ -2973,11 +2981,12 @@ DEFINE_SIMPLE_ATTRIBUTE(force_dcin_icl_ops, NULL,
 * set the dc charge path's maximum allowed current draw
 * that may be limited by the system's thermal level
 */
static int set_dc_current_limit_vote_cb(struct device *dev,
static int set_dc_current_limit_vote_cb(struct votable *votable,
						void *data,
						int icl_ma,
						const char *client)
{
	struct smbchg_chip *chip = dev_get_drvdata(dev);
	struct smbchg_chip *chip = data;

	if (icl_ma < 0) {
		pr_err("No voters\n");
@@ -2991,11 +3000,12 @@ static int set_dc_current_limit_vote_cb(struct device *dev,
 * set the usb charge path's maximum allowed current draw
 * that may be limited by the system's thermal level
 */
static int set_usb_current_limit_vote_cb(struct device *dev,
static int set_usb_current_limit_vote_cb(struct votable *votable,
						void *data,
						int icl_ma,
						const char *client)
{
	struct smbchg_chip *chip = dev_get_drvdata(dev);
	struct smbchg_chip *chip = data;
	int rc, aicl_ma;
	const char *effective_client;

@@ -3615,12 +3625,13 @@ static void smbchg_soc_changed(struct smbchg_chip *chip)
#define AICL_RERUN_ON			(BIT(5) | BIT(4))
#define AICL_RERUN_OFF			0

static int smbchg_hw_aicl_rerun_enable_indirect_cb(struct device *dev,
static int smbchg_hw_aicl_rerun_enable_indirect_cb(struct votable *votable,
						void *data,
						int enable,
						const char *client)
{
	int rc = 0;
	struct smbchg_chip *chip = dev_get_drvdata(dev);
	struct smbchg_chip *chip = data;

	if (enable < 0) {
		pr_err("No voters\n");
@@ -3640,11 +3651,12 @@ static int smbchg_hw_aicl_rerun_enable_indirect_cb(struct device *dev,
	return rc;
}

static int smbchg_hw_aicl_rerun_disable_cb(struct device *dev, int disable,
static int smbchg_hw_aicl_rerun_disable_cb(struct votable *votable, void *data,
						int disable,
						const char *client)
{
	int rc = 0;
	struct smbchg_chip *chip = dev_get_drvdata(dev);
	struct smbchg_chip *chip = data;

	if (disable < 0) {
		pr_err("No voters\n");
@@ -3660,11 +3672,12 @@ static int smbchg_hw_aicl_rerun_disable_cb(struct device *dev, int disable,
	return rc;
}

static int smbchg_aicl_deglitch_config_cb(struct device *dev, int shorter,
static int smbchg_aicl_deglitch_config_cb(struct votable *votable, void *data,
						int shorter,
						const char *client)
{
	int rc = 0;
	struct smbchg_chip *chip = dev_get_drvdata(dev);
	struct smbchg_chip *chip = data;

	if (shorter < 0) {
		pr_err("No voters\n");
@@ -8416,75 +8429,88 @@ static int smbchg_probe(struct spmi_device *spmi)
		return -ENOMEM;
	}

	chip->fcc_votable = create_votable(&spmi->dev,
			"BATT_FCC",
	chip->fcc_votable = create_votable("BATT_FCC",
			VOTE_MIN,
			set_fastchg_current_vote_cb);
	if (IS_ERR(chip->fcc_votable))
		return PTR_ERR(chip->fcc_votable);
			set_fastchg_current_vote_cb, chip);
	if (IS_ERR(chip->fcc_votable)) {
		rc = PTR_ERR(chip->fcc_votable);
		goto votables_cleanup;
	}

	chip->usb_icl_votable = create_votable(&spmi->dev,
			"USB_ICL",
	chip->usb_icl_votable = create_votable("USB_ICL",
			VOTE_MIN,
			set_usb_current_limit_vote_cb);
	if (IS_ERR(chip->usb_icl_votable))
		return PTR_ERR(chip->usb_icl_votable);
			set_usb_current_limit_vote_cb, chip);
	if (IS_ERR(chip->usb_icl_votable)) {
		rc = PTR_ERR(chip->usb_icl_votable);
		goto votables_cleanup;
	}

	chip->dc_icl_votable = create_votable(&spmi->dev,
			"DCIN_ICL",
	chip->dc_icl_votable = create_votable("DCIN_ICL",
			VOTE_MIN,
			set_dc_current_limit_vote_cb);
	if (IS_ERR(chip->dc_icl_votable))
		return PTR_ERR(chip->dc_icl_votable);
			set_dc_current_limit_vote_cb, chip);
	if (IS_ERR(chip->dc_icl_votable)) {
		rc = PTR_ERR(chip->dc_icl_votable);
		goto votables_cleanup;
	}

	chip->usb_suspend_votable = create_votable(&spmi->dev,
			"USB_SUSPEND",
	chip->usb_suspend_votable = create_votable("USB_SUSPEND",
			VOTE_SET_ANY,
			usb_suspend_vote_cb);
	if (IS_ERR(chip->usb_suspend_votable))
		return PTR_ERR(chip->usb_suspend_votable);
			usb_suspend_vote_cb, chip);
	if (IS_ERR(chip->usb_suspend_votable)) {
		rc = PTR_ERR(chip->usb_suspend_votable);
		goto votables_cleanup;
	}

	chip->dc_suspend_votable = create_votable(&spmi->dev,
			"DC_SUSPEND",
	chip->dc_suspend_votable = create_votable("DC_SUSPEND",
			VOTE_SET_ANY,
			dc_suspend_vote_cb);
	if (IS_ERR(chip->dc_suspend_votable))
		return PTR_ERR(chip->dc_suspend_votable);
			dc_suspend_vote_cb, chip);
	if (IS_ERR(chip->dc_suspend_votable)) {
		rc = PTR_ERR(chip->dc_suspend_votable);
		goto votables_cleanup;
	}

	chip->battchg_suspend_votable = create_votable(&spmi->dev,
			"BATTCHG_SUSPEND",
	chip->battchg_suspend_votable = create_votable("BATTCHG_SUSPEND",
			VOTE_SET_ANY,
			charging_suspend_vote_cb);
	if (IS_ERR(chip->battchg_suspend_votable))
		return PTR_ERR(chip->battchg_suspend_votable);
			charging_suspend_vote_cb, chip);
	if (IS_ERR(chip->battchg_suspend_votable)) {
		rc = PTR_ERR(chip->battchg_suspend_votable);
		goto votables_cleanup;
	}

	chip->hw_aicl_rerun_disable_votable = create_votable(&spmi->dev,
			"HWAICL_DISABLE",
	chip->hw_aicl_rerun_disable_votable = create_votable("HWAICL_DISABLE",
			VOTE_SET_ANY,
			smbchg_hw_aicl_rerun_disable_cb);
	if (IS_ERR(chip->hw_aicl_rerun_disable_votable))
		return PTR_ERR(chip->hw_aicl_rerun_disable_votable);
			smbchg_hw_aicl_rerun_disable_cb, chip);
	if (IS_ERR(chip->hw_aicl_rerun_disable_votable)) {
		rc = PTR_ERR(chip->hw_aicl_rerun_disable_votable);
		goto votables_cleanup;
	}

	chip->hw_aicl_rerun_enable_indirect_votable = create_votable(&spmi->dev,
	chip->hw_aicl_rerun_enable_indirect_votable = create_votable(
			"HWAICL_ENABLE_INDIRECT",
			VOTE_SET_ANY,
			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);
			smbchg_hw_aicl_rerun_enable_indirect_cb, chip);
	if (IS_ERR(chip->hw_aicl_rerun_enable_indirect_votable)) {
		rc = PTR_ERR(chip->hw_aicl_rerun_enable_indirect_votable);
		goto votables_cleanup;
	}

	chip->aicl_deglitch_short_votable = create_votable(&spmi->dev,
	chip->aicl_deglitch_short_votable = create_votable(
			"HWAICL_SHORT_DEGLITCH",
			VOTE_SET_ANY,
			smbchg_aicl_deglitch_config_cb);
	if (IS_ERR(chip->aicl_deglitch_short_votable))
		return PTR_ERR(chip->aicl_deglitch_short_votable);
			smbchg_aicl_deglitch_config_cb, chip);
	if (IS_ERR(chip->aicl_deglitch_short_votable)) {
		rc = PTR_ERR(chip->aicl_deglitch_short_votable);
		goto votables_cleanup;
	}

	chip->hvdcp_enable_votable = create_votable(&spmi->dev,
	chip->hvdcp_enable_votable = create_votable(
			"HVDCP_ENABLE",
			VOTE_MIN,
			smbchg_hvdcp_enable_cb);
	if (IS_ERR(chip->hvdcp_enable_votable))
		return PTR_ERR(chip->hvdcp_enable_votable);
			smbchg_hvdcp_enable_cb, chip);
	if (IS_ERR(chip->hvdcp_enable_votable)) {
		rc = PTR_ERR(chip->hvdcp_enable_votable);
		goto votables_cleanup;
	}

	INIT_WORK(&chip->usb_set_online_work, smbchg_usb_update_online_work);
	INIT_DELAYED_WORK(&chip->parallel_en_work,
@@ -8519,26 +8545,26 @@ static int smbchg_probe(struct spmi_device *spmi)
	rc = smbchg_parse_peripherals(chip);
	if (rc) {
		dev_err(chip->dev, "Error parsing DT peripherals: %d\n", rc);
		return rc;
		goto votables_cleanup;
	}

	rc = smbchg_check_chg_version(chip);
	if (rc) {
		pr_err("Unable to check schg version rc=%d\n", rc);
		return rc;
		goto votables_cleanup;
	}

	rc = smb_parse_dt(chip);
	if (rc < 0) {
		dev_err(&spmi->dev, "Unable to parse DT nodes: %d\n", rc);
		return rc;
		goto votables_cleanup;
	}

	rc = smbchg_regulator_init(chip);
	if (rc) {
		dev_err(&spmi->dev,
			"Couldn't initialize regulator rc=%d\n", rc);
		return rc;
		goto votables_cleanup;
	}

	rc = smbchg_hw_init(chip);
@@ -8646,6 +8672,25 @@ unregister_batt_psy:
	power_supply_unregister(&chip->batt_psy);
out:
	handle_usb_removal(chip);
votables_cleanup:
	if (chip->aicl_deglitch_short_votable)
		destroy_votable(chip->aicl_deglitch_short_votable);
	if (chip->hw_aicl_rerun_enable_indirect_votable)
		destroy_votable(chip->hw_aicl_rerun_enable_indirect_votable);
	if (chip->hw_aicl_rerun_disable_votable)
		destroy_votable(chip->hw_aicl_rerun_disable_votable);
	if (chip->battchg_suspend_votable)
		destroy_votable(chip->battchg_suspend_votable);
	if (chip->dc_suspend_votable)
		destroy_votable(chip->dc_suspend_votable);
	if (chip->usb_suspend_votable)
		destroy_votable(chip->usb_suspend_votable);
	if (chip->dc_icl_votable)
		destroy_votable(chip->dc_icl_votable);
	if (chip->usb_icl_votable)
		destroy_votable(chip->usb_icl_votable);
	if (chip->fcc_votable)
		destroy_votable(chip->fcc_votable);
	return rc;
}

@@ -8659,6 +8704,15 @@ static int smbchg_remove(struct spmi_device *spmi)
		power_supply_unregister(&chip->dc_psy);

	power_supply_unregister(&chip->batt_psy);
	destroy_votable(chip->aicl_deglitch_short_votable);
	destroy_votable(chip->hw_aicl_rerun_enable_indirect_votable);
	destroy_votable(chip->hw_aicl_rerun_disable_votable);
	destroy_votable(chip->battchg_suspend_votable);
	destroy_votable(chip->dc_suspend_votable);
	destroy_votable(chip->usb_suspend_votable);
	destroy_votable(chip->dc_icl_votable);
	destroy_votable(chip->usb_icl_votable);
	destroy_votable(chip->fcc_votable);

	return 0;
}