Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 369eba09 authored by Wenyou Yang's avatar Wenyou Yang Committed by Sebastian Reichel
Browse files

power: supply: act8945a_charger: Add capacity level property



Add the power supply capacity level property, it corresponds to
POWER_SUPPLY_CAPACITY_LEVEL_*.

It also utilizes the precision voltage detector function module
to catch the low battery voltage.

Signed-off-by: default avatarWenyou Yang <wenyou.yang@atmel.com>
Signed-off-by: default avatarSebastian Reichel <sre@kernel.org>
parent 30953650
Loading
Loading
Loading
Loading
+78 −1
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/power_supply.h>
#include <linux/regmap.h>
#include <linux/regmap.h>
#include <linux/gpio/consumer.h>


static const char *act8945a_charger_model = "ACT8945A";
static const char *act8945a_charger_model = "ACT8945A";
static const char *act8945a_charger_manufacturer = "Active-semi";
static const char *act8945a_charger_manufacturer = "Active-semi";
@@ -83,6 +84,7 @@ struct act8945a_charger {
	struct work_struct work;
	struct work_struct work;


	bool init_done;
	bool init_done;
	struct gpio_desc *lbo_gpio;
};
};


static int act8945a_get_charger_state(struct regmap *regmap, int *val)
static int act8945a_get_charger_state(struct regmap *regmap, int *val)
@@ -208,11 +210,67 @@ static int act8945a_get_battery_health(struct regmap *regmap, int *val)
	return 0;
	return 0;
}
}


static int act8945a_get_capacity_level(struct act8945a_charger *charger,
				       struct regmap *regmap, int *val)
{
	int ret;
	unsigned int status, state, config;
	int lbo_level = gpiod_get_value(charger->lbo_gpio);

	ret = regmap_read(regmap, ACT8945A_APCH_STATUS, &status);
	if (ret < 0)
		return ret;

	ret = regmap_read(regmap, ACT8945A_APCH_CFG, &config);
	if (ret < 0)
		return ret;

	ret = regmap_read(regmap, ACT8945A_APCH_STATE, &state);
	if (ret < 0)
		return ret;

	state &= APCH_STATE_CSTATE;
	state >>= APCH_STATE_CSTATE_SHIFT;

	switch (state) {
	case APCH_STATE_CSTATE_PRE:
		*val = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
		break;
	case APCH_STATE_CSTATE_FAST:
		if (lbo_level)
			*val = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
		else
			*val = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
		break;
	case APCH_STATE_CSTATE_EOC:
		if (status & APCH_STATUS_CHGDAT)
			*val = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
		else
			*val = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
		break;
	case APCH_STATE_CSTATE_DISABLED:
	default:
		if (config & APCH_CFG_SUSCHG) {
			*val = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
		} else {
			*val = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
			if (!(status & APCH_STATUS_INDAT)) {
				if (!lbo_level)
					*val = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
			}
		}
		break;
	}

	return 0;
}

static enum power_supply_property act8945a_charger_props[] = {
static enum power_supply_property act8945a_charger_props[] = {
	POWER_SUPPLY_PROP_STATUS,
	POWER_SUPPLY_PROP_STATUS,
	POWER_SUPPLY_PROP_CHARGE_TYPE,
	POWER_SUPPLY_PROP_CHARGE_TYPE,
	POWER_SUPPLY_PROP_TECHNOLOGY,
	POWER_SUPPLY_PROP_TECHNOLOGY,
	POWER_SUPPLY_PROP_HEALTH,
	POWER_SUPPLY_PROP_HEALTH,
	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
	POWER_SUPPLY_PROP_MODEL_NAME,
	POWER_SUPPLY_PROP_MODEL_NAME,
	POWER_SUPPLY_PROP_MANUFACTURER
	POWER_SUPPLY_PROP_MANUFACTURER
};
};
@@ -238,6 +296,10 @@ static int act8945a_charger_get_property(struct power_supply *psy,
	case POWER_SUPPLY_PROP_HEALTH:
	case POWER_SUPPLY_PROP_HEALTH:
		ret = act8945a_get_battery_health(regmap, &val->intval);
		ret = act8945a_get_battery_health(regmap, &val->intval);
		break;
		break;
	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
		ret = act8945a_get_capacity_level(charger,
						  regmap, &val->intval);
		break;
	case POWER_SUPPLY_PROP_MODEL_NAME:
	case POWER_SUPPLY_PROP_MODEL_NAME:
		val->strval = act8945a_charger_model;
		val->strval = act8945a_charger_model;
		break;
		break;
@@ -335,7 +397,7 @@ static int act8945a_charger_config(struct device *dev,
	u32 pre_time_out;
	u32 pre_time_out;
	u32 input_voltage_threshold;
	u32 input_voltage_threshold;
	int chglev_pin;
	int chglev_pin;
	int ret;
	int err, ret;


	unsigned int tmp;
	unsigned int tmp;
	unsigned int value = 0;
	unsigned int value = 0;
@@ -354,6 +416,21 @@ static int act8945a_charger_config(struct device *dev,
		dev_info(dev, "have been suspended\n");
		dev_info(dev, "have been suspended\n");
	}
	}


	charger->lbo_gpio = devm_gpiod_get_optional(dev, "active-semi,lbo",
						    GPIOD_IN);
	if (IS_ERR(charger->lbo_gpio)) {
		err = PTR_ERR(charger->lbo_gpio);
		dev_err(dev, "unable to claim gpio \"lbo\": %d\n", err);
		return err;
	}

	ret = devm_request_irq(dev, gpiod_to_irq(charger->lbo_gpio),
			       act8945a_status_changed,
			       (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING),
			       "act8945a_lbo_detect", charger);
	if (ret)
		dev_info(dev, "failed to request gpio \"lbo\" IRQ\n");

	chglev_pin = of_get_named_gpio_flags(np,
	chglev_pin = of_get_named_gpio_flags(np,
				"active-semi,chglev-gpios", 0, &flags);
				"active-semi,chglev-gpios", 0, &flags);