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>
This commit is contained in:
Maarten ter Huurne 2019-07-22 21:14:18 -04:00 committed by Mark Brown
parent d850c6f5fa
commit 2d09a79bf6
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
1 changed files with 84 additions and 0 deletions

View File

@ -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;