mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 00:22:00 +02:00
Power Supply Fixes for 6.13 cycle
* gpio-charger: fix potential array out of bounds access
* cros_charge-control: fix concurrent sysfs access
* cros_charge-control: allow start_threshold == end_threshold
* cros_charge-control: workaround limited v2 charge threshold API
* bq24296: fix vbus regulator handling
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEE72YNB0Y/i3JqeVQT2O7X88g7+poFAmduuvwACgkQ2O7X88g7
+pqhUQ/+L1yIOlX6CCqUOCTBVw15raepucxUZiY2prqDlDVPjxTsdvB307uPKeLI
uWIajYGIuZoOfabHZovhTouDb1ygYZX55Ud3Egzbqjhdkqyl/aXfel0bjh1nOyaO
22Ga2keBXUp4ySs2iyfkvadpugTeXcq7jBc2WMkW6yuWGvd8NQ9my9E1aAAlpwCt
fyjvQ43U/8UMecVSAK2rfisVAy2hZnKBdf5b9bmPOgiAC04ncTBXgR+8j4bxNGDA
xU+xk96lQROxpa3d7qg5MDYV5uxmZhsw09d7cfpMKm2268EmCzrmVSJm6TPLQW7E
04ijngTVA4Zcj4lWi2TuLQtQDGXZkKirNk76PdP4Kz9yf9KNMfDLFFOjaDJbR0rY
3dFGDHMsuiDMesw9LbHz+H69/RbrI0RdK/HtttoQJS0VobmQjulFxP1GKwzyt/r3
XlTiaur9ip2MAPPZViYeBSbXZsnvMOnlEY6SBsDrviq1s379FOXxEI/uongmFQY9
4jawFfDqxq9UvOrjB1MqVJXcEYYYBqLP4oBt+izb2AWrXj3MKT5AECHV4RTjbql0
eXE5V5fXY3wljggoWyarvYW9dLWfDeD3D3b1QYoCyGX8agXHRGoIWi6T+dZWUy5M
i+c1/B/2WgRfMErbc5hdScLztTsLH0XVdKLZAVe1jIxdocpLc/8=
=Nj7G
-----END PGP SIGNATURE-----
Merge tag 'for-v6.13-rc' of git://git.kernel.org/pub/scm/linux/kernel/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
This commit is contained in:
commit
8379578b11
|
|
@ -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);
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
|
@ -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) {
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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++) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user