Unverified Commit 2d09a79b authored by Maarten ter Huurne's avatar Maarten ter Huurne Committed by Mark Brown
Browse files

regulator: act8865: Add support for act8600 charger



This provides a way to monitor battery charge status via the power
supply subsystem.

Signed-off-by: default avatarMaarten ter Huurne <maarten@treewalker.org>
Signed-off-by: default avatarPaul Cercueil <paul@crapouillou.net>
Link: https://lore.kernel.org/r/20190723011418.29143-1-paul@crapouillou.net


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent d850c6f5
Loading
Loading
Loading
Loading
+84 −0
Original line number Diff line number Diff line
@@ -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;