Skip to content

Commit

Permalink
Merge tag 'for-v6.13-rc' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/sre/linux-power-supply

Pull power supply fixes from Sebastian Reichel:

 - fix potential array out of bounds access in gpio-charger

 - cros_charge-control:
    - fix concurrent sysfs access
    - allow start_threshold == end_threshold
    - workaround limited v2 charge threshold API

 - bq24296: fix vbus regulator handling

* tag 'for-v6.13-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply:
  power: supply: bq24190: Fix BQ24296 Vbus regulator support
  power: supply: cros_charge-control: hide start threshold on v2 cmd
  power: supply: cros_charge-control: allow start_threshold == end_threshold
  power: supply: cros_charge-control: add mutex for driver data
  power: supply: gpio-charger: Fix set charge current limits
  • Loading branch information
torvalds committed Dec 27, 2024
2 parents eff4f67 + b3ded60 commit 8379578
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 12 deletions.
12 changes: 9 additions & 3 deletions drivers/power/supply/bq24190_charger.c
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@ static int bq24190_set_otg_vbus(struct bq24190_dev_info *bdi, bool enable)

static int bq24296_set_otg_vbus(struct bq24190_dev_info *bdi, bool enable)
{
union power_supply_propval val = { .intval = bdi->charge_type };
int ret;

ret = pm_runtime_resume_and_get(bdi->dev);
Expand All @@ -587,13 +588,18 @@ static int bq24296_set_otg_vbus(struct bq24190_dev_info *bdi, bool enable)

ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
BQ24296_REG_POC_OTG_CONFIG_MASK,
BQ24296_REG_POC_CHG_CONFIG_SHIFT,
BQ24296_REG_POC_OTG_CONFIG_SHIFT,
BQ24296_REG_POC_OTG_CONFIG_OTG);
} else
} else {
ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
BQ24296_REG_POC_OTG_CONFIG_MASK,
BQ24296_REG_POC_CHG_CONFIG_SHIFT,
BQ24296_REG_POC_OTG_CONFIG_SHIFT,
BQ24296_REG_POC_OTG_CONFIG_DISABLE);
if (ret < 0)
goto out;

ret = bq24190_charger_set_charge_type(bdi, &val);
}

out:
pm_runtime_mark_last_busy(bdi->dev);
Expand Down
36 changes: 27 additions & 9 deletions drivers/power/supply/cros_charge-control.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
#include <acpi/battery.h>
#include <linux/container_of.h>
#include <linux/dmi.h>
#include <linux/lockdep.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_data/cros_ec_commands.h>
#include <linux/platform_data/cros_ec_proto.h>
#include <linux/platform_device.h>
Expand Down Expand Up @@ -49,6 +51,7 @@ struct cros_chctl_priv {
struct attribute *attributes[_CROS_CHCTL_ATTR_COUNT];
struct attribute_group group;

struct mutex lock; /* protects fields below and cros_ec */
enum power_supply_charge_behaviour current_behaviour;
u8 current_start_threshold, current_end_threshold;
};
Expand Down Expand Up @@ -85,6 +88,8 @@ static int cros_chctl_configure_ec(struct cros_chctl_priv *priv)
{
struct ec_params_charge_control req = {};

lockdep_assert_held(&priv->lock);

req.cmd = EC_CHARGE_CONTROL_CMD_SET;

switch (priv->current_behaviour) {
Expand Down Expand Up @@ -134,11 +139,15 @@ static ssize_t cros_chctl_store_threshold(struct device *dev, struct cros_chctl_
return -EINVAL;

if (is_end_threshold) {
if (val <= priv->current_start_threshold)
/* Start threshold is not exposed, use fixed value */
if (priv->cmd_version == 2)
priv->current_start_threshold = val == 100 ? 0 : val;

if (val < priv->current_start_threshold)
return -EINVAL;
priv->current_end_threshold = val;
} else {
if (val >= priv->current_end_threshold)
if (val > priv->current_end_threshold)
return -EINVAL;
priv->current_start_threshold = val;
}
Expand All @@ -159,6 +168,7 @@ static ssize_t charge_control_start_threshold_show(struct device *dev,
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
CROS_CHCTL_ATTR_START_THRESHOLD);

guard(mutex)(&priv->lock);
return sysfs_emit(buf, "%u\n", (unsigned int)priv->current_start_threshold);
}

Expand All @@ -169,6 +179,7 @@ static ssize_t charge_control_start_threshold_store(struct device *dev,
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
CROS_CHCTL_ATTR_START_THRESHOLD);

guard(mutex)(&priv->lock);
return cros_chctl_store_threshold(dev, priv, 0, buf, count);
}

Expand All @@ -178,6 +189,7 @@ static ssize_t charge_control_end_threshold_show(struct device *dev, struct devi
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
CROS_CHCTL_ATTR_END_THRESHOLD);

guard(mutex)(&priv->lock);
return sysfs_emit(buf, "%u\n", (unsigned int)priv->current_end_threshold);
}

Expand All @@ -187,6 +199,7 @@ static ssize_t charge_control_end_threshold_store(struct device *dev, struct dev
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
CROS_CHCTL_ATTR_END_THRESHOLD);

guard(mutex)(&priv->lock);
return cros_chctl_store_threshold(dev, priv, 1, buf, count);
}

Expand All @@ -195,6 +208,7 @@ static ssize_t charge_behaviour_show(struct device *dev, struct device_attribute
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
CROS_CHCTL_ATTR_CHARGE_BEHAVIOUR);

guard(mutex)(&priv->lock);
return power_supply_charge_behaviour_show(dev, EC_CHARGE_CONTROL_BEHAVIOURS,
priv->current_behaviour, buf);
}
Expand All @@ -210,6 +224,7 @@ static ssize_t charge_behaviour_store(struct device *dev, struct device_attribut
if (ret < 0)
return ret;

guard(mutex)(&priv->lock);
priv->current_behaviour = ret;

ret = cros_chctl_configure_ec(priv);
Expand All @@ -223,12 +238,10 @@ static umode_t cros_chtl_attr_is_visible(struct kobject *kobj, struct attribute
{
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(attr, n);

if (priv->cmd_version < 2) {
if (n == CROS_CHCTL_ATTR_START_THRESHOLD)
return 0;
if (n == CROS_CHCTL_ATTR_END_THRESHOLD)
return 0;
}
if (n == CROS_CHCTL_ATTR_START_THRESHOLD && priv->cmd_version < 3)
return 0;
else if (n == CROS_CHCTL_ATTR_END_THRESHOLD && priv->cmd_version < 2)
return 0;

return attr->mode;
}
Expand Down Expand Up @@ -290,6 +303,10 @@ static int cros_chctl_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;

ret = devm_mutex_init(dev, &priv->lock);
if (ret)
return ret;

ret = cros_ec_get_cmd_versions(cros_ec, EC_CMD_CHARGE_CONTROL);
if (ret < 0)
return ret;
Expand Down Expand Up @@ -327,7 +344,8 @@ static int cros_chctl_probe(struct platform_device *pdev)
priv->current_end_threshold = 100;

/* Bring EC into well-known state */
ret = cros_chctl_configure_ec(priv);
scoped_guard(mutex, &priv->lock)
ret = cros_chctl_configure_ec(priv);
if (ret < 0)
return ret;

Expand Down
8 changes: 8 additions & 0 deletions drivers/power/supply/gpio-charger.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ static int set_charge_current_limit(struct gpio_charger *gpio_charger, int val)
if (gpio_charger->current_limit_map[i].limit_ua <= val)
break;
}

/*
* If a valid charge current limit isn't found, default to smallest
* current limitation for safety reasons.
*/
if (i >= gpio_charger->current_limit_map_size)
i = gpio_charger->current_limit_map_size - 1;

mapping = gpio_charger->current_limit_map[i];

for (i = 0; i < ndescs; i++) {
Expand Down

0 comments on commit 8379578

Please sign in to comment.