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

Commit 52e423da authored by Chunmei Cai's avatar Chunmei Cai Committed by Gerrit - the friendly Code Review server
Browse files

power: qpnp-linear-charger: Add an led device controlled by LBC



Register an led device controlled by linear battery charger (LBC).
It can be used as a red indication led as well as a charging led.

Change-Id: I1ceb8af000ffdab0a2e1da3d3344487be5509678
Signed-off-by: default avatarChunmei Cai <ccai@codeaurora.org>
parent 502b33f8
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -93,6 +93,10 @@ Parent node optional properties:
					BPD and disables BTC. Declare this node
					only if you are using an external charger
					and not the PMIC internal LBC.
- qcom,chgr-led-support			There is a current sink device in linear
					charger module, it is used to control a
					led which can act as a charger led as well
					as a general notification led.

Sub node required structure:
- A qcom,charger node must be a child of an SPMI node that has specified
+80 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <linux/qpnp/qpnp-adc.h>
#include <linux/alarmtimer.h>
#include <linux/bitops.h>
#include <linux/leds.h>

#define CREATE_MASK(NUM_BITS, POS) \
	((unsigned char) (((1 << (NUM_BITS)) - 1) << (POS)))
@@ -267,6 +268,7 @@ struct vddtrim_map vddtrim_map[] = {
 * @cfg_charger_detect_eoc:	charger can detect end of charging
 * @cfg_disable_vbatdet_based_recharge:	keep VBATDET comparator overriden to
 *				low and VBATDET irq disabled.
 * @cfg_chgr_led_support:	support charger led work.
 * @cfg_safe_current:		battery safety current setting
 * @cfg_hot_batt_p:		hot battery threshold setting
 * @cfg_cold_batt_p:		eold battery threshold setting
@@ -317,6 +319,7 @@ struct qpnp_lbc_chip {
	bool				cfg_use_fake_battery;
	bool				fastchg_on;
	bool				cfg_use_external_charger;
	bool				cfg_chgr_led_support;
	unsigned int			cfg_warm_bat_chg_ma;
	unsigned int			cfg_cool_bat_chg_ma;
	unsigned int			cfg_safe_voltage_mv;
@@ -361,6 +364,7 @@ struct qpnp_lbc_chip {
	struct qpnp_adc_tm_btm_param	adc_param;
	struct qpnp_vadc_chip		*vadc_dev;
	struct qpnp_adc_tm_chip		*adc_tm_dev;
	struct led_classdev		led_cdev;
};

static void qpnp_lbc_enable_irq(struct qpnp_lbc_chip *chip,
@@ -971,6 +975,68 @@ static int qpnp_lbc_tchg_max_set(struct qpnp_lbc_chip *chip, int minutes)
	return rc;
}

#define LBC_CHGR_LED	0x4D
#define CHGR_LED_ON	BIT(0)
#define CHGR_LED_OFF	0x0
#define CHGR_LED_STAT_MASK	LBC_MASK(1, 0)
static void qpnp_lbc_chgr_led_brightness_set(struct led_classdev *cdev,
		enum led_brightness value)
{
	struct qpnp_lbc_chip *chip = container_of(cdev, struct qpnp_lbc_chip,
			led_cdev);
	u8 reg;
	int rc;

	if (value > LED_FULL)
		value = LED_FULL;

	pr_debug("set the charger led brightness to value=%d\n", value);
	reg = (value > LED_OFF) ? CHGR_LED_ON : CHGR_LED_OFF;

	rc = qpnp_lbc_masked_write(chip, chip->chgr_base + LBC_CHGR_LED,
				CHGR_LED_STAT_MASK, reg);
	if (rc)
		pr_err("Failed to write charger led rc=%d\n", rc);
}

static enum
led_brightness qpnp_lbc_chgr_led_brightness_get(struct led_classdev *cdev)
{

	struct qpnp_lbc_chip *chip = container_of(cdev, struct qpnp_lbc_chip,
			led_cdev);
	u8 reg_val, chgr_led_sts;
	int rc;

	rc = qpnp_lbc_read(chip, chip->chgr_base + LBC_CHGR_LED,
				&reg_val, 1);
	if (rc) {
		pr_err("Failed to read charger led rc=%d\n", rc);
		return rc;
	}

	chgr_led_sts = reg_val & CHGR_LED_STAT_MASK;
	pr_debug("charger led brightness chgr_led_sts=%d\n", chgr_led_sts);

	return (chgr_led_sts == CHGR_LED_ON) ? LED_FULL : LED_OFF;
}

static int qpnp_lbc_register_chgr_led(struct qpnp_lbc_chip *chip)
{
	int rc;

	chip->led_cdev.name = "red";
	chip->led_cdev.brightness_set = qpnp_lbc_chgr_led_brightness_set;
	chip->led_cdev.brightness_get = qpnp_lbc_chgr_led_brightness_get;

	rc = led_classdev_register(chip->dev, &chip->led_cdev);
	if (rc)
		dev_err(chip->dev, "unable to register charger led, rc=%d\n",
				rc);

	return rc;
};

static int qpnp_lbc_vbatdet_override(struct qpnp_lbc_chip *chip, int ovr_val)
{
	int rc;
@@ -1941,6 +2007,12 @@ static int qpnp_charger_read_dt_props(struct qpnp_lbc_chip *chip)
	chip->cfg_disable_vbatdet_based_recharge =
			of_property_read_bool(chip->spmi->dev.of_node,
					"qcom,disable-vbatdet-based-recharge");

	/* Get the charger led support property */
	chip->cfg_chgr_led_support =
			of_property_read_bool(chip->spmi->dev.of_node,
					"qcom,chgr-led-support");

	/* Disable charging when faking battery values */
	if (chip->cfg_use_fake_battery)
		chip->cfg_charging_disabled = true;
@@ -2563,6 +2635,14 @@ static int qpnp_lbc_probe(struct spmi_device *spmi)
		return rc;
	}

	if (chip->cfg_chgr_led_support) {
		rc = qpnp_lbc_register_chgr_led(chip);
		if (rc) {
			pr_err("unable to register charger led rc=%d\n", rc);
			return rc;
		}
	}

	if (chip->bat_if_base) {
		chip->batt_present = qpnp_lbc_is_batt_present(chip);
		chip->batt_psy.name = "battery";