summaryrefslogtreecommitdiff
path: root/drivers/power/supply
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/supply')
-rw-r--r--drivers/power/supply/ab8500_fg.c2
-rw-r--r--drivers/power/supply/axp20x_battery.c591
-rw-r--r--drivers/power/supply/axp20x_usb_power.c368
-rw-r--r--drivers/power/supply/bq256xx_charger.c15
-rw-r--r--drivers/power/supply/cpcap-charger.c2
-rw-r--r--drivers/power/supply/cros_usbpd-charger.c22
-rw-r--r--drivers/power/supply/lenovo_yoga_c630_battery.c7
-rw-r--r--drivers/power/supply/max17042_battery.c5
-rw-r--r--drivers/power/supply/max1720x_battery.c209
-rw-r--r--drivers/power/supply/max77693_charger.c52
-rw-r--r--drivers/power/supply/max8998_charger.c1
-rw-r--r--drivers/power/supply/mp2629_charger.c15
-rw-r--r--drivers/power/supply/mt6360_charger.c13
-rw-r--r--drivers/power/supply/mt6370-charger.c13
-rw-r--r--drivers/power/supply/power_supply_core.c19
-rw-r--r--drivers/power/supply/power_supply_hwmon.c3
-rw-r--r--drivers/power/supply/power_supply_sysfs.c66
-rw-r--r--drivers/power/supply/qcom_battmgr.c37
-rw-r--r--drivers/power/supply/qcom_pmi8998_charger.c13
-rw-r--r--drivers/power/supply/rk817_charger.c9
-rw-r--r--drivers/power/supply/rn5t618_power.c13
-rw-r--r--drivers/power/supply/rt9467-charger.c16
-rw-r--r--drivers/power/supply/rt9471.c15
-rw-r--r--drivers/power/supply/twl4030_charger.c2
-rw-r--r--drivers/power/supply/ucs1002_power.c26
25 files changed, 1222 insertions, 312 deletions
diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c
index 270874eeb934..a71903b1bf78 100644
--- a/drivers/power/supply/ab8500_fg.c
+++ b/drivers/power/supply/ab8500_fg.c
@@ -2531,7 +2531,7 @@ static struct attribute *ab8500_fg_attrs[] = {
};
ATTRIBUTE_GROUPS(ab8500_fg);
-static struct kobj_type ab8500_fg_ktype = {
+static const struct kobj_type ab8500_fg_ktype = {
.sysfs_ops = &ab8500_fg_sysfs_ops,
.default_groups = ab8500_fg_groups,
};
diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c
index 6ac5c80cfda2..f71cc90fea12 100644
--- a/drivers/power/supply/axp20x_battery.c
+++ b/drivers/power/supply/axp20x_battery.c
@@ -17,6 +17,7 @@
* GNU General Public License for more details.
*/
+#include <linux/bitfield.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
@@ -32,9 +33,19 @@
#include <linux/mfd/axp20x.h>
#define AXP20X_PWR_STATUS_BAT_CHARGING BIT(2)
+#define AXP717_PWR_STATUS_MASK GENMASK(6, 5)
+#define AXP717_PWR_STATUS_BAT_STANDBY 0
+#define AXP717_PWR_STATUS_BAT_CHRG 1
+#define AXP717_PWR_STATUS_BAT_DISCHRG 2
#define AXP20X_PWR_OP_BATT_PRESENT BIT(5)
#define AXP20X_PWR_OP_BATT_ACTIVATED BIT(3)
+#define AXP717_PWR_OP_BATT_PRESENT BIT(3)
+
+#define AXP717_BATT_PMU_FAULT_MASK GENMASK(2, 0)
+#define AXP717_BATT_UVLO_2_5V BIT(2)
+#define AXP717_BATT_OVER_TEMP BIT(1)
+#define AXP717_BATT_UNDER_TEMP BIT(0)
#define AXP209_FG_PERCENT GENMASK(6, 0)
#define AXP22X_FG_VALID BIT(7)
@@ -49,20 +60,51 @@
#define AXP22X_CHRG_CTRL1_TGT_4_22V (1 << 5)
#define AXP22X_CHRG_CTRL1_TGT_4_24V (3 << 5)
+#define AXP717_CHRG_ENABLE BIT(1)
+#define AXP717_CHRG_CV_VOLT_MASK GENMASK(2, 0)
+#define AXP717_CHRG_CV_4_0V 0
+#define AXP717_CHRG_CV_4_1V 1
+#define AXP717_CHRG_CV_4_2V 2
+#define AXP717_CHRG_CV_4_35V 3
+#define AXP717_CHRG_CV_4_4V 4
+/* Values 5 and 6 reserved. */
+#define AXP717_CHRG_CV_5_0V 7
+
#define AXP813_CHRG_CTRL1_TGT_4_35V (3 << 5)
#define AXP20X_CHRG_CTRL1_TGT_CURR GENMASK(3, 0)
+#define AXP717_ICC_CHARGER_LIM_MASK GENMASK(5, 0)
+
+#define AXP717_ITERM_CHG_LIM_MASK GENMASK(3, 0)
+#define AXP717_ITERM_CC_STEP 64000
#define AXP20X_V_OFF_MASK GENMASK(2, 0)
+#define AXP717_V_OFF_MASK GENMASK(6, 4)
+
+#define AXP717_BAT_VMIN_MIN_UV 2600000
+#define AXP717_BAT_VMIN_MAX_UV 3300000
+#define AXP717_BAT_VMIN_STEP 100000
+#define AXP717_BAT_CV_MIN_UV 4000000
+#define AXP717_BAT_CV_MAX_UV 5000000
+#define AXP717_BAT_CC_MIN_UA 0
+#define AXP717_BAT_CC_MAX_UA 3008000
struct axp20x_batt_ps;
struct axp_data {
- int ccc_scale;
- int ccc_offset;
- bool has_fg_valid;
+ int ccc_scale;
+ int ccc_offset;
+ unsigned int ccc_reg;
+ unsigned int ccc_mask;
+ bool has_fg_valid;
+ const struct power_supply_desc *bat_ps_desc;
int (*get_max_voltage)(struct axp20x_batt_ps *batt, int *val);
int (*set_max_voltage)(struct axp20x_batt_ps *batt, int val);
+ int (*cfg_iio_chan)(struct platform_device *pdev,
+ struct axp20x_batt_ps *axp_batt);
+ void (*set_bat_info)(struct platform_device *pdev,
+ struct axp20x_batt_ps *axp_batt,
+ struct power_supply_battery_info *info);
};
struct axp20x_batt_ps {
@@ -135,6 +177,39 @@ static int axp22x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
return 0;
}
+static int axp717_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
+ int *val)
+{
+ int ret, reg;
+
+ ret = regmap_read(axp20x_batt->regmap, AXP717_CV_CHG_SET, &reg);
+ if (ret)
+ return ret;
+
+ switch (reg & AXP717_CHRG_CV_VOLT_MASK) {
+ case AXP717_CHRG_CV_4_0V:
+ *val = 4000000;
+ return 0;
+ case AXP717_CHRG_CV_4_1V:
+ *val = 4100000;
+ return 0;
+ case AXP717_CHRG_CV_4_2V:
+ *val = 4200000;
+ return 0;
+ case AXP717_CHRG_CV_4_35V:
+ *val = 4350000;
+ return 0;
+ case AXP717_CHRG_CV_4_4V:
+ *val = 4400000;
+ return 0;
+ case AXP717_CHRG_CV_5_0V:
+ *val = 5000000;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
static int axp813_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
int *val)
{
@@ -180,6 +255,21 @@ static int axp20x_get_constant_charge_current(struct axp20x_batt_ps *axp,
return 0;
}
+static int axp717_get_constant_charge_current(struct axp20x_batt_ps *axp,
+ int *val)
+{
+ int ret;
+
+ ret = regmap_read(axp->regmap, AXP717_ICC_CHG_SET, val);
+ if (ret)
+ return ret;
+
+ *val = FIELD_GET(AXP717_ICC_CHARGER_LIM_MASK, *val) *
+ axp->data->ccc_scale;
+
+ return 0;
+}
+
static int axp20x_battery_get_prop(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
@@ -303,11 +393,11 @@ static int axp20x_battery_get_prop(struct power_supply *psy,
val->intval = reg & AXP209_FG_PERCENT;
break;
- case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
return axp20x_batt->data->get_max_voltage(axp20x_batt,
&val->intval);
- case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN:
ret = regmap_read(axp20x_batt->regmap, AXP20X_V_OFF, &reg);
if (ret)
return ret;
@@ -332,6 +422,171 @@ static int axp20x_battery_get_prop(struct power_supply *psy,
return 0;
}
+static int axp717_battery_get_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
+ int ret = 0, reg;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_PRESENT:
+ case POWER_SUPPLY_PROP_ONLINE:
+ ret = regmap_read(axp20x_batt->regmap, AXP717_ON_INDICATE,
+ &reg);
+ if (ret)
+ return ret;
+
+ val->intval = FIELD_GET(AXP717_PWR_OP_BATT_PRESENT, reg);
+ return 0;
+
+ case POWER_SUPPLY_PROP_STATUS:
+ ret = regmap_read(axp20x_batt->regmap, AXP717_PMU_STATUS_2,
+ &reg);
+ if (ret)
+ return ret;
+
+ switch (FIELD_GET(AXP717_PWR_STATUS_MASK, reg)) {
+ case AXP717_PWR_STATUS_BAT_STANDBY:
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ return 0;
+
+ case AXP717_PWR_STATUS_BAT_CHRG:
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ return 0;
+
+ case AXP717_PWR_STATUS_BAT_DISCHRG:
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ return 0;
+
+ default:
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+ return 0;
+ }
+
+ /*
+ * If a fault is detected it must also be cleared; if the
+ * condition persists it should reappear (This is an
+ * assumption, it's actually not documented). A restart was
+ * not sufficient to clear the bit in testing despite the
+ * register listed as POR.
+ */
+ case POWER_SUPPLY_PROP_HEALTH:
+ ret = regmap_read(axp20x_batt->regmap, AXP717_PMU_FAULT,
+ &reg);
+ if (ret)
+ return ret;
+
+ switch (reg & AXP717_BATT_PMU_FAULT_MASK) {
+ case AXP717_BATT_UVLO_2_5V:
+ val->intval = POWER_SUPPLY_HEALTH_DEAD;
+ regmap_update_bits(axp20x_batt->regmap,
+ AXP717_PMU_FAULT,
+ AXP717_BATT_UVLO_2_5V,
+ AXP717_BATT_UVLO_2_5V);
+ return 0;
+
+ case AXP717_BATT_OVER_TEMP:
+ val->intval = POWER_SUPPLY_HEALTH_HOT;
+ regmap_update_bits(axp20x_batt->regmap,
+ AXP717_PMU_FAULT,
+ AXP717_BATT_OVER_TEMP,
+ AXP717_BATT_OVER_TEMP);
+ return 0;
+
+ case AXP717_BATT_UNDER_TEMP:
+ val->intval = POWER_SUPPLY_HEALTH_COLD;
+ regmap_update_bits(axp20x_batt->regmap,
+ AXP717_PMU_FAULT,
+ AXP717_BATT_UNDER_TEMP,
+ AXP717_BATT_UNDER_TEMP);
+ return 0;
+
+ default:
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+ return 0;
+ }
+
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
+ ret = axp717_get_constant_charge_current(axp20x_batt,
+ &val->intval);
+ if (ret)
+ return ret;
+ return 0;
+
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ /*
+ * The offset of this value is currently unknown and is
+ * not documented in the datasheet. Based on
+ * observation it's assumed to be somewhere around
+ * 450ma. I will leave the value raw for now.
+ */
+ ret = iio_read_channel_processed(axp20x_batt->batt_chrg_i, &val->intval);
+ if (ret)
+ return ret;
+ /* IIO framework gives mA but Power Supply framework gives uA */
+ val->intval *= 1000;
+ return 0;
+
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = regmap_read(axp20x_batt->regmap, AXP717_ON_INDICATE,
+ &reg);
+ if (ret)
+ return ret;
+
+ if (!FIELD_GET(AXP717_PWR_OP_BATT_PRESENT, reg))
+ return -ENODEV;
+
+ ret = regmap_read(axp20x_batt->regmap,
+ AXP717_BATT_PERCENT_DATA, &reg);
+ if (ret)
+ return ret;
+
+ /*
+ * Fuel Gauge data takes 7 bits but the stored value seems to be
+ * directly the raw percentage without any scaling to 7 bits.
+ */
+ val->intval = reg & AXP209_FG_PERCENT;
+ return 0;
+
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ return axp20x_batt->data->get_max_voltage(axp20x_batt,
+ &val->intval);
+
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+ ret = regmap_read(axp20x_batt->regmap,
+ AXP717_VSYS_V_POWEROFF, &reg);
+ if (ret)
+ return ret;
+
+ val->intval = AXP717_BAT_VMIN_MIN_UV + AXP717_BAT_VMIN_STEP *
+ (reg & AXP717_V_OFF_MASK);
+ return 0;
+
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ ret = iio_read_channel_processed(axp20x_batt->batt_v,
+ &val->intval);
+ if (ret)
+ return ret;
+
+ /* IIO framework gives mV but Power Supply framework gives uV */
+ val->intval *= 1000;
+ return 0;
+
+ case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+ ret = regmap_read(axp20x_batt->regmap,
+ AXP717_ITERM_CHG_SET, &reg);
+ if (ret)
+ return ret;
+
+ val->intval = (reg & AXP717_ITERM_CHG_LIM_MASK) * AXP717_ITERM_CC_STEP;
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
static int axp22x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt,
int val)
{
@@ -388,6 +643,35 @@ static int axp20x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt,
AXP20X_CHRG_CTRL1_TGT_VOLT, val);
}
+static int axp717_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt,
+ int val)
+{
+ switch (val) {
+ case 4000000:
+ val = AXP717_CHRG_CV_4_0V;
+ break;
+
+ case 4100000:
+ val = AXP717_CHRG_CV_4_1V;
+ break;
+
+ case 4200000:
+ val = AXP717_CHRG_CV_4_2V;
+ break;
+
+ default:
+ /*
+ * AXP717 can go up to 4.35, 4.4, and 5.0 volts which
+ * seem too high for lithium batteries, so do not allow.
+ */
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(axp20x_batt->regmap,
+ AXP717_CV_CHG_SET,
+ AXP717_CHRG_CV_VOLT_MASK, val);
+}
+
static int axp20x_set_constant_charge_current(struct axp20x_batt_ps *axp_batt,
int charge_current)
{
@@ -404,6 +688,24 @@ static int axp20x_set_constant_charge_current(struct axp20x_batt_ps *axp_batt,
AXP20X_CHRG_CTRL1_TGT_CURR, charge_current);
}
+static int axp717_set_constant_charge_current(struct axp20x_batt_ps *axp,
+ int charge_current)
+{
+ int val;
+
+ if (charge_current > axp->max_ccc)
+ return -EINVAL;
+
+ if (charge_current > AXP717_BAT_CC_MAX_UA || charge_current < 0)
+ return -EINVAL;
+
+ val = (charge_current - axp->data->ccc_offset) /
+ axp->data->ccc_scale;
+
+ return regmap_update_bits(axp->regmap, AXP717_ICC_CHG_SET,
+ AXP717_ICC_CHARGER_LIM_MASK, val);
+}
+
static int axp20x_set_max_constant_charge_current(struct axp20x_batt_ps *axp,
int charge_current)
{
@@ -448,6 +750,19 @@ static int axp20x_set_voltage_min_design(struct axp20x_batt_ps *axp_batt,
AXP20X_V_OFF_MASK, val1);
}
+static int axp717_set_voltage_min_design(struct axp20x_batt_ps *axp_batt,
+ int min_voltage)
+{
+ int val1 = (min_voltage - AXP717_BAT_VMIN_MIN_UV) / AXP717_BAT_VMIN_STEP;
+
+ if (val1 < 0 || val1 > AXP717_V_OFF_MASK)
+ return -EINVAL;
+
+ return regmap_update_bits(axp_batt->regmap,
+ AXP717_VSYS_V_POWEROFF,
+ AXP717_V_OFF_MASK, val1);
+}
+
static int axp20x_battery_set_prop(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
@@ -455,10 +770,10 @@ static int axp20x_battery_set_prop(struct power_supply *psy,
struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
switch (psp) {
- case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN:
return axp20x_set_voltage_min_design(axp20x_batt, val->intval);
- case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
return axp20x_batt->data->set_max_voltage(axp20x_batt, val->intval);
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
@@ -484,6 +799,42 @@ static int axp20x_battery_set_prop(struct power_supply *psy,
}
}
+static int axp717_battery_set_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+ return axp717_set_voltage_min_design(axp20x_batt, val->intval);
+
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ return axp20x_batt->data->set_max_voltage(axp20x_batt, val->intval);
+
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
+ return axp717_set_constant_charge_current(axp20x_batt,
+ val->intval);
+ case POWER_SUPPLY_PROP_STATUS:
+ switch (val->intval) {
+ case POWER_SUPPLY_STATUS_CHARGING:
+ return regmap_update_bits(axp20x_batt->regmap,
+ AXP717_MODULE_EN_CONTROL_2,
+ AXP717_CHRG_ENABLE,
+ AXP717_CHRG_ENABLE);
+
+ case POWER_SUPPLY_STATUS_DISCHARGING:
+ case POWER_SUPPLY_STATUS_NOT_CHARGING:
+ return regmap_update_bits(axp20x_batt->regmap,
+ AXP717_MODULE_EN_CONTROL_2,
+ AXP717_CHRG_ENABLE, 0);
+ }
+ return -EINVAL;
+ default:
+ return -EINVAL;
+ }
+}
+
static enum power_supply_property axp20x_battery_props[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
@@ -493,22 +844,45 @@ static enum power_supply_property axp20x_battery_props[] = {
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
POWER_SUPPLY_PROP_HEALTH,
- POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
- POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN,
POWER_SUPPLY_PROP_CAPACITY,
};
+static enum power_supply_property axp717_battery_props[] = {
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
+};
+
static int axp20x_battery_prop_writeable(struct power_supply *psy,
enum power_supply_property psp)
{
return psp == POWER_SUPPLY_PROP_STATUS ||
- psp == POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN ||
- psp == POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN ||
+ psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
+ psp == POWER_SUPPLY_PROP_VOLTAGE_MAX ||
psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT ||
psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX;
}
-static const struct power_supply_desc axp20x_batt_ps_desc = {
+static int axp717_battery_prop_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ return psp == POWER_SUPPLY_PROP_STATUS ||
+ psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
+ psp == POWER_SUPPLY_PROP_VOLTAGE_MAX ||
+ psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX;
+}
+
+static const struct power_supply_desc axp209_batt_ps_desc = {
.name = "axp20x-battery",
.type = POWER_SUPPLY_TYPE_BATTERY,
.properties = axp20x_battery_props,
@@ -518,27 +892,163 @@ static const struct power_supply_desc axp20x_batt_ps_desc = {
.set_property = axp20x_battery_set_prop,
};
+static const struct power_supply_desc axp717_batt_ps_desc = {
+ .name = "axp20x-battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = axp717_battery_props,
+ .num_properties = ARRAY_SIZE(axp717_battery_props),
+ .property_is_writeable = axp717_battery_prop_writeable,
+ .get_property = axp717_battery_get_prop,
+ .set_property = axp717_battery_set_prop,
+};
+
+static int axp209_bat_cfg_iio_channels(struct platform_device *pdev,
+ struct axp20x_batt_ps *axp_batt)
+{
+ axp_batt->batt_v = devm_iio_channel_get(&pdev->dev, "batt_v");
+ if (IS_ERR(axp_batt->batt_v)) {
+ if (PTR_ERR(axp_batt->batt_v) == -ENODEV)
+ return -EPROBE_DEFER;
+ return PTR_ERR(axp_batt->batt_v);
+ }
+
+ axp_batt->batt_chrg_i = devm_iio_channel_get(&pdev->dev,
+ "batt_chrg_i");
+ if (IS_ERR(axp_batt->batt_chrg_i)) {
+ if (PTR_ERR(axp_batt->batt_chrg_i) == -ENODEV)
+ return -EPROBE_DEFER;
+ return PTR_ERR(axp_batt->batt_chrg_i);
+ }
+
+ axp_batt->batt_dischrg_i = devm_iio_channel_get(&pdev->dev,
+ "batt_dischrg_i");
+ if (IS_ERR(axp_batt->batt_dischrg_i)) {
+ if (PTR_ERR(axp_batt->batt_dischrg_i) == -ENODEV)
+ return -EPROBE_DEFER;
+ return PTR_ERR(axp_batt->batt_dischrg_i);
+ }
+
+ return 0;
+}
+
+static int axp717_bat_cfg_iio_channels(struct platform_device *pdev,
+ struct axp20x_batt_ps *axp_batt)
+{
+ axp_batt->batt_v = devm_iio_channel_get(&pdev->dev, "batt_v");
+ if (IS_ERR(axp_batt->batt_v)) {
+ if (PTR_ERR(axp_batt->batt_v) == -ENODEV)
+ return -EPROBE_DEFER;
+ return PTR_ERR(axp_batt->batt_v);
+ }
+
+ axp_batt->batt_chrg_i = devm_iio_channel_get(&pdev->dev,
+ "batt_chrg_i");
+ if (IS_ERR(axp_batt->batt_chrg_i)) {
+ if (PTR_ERR(axp_batt->batt_chrg_i) == -ENODEV)
+ return -EPROBE_DEFER;
+ return PTR_ERR(axp_batt->batt_chrg_i);
+ }
+
+ return 0;
+}
+
+static void axp209_set_battery_info(struct platform_device *pdev,
+ struct axp20x_batt_ps *axp_batt,
+ struct power_supply_battery_info *info)
+{
+ int vmin = info->voltage_min_design_uv;
+ int ccc = info->constant_charge_current_max_ua;
+
+ if (vmin > 0 && axp20x_set_voltage_min_design(axp_batt, vmin))
+ dev_err(&pdev->dev,
+ "couldn't set voltage_min_design\n");
+
+ /* Set max to unverified value to be able to set CCC */
+ axp_batt->max_ccc = ccc;
+
+ if (ccc <= 0 || axp20x_set_constant_charge_current(axp_batt, ccc)) {
+ dev_err(&pdev->dev,
+ "couldn't set ccc from DT: fallback to min value\n");
+ ccc = 300000;
+ axp_batt->max_ccc = ccc;
+ axp20x_set_constant_charge_current(axp_batt, ccc);
+ }
+}
+
+static void axp717_set_battery_info(struct platform_device *pdev,
+ struct axp20x_batt_ps *axp_batt,
+ struct power_supply_battery_info *info)
+{
+ int vmin = info->voltage_min_design_uv;
+ int vmax = info->voltage_max_design_uv;
+ int ccc = info->constant_charge_current_max_ua;
+ int val;
+
+ if (vmin > 0 && axp717_set_voltage_min_design(axp_batt, vmin))
+ dev_err(&pdev->dev,
+ "couldn't set voltage_min_design\n");
+
+ if (vmax > 0 && axp717_battery_set_max_voltage(axp_batt, vmax))
+ dev_err(&pdev->dev,
+ "couldn't set voltage_max_design\n");
+
+ axp717_get_constant_charge_current(axp_batt, &val);
+ axp_batt->max_ccc = ccc;
+ if (ccc <= 0 || axp717_set_constant_charge_current(axp_batt, ccc)) {
+ dev_err(&pdev->dev,
+ "couldn't set ccc from DT: current ccc is %d\n",
+ val);
+ }
+}
+
static const struct axp_data axp209_data = {
.ccc_scale = 100000,
.ccc_offset = 300000,
+ .ccc_reg = AXP20X_CHRG_CTRL1,
+ .ccc_mask = AXP20X_CHRG_CTRL1_TGT_CURR,
+ .bat_ps_desc = &axp209_batt_ps_desc,
.get_max_voltage = axp20x_battery_get_max_voltage,
.set_max_voltage = axp20x_battery_set_max_voltage,
+ .cfg_iio_chan = axp209_bat_cfg_iio_channels,
+ .set_bat_info = axp209_set_battery_info,
};
static const struct axp_data axp221_data = {
.ccc_scale = 150000,
.ccc_offset = 300000,
+ .ccc_reg = AXP20X_CHRG_CTRL1,
+ .ccc_mask = AXP20X_CHRG_CTRL1_TGT_CURR,
.has_fg_valid = true,
+ .bat_ps_desc = &axp209_batt_ps_desc,
.get_max_voltage = axp22x_battery_get_max_voltage,
.set_max_voltage = axp22x_battery_set_max_voltage,
+ .cfg_iio_chan = axp209_bat_cfg_iio_channels,
+ .set_bat_info = axp209_set_battery_info,
+};
+
+static const struct axp_data axp717_data = {
+ .ccc_scale = 64000,
+ .ccc_offset = 0,
+ .ccc_reg = AXP717_ICC_CHG_SET,
+ .ccc_mask = AXP717_ICC_CHARGER_LIM_MASK,
+ .bat_ps_desc = &axp717_batt_ps_desc,
+ .get_max_voltage = axp717_battery_get_max_voltage,
+ .set_max_voltage = axp717_battery_set_max_voltage,
+ .cfg_iio_chan = axp717_bat_cfg_iio_channels,
+ .set_bat_info = axp717_set_battery_info,
};
static const struct axp_data axp813_data = {
.ccc_scale = 200000,
.ccc_offset = 200000,
+ .ccc_reg = AXP20X_CHRG_CTRL1,
+ .ccc_mask = AXP20X_CHRG_CTRL1_TGT_CURR,
.has_fg_valid = true,
+ .bat_ps_desc = &axp209_batt_ps_desc,
.get_max_voltage = axp813_battery_get_max_voltage,
.set_max_voltage = axp20x_battery_set_max_voltage,
+ .cfg_iio_chan = axp209_bat_cfg_iio_channels,
+ .set_bat_info = axp209_set_battery_info,
};
static const struct of_device_id axp20x_battery_ps_id[] = {
@@ -549,6 +1059,9 @@ static const struct of_device_id axp20x_battery_ps_id[] = {
.compatible = "x-powers,axp221-battery-power-supply",
.data = (void *)&axp221_data,
}, {
+ .compatible = "x-powers,axp717-battery-power-supply",
+ .data = (void *)&axp717_data,
+ }, {
.compatible = "x-powers,axp813-battery-power-supply",
.data = (void *)&axp813_data,
}, { /* sentinel */ },
@@ -561,6 +1074,7 @@ static int axp20x_power_probe(struct platform_device *pdev)
struct power_supply_config psy_cfg = {};
struct power_supply_battery_info *info;
struct device *dev = &pdev->dev;
+ int ret;
if (!of_device_is_available(pdev->dev.of_node))
return -ENODEV;
@@ -572,29 +1086,6 @@ static int axp20x_power_probe(struct platform_device *pdev)
axp20x_batt->dev = &pdev->dev;
- axp20x_batt->batt_v = devm_iio_channel_get(&pdev->dev, "batt_v");
- if (IS_ERR(axp20x_batt->batt_v)) {
- if (PTR_ERR(axp20x_batt->batt_v) == -ENODEV)
- return -EPROBE_DEFER;
- return PTR_ERR(axp20x_batt->batt_v);
- }
-
- axp20x_batt->batt_chrg_i = devm_iio_channel_get(&pdev->dev,
- "batt_chrg_i");
- if (IS_ERR(axp20x_batt->batt_chrg_i)) {
- if (PTR_ERR(axp20x_batt->batt_chrg_i) == -ENODEV)
- return -EPROBE_DEFER;
- return PTR_ERR(axp20x_batt->batt_chrg_i);
- }
-
- axp20x_batt->batt_dischrg_i = devm_iio_channel_get(&pdev->dev,
- "batt_dischrg_i");
- if (IS_ERR(axp20x_batt->batt_dischrg_i)) {
- if (PTR_ERR(axp20x_batt->batt_dischrg_i) == -ENODEV)
- return -EPROBE_DEFER;
- return PTR_ERR(axp20x_batt->batt_dischrg_i);
- }
-
axp20x_batt->regmap = dev_get_regmap(pdev->dev.parent, NULL);
platform_set_drvdata(pdev, axp20x_batt);
@@ -603,8 +1094,12 @@ static int axp20x_power_probe(struct platform_device *pdev)
axp20x_batt->data = (struct axp_data *)of_device_get_match_data(dev);
+ ret = axp20x_batt->data->cfg_iio_chan(pdev, axp20x_batt);
+ if (ret)
+ return ret;
+
axp20x_batt->batt = devm_power_supply_register(&pdev->dev,
- &axp20x_batt_ps_desc,
+ axp20x_batt->data->bat_ps_desc,
&psy_cfg);
if (IS_ERR(axp20x_batt->batt)) {
dev_err(&pdev->dev, "failed to register power supply: %ld\n",
@@ -613,33 +1108,15 @@ static int axp20x_power_probe(struct platform_device *pdev)
}
if (!power_supply_get_battery_info(axp20x_batt->batt, &info)) {
- int vmin = info->voltage_min_design_uv;
- int ccc = info->constant_charge_current_max_ua;
-
- if (vmin > 0 && axp20x_set_voltage_min_design(axp20x_batt,
- vmin))
- dev_err(&pdev->dev,
- "couldn't set voltage_min_design\n");
-
- /* Set max to unverified value to be able to set CCC */
- axp20x_batt->max_ccc = ccc;
-
- if (ccc <= 0 || axp20x_set_constant_charge_current(axp20x_batt,
- ccc)) {
- dev_err(&pdev->dev,
- "couldn't set constant charge current from DT: fallback to minimum value\n");
- ccc = 300000;
- axp20x_batt->max_ccc = ccc;
- axp20x_set_constant_charge_current(axp20x_batt, ccc);
- }
+ axp20x_batt->data->set_bat_info(pdev, axp20x_batt, info);
+ power_supply_put_battery_info(axp20x_batt->batt, info);
}
/*
* Update max CCC to a valid value if battery info is present or set it
* to current register value by default.
*/
- axp20x_get_constant_charge_current(axp20x_batt,
- &axp20x_batt->max_ccc);
+ axp20x_get_constant_charge_current(axp20x_batt, &axp20x_batt->max_ccc);
return 0;
}
diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index dae7e5cfc54e..2766352ab737 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -30,8 +30,13 @@
#define AXP20X_PWR_STATUS_VBUS_PRESENT BIT(5)
#define AXP20X_PWR_STATUS_VBUS_USED BIT(4)
+#define AXP717_PWR_STATUS_VBUS_GOOD BIT(5)
+
#define AXP20X_USB_STATUS_VBUS_VALID BIT(2)
+#define AXP717_PMU_FAULT_VBUS BIT(5)
+#define AXP717_PMU_FAULT_VSYS BIT(3)
+
#define AXP20X_VBUS_VHOLD_uV(b) (4000000 + (((b) >> 3) & 7) * 100000)
#define AXP20X_VBUS_VHOLD_MASK GENMASK(5, 3)
#define AXP20X_VBUS_VHOLD_OFFSET 3
@@ -39,12 +44,20 @@
#define AXP20X_ADC_EN1_VBUS_CURR BIT(2)
#define AXP20X_ADC_EN1_VBUS_VOLT BIT(3)
+#define AXP717_INPUT_VOL_LIMIT_MASK GENMASK(3, 0)
+#define AXP717_INPUT_CUR_LIMIT_MASK GENMASK(5, 0)
+#define AXP717_ADC_DATA_MASK GENMASK(14, 0)
+
+#define AXP717_ADC_EN_VBUS_VOLT BIT(2)
+
/*
* Note do not raise the debounce time, we must report Vusb high within
* 100ms otherwise we get Vbus errors in musb.
*/
#define DEBOUNCE_TIME msecs_to_jiffies(50)
+struct axp20x_usb_power;
+
struct axp_data {
const struct power_supply_desc *power_desc;
const char * const *irq_names;
@@ -58,6 +71,10 @@ struct axp_data {
struct reg_field usb_bc_det_fld;
struct reg_field vbus_disable_bit;
bool vbus_needs_polling: 1;
+ void (*axp20x_read_vbus)(struct work_struct *work);
+ int (*axp20x_cfg_iio_chan)(struct platform_device *pdev,
+ struct axp20x_usb_power *power);
+ int (*axp20x_cfg_adc_reg)(struct axp20x_usb_power *power);
};
struct axp20x_usb_power {
@@ -74,6 +91,7 @@ struct axp20x_usb_power {
struct iio_channel *vbus_v;
struct iio_channel *vbus_i;
struct delayed_work vbus_detect;
+ int max_input_cur;
unsigned int old_status;
unsigned int online;
unsigned int num_irqs;
@@ -136,6 +154,24 @@ out:
mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);
}
+static void axp717_usb_power_poll_vbus(struct work_struct *work)
+{
+ struct axp20x_usb_power *power =
+ container_of(work, struct axp20x_usb_power, vbus_detect.work);
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(power->regmap, AXP717_ON_INDICATE, &val);
+ if (ret)
+ return;
+
+ val &= AXP717_PWR_STATUS_VBUS_GOOD;
+ if (val != power->old_status)
+ power_supply_changed(power->supply);
+
+ power->old_status = val;
+}
+
static int axp20x_get_usb_type(struct axp20x_usb_power *power,
union power_supply_propval *val)
{
@@ -281,6 +317,91 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
return 0;
}
+static int axp717_usb_power_get_property(struct power_supply *psy,
+ enum power_supply_property psp, union power_supply_propval *val)
+{
+ struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
+ unsigned int v;
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_HEALTH:
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+ ret = regmap_read(power->regmap, AXP717_ON_INDICATE, &v);
+ if (ret)
+ return ret;
+
+ if (!(v & AXP717_PWR_STATUS_VBUS_GOOD))
+ val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
+
+ ret = regmap_read(power->regmap, AXP717_PMU_FAULT_VBUS, &v);
+ if (ret)
+ return ret;
+
+ v &= (AXP717_PMU_FAULT_VBUS | AXP717_PMU_FAULT_VSYS);
+ if (v) {
+ val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+ regmap_write(power->regmap, AXP717_PMU_FAULT_VBUS, v);
+ }
+
+ break;
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ ret = regmap_read(power->regmap, AXP717_INPUT_CUR_LIMIT_CTRL, &v);
+ if (ret)
+ return ret;
+
+ /* 50ma step size with 100ma offset. */
+ v &= AXP717_INPUT_CUR_LIMIT_MASK;
+ val->intval = (v * 50000) + 100000;
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ case POWER_SUPPLY_PROP_PRESENT:
+ ret = regmap_read(power->regmap, AXP717_ON_INDICATE, &v);
+ if (ret)
+ return ret;
+ val->intval = !!(v & AXP717_PWR_STATUS_VBUS_GOOD);
+ break;
+ case POWER_SUPPLY_PROP_USB_TYPE:
+ return axp20x_get_usb_type(power, val);
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+ ret = regmap_read(power->regmap, AXP717_INPUT_VOL_LIMIT_CTRL, &v);
+ if (ret)
+ return ret;
+
+ /* 80mv step size with 3.88v offset. */
+ v &= AXP717_INPUT_VOL_LIMIT_MASK;
+ val->intval = (v * 80000) + 3880000;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
+ ret = iio_read_channel_processed(power->vbus_v,
+ &val->intval);
+ if (ret)
+ return ret;
+
+ /*
+ * IIO framework gives mV but Power Supply framework
+ * gives uV.
+ */
+ val->intval *= 1000;
+ return 0;
+ }
+
+ ret = axp20x_read_variable_width(power->regmap,
+ AXP717_VBUS_V_H, 16);
+ if (ret < 0)
+ return ret;
+
+ val->intval = (ret % AXP717_ADC_DATA_MASK) * 1000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+
+}
+
static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
int intval)
{
@@ -307,6 +428,22 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
return -EINVAL;
}
+static int axp717_usb_power_set_voltage_min(struct axp20x_usb_power *power,
+ int intval)
+{
+ int val;
+
+ /* Minimum value of 3.88v and maximum of 5.08v. */
+ if (intval < 3880000 || intval > 5080000)
+ return -EINVAL;
+
+ /* step size of 80ma with 3.88v offset. */
+ val = (intval - 3880000) / 80000;
+ return regmap_update_bits(power->regmap,
+ AXP717_INPUT_VOL_LIMIT_CTRL,
+ AXP717_INPUT_VOL_LIMIT_MASK, val);
+}
+
static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *power,
int intval)
{
@@ -317,6 +454,13 @@ static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *pow
if (intval == -1)
return -EINVAL;
+ if (power->max_input_cur && (intval > power->max_input_cur)) {
+ dev_warn(power->dev,
+ "requested current %d clamped to max current %d\n",
+ intval, power->max_input_cur);
+ intval = power->max_input_cur;
+ }
+
/*
* BC1.2 detection can cause a race condition if we try to set a current
* limit while it's in progress. When it finishes it will overwrite the
@@ -340,6 +484,29 @@ static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *pow
return regmap_field_write(power->curr_lim_fld, reg);
}
+static int axp717_usb_power_set_input_current_limit(struct axp20x_usb_power *power,
+ int intval)
+{
+ int tmp;
+
+ /* Minimum value of 100mA and maximum value of 3.25A*/
+ if (intval < 100000 || intval > 3250000)
+ return -EINVAL;
+
+ if (power->max_input_cur && (intval > power->max_input_cur)) {
+ dev_warn(power->dev,
+ "reqested current %d clamped to max current %d\n",
+ intval, power->max_input_cur);
+ intval = power->max_input_cur;
+ }
+
+ /* Minimum value of 100mA with step size of 50mA. */
+ tmp = (intval - 100000) / 50000;
+ return regmap_update_bits(power->regmap,
+ AXP717_INPUT_CUR_LIMIT_CTRL,
+ AXP717_INPUT_CUR_LIMIT_MASK, tmp);
+}
+
static int axp20x_usb_power_set_property(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
@@ -362,6 +529,24 @@ static int axp20x_usb_power_set_property(struct power_supply *psy,
default:
return -EINVAL;
}
+}
+
+static int axp717_usb_power_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ return axp717_usb_power_set_input_current_limit(power, val->intval);
+
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+ return axp717_usb_power_set_voltage_min(power, val->intval);
+
+ default:
+ return -EINVAL;
+ }
return -EINVAL;
}
@@ -385,6 +570,64 @@ static int axp20x_usb_power_prop_writeable(struct power_supply *psy,
psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;
}
+static int axp717_usb_power_prop_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
+ psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;
+}
+
+static int axp20x_configure_iio_channels(struct platform_device *pdev,
+ struct axp20x_usb_power *power)
+{
+ power->vbus_v = devm_iio_channel_get(&pdev->dev, "vbus_v");
+ if (IS_ERR(power->vbus_v)) {
+ if (PTR_ERR(power->vbus_v) == -ENODEV)
+ return -EPROBE_DEFER;
+ return PTR_ERR(power->vbus_v);
+ }
+
+ power->vbus_i = devm_iio_channel_get(&pdev->dev, "vbus_i");
+ if (IS_ERR(power->vbus_i)) {
+ if (PTR_ERR(power->vbus_i) == -ENODEV)
+ return -EPROBE_DEFER;
+ return PTR_ERR(power->vbus_i);
+ }
+
+ return 0;
+}
+
+static int axp717_configure_iio_channels(struct platform_device *pdev,
+ struct axp20x_usb_power *power)
+{
+ power->vbus_v = devm_iio_channel_get(&pdev->dev, "vbus_v");
+ if (IS_ERR(power->vbus_v)) {
+ if (PTR_ERR(power->vbus_v) == -ENODEV)
+ return -EPROBE_DEFER;
+ return PTR_ERR(power->vbus_v);
+ }
+
+ return 0;
+}
+
+static int axp20x_configure_adc_registers(struct axp20x_usb_power *power)
+{
+ /* Enable vbus voltage and current measurement */
+ return regmap_update_bits(power->regmap, AXP20X_ADC_EN1,
+ AXP20X_ADC_EN1_VBUS_CURR |
+ AXP20X_ADC_EN1_VBUS_VOLT,
+ AXP20X_ADC_EN1_VBUS_CURR |
+ AXP20X_ADC_EN1_VBUS_VOLT);
+}
+
+static int axp717_configure_adc_registers(struct axp20x_usb_power *power)
+{
+ /* Enable vbus voltage measurement */
+ return regmap_update_bits(power->regmap, AXP717_ADC_CH_EN_CONTROL,
+ AXP717_ADC_EN_VBUS_VOLT,
+ AXP717_ADC_EN_VBUS_VOLT);
+}
+
static enum power_supply_property axp20x_usb_power_properties[] = {
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_PRESENT,
@@ -403,6 +646,16 @@ static enum power_supply_property axp22x_usb_power_properties[] = {
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
};
+static enum power_supply_property axp717_usb_power_properties[] = {
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_USB_TYPE,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
static enum power_supply_property axp813_usb_power_properties[] = {
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_PRESENT,
@@ -412,13 +665,6 @@ static enum power_supply_property axp813_usb_power_properties[] = {
POWER_SUPPLY_PROP_USB_TYPE,
};
-static enum power_supply_usb_type axp813_usb_types[] = {
- POWER_SUPPLY_USB_TYPE_SDP,
- POWER_SUPPLY_USB_TYPE_DCP,
- POWER_SUPPLY_USB_TYPE_CDP,
- POWER_SUPPLY_USB_TYPE_UNKNOWN,
-};
-
static const struct power_supply_desc axp20x_usb_power_desc = {
.name = "axp20x-usb",
.type = POWER_SUPPLY_TYPE_USB,
@@ -439,6 +685,20 @@ static const struct power_supply_desc axp22x_usb_power_desc = {
.set_property = axp20x_usb_power_set_property,
};
+static const struct power_supply_desc axp717_usb_power_desc = {
+ .name = "axp20x-usb",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .properties = axp717_usb_power_properties,
+ .num_properties = ARRAY_SIZE(axp717_usb_power_properties),
+ .property_is_writeable = axp717_usb_power_prop_writeable,
+ .get_property = axp717_usb_power_get_property,
+ .set_property = axp717_usb_power_set_property,
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
+};
+
static const struct power_supply_desc axp813_usb_power_desc = {
.name = "axp20x-usb",
.type = POWER_SUPPLY_TYPE_USB,
@@ -447,8 +707,10 @@ static const struct power_supply_desc axp813_usb_power_desc = {
.property_is_writeable = axp20x_usb_power_prop_writeable,
.get_property = axp20x_usb_power_get_property,
.set_property = axp20x_usb_power_set_property,
- .usb_types = axp813_usb_types,
- .num_usb_types = ARRAY_SIZE(axp813_usb_types),
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
};
static const char * const axp20x_irq_names[] = {
@@ -463,6 +725,12 @@ static const char * const axp22x_irq_names[] = {
"VBUS_REMOVAL",
};
+static const char * const axp717_irq_names[] = {
+ "VBUS_PLUGIN",
+ "VBUS_REMOVAL",
+ "VBUS_OVER_V",
+};
+
static int axp192_usb_curr_lim_table[] = {
-1,
-1,
@@ -505,6 +773,9 @@ static const struct axp_data axp192_data = {
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_valid_bit = REG_FIELD(AXP192_USB_OTG_STATUS, 2, 2),
.vbus_mon_bit = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
+ .axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
+ .axp20x_cfg_iio_chan = axp20x_configure_iio_channels,
+ .axp20x_cfg_adc_reg = axp20x_configure_adc_registers,
};
static const struct axp_data axp202_data = {
@@ -516,6 +787,9 @@ static const struct axp_data axp202_data = {
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_valid_bit = REG_FIELD(AXP20X_USB_OTG_STATUS, 2, 2),
.vbus_mon_bit = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
+ .axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
+ .axp20x_cfg_iio_chan = axp20x_configure_iio_channels,
+ .axp20x_cfg_adc_reg = axp20x_configure_adc_registers,
};
static const struct axp_data axp221_data = {
@@ -526,6 +800,9 @@ static const struct axp_data axp221_data = {
.curr_lim_table_size = ARRAY_SIZE(axp221_usb_curr_lim_table),
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_needs_polling = true,
+ .axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
+ .axp20x_cfg_iio_chan = axp20x_configure_iio_channels,
+ .axp20x_cfg_adc_reg = axp20x_configure_adc_registers,
};
static const struct axp_data axp223_data = {
@@ -536,6 +813,23 @@ static const struct axp_data axp223_data = {
.curr_lim_table_size = ARRAY_SIZE(axp20x_usb_curr_lim_table),
.curr_lim_fld = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
.vbus_needs_polling = true,
+ .axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
+ .axp20x_cfg_iio_chan = axp20x_configure_iio_channels,
+ .axp20x_cfg_adc_reg = axp20x_configure_adc_registers,
+};
+
+static const struct axp_data axp717_data = {
+ .power_desc = &axp717_usb_power_desc,
+ .irq_names = axp717_irq_names,
+ .num_irq_names = ARRAY_SIZE(axp717_irq_names),
+ .curr_lim_fld = REG_FIELD(AXP717_INPUT_CUR_LIMIT_CTRL, 0, 5),
+ .usb_bc_en_bit = REG_FIELD(AXP717_MODULE_EN_CONTROL_1, 4, 4),
+ .usb_bc_det_fld = REG_FIELD(AXP717_BC_DETECT, 5, 7),
+ .vbus_mon_bit = REG_FIELD(AXP717_ADC_CH_EN_CONTROL, 2, 2),
+ .vbus_needs_polling = false,
+ .axp20x_read_vbus = &axp717_usb_power_poll_vbus,
+ .axp20x_cfg_iio_chan = axp717_configure_iio_channels,
+ .axp20x_cfg_adc_reg = axp717_configure_adc_registers,
};
static const struct axp_data axp813_data = {
@@ -549,6 +843,9 @@ static const struct axp_data axp813_data = {
.usb_bc_det_fld = REG_FIELD(AXP288_BC_DET_STAT, 5, 7),
.vbus_disable_bit = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 7, 7),
.vbus_needs_polling = true,
+ .axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
+ .axp20x_cfg_iio_chan = axp20x_configure_iio_channels,
+ .axp20x_cfg_adc_reg = axp20x_configure_adc_registers,
};
#ifdef CONFIG_PM_SLEEP
@@ -590,36 +887,6 @@ static int axp20x_usb_power_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(axp20x_usb_power_pm_ops, axp20x_usb_power_suspend,
axp20x_usb_power_resume);
-static int configure_iio_channels(struct platform_device *pdev,
- struct axp20x_usb_power *power)
-{
- power->vbus_v = devm_iio_channel_get(&pdev->dev, "vbus_v");
- if (IS_ERR(power->vbus_v)) {
- if (PTR_ERR(power->vbus_v) == -ENODEV)
- return -EPROBE_DEFER;
- return PTR_ERR(power->vbus_v);
- }
-
- power->vbus_i = devm_iio_channel_get(&pdev->dev, "vbus_i");
- if (IS_ERR(power->vbus_i)) {
- if (PTR_ERR(power->vbus_i) == -ENODEV)
- return -EPROBE_DEFER;
- return PTR_ERR(power->vbus_i);
- }
-
- return 0;
-}
-
-static int configure_adc_registers(struct axp20x_usb_power *power)
-{
- /* Enable vbus voltage and current measurement */
- return regmap_update_bits(power->regmap, AXP20X_ADC_EN1,
- AXP20X_ADC_EN1_VBUS_CURR |
- AXP20X_ADC_EN1_VBUS_VOLT,
- AXP20X_ADC_EN1_VBUS_CURR |
- AXP20X_ADC_EN1_VBUS_VOLT);
-}
-
static int axp20x_regmap_field_alloc_optional(struct device *dev,
struct regmap *regmap,
struct reg_field fdesc,
@@ -640,6 +907,18 @@ static int axp20x_regmap_field_alloc_optional(struct device *dev,
return 0;
}
+/* Optionally allow users to specify a maximum charging current. */
+static void axp20x_usb_power_parse_dt(struct device *dev,
+ struct axp20x_usb_power *power)
+{
+ int ret;
+
+ ret = device_property_read_u32(dev, "input-current-limit-microamp",
+ &power->max_input_cur);
+ if (ret)
+ dev_dbg(dev, "%s() no input-current-limit specified\n", __func__);
+}
+
static int axp20x_usb_power_probe(struct platform_device *pdev)
{
struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
@@ -676,6 +955,8 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
if (IS_ERR(power->curr_lim_fld))
return PTR_ERR(power->curr_lim_fld);
+ axp20x_usb_power_parse_dt(&pdev->dev, power);
+
ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
axp_data->vbus_valid_bit,
&power->vbus_valid_bit);
@@ -707,7 +988,7 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
return ret;
ret = devm_delayed_work_autocancel(&pdev->dev, &power->vbus_detect,
- axp20x_usb_power_poll_vbus);
+ axp_data->axp20x_read_vbus);
if (ret)
return ret;
@@ -718,9 +999,9 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
return ret;
if (IS_ENABLED(CONFIG_AXP20X_ADC))
- ret = configure_iio_channels(pdev, power);
+ ret = axp_data->axp20x_cfg_iio_chan(pdev, power);
else
- ret = configure_adc_registers(power);
+ ret = axp_data->axp20x_cfg_adc_reg(power);
if (ret)
return ret;
@@ -779,6 +1060,9 @@ static const struct of_device_id axp20x_usb_power_match[] = {
.compatible = "x-powers,axp223-usb-power-supply",
.data = &axp223_data,
}, {
+ .compatible = "x-powers,axp717-usb-power-supply",
+ .data = &axp717_data,
+ }, {
.compatible = "x-powers,axp813-usb-power-supply",
.data = &axp813_data,
}, { /* sentinel */ }
diff --git a/drivers/power/supply/bq256xx_charger.c b/drivers/power/supply/bq256xx_charger.c
index 1a935bc88510..5514d1896bb8 100644
--- a/drivers/power/supply/bq256xx_charger.c
+++ b/drivers/power/supply/bq256xx_charger.c
@@ -334,14 +334,6 @@ static const int bq25618_619_ichg_values[] = {
1290000, 1360000, 1430000, 1500000
};
-static enum power_supply_usb_type bq256xx_usb_type[] = {
- POWER_SUPPLY_USB_TYPE_SDP,
- POWER_SUPPLY_USB_TYPE_CDP,
- POWER_SUPPLY_USB_TYPE_DCP,
- POWER_SUPPLY_USB_TYPE_UNKNOWN,
- POWER_SUPPLY_USB_TYPE_ACA,
-};
-
static int bq256xx_array_parse(int array_size, int val, const int array[])
{
int i = 0;
@@ -1252,8 +1244,11 @@ static int bq256xx_property_is_writeable(struct power_supply *psy,
static const struct power_supply_desc bq256xx_power_supply_desc = {
.name = "bq256xx-charger",
.type = POWER_SUPPLY_TYPE_USB,
- .usb_types = bq256xx_usb_type,
- .num_usb_types = ARRAY_SIZE(bq256xx_usb_type),
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_ACA) |
+ BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.properties = bq256xx_power_supply_props,
.num_properties = ARRAY_SIZE(bq256xx_power_supply_props),
.get_property = bq256xx_get_charger_property,
diff --git a/drivers/power/supply/cpcap-charger.c b/drivers/power/supply/cpcap-charger.c
index cebca34ff872..91e7292d86bb 100644
--- a/drivers/power/supply/cpcap-charger.c
+++ b/drivers/power/supply/cpcap-charger.c
@@ -904,7 +904,7 @@ static int cpcap_charger_probe(struct platform_device *pdev)
psy_cfg.of_node = pdev->dev.of_node;
psy_cfg.drv_data = ddata;
psy_cfg.supplied_to = cpcap_charger_supplied_to;
- psy_cfg.num_supplicants = ARRAY_SIZE(cpcap_charger_supplied_to),
+ psy_cfg.num_supplicants = ARRAY_SIZE(cpcap_charger_supplied_to);
ddata->usb = devm_power_supply_register(ddata->dev,
&cpcap_charger_usb_desc,
diff --git a/drivers/power/supply/cros_usbpd-charger.c b/drivers/power/supply/cros_usbpd-charger.c
index 8008e31c0c09..bed3e2e9bfea 100644
--- a/drivers/power/supply/cros_usbpd-charger.c
+++ b/drivers/power/supply/cros_usbpd-charger.c
@@ -73,17 +73,6 @@ static enum power_supply_property cros_usbpd_dedicated_charger_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
};
-static enum power_supply_usb_type cros_usbpd_charger_usb_types[] = {
- POWER_SUPPLY_USB_TYPE_UNKNOWN,
- POWER_SUPPLY_USB_TYPE_SDP,
- POWER_SUPPLY_USB_TYPE_DCP,
- POWER_SUPPLY_USB_TYPE_CDP,
- POWER_SUPPLY_USB_TYPE_C,
- POWER_SUPPLY_USB_TYPE_PD,
- POWER_SUPPLY_USB_TYPE_PD_DRP,
- POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID
-};
-
/* Input voltage/current limit in mV/mA. Default to none. */
static u16 input_voltage_limit = EC_POWER_LIMIT_NONE;
static u16 input_current_limit = EC_POWER_LIMIT_NONE;
@@ -643,9 +632,14 @@ static int cros_usbpd_charger_probe(struct platform_device *pd)
psy_desc->properties = cros_usbpd_charger_props;
psy_desc->num_properties =
ARRAY_SIZE(cros_usbpd_charger_props);
- psy_desc->usb_types = cros_usbpd_charger_usb_types;
- psy_desc->num_usb_types =
- ARRAY_SIZE(cros_usbpd_charger_usb_types);
+ psy_desc->usb_types = BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN) |
+ BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_C) |
+ BIT(POWER_SUPPLY_USB_TYPE_PD) |
+ BIT(POWER_SUPPLY_USB_TYPE_PD_DRP) |
+ BIT(POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID);
}
psy_desc->name = port->name;
diff --git a/drivers/power/supply/lenovo_yoga_c630_battery.c b/drivers/power/supply/lenovo_yoga_c630_battery.c
index d4d422cc5353..f98f65e00831 100644
--- a/drivers/power/supply/lenovo_yoga_c630_battery.c
+++ b/drivers/power/supply/lenovo_yoga_c630_battery.c
@@ -353,15 +353,10 @@ static enum power_supply_property yoga_c630_psy_adpt_properties[] = {
POWER_SUPPLY_PROP_USB_TYPE,
};
-static const enum power_supply_usb_type yoga_c630_psy_adpt_usb_type[] = {
- POWER_SUPPLY_USB_TYPE_C,
-};
-
static const struct power_supply_desc yoga_c630_psy_adpt_psy_desc = {
.name = "yoga-c630-adapter",
.type = POWER_SUPPLY_TYPE_USB,
- .usb_types = yoga_c630_psy_adpt_usb_type,
- .num_usb_types = ARRAY_SIZE(yoga_c630_psy_adpt_usb_type),
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_C),
.properties = yoga_c630_psy_adpt_properties,
.num_properties = ARRAY_SIZE(yoga_c630_psy_adpt_properties),
.get_property = yoga_c630_psy_adpt_get_property,
diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c
index e7d37e422c3f..496c3e1f2ee6 100644
--- a/drivers/power/supply/max17042_battery.c
+++ b/drivers/power/supply/max17042_battery.c
@@ -853,7 +853,10 @@ static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off)
/* program interrupt thresholds such that we should
* get interrupt for every 'off' perc change in the soc
*/
- regmap_read(map, MAX17042_RepSOC, &soc);
+ if (chip->pdata->enable_current_sense)
+ regmap_read(map, MAX17042_RepSOC, &soc);
+ else
+ regmap_read(map, MAX17042_VFSOC, &soc);
soc >>= 8;
soc_tr = (soc + off) << 8;
if (off < soc)
diff --git a/drivers/power/supply/max1720x_battery.c b/drivers/power/supply/max1720x_battery.c
index edc262f0a62f..2bc3dce963a3 100644
--- a/drivers/power/supply/max1720x_battery.c
+++ b/drivers/power/supply/max1720x_battery.c
@@ -10,13 +10,16 @@
#include <linux/bitfield.h>
#include <linux/i2c.h>
#include <linux/module.h>
+#include <linux/nvmem-provider.h>
#include <linux/power_supply.h>
#include <linux/regmap.h>
#include <asm/unaligned.h>
/* Nonvolatile registers */
+#define MAX1720X_NXTABLE0 0x80
#define MAX1720X_NRSENSE 0xCF /* RSense in 10^-5 Ohm */
+#define MAX1720X_NDEVICE_NAME4 0xDF
/* ModelGauge m5 */
#define MAX172XX_STATUS 0x00 /* Status */
@@ -46,6 +49,8 @@ static const char *const max17205_model = "MAX17205";
struct max1720x_device_info {
struct regmap *regmap;
+ struct regmap *regmap_nv;
+ struct i2c_client *ancillary;
int rsense;
};
@@ -106,6 +111,134 @@ static const struct regmap_config max1720x_regmap_cfg = {
.cache_type = REGCACHE_RBTREE,
};
+static const struct regmap_range max1720x_nvmem_allow[] = {
+ regmap_reg_range(MAX1720X_NXTABLE0, MAX1720X_NDEVICE_NAME4),
+};
+
+static const struct regmap_range max1720x_nvmem_deny[] = {
+ regmap_reg_range(0x00, 0x7F),
+ regmap_reg_range(0xE0, 0xFF),
+};
+
+static const struct regmap_access_table max1720x_nvmem_regs = {
+ .yes_ranges = max1720x_nvmem_allow,
+ .n_yes_ranges = ARRAY_SIZE(max1720x_nvmem_allow),
+ .no_ranges = max1720x_nvmem_deny,
+ .n_no_ranges = ARRAY_SIZE(max1720x_nvmem_deny),
+};
+
+static const struct regmap_config max1720x_nvmem_regmap_cfg = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = MAX1720X_NDEVICE_NAME4,
+ .val_format_endian = REGMAP_ENDIAN_LITTLE,
+ .rd_table = &max1720x_nvmem_regs,
+};
+
+static const struct nvmem_cell_info max1720x_nvmem_cells[] = {
+ { .name = "nXTable0", .offset = 0, .bytes = 2, },
+ { .name = "nXTable1", .offset = 2, .bytes = 2, },
+ { .name = "nXTable2", .offset = 4, .bytes = 2, },
+ { .name = "nXTable3", .offset = 6, .bytes = 2, },
+ { .name = "nXTable4", .offset = 8, .bytes = 2, },
+ { .name = "nXTable5", .offset = 10, .bytes = 2, },
+ { .name = "nXTable6", .offset = 12, .bytes = 2, },
+ { .name = "nXTable7", .offset = 14, .bytes = 2, },
+ { .name = "nXTable8", .offset = 16, .bytes = 2, },
+ { .name = "nXTable9", .offset = 18, .bytes = 2, },
+ { .name = "nXTable10", .offset = 20, .bytes = 2, },
+ { .name = "nXTable11", .offset = 22, .bytes = 2, },
+ { .name = "nUser18C", .offset = 24, .bytes = 2, },
+ { .name = "nUser18D", .offset = 26, .bytes = 2, },
+ { .name = "nODSCTh", .offset = 28, .bytes = 2, },
+ { .name = "nODSCCfg", .offset = 30, .bytes = 2, },
+
+ { .name = "nOCVTable0", .offset = 32, .bytes = 2, },
+ { .name = "nOCVTable1", .offset = 34, .bytes = 2, },
+ { .name = "nOCVTable2", .offset = 36, .bytes = 2, },
+ { .name = "nOCVTable3", .offset = 38, .bytes = 2, },
+ { .name = "nOCVTable4", .offset = 40, .bytes = 2, },
+ { .name = "nOCVTable5", .offset = 42, .bytes = 2, },
+ { .name = "nOCVTable6", .offset = 44, .bytes = 2, },
+ { .name = "nOCVTable7", .offset = 46, .bytes = 2, },
+ { .name = "nOCVTable8", .offset = 48, .bytes = 2, },
+ { .name = "nOCVTable9", .offset = 50, .bytes = 2, },
+ { .name = "nOCVTable10", .offset = 52, .bytes = 2, },
+ { .name = "nOCVTable11", .offset = 54, .bytes = 2, },
+ { .name = "nIChgTerm", .offset = 56, .bytes = 2, },
+ { .name = "nFilterCfg", .offset = 58, .bytes = 2, },
+ { .name = "nVEmpty", .offset = 60, .bytes = 2, },
+ { .name = "nLearnCfg", .offset = 62, .bytes = 2, },
+
+ { .name = "nQRTable00", .offset = 64, .bytes = 2, },
+ { .name = "nQRTable10", .offset = 66, .bytes = 2, },
+ { .name = "nQRTable20", .offset = 68, .bytes = 2, },
+ { .name = "nQRTable30", .offset = 70, .bytes = 2, },
+ { .name = "nCycles", .offset = 72, .bytes = 2, },
+ { .name = "nFullCapNom", .offset = 74, .bytes = 2, },
+ { .name = "nRComp0", .offset = 76, .bytes = 2, },
+ { .name = "nTempCo", .offset = 78, .bytes = 2, },
+ { .name = "nIAvgEmpty", .offset = 80, .bytes = 2, },
+ { .name = "nFullCapRep", .offset = 82, .bytes = 2, },
+ { .name = "nVoltTemp", .offset = 84, .bytes = 2, },
+ { .name = "nMaxMinCurr", .offset = 86, .bytes = 2, },
+ { .name = "nMaxMinVolt", .offset = 88, .bytes = 2, },
+ { .name = "nMaxMinTemp", .offset = 90, .bytes = 2, },
+ { .name = "nSOC", .offset = 92, .bytes = 2, },
+ { .name = "nTimerH", .offset = 94, .bytes = 2, },
+
+ { .name = "nConfig", .offset = 96, .bytes = 2, },
+ { .name = "nRippleCfg", .offset = 98, .bytes = 2, },
+ { .name = "nMiscCfg", .offset = 100, .bytes = 2, },
+ { .name = "nDesignCap", .offset = 102, .bytes = 2, },
+ { .name = "nHibCfg", .offset = 104, .bytes = 2, },
+ { .name = "nPackCfg", .offset = 106, .bytes = 2, },
+ { .name = "nRelaxCfg", .offset = 108, .bytes = 2, },
+ { .name = "nConvgCfg", .offset = 110, .bytes = 2, },
+ { .name = "nNVCfg0", .offset = 112, .bytes = 2, },
+ { .name = "nNVCfg1", .offset = 114, .bytes = 2, },
+ { .name = "nNVCfg2", .offset = 116, .bytes = 2, },
+ { .name = "nSBSCfg", .offset = 118, .bytes = 2, },
+ { .name = "nROMID0", .offset = 120, .bytes = 2, },
+ { .name = "nROMID1", .offset = 122, .bytes = 2, },
+ { .name = "nROMID2", .offset = 124, .bytes = 2, },
+ { .name = "nROMID3", .offset = 126, .bytes = 2, },
+
+ { .name = "nVAlrtTh", .offset = 128, .bytes = 2, },
+ { .name = "nTAlrtTh", .offset = 130, .bytes = 2, },
+ { .name = "nSAlrtTh", .offset = 132, .bytes = 2, },
+ { .name = "nIAlrtTh", .offset = 134, .bytes = 2, },
+ { .name = "nUser1C4", .offset = 136, .bytes = 2, },
+ { .name = "nUser1C5", .offset = 138, .bytes = 2, },
+ { .name = "nFullSOCThr", .offset = 140, .bytes = 2, },
+ { .name = "nTTFCfg", .offset = 142, .bytes = 2, },
+ { .name = "nCGain", .offset = 144, .bytes = 2, },
+ { .name = "nTCurve", .offset = 146, .bytes = 2, },
+ { .name = "nTGain", .offset = 148, .bytes = 2, },
+ { .name = "nTOff", .offset = 150, .bytes = 2, },
+ { .name = "nManfctrName0", .offset = 152, .bytes = 2, },
+ { .name = "nManfctrName1", .offset = 154, .bytes = 2, },
+ { .name = "nManfctrName2", .offset = 156, .bytes = 2, },
+ { .name = "nRSense", .offset = 158, .bytes = 2, },
+
+ { .name = "nUser1D0", .offset = 160, .bytes = 2, },
+ { .name = "nUser1D1", .offset = 162, .bytes = 2, },
+ { .name = "nAgeFcCfg", .offset = 164, .bytes = 2, },
+ { .name = "nDesignVoltage", .offset = 166, .bytes = 2, },
+ { .name = "nUser1D4", .offset = 168, .bytes = 2, },
+ { .name = "nRFastVShdn", .offset = 170, .bytes = 2, },
+ { .name = "nManfctrDate", .offset = 172, .bytes = 2, },
+ { .name = "nFirstUsed", .offset = 174, .bytes = 2, },
+ { .name = "nSerialNumber0", .offset = 176, .bytes = 2, },
+ { .name = "nSerialNumber1", .offset = 178, .bytes = 2, },
+ { .name = "nSerialNumber2", .offset = 180, .bytes = 2, },
+ { .name = "nDeviceName0", .offset = 182, .bytes = 2, },
+ { .name = "nDeviceName1", .offset = 184, .bytes = 2, },
+ { .name = "nDeviceName2", .offset = 186, .bytes = 2, },
+ { .name = "nDeviceName3", .offset = 188, .bytes = 2, },
+ { .name = "nDeviceName4", .offset = 190, .bytes = 2, },
+};
+
static const enum power_supply_property max1720x_battery_props[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_CAPACITY,
@@ -249,30 +382,80 @@ static int max1720x_battery_get_property(struct power_supply *psy,
return ret;
}
-static int max1720x_probe_sense_resistor(struct i2c_client *client,
- struct max1720x_device_info *info)
+static
+int max1720x_nvmem_reg_read(void *priv, unsigned int off, void *val, size_t len)
+{
+ struct max1720x_device_info *info = priv;
+ unsigned int reg = MAX1720X_NXTABLE0 + (off / 2);
+
+ return regmap_bulk_read(info->regmap_nv, reg, val, len / 2);
+}
+
+static void max1720x_unregister_ancillary(void *data)
+{
+ struct max1720x_device_info *info = data;
+
+ i2c_unregister_device(info->ancillary);
+}
+
+static int max1720x_probe_nvmem(struct i2c_client *client,
+ struct max1720x_device_info *info)
{
struct device *dev = &client->dev;
- struct i2c_client *ancillary;
+ struct nvmem_config nvmem_config = {
+ .dev = dev,
+ .name = "max1720x_nvmem",
+ .cells = max1720x_nvmem_cells,
+ .ncells = ARRAY_SIZE(max1720x_nvmem_cells),
+ .read_only = true,
+ .root_only = true,
+ .reg_read = max1720x_nvmem_reg_read,
+ .size = ARRAY_SIZE(max1720x_nvmem_cells) * 2,
+ .word_size = 2,
+ .stride = 2,
+ .priv = info,
+ };
+ struct nvmem_device *nvmem;
+ unsigned int val;
int ret;
- ancillary = i2c_new_ancillary_device(client, "nvmem", 0xb);
- if (IS_ERR(ancillary)) {
+ info->ancillary = i2c_new_ancillary_device(client, "nvmem", 0xb);
+ if (IS_ERR(info->ancillary)) {
dev_err(dev, "Failed to initialize ancillary i2c device\n");
- return PTR_ERR(ancillary);
+ return PTR_ERR(info->ancillary);
}
- ret = i2c_smbus_read_word_data(ancillary, MAX1720X_NRSENSE);
- i2c_unregister_device(ancillary);
- if (ret < 0)
+ ret = devm_add_action_or_reset(dev, max1720x_unregister_ancillary, info);
+ if (ret) {
+ dev_err(dev, "Failed to add unregister callback\n");
return ret;
+ }
+
+ info->regmap_nv = devm_regmap_init_i2c(info->ancillary,
+ &max1720x_nvmem_regmap_cfg);
+ if (IS_ERR(info->regmap_nv)) {
+ dev_err(dev, "regmap initialization of nvmem failed\n");
+ return PTR_ERR(info->regmap_nv);
+ }
+
+ ret = regmap_read(info->regmap_nv, MAX1720X_NRSENSE, &val);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read sense resistor value\n");
+ return ret;
+ }
- info->rsense = ret;
+ info->rsense = val;
if (!info->rsense) {
dev_warn(dev, "RSense not calibrated, set 10 mOhms!\n");
info->rsense = 1000; /* in regs in 10^-5 */
}
+ nvmem = devm_nvmem_register(dev, &nvmem_config);
+ if (IS_ERR(nvmem)) {
+ dev_err(dev, "Could not register nvmem!");
+ return PTR_ERR(nvmem);
+ }
+
return 0;
}
@@ -299,15 +482,15 @@ static int max1720x_probe(struct i2c_client *client)
psy_cfg.drv_data = info;
psy_cfg.fwnode = dev_fwnode(dev);
+ i2c_set_clientdata(client, info);
info->regmap = devm_regmap_init_i2c(client, &max1720x_regmap_cfg);
if (IS_ERR(info->regmap))
return dev_err_probe(dev, PTR_ERR(info->regmap),
"regmap initialization failed\n");
- ret = max1720x_probe_sense_resistor(client, info);
+ ret = max1720x_probe_nvmem(client, info);
if (ret)
- return dev_err_probe(dev, ret,
- "Failed to read sense resistor value\n");
+ return dev_err_probe(dev, ret, "Failed to probe nvmem\n");
bat = devm_power_supply_register(dev, &max1720x_bat_desc, &psy_cfg);
if (IS_ERR(bat))
diff --git a/drivers/power/supply/max77693_charger.c b/drivers/power/supply/max77693_charger.c
index 2001e12c9f7d..4caac142c428 100644
--- a/drivers/power/supply/max77693_charger.c
+++ b/drivers/power/supply/max77693_charger.c
@@ -197,12 +197,58 @@ static int max77693_get_online(struct regmap *regmap, int *val)
return 0;
}
+/*
+ * There are *two* current limit registers:
+ * - CHGIN limit, which limits the input current from the external charger;
+ * - Fast charge current limit, which limits the current going to the battery.
+ */
+
+static int max77693_get_input_current_limit(struct regmap *regmap, int *val)
+{
+ unsigned int data;
+ int ret;
+
+ ret = regmap_read(regmap, MAX77693_CHG_REG_CHG_CNFG_09, &data);
+ if (ret < 0)
+ return ret;
+
+ data &= CHG_CNFG_09_CHGIN_ILIM_MASK;
+ data >>= CHG_CNFG_09_CHGIN_ILIM_SHIFT;
+
+ if (data <= 0x03)
+ /* The first four values (0x00..0x03) are 60mA */
+ *val = 60000;
+ else
+ *val = data * 20000; /* 20mA steps */
+
+ return 0;
+}
+
+static int max77693_get_fast_charge_current(struct regmap *regmap, int *val)
+{
+ unsigned int data;
+ int ret;
+
+ ret = regmap_read(regmap, MAX77693_CHG_REG_CHG_CNFG_02, &data);
+ if (ret < 0)
+ return ret;
+
+ data &= CHG_CNFG_02_CC_MASK;
+ data >>= CHG_CNFG_02_CC_SHIFT;
+
+ *val = data * 33300; /* 33.3mA steps */
+
+ return 0;
+}
+
static enum power_supply_property max77693_charger_props[] = {
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_CHARGE_TYPE,
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
POWER_SUPPLY_PROP_MODEL_NAME,
POWER_SUPPLY_PROP_MANUFACTURER,
};
@@ -231,6 +277,12 @@ static int max77693_charger_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_ONLINE:
ret = max77693_get_online(regmap, &val->intval);
break;
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ ret = max77693_get_input_current_limit(regmap, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
+ ret = max77693_get_fast_charge_current(regmap, &val->intval);
+ break;
case POWER_SUPPLY_PROP_MODEL_NAME:
val->strval = max77693_charger_model;
break;
diff --git a/drivers/power/supply/max8998_charger.c b/drivers/power/supply/max8998_charger.c
index c26023b19f26..418b882b163d 100644
--- a/drivers/power/supply/max8998_charger.c
+++ b/drivers/power/supply/max8998_charger.c
@@ -191,6 +191,7 @@ static const struct platform_device_id max8998_battery_id[] = {
{ "max8998-battery", TYPE_MAX8998 },
{ }
};
+MODULE_DEVICE_TABLE(platform, max8998_battery_id);
static struct platform_driver max8998_battery_driver = {
.driver = {
diff --git a/drivers/power/supply/mp2629_charger.c b/drivers/power/supply/mp2629_charger.c
index 3a2a28fbba73..d281c1059629 100644
--- a/drivers/power/supply/mp2629_charger.c
+++ b/drivers/power/supply/mp2629_charger.c
@@ -94,14 +94,6 @@ struct mp2629_prop {
int shift;
};
-static enum power_supply_usb_type mp2629_usb_types[] = {
- POWER_SUPPLY_USB_TYPE_SDP,
- POWER_SUPPLY_USB_TYPE_DCP,
- POWER_SUPPLY_USB_TYPE_CDP,
- POWER_SUPPLY_USB_TYPE_PD_DRP,
- POWER_SUPPLY_USB_TYPE_UNKNOWN
-};
-
static enum power_supply_property mp2629_charger_usb_props[] = {
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_USB_TYPE,
@@ -487,8 +479,11 @@ unlock:
static const struct power_supply_desc mp2629_usb_desc = {
.name = "mp2629_usb",
.type = POWER_SUPPLY_TYPE_USB,
- .usb_types = mp2629_usb_types,
- .num_usb_types = ARRAY_SIZE(mp2629_usb_types),
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_PD_DRP) |
+ BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.properties = mp2629_charger_usb_props,
.num_properties = ARRAY_SIZE(mp2629_charger_usb_props),
.get_property = mp2629_charger_usb_get_prop,
diff --git a/drivers/power/supply/mt6360_charger.c b/drivers/power/supply/mt6360_charger.c
index aca123783efc..e99e55148976 100644
--- a/drivers/power/supply/mt6360_charger.c
+++ b/drivers/power/supply/mt6360_charger.c
@@ -154,13 +154,6 @@ enum mt6360_pmu_chg_type {
MT6360_CHG_TYPE_MAX,
};
-static enum power_supply_usb_type mt6360_charger_usb_types[] = {
- POWER_SUPPLY_USB_TYPE_UNKNOWN,
- POWER_SUPPLY_USB_TYPE_SDP,
- POWER_SUPPLY_USB_TYPE_DCP,
- POWER_SUPPLY_USB_TYPE_CDP,
-};
-
static int mt6360_get_chrdet_ext_stat(struct mt6360_chg_info *mci,
bool *pwr_rdy)
{
@@ -574,8 +567,10 @@ static const struct power_supply_desc mt6360_charger_desc = {
.get_property = mt6360_charger_get_property,
.set_property = mt6360_charger_set_property,
.property_is_writeable = mt6360_charger_property_is_writeable,
- .usb_types = mt6360_charger_usb_types,
- .num_usb_types = ARRAY_SIZE(mt6360_charger_usb_types),
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
};
static const struct regulator_ops mt6360_chg_otg_ops = {
diff --git a/drivers/power/supply/mt6370-charger.c b/drivers/power/supply/mt6370-charger.c
index e24fce087d80..ad8793bf997e 100644
--- a/drivers/power/supply/mt6370-charger.c
+++ b/drivers/power/supply/mt6370-charger.c
@@ -624,13 +624,6 @@ static enum power_supply_property mt6370_chg_properties[] = {
POWER_SUPPLY_PROP_USB_TYPE,
};
-static enum power_supply_usb_type mt6370_chg_usb_types[] = {
- POWER_SUPPLY_USB_TYPE_UNKNOWN,
- POWER_SUPPLY_USB_TYPE_SDP,
- POWER_SUPPLY_USB_TYPE_CDP,
- POWER_SUPPLY_USB_TYPE_DCP,
-};
-
static const struct power_supply_desc mt6370_chg_psy_desc = {
.name = "mt6370-charger",
.type = POWER_SUPPLY_TYPE_USB,
@@ -639,8 +632,10 @@ static const struct power_supply_desc mt6370_chg_psy_desc = {
.get_property = mt6370_chg_get_property,
.set_property = mt6370_chg_set_property,
.property_is_writeable = mt6370_chg_property_is_writeable,
- .usb_types = mt6370_chg_usb_types,
- .num_usb_types = ARRAY_SIZE(mt6370_chg_usb_types),
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
};
static const struct regulator_ops mt6370_chg_otg_ops = {
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index 8f6025acd10a..49534458a9f7 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -9,6 +9,7 @@
* Modified: 2004, Oct Szabolcs Gyurko
*/
+#include <linux/cleanup.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
@@ -756,10 +757,10 @@ int power_supply_get_battery_info(struct power_supply *psy,
for (index = 0; index < len; index++) {
struct power_supply_battery_ocv_table *table;
- char *propname;
int i, tab_len, size;
- propname = kasprintf(GFP_KERNEL, "ocv-capacity-table-%d", index);
+ char *propname __free(kfree) = kasprintf(GFP_KERNEL, "ocv-capacity-table-%d",
+ index);
if (!propname) {
power_supply_put_battery_info(psy, info);
err = -ENOMEM;
@@ -768,13 +769,11 @@ int power_supply_get_battery_info(struct power_supply *psy,
list = of_get_property(battery_np, propname, &size);
if (!list || !size) {
dev_err(&psy->dev, "failed to get %s\n", propname);
- kfree(propname);
power_supply_put_battery_info(psy, info);
err = -EINVAL;
goto out_put_node;
}
- kfree(propname);
tab_len = size / (2 * sizeof(__be32));
info->ocv_table_size[index] = tab_len;
@@ -1232,11 +1231,7 @@ EXPORT_SYMBOL_GPL(power_supply_set_property);
int power_supply_property_is_writeable(struct power_supply *psy,
enum power_supply_property psp)
{
- if (atomic_read(&psy->use_cnt) <= 0 ||
- !psy->desc->property_is_writeable)
- return -ENODEV;
-
- return psy->desc->property_is_writeable(psy, psp);
+ return psy->desc->property_is_writeable && psy->desc->property_is_writeable(psy, psp);
}
EXPORT_SYMBOL_GPL(power_supply_property_is_writeable);
@@ -1296,7 +1291,7 @@ static int power_supply_read_temp(struct thermal_zone_device *tzd,
return ret;
}
-static struct thermal_zone_device_ops psy_tzd_ops = {
+static const struct thermal_zone_device_ops psy_tzd_ops = {
.get_temp = power_supply_read_temp,
};
@@ -1361,10 +1356,6 @@ __power_supply_register(struct device *parent,
pr_warn("%s: Expected proper parent device for '%s'\n",
__func__, desc->name);
- if (psy_has_property(desc, POWER_SUPPLY_PROP_USB_TYPE) &&
- (!desc->usb_types || !desc->num_usb_types))
- return ERR_PTR(-EINVAL);
-
psy = kzalloc(sizeof(*psy), GFP_KERNEL);
if (!psy)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/power/supply/power_supply_hwmon.c b/drivers/power/supply/power_supply_hwmon.c
index baacefbdf768..6fbbfb1c685e 100644
--- a/drivers/power/supply/power_supply_hwmon.c
+++ b/drivers/power/supply/power_supply_hwmon.c
@@ -318,7 +318,8 @@ static const struct hwmon_channel_info * const power_supply_hwmon_info[] = {
HWMON_T_INPUT |
HWMON_T_MAX |
HWMON_T_MIN |
- HWMON_T_MIN_ALARM,
+ HWMON_T_MIN_ALARM |
+ HWMON_T_MAX_ALARM,
HWMON_T_LABEL |
HWMON_T_INPUT |
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index 3e63d165b2f7..16b3c5880cd8 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -209,7 +209,7 @@ static struct power_supply_attr power_supply_attrs[] = {
POWER_SUPPLY_ATTR(TIME_TO_FULL_NOW),
POWER_SUPPLY_ATTR(TIME_TO_FULL_AVG),
POWER_SUPPLY_ENUM_ATTR(TYPE),
- POWER_SUPPLY_ATTR(USB_TYPE),
+ POWER_SUPPLY_ENUM_ATTR(USB_TYPE),
POWER_SUPPLY_ENUM_ATTR(SCOPE),
POWER_SUPPLY_ATTR(PRECHARGE_CURRENT),
POWER_SUPPLY_ATTR(CHARGE_TERM_CURRENT),
@@ -237,31 +237,28 @@ static enum power_supply_property dev_attr_psp(struct device_attribute *attr)
return to_ps_attr(attr) - power_supply_attrs;
}
-static ssize_t power_supply_show_usb_type(struct device *dev,
- const struct power_supply_desc *desc,
- union power_supply_propval *value,
- char *buf)
+static ssize_t power_supply_show_enum_with_available(
+ struct device *dev, const char * const labels[], int label_count,
+ unsigned int available_values, int value, char *buf)
{
- enum power_supply_usb_type usb_type;
+ bool match = false, available, active;
ssize_t count = 0;
- bool match = false;
int i;
- for (i = 0; i < desc->num_usb_types; ++i) {
- usb_type = desc->usb_types[i];
+ for (i = 0; i < label_count; i++) {
+ available = available_values & BIT(i);
+ active = i == value;
- if (value->intval == usb_type) {
- count += sysfs_emit_at(buf, count, "[%s] ",
- POWER_SUPPLY_USB_TYPE_TEXT[usb_type]);
+ if (available && active) {
+ count += sysfs_emit_at(buf, count, "[%s] ", labels[i]);
match = true;
- } else {
- count += sysfs_emit_at(buf, count, "%s ",
- POWER_SUPPLY_USB_TYPE_TEXT[usb_type]);
+ } else if (available) {
+ count += sysfs_emit_at(buf, count, "%s ", labels[i]);
}
}
if (!match) {
- dev_warn(dev, "driver reporting unsupported connected type\n");
+ dev_warn(dev, "driver reporting unavailable enum value %d\n", value);
return -EINVAL;
}
@@ -300,8 +297,10 @@ static ssize_t power_supply_show_property(struct device *dev,
switch (psp) {
case POWER_SUPPLY_PROP_USB_TYPE:
- ret = power_supply_show_usb_type(dev, psy->desc,
- &value, buf);
+ ret = power_supply_show_enum_with_available(
+ dev, POWER_SUPPLY_USB_TYPE_TEXT,
+ ARRAY_SIZE(POWER_SUPPLY_USB_TYPE_TEXT),
+ psy->desc->usb_types, value.intval, buf);
break;
case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
ret = power_supply_charge_behaviour_show(dev, psy->desc->charge_behaviours,
@@ -523,33 +522,10 @@ ssize_t power_supply_charge_behaviour_show(struct device *dev,
enum power_supply_charge_behaviour current_behaviour,
char *buf)
{
- bool match = false, available, active;
- ssize_t count = 0;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT); i++) {
- available = available_behaviours & BIT(i);
- active = i == current_behaviour;
-
- if (available && active) {
- count += sysfs_emit_at(buf, count, "[%s] ",
- POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT[i]);
- match = true;
- } else if (available) {
- count += sysfs_emit_at(buf, count, "%s ",
- POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT[i]);
- }
- }
-
- if (!match) {
- dev_warn(dev, "driver reporting unsupported charge behaviour\n");
- return -EINVAL;
- }
-
- if (count)
- buf[count - 1] = '\n';
-
- return count;
+ return power_supply_show_enum_with_available(
+ dev, POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT,
+ ARRAY_SIZE(POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT),
+ available_behaviours, current_behaviour, buf);
}
EXPORT_SYMBOL_GPL(power_supply_charge_behaviour_show);
diff --git a/drivers/power/supply/qcom_battmgr.c b/drivers/power/supply/qcom_battmgr.c
index 8b3df3ee59ba..f0a64c00ddaa 100644
--- a/drivers/power/supply/qcom_battmgr.c
+++ b/drivers/power/supply/qcom_battmgr.c
@@ -786,19 +786,6 @@ static int qcom_battmgr_usb_get_property(struct power_supply *psy,
return 0;
}
-static const enum power_supply_usb_type usb_psy_supported_types[] = {
- POWER_SUPPLY_USB_TYPE_UNKNOWN,
- POWER_SUPPLY_USB_TYPE_SDP,
- POWER_SUPPLY_USB_TYPE_DCP,
- POWER_SUPPLY_USB_TYPE_CDP,
- POWER_SUPPLY_USB_TYPE_ACA,
- POWER_SUPPLY_USB_TYPE_C,
- POWER_SUPPLY_USB_TYPE_PD,
- POWER_SUPPLY_USB_TYPE_PD_DRP,
- POWER_SUPPLY_USB_TYPE_PD_PPS,
- POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID,
-};
-
static const enum power_supply_property sc8280xp_usb_props[] = {
POWER_SUPPLY_PROP_ONLINE,
};
@@ -809,8 +796,16 @@ static const struct power_supply_desc sc8280xp_usb_psy_desc = {
.properties = sc8280xp_usb_props,
.num_properties = ARRAY_SIZE(sc8280xp_usb_props),
.get_property = qcom_battmgr_usb_get_property,
- .usb_types = usb_psy_supported_types,
- .num_usb_types = ARRAY_SIZE(usb_psy_supported_types),
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN) |
+ BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_ACA) |
+ BIT(POWER_SUPPLY_USB_TYPE_C) |
+ BIT(POWER_SUPPLY_USB_TYPE_PD) |
+ BIT(POWER_SUPPLY_USB_TYPE_PD_DRP) |
+ BIT(POWER_SUPPLY_USB_TYPE_PD_PPS) |
+ BIT(POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID),
};
static const enum power_supply_property sm8350_usb_props[] = {
@@ -829,8 +824,16 @@ static const struct power_supply_desc sm8350_usb_psy_desc = {
.properties = sm8350_usb_props,
.num_properties = ARRAY_SIZE(sm8350_usb_props),
.get_property = qcom_battmgr_usb_get_property,
- .usb_types = usb_psy_supported_types,
- .num_usb_types = ARRAY_SIZE(usb_psy_supported_types),
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN) |
+ BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_ACA) |
+ BIT(POWER_SUPPLY_USB_TYPE_C) |
+ BIT(POWER_SUPPLY_USB_TYPE_PD) |
+ BIT(POWER_SUPPLY_USB_TYPE_PD_DRP) |
+ BIT(POWER_SUPPLY_USB_TYPE_PD_PPS) |
+ BIT(POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID),
};
static const u8 sm8350_wls_prop_map[] = {
diff --git a/drivers/power/supply/qcom_pmi8998_charger.c b/drivers/power/supply/qcom_pmi8998_charger.c
index 9bb777406013..81acbd8b2169 100644
--- a/drivers/power/supply/qcom_pmi8998_charger.c
+++ b/drivers/power/supply/qcom_pmi8998_charger.c
@@ -411,13 +411,6 @@ static enum power_supply_property smb2_properties[] = {
POWER_SUPPLY_PROP_USB_TYPE,
};
-static enum power_supply_usb_type smb2_usb_types[] = {
- POWER_SUPPLY_USB_TYPE_UNKNOWN,
- POWER_SUPPLY_USB_TYPE_SDP,
- POWER_SUPPLY_USB_TYPE_DCP,
- POWER_SUPPLY_USB_TYPE_CDP,
-};
-
static int smb2_get_prop_usb_online(struct smb2_chip *chip, int *val)
{
unsigned int stat;
@@ -775,8 +768,10 @@ static irqreturn_t smb2_handle_wdog_bark(int irq, void *data)
static const struct power_supply_desc smb2_psy_desc = {
.name = "pmi8998_charger",
.type = POWER_SUPPLY_TYPE_USB,
- .usb_types = smb2_usb_types,
- .num_usb_types = ARRAY_SIZE(smb2_usb_types),
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.properties = smb2_properties,
.num_properties = ARRAY_SIZE(smb2_properties),
.get_property = smb2_get_property,
diff --git a/drivers/power/supply/rk817_charger.c b/drivers/power/supply/rk817_charger.c
index 7ca91739c6cc..a3d377a32b49 100644
--- a/drivers/power/supply/rk817_charger.c
+++ b/drivers/power/supply/rk817_charger.c
@@ -673,11 +673,6 @@ static enum power_supply_property rk817_chg_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_AVG,
};
-static enum power_supply_usb_type rk817_usb_type[] = {
- POWER_SUPPLY_USB_TYPE_DCP,
- POWER_SUPPLY_USB_TYPE_UNKNOWN,
-};
-
static const struct power_supply_desc rk817_bat_desc = {
.name = "rk817-battery",
.type = POWER_SUPPLY_TYPE_BATTERY,
@@ -689,8 +684,8 @@ static const struct power_supply_desc rk817_bat_desc = {
static const struct power_supply_desc rk817_chg_desc = {
.name = "rk817-charger",
.type = POWER_SUPPLY_TYPE_USB,
- .usb_types = rk817_usb_type,
- .num_usb_types = ARRAY_SIZE(rk817_usb_type),
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.properties = rk817_chg_props,
.num_properties = ARRAY_SIZE(rk817_chg_props),
.get_property = rk817_chg_get_prop,
diff --git a/drivers/power/supply/rn5t618_power.c b/drivers/power/supply/rn5t618_power.c
index ebea3522a2ac..40dec55a9f73 100644
--- a/drivers/power/supply/rn5t618_power.c
+++ b/drivers/power/supply/rn5t618_power.c
@@ -70,13 +70,6 @@ struct rn5t618_power_info {
int irq;
};
-static enum power_supply_usb_type rn5t618_usb_types[] = {
- POWER_SUPPLY_USB_TYPE_SDP,
- POWER_SUPPLY_USB_TYPE_DCP,
- POWER_SUPPLY_USB_TYPE_CDP,
- POWER_SUPPLY_USB_TYPE_UNKNOWN
-};
-
static enum power_supply_property rn5t618_usb_props[] = {
/* input current limit is not very accurate */
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
@@ -681,8 +674,10 @@ static const struct power_supply_desc rn5t618_adp_desc = {
static const struct power_supply_desc rn5t618_usb_desc = {
.name = "rn5t618-usb",
.type = POWER_SUPPLY_TYPE_USB,
- .usb_types = rn5t618_usb_types,
- .num_usb_types = ARRAY_SIZE(rn5t618_usb_types),
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.properties = rn5t618_usb_props,
.num_properties = ARRAY_SIZE(rn5t618_usb_props),
.get_property = rn5t618_usb_get_property,
diff --git a/drivers/power/supply/rt9467-charger.c b/drivers/power/supply/rt9467-charger.c
index fdfdc83ab045..235169c85c5d 100644
--- a/drivers/power/supply/rt9467-charger.c
+++ b/drivers/power/supply/rt9467-charger.c
@@ -630,13 +630,6 @@ out:
return ret;
}
-static const enum power_supply_usb_type rt9467_chg_usb_types[] = {
- POWER_SUPPLY_USB_TYPE_UNKNOWN,
- POWER_SUPPLY_USB_TYPE_SDP,
- POWER_SUPPLY_USB_TYPE_DCP,
- POWER_SUPPLY_USB_TYPE_CDP,
-};
-
static const enum power_supply_property rt9467_chg_properties[] = {
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_ONLINE,
@@ -745,8 +738,6 @@ static int rt9467_psy_set_property(struct power_supply *psy,
RT9467_RANGE_IPREC, val->intval);
case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
return rt9467_psy_set_ieoc(data, val->intval);
- case POWER_SUPPLY_PROP_USB_TYPE:
- return regmap_field_write(data->rm_field[F_USBCHGEN], val->intval);
default:
return -EINVAL;
}
@@ -764,7 +755,6 @@ static int rt9467_chg_prop_is_writeable(struct power_supply *psy,
case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
- case POWER_SUPPLY_PROP_USB_TYPE:
return 1;
default:
return 0;
@@ -774,8 +764,10 @@ static int rt9467_chg_prop_is_writeable(struct power_supply *psy,
static const struct power_supply_desc rt9467_chg_psy_desc = {
.name = "rt9467-charger",
.type = POWER_SUPPLY_TYPE_USB,
- .usb_types = rt9467_chg_usb_types,
- .num_usb_types = ARRAY_SIZE(rt9467_chg_usb_types),
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.properties = rt9467_chg_properties,
.num_properties = ARRAY_SIZE(rt9467_chg_properties),
.property_is_writeable = rt9467_chg_prop_is_writeable,
diff --git a/drivers/power/supply/rt9471.c b/drivers/power/supply/rt9471.c
index 868b0703d15c..c04af1ee89c6 100644
--- a/drivers/power/supply/rt9471.c
+++ b/drivers/power/supply/rt9471.c
@@ -333,14 +333,6 @@ static enum power_supply_property rt9471_charger_properties[] = {
POWER_SUPPLY_PROP_MANUFACTURER,
};
-static enum power_supply_usb_type rt9471_charger_usb_types[] = {
- POWER_SUPPLY_USB_TYPE_UNKNOWN,
- POWER_SUPPLY_USB_TYPE_SDP,
- POWER_SUPPLY_USB_TYPE_DCP,
- POWER_SUPPLY_USB_TYPE_CDP,
- POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID,
-};
-
static int rt9471_charger_property_is_writeable(struct power_supply *psy,
enum power_supply_property psp)
{
@@ -726,8 +718,11 @@ static int rt9471_register_psy(struct rt9471_chip *chip)
desc->name = psy_name;
desc->type = POWER_SUPPLY_TYPE_USB;
- desc->usb_types = rt9471_charger_usb_types;
- desc->num_usb_types = ARRAY_SIZE(rt9471_charger_usb_types);
+ desc->usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID) |
+ BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN);
desc->properties = rt9471_charger_properties;
desc->num_properties = ARRAY_SIZE(rt9471_charger_properties);
desc->get_property = rt9471_charger_get_property;
diff --git a/drivers/power/supply/twl4030_charger.c b/drivers/power/supply/twl4030_charger.c
index 7b9b0b3e164e..f3f1a0862e93 100644
--- a/drivers/power/supply/twl4030_charger.c
+++ b/drivers/power/supply/twl4030_charger.c
@@ -363,7 +363,7 @@ static int twl4030_charger_update_current(struct twl4030_bci *bci)
if (status < 0)
return status;
cur_reg |= oldreg << 8;
- if (reg != oldreg) {
+ if (reg != cur_reg) {
/* disable write protection for one write access for
* BCIIREF */
status = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, 0xE7,
diff --git a/drivers/power/supply/ucs1002_power.c b/drivers/power/supply/ucs1002_power.c
index 7970843a4f48..7382bec6a43c 100644
--- a/drivers/power/supply/ucs1002_power.c
+++ b/drivers/power/supply/ucs1002_power.c
@@ -296,22 +296,17 @@ static int ucs1002_set_max_current(struct ucs1002_info *info, u32 val)
return 0;
}
-static enum power_supply_usb_type ucs1002_usb_types[] = {
- POWER_SUPPLY_USB_TYPE_PD,
- POWER_SUPPLY_USB_TYPE_SDP,
- POWER_SUPPLY_USB_TYPE_DCP,
- POWER_SUPPLY_USB_TYPE_CDP,
- POWER_SUPPLY_USB_TYPE_UNKNOWN,
-};
-
static int ucs1002_set_usb_type(struct ucs1002_info *info, int val)
{
unsigned int mode;
- if (val < 0 || val >= ARRAY_SIZE(ucs1002_usb_types))
- return -EINVAL;
-
- switch (ucs1002_usb_types[val]) {
+ switch (val) {
+ /*
+ * POWER_SUPPLY_USB_TYPE_UNKNOWN == 0, map this to dedicated for
+ * userspace API compatibility with older versions of this driver
+ * which mapped 0 to dedicated.
+ */
+ case POWER_SUPPLY_USB_TYPE_UNKNOWN:
case POWER_SUPPLY_USB_TYPE_PD:
mode = V_SET_ACTIVE_MODE_DEDICATED;
break;
@@ -428,8 +423,11 @@ static int ucs1002_property_is_writeable(struct power_supply *psy,
static const struct power_supply_desc ucs1002_charger_desc = {
.name = "ucs1002",
.type = POWER_SUPPLY_TYPE_USB,
- .usb_types = ucs1002_usb_types,
- .num_usb_types = ARRAY_SIZE(ucs1002_usb_types),
+ .usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_CDP) |
+ BIT(POWER_SUPPLY_USB_TYPE_DCP) |
+ BIT(POWER_SUPPLY_USB_TYPE_PD) |
+ BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
.get_property = ucs1002_get_property,
.set_property = ucs1002_set_property,
.property_is_writeable = ucs1002_property_is_writeable,