diff options
author | Maarten ter Huurne <maarten@treewalker.org> | 2019-07-23 04:14:18 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2019-07-23 14:27:42 +0300 |
commit | 2d09a79bf637f91d1bbfcfd4520e3639dd15897c (patch) | |
tree | f6e53ccfc7d3ed3fd73765f7f09d66478cb2c680 /drivers/regulator | |
parent | d850c6f5fad60b6edec08300977303aae855ffff (diff) | |
download | linux-2d09a79bf637f91d1bbfcfd4520e3639dd15897c.tar.xz |
regulator: act8865: Add support for act8600 charger
This provides a way to monitor battery charge status via the power
supply subsystem.
Signed-off-by: Maarten ter Huurne <maarten@treewalker.org>
Signed-off-by: Paul Cercueil <paul@crapouillou.net>
Link: https://lore.kernel.org/r/20190723011418.29143-1-paul@crapouillou.net
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/act8865-regulator.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c index cf72d7c6b8c9..e63285de485d 100644 --- a/drivers/regulator/act8865-regulator.c +++ b/drivers/regulator/act8865-regulator.c @@ -16,6 +16,7 @@ #include <linux/regulator/act8865.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/power_supply.h> #include <linux/regulator/of_regulator.h> #include <linux/regmap.h> @@ -118,6 +119,11 @@ #define ACT8600_LDO10_ENA 0x40 /* ON - [6] */ #define ACT8600_SUDCDC_VSEL_MASK 0xFF /* SUDCDC VSET - [7:0] */ +#define ACT8600_APCH_CHG_ACIN BIT(7) +#define ACT8600_APCH_CHG_USB BIT(6) +#define ACT8600_APCH_CSTATE0 BIT(5) +#define ACT8600_APCH_CSTATE1 BIT(4) + /* * ACT8865 voltage number */ @@ -372,6 +378,75 @@ static void act8865_power_off(void) while (1); } +static int act8600_charger_get_status(struct regmap *map) +{ + unsigned int val; + int ret; + u8 state0, state1; + + ret = regmap_read(map, ACT8600_APCH_STAT, &val); + if (ret < 0) + return ret; + + state0 = val & ACT8600_APCH_CSTATE0; + state1 = val & ACT8600_APCH_CSTATE1; + + if (state0 && !state1) + return POWER_SUPPLY_STATUS_CHARGING; + if (!state0 && state1) + return POWER_SUPPLY_STATUS_NOT_CHARGING; + if (!state0 && !state1) + return POWER_SUPPLY_STATUS_DISCHARGING; + + return POWER_SUPPLY_STATUS_UNKNOWN; +} + +static int act8600_charger_get_property(struct power_supply *psy, + enum power_supply_property psp, union power_supply_propval *val) +{ + struct regmap *map = power_supply_get_drvdata(psy); + int ret; + + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + ret = act8600_charger_get_status(map); + if (ret < 0) + return ret; + + val->intval = ret; + break; + default: + return -EINVAL; + } + + return 0; +} + +static enum power_supply_property act8600_charger_properties[] = { + POWER_SUPPLY_PROP_STATUS, +}; + +static const struct power_supply_desc act8600_charger_desc = { + .name = "act8600-charger", + .type = POWER_SUPPLY_TYPE_BATTERY, + .properties = act8600_charger_properties, + .num_properties = ARRAY_SIZE(act8600_charger_properties), + .get_property = act8600_charger_get_property, +}; + +static int act8600_charger_probe(struct device *dev, struct regmap *regmap) +{ + struct power_supply *charger; + struct power_supply_config cfg = { + .drv_data = regmap, + .of_node = dev->of_node, + }; + + charger = devm_power_supply_register(dev, &act8600_charger_desc, &cfg); + + return IS_ERR(charger) ? PTR_ERR(charger) : 0; +} + static int act8865_pmic_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { @@ -483,6 +558,15 @@ static int act8865_pmic_probe(struct i2c_client *client, } } + if (type == ACT8600) { + ret = act8600_charger_probe(dev, act8865->regmap); + if (ret < 0) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to probe charger"); + return ret; + } + } + i2c_set_clientdata(client, act8865); return 0; |