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

Commit 75b2f358 authored by Abhijeet Dharmapurikar's avatar Abhijeet Dharmapurikar Committed by Stephen Boyd
Browse files

power: qpnp-charger: add support for batfet control regulator



The battery FET (batfet) is put in low power mode (LPM) where it can
allow less than 100mA of current when the PMIC goes to sleep.

This causes problems if high current discharge from the battery
is expected when the system (and the PMIC) go to sleep. Override
this LPM feature and let the batfet remain in high power mode (HPM) if a
high current discharge is expected.

Expose the batfet as a regulator and let the consumers decide whether
to enable or disable this regulator. Enabled means the batfet will stay
in HPM while PMIC goes to sleep whereas disabled means the batfet will
be switched to LPM when the PMIC goes to sleep.

CRs-Fixed: 503417
Change-Id: I883271f17ed04b37016afc9c3ea89235bde7af88
Signed-off-by: default avatarAbhijeet Dharmapurikar <adharmap@codeaurora.org>
parent fe2a69fa
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -176,6 +176,9 @@ Sub node optional properties:
			 - regulator-name:	A string used as a descriptive name
						for the boost regulator.

			qcom,batfet:
			 - regulator-name:	A string used as a descriptive name
						for the batfet regulator.
Example:
	pm8941-chg {
		spmi-dev-container;
@@ -303,6 +306,10 @@ In regulator specific device tree file:
		regulator-name = "8941_smbb_boost";
	};

	&pm8941_chg_batif  {
		regulator-name = "batfet";
	};

	&pm8941_chg_otg {
		regulator-name = "8941_smbb_otg";
	};
+88 −0
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@
#define CHGR_STATUS				0x09
#define CHGR_BAT_IF_VCP				0x42
#define CHGR_BAT_IF_BATFET_CTRL1		0x90
#define CHGR_BAT_IF_SPARE			0xDF
#define CHGR_MISC_BOOT_DONE			0x42
#define CHGR_BUCK_COMPARATOR_OVRIDE_1		0xEB
#define CHGR_BUCK_COMPARATOR_OVRIDE_3		0xED
@@ -338,6 +339,7 @@ struct qpnp_chg_chip {
	struct work_struct		soc_check_work;
	struct qpnp_chg_regulator	otg_vreg;
	struct qpnp_chg_regulator	boost_vreg;
	struct qpnp_chg_regulator	batfet_vreg;
	struct qpnp_vadc_chip		*vadc_dev;
	struct qpnp_adc_tm_chip		*adc_tm_dev;
	struct mutex			jeita_configure_lock;
@@ -2258,6 +2260,63 @@ static struct regulator_ops qpnp_chg_boost_reg_ops = {
	.list_voltage		= qpnp_chg_regulator_boost_list_voltage,
};

#define BATFET_LPM_MASK		0xC0
#define BATFET_LPM		0x40
#define BATFET_NO_LPM		0x00
static int
qpnp_chg_regulator_batfet_enable(struct regulator_dev *rdev)
{
	struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
	int rc;

	rc = qpnp_chg_masked_write(chip,
			chip->bat_if_base + CHGR_BAT_IF_SPARE,
			BATFET_LPM_MASK, BATFET_NO_LPM, 1);
	if (rc)
		pr_err("failed to write to batt_if rc=%d\n", rc);
	return rc;
}

static int
qpnp_chg_regulator_batfet_disable(struct regulator_dev *rdev)
{
	struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
	int rc;

	rc = qpnp_chg_masked_write(chip,
			chip->bat_if_base + CHGR_BAT_IF_SPARE,
			BATFET_LPM_MASK, BATFET_LPM, 1);
	if (rc)
		pr_err("failed to write to batt_if rc=%d\n", rc);
	return rc;
}

static int
qpnp_chg_regulator_batfet_is_enabled(struct regulator_dev *rdev)
{
	struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
	int rc;
	u8 reg;

	rc = qpnp_chg_read(chip, &reg,
				chip->bat_if_base + CHGR_BAT_IF_SPARE, 1);
	if (rc) {
		pr_err("failed to read batt_if rc=%d\n", rc);
		return rc;
	}

	if (reg && BATFET_LPM_MASK == BATFET_NO_LPM)
		return 1;

	return 0;
}

static struct regulator_ops qpnp_chg_batfet_vreg_ops = {
	.enable			= qpnp_chg_regulator_batfet_enable,
	.disable		= qpnp_chg_regulator_batfet_disable,
	.is_enabled		= qpnp_chg_regulator_batfet_is_enabled,
};

#define MIN_DELTA_MV_TO_INCREASE_VDD_MAX	13
#define MAX_DELTA_VDD_MAX_MV			30
static void
@@ -3067,6 +3126,35 @@ qpnp_chg_hwinit(struct qpnp_chg_chip *chip, u8 subtype,
			pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
			return rc;
		}

		init_data = of_get_regulator_init_data(chip->dev,
					       spmi_resource->of_node);

		if (init_data->constraints.name) {
			rdesc			= &(chip->batfet_vreg.rdesc);
			rdesc->owner		= THIS_MODULE;
			rdesc->type		= REGULATOR_VOLTAGE;
			rdesc->ops		= &qpnp_chg_batfet_vreg_ops;
			rdesc->name		= init_data->constraints.name;

			init_data->constraints.valid_ops_mask
				|= REGULATOR_CHANGE_STATUS;

			cfg.dev = chip->dev;
			cfg.init_data = init_data;
			cfg.driver_data = chip;
			cfg.of_node = spmi_resource->of_node;
			chip->batfet_vreg.rdev = regulator_register(rdesc,
								    &cfg);
			if (IS_ERR(chip->batfet_vreg.rdev)) {
				rc = PTR_ERR(chip->batfet_vreg.rdev);
				chip->batfet_vreg.rdev = NULL;
				if (rc != -EPROBE_DEFER)
					pr_err("batfet reg failed, rc=%d\n",
							rc);
				return rc;
			}
		}
		break;
	case SMBB_USB_CHGPTH_SUBTYPE:
	case SMBBP_USB_CHGPTH_SUBTYPE: