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

Commit 99e111e9 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "regulator: qcom_pm8008-regulator: correct chip-en chip variable type"

parents 0ea62676 f5f58edb
Loading
Loading
Loading
Loading
+127 −61
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2019, The Linux Foundation. All rights reserved. */
/* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */

#define pr_fmt(fmt) "PM8008: %s: " fmt, __func__

#include <linux/delay.h>
#include <linux/device.h>
#include <linux/regmap.h>
#include <linux/interrupt.h>
@@ -24,6 +25,7 @@
#define STARTUP_DELAY_USEC		20
#define VSET_STEP_SIZE_MV		1
#define VSET_STEP_MV			8
#define VSET_STEP_UV			(VSET_STEP_MV * 1000)

#define MISC_BASE			0x900

@@ -187,9 +189,16 @@ static int pm8008_regulator_is_enabled(struct regulator_dev *rdev)
static int pm8008_regulator_enable(struct regulator_dev *rdev)
{
	struct pm8008_regulator *pm8008_reg = rdev_get_drvdata(rdev);
	int rc, init_mv, delay_us, delay_ms, retry_count = 10;
	int rc, rc2, current_uv, delay_us, delay_ms, retry_count = 10;
	u8 reg;

	current_uv = pm8008_regulator_get_voltage(rdev);
	if (current_uv < 0) {
		pm8008_err(pm8008_reg, "failed to get current voltage rc=%d\n",
			current_uv);
		return current_uv;
	}

	rc = regulator_enable(pm8008_reg->en_supply);
	if (rc < 0) {
		pm8008_err(pm8008_reg,
@@ -198,12 +207,22 @@ static int pm8008_regulator_enable(struct regulator_dev *rdev)
	}

	if (pm8008_reg->parent_supply) {
		rc = regulator_set_voltage(pm8008_reg->parent_supply,
					current_uv + pm8008_reg->min_dropout_uv,
					INT_MAX);
		if (rc < 0) {
			pm8008_err(pm8008_reg, "failed to request parent supply voltage rc=%d\n",
				rc);
			goto remove_en;
		}

		rc = regulator_enable(pm8008_reg->parent_supply);
		if (rc < 0) {
			pm8008_err(pm8008_reg,
				"failed to enable parent rc=%d\n", rc);
			regulator_disable(pm8008_reg->en_supply);
			return rc;
			regulator_set_voltage(pm8008_reg->parent_supply, 0,
						INT_MAX);
			goto remove_en;
		}
	}

@@ -217,20 +236,14 @@ static int pm8008_regulator_enable(struct regulator_dev *rdev)
	}

	/*
	 * wait for VREG_OK
	 * Read voltage and calculate the delay.
	 * Wait for the VREG_READY status bit to be set using a timeout delay
	 * calculated from the current commanded voltage.
	 */
	init_mv = pm8008_regulator_get_voltage(rdev) / 1000;
	if (init_mv < 0) {
		pm8008_err(pm8008_reg,
			"failed to get regulator voltage rc=%d\n", rc);
		goto out;
	}
	delay_us = STARTUP_DELAY_USEC
			+ DIV_ROUND_UP(init_mv * 1000, pm8008_reg->step_rate);
			+ DIV_ROUND_UP(current_uv, pm8008_reg->step_rate);
	delay_ms = DIV_ROUND_UP(delay_us, 1000);

	/* Retry 10 times for VREG_OK before bailing out */
	/* Retry 10 times for VREG_READY before bailing out */
	while (retry_count--) {
		if (delay_ms > 20)
			msleep(delay_ms);
@@ -242,7 +255,7 @@ static int pm8008_regulator_enable(struct regulator_dev *rdev)
		if (rc < 0) {
			pm8008_err(pm8008_reg,
				"failed to read regulator status rc=%d\n", rc);
			goto out;
			goto disable_ldo;
		}
		if (reg & VREG_READY_BIT) {
			pm8008_debug(pm8008_reg, "regulator enabled\n");
@@ -250,20 +263,33 @@ static int pm8008_regulator_enable(struct regulator_dev *rdev)
		}
	}

	pm8008_err(pm8008_reg,
		"failed to enable regulator VREG_READY not set\n");
out:
	pm8008_err(pm8008_reg, "failed to enable regulator, VREG_READY not set\n");
	rc = -ETIME;

disable_ldo:
	pm8008_masked_write(pm8008_reg->regmap,
			LDO_ENABLE_REG(pm8008_reg->base), ENABLE_BIT, 0);

remove_vote:
	rc = regulator_disable(pm8008_reg->en_supply);
	if (pm8008_reg->parent_supply)
		rc |= regulator_disable(pm8008_reg->parent_supply);
	if (rc < 0)
		pm8008_err(pm8008_reg,
			"failed to disable parent regulator rc=%d\n", rc);
	if (pm8008_reg->parent_supply) {
		rc2 = regulator_disable(pm8008_reg->parent_supply);
		if (rc2 < 0)
			pm8008_err(pm8008_reg, "failed to disable parent supply rc=%d\n",
				rc2);
		rc2 = regulator_set_voltage(pm8008_reg->parent_supply, 0,
						INT_MAX);
		if (rc2 < 0)
			pm8008_err(pm8008_reg, "failed to remove voltage vote for parent supply rc=%d\n",
				rc2);
	}

	return -ETIME;
remove_en:
	rc2 = regulator_disable(pm8008_reg->en_supply);
	if (rc2 < 0)
		pm8008_err(pm8008_reg, "failed to disable en_supply rc=%d\n",
			rc2);

	return rc;
}

static int pm8008_regulator_disable(struct regulator_dev *rdev)
@@ -280,29 +306,30 @@ static int pm8008_regulator_disable(struct regulator_dev *rdev)
		return rc;
	}

	/* remove vote from chip enable regulator */
	rc = regulator_disable(pm8008_reg->en_supply);
	if (rc < 0) {
		pm8008_err(pm8008_reg,
		       "failed to disable en_supply rc=%d\n", rc);
	}

	/* remove voltage vote from parent regulator */
	if (pm8008_reg->parent_supply) {
		rc = regulator_disable(pm8008_reg->parent_supply);
		if (rc < 0) {
			pm8008_err(pm8008_reg, "failed to disable parent rc=%d\n",
				rc);
			return rc;
		}
		rc = regulator_set_voltage(pm8008_reg->parent_supply,
					0, INT_MAX);
		if (rc < 0) {
			pm8008_err(pm8008_reg,
				"failed to remove parent voltage rc=%d\n", rc);
			pm8008_err(pm8008_reg, "failed to remove parent voltage rc=%d\n",
				rc);
			return rc;
		}
		rc = regulator_disable(pm8008_reg->parent_supply);
	}

	/* remove vote from chip enable regulator */
	rc = regulator_disable(pm8008_reg->en_supply);
	if (rc < 0) {
			pm8008_err(pm8008_reg,
				"failed to disable parent rc=%d\n", rc);
		pm8008_err(pm8008_reg, "failed to disable en_supply rc=%d\n",
			rc);
		return rc;
	}
	}

	pm8008_debug(pm8008_reg, "regulator disabled\n");
	return 0;
@@ -341,31 +368,76 @@ static int pm8008_write_voltage(struct pm8008_regulator *pm8008_reg, int min_uv,
	return 0;
}

static int pm8008_regulator_set_voltage_time(struct regulator_dev *rdev,
				int old_uV, int new_uv)
{
	struct pm8008_regulator *pm8008_reg = rdev_get_drvdata(rdev);

	return DIV_ROUND_UP(abs(new_uv - old_uV), pm8008_reg->step_rate);
}

static int pm8008_regulator_set_voltage(struct regulator_dev *rdev,
				int min_uv, int max_uv, unsigned int *selector)
{
	struct pm8008_regulator *pm8008_reg = rdev_get_drvdata(rdev);
	int rc = 0;
	int rc = 0, current_uv = 0, rounded_uv = 0, enabled = 0;

	if (pm8008_reg->parent_supply) {
		/* request on parent regulator with headroom */
		enabled = pm8008_regulator_is_enabled(rdev);
		if (enabled < 0) {
			return enabled;
		} else if (enabled) {
			current_uv = pm8008_regulator_get_voltage(rdev);
			if (current_uv < 0)
				return current_uv;
			rounded_uv = roundup(min_uv, VSET_STEP_UV);
		}
	}

	/*
	 * Set the parent_supply voltage before changing the LDO voltage when
	 * the LDO voltage is being increased.
	 */
	if (pm8008_reg->parent_supply && enabled && rounded_uv >= current_uv) {
		/* Request parent voltage with headroom */
		rc = regulator_set_voltage(pm8008_reg->parent_supply,
					pm8008_reg->min_dropout_uv + min_uv,
					rounded_uv + pm8008_reg->min_dropout_uv,
					INT_MAX);
		if (rc < 0) {
			pm8008_err(pm8008_reg,
				"failed to request parent supply voltage rc=%d\n",
			pm8008_err(pm8008_reg, "failed to request parent supply voltage rc=%d\n",
				rc);
			return rc;
		}
	}

	rc = pm8008_write_voltage(pm8008_reg, min_uv, max_uv);
	if (rc < 0)
		return rc;

	/*
	 * Set the parent_supply voltage after changing the LDO voltage when
	 * the LDO voltage is being reduced.
	 */
	if (pm8008_reg->parent_supply && enabled && rounded_uv < current_uv) {
		/*
		 * Ensure sufficient time for the LDO voltage to slew down
		 * before reducing the parent supply voltage.  The regulator
		 * framework will add the same delay after this function returns
		 * in all cases (i.e. enabled/disabled and increasing/decreasing
		 * voltage).
		 */
		udelay(pm8008_regulator_set_voltage_time(rdev, rounded_uv,
							current_uv));

		/* Request parent voltage with headroom */
		rc = regulator_set_voltage(pm8008_reg->parent_supply,
					rounded_uv + pm8008_reg->min_dropout_uv,
					INT_MAX);
		if (rc < 0) {
		/* remove parent's voltage vote */
		if (pm8008_reg->parent_supply)
			regulator_set_voltage(pm8008_reg->parent_supply,
						0, INT_MAX);
			pm8008_err(pm8008_reg, "failed to request parent supply voltage rc=%d\n",
				rc);
			return rc;
		}
	}

	pm8008_debug(pm8008_reg, "voltage set to %d\n", min_uv);
@@ -423,14 +495,6 @@ static int pm8008_regulator_set_load(struct regulator_dev *rdev, int load_uA)
	return pm8008_regulator_set_mode(rdev, mode);
}

static int pm8008_regulator_set_voltage_time(struct regulator_dev *rdev,
				int old_uV, int new_uv)
{
	struct pm8008_regulator *pm8008_reg = rdev_get_drvdata(rdev);

	return DIV_ROUND_UP(abs(new_uv - old_uV), pm8008_reg->step_rate);
}

static struct regulator_ops pm8008_regulator_ops = {
	.enable			= pm8008_regulator_enable,
	.disable		= pm8008_regulator_disable,
@@ -506,6 +570,7 @@ static int pm8008_register_ldo(struct pm8008_regulator *pm8008_reg,
	struct device_node *reg_node = pm8008_reg->of_node;
	char buff[MAX_REG_NAME];
	int rc, i, init_voltage;
	u32 base = 0;
	u8 reg;

	/* get regulator data */
@@ -518,11 +583,12 @@ static int pm8008_register_ldo(struct pm8008_regulator *pm8008_reg,
		return -EINVAL;
	}

	rc = of_property_read_u16(reg_node, "reg", &pm8008_reg->base);
	rc = of_property_read_u32(reg_node, "reg", &base);
	if (rc < 0) {
		pr_err("%s: failed to get regulator base rc=%d\n", name, rc);
		return rc;
	}
	pm8008_reg->base = base;

	pm8008_reg->min_dropout_uv = reg_data[i].min_dropout_uv;
	of_property_read_u32(reg_node, "qcom,min-dropout-voltage",
@@ -709,7 +775,7 @@ static int pm8008_regulator_probe(struct platform_device *pdev)
/* PM8008 chip enable regulator callbacks */
static int pm8008_enable_regulator_enable(struct regulator_dev *rdev)
{
	struct pm8008_regulator *chip = rdev_get_drvdata(rdev);
	struct pm8008_chip *chip = rdev_get_drvdata(rdev);
	int rc;

	rc = pm8008_masked_write(chip->regmap, MISC_CHIP_ENABLE_REG,
@@ -725,7 +791,7 @@ static int pm8008_enable_regulator_enable(struct regulator_dev *rdev)

static int pm8008_enable_regulator_disable(struct regulator_dev *rdev)
{
	struct pm8008_regulator *chip = rdev_get_drvdata(rdev);
	struct pm8008_chip *chip = rdev_get_drvdata(rdev);
	int rc;

	rc = pm8008_masked_write(chip->regmap, MISC_CHIP_ENABLE_REG,
@@ -741,7 +807,7 @@ static int pm8008_enable_regulator_disable(struct regulator_dev *rdev)

static int pm8008_enable_regulator_is_enabled(struct regulator_dev *rdev)
{
	struct pm8008_regulator *chip = rdev_get_drvdata(rdev);
	struct pm8008_chip *chip = rdev_get_drvdata(rdev);
	int rc;
	u8 reg;