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

Commit 401c4242 authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branch 'regulator/topic/core' into regulator-next

parents 0fe3f971 a4d7641f
Loading
Loading
Loading
Loading
+74 −71
Original line number Diff line number Diff line
@@ -1455,12 +1455,14 @@ static struct regulator_dev *regulator_lookup_by_name(const char *name)
 * lookup could succeed in the future.
 *
 * If successful, returns a struct regulator_dev that corresponds to the name
 * @supply and with the embedded struct device refcount incremented by one,
 * or NULL on failure. The refcount must be dropped by calling put_device().
 * @supply and with the embedded struct device refcount incremented by one.
 * The refcount must be dropped by calling put_device().
 * On failure one of the following ERR-PTR-encoded values is returned:
 * -ENODEV if lookup fails permanently, -EPROBE_DEFER if lookup could succeed
 * in the future.
 */
static struct regulator_dev *regulator_dev_lookup(struct device *dev,
						  const char *supply,
						  int *ret)
						  const char *supply)
{
	struct regulator_dev *r;
	struct device_node *node;
@@ -1476,16 +1478,12 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
			r = of_find_regulator_by_node(node);
			if (r)
				return r;
			*ret = -EPROBE_DEFER;
			return NULL;
		} else {

			/*
			 * If we couldn't even get the node then it's
			 * not just that the device didn't register
			 * yet, there's no node and we'll never
			 * succeed.
			 * We have a node, but there is no device.
			 * assume it has not registered yet.
			 */
			*ret = -ENODEV;
			return ERR_PTR(-EPROBE_DEFER);
		}
	}

@@ -1506,13 +1504,16 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,

		if (strcmp(map->supply, supply) == 0 &&
		    get_device(&map->regulator->dev)) {
			mutex_unlock(&regulator_list_mutex);
			return map->regulator;
			r = map->regulator;
			break;
		}
	}
	mutex_unlock(&regulator_list_mutex);

	return NULL;
	if (r)
		return r;

	return ERR_PTR(-ENODEV);
}

static int regulator_resolve_supply(struct regulator_dev *rdev)
@@ -1529,8 +1530,10 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
	if (rdev->supply)
		return 0;

	r = regulator_dev_lookup(dev, rdev->supply_name, &ret);
	if (!r) {
	r = regulator_dev_lookup(dev, rdev->supply_name);
	if (IS_ERR(r)) {
		ret = PTR_ERR(r);

		if (ret == -ENODEV) {
			/*
			 * No supply was specified for this regulator and
@@ -1580,69 +1583,72 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
}

/* Internal regulator request function */
static struct regulator *_regulator_get(struct device *dev, const char *id,
					bool exclusive, bool allow_dummy)
struct regulator *_regulator_get(struct device *dev, const char *id,
				 enum regulator_get_type get_type)
{
	struct regulator_dev *rdev;
	struct regulator *regulator = ERR_PTR(-EPROBE_DEFER);
	const char *devname = NULL;
	struct regulator *regulator;
	const char *devname = dev ? dev_name(dev) : "deviceless";
	int ret;

	if (get_type >= MAX_GET_TYPE) {
		dev_err(dev, "invalid type %d in %s\n", get_type, __func__);
		return ERR_PTR(-EINVAL);
	}

	if (id == NULL) {
		pr_err("get() with no identifier\n");
		return ERR_PTR(-EINVAL);
	}

	if (dev)
		devname = dev_name(dev);

	if (have_full_constraints())
		ret = -ENODEV;
	else
		ret = -EPROBE_DEFER;

	rdev = regulator_dev_lookup(dev, id, &ret);
	if (rdev)
		goto found;

	regulator = ERR_PTR(ret);
	rdev = regulator_dev_lookup(dev, id);
	if (IS_ERR(rdev)) {
		ret = PTR_ERR(rdev);

		/*
	 * If we have return value from dev_lookup fail, we do not expect to
	 * succeed, so, quit with appropriate error value
		 * If regulator_dev_lookup() fails with error other
		 * than -ENODEV our job here is done, we simply return it.
		 */
	if (ret && ret != -ENODEV)
		return regulator;
		if (ret != -ENODEV)
			return ERR_PTR(ret);

	if (!devname)
		devname = "deviceless";
		if (!have_full_constraints()) {
			dev_warn(dev,
				 "incomplete constraints, dummy supplies not allowed\n");
			return ERR_PTR(-ENODEV);
		}

		switch (get_type) {
		case NORMAL_GET:
			/*
	 * Assume that a regulator is physically present and enabled
	 * even if it isn't hooked up and just provide a dummy.
			 * Assume that a regulator is physically present and
			 * enabled, even if it isn't hooked up, and just
			 * provide a dummy.
			 */
	if (have_full_constraints() && allow_dummy) {
		pr_warn("%s supply %s not found, using dummy regulator\n",
			dev_warn(dev,
				 "%s supply %s not found, using dummy regulator\n",
				 devname, id);

			rdev = dummy_regulator_rdev;
			get_device(&rdev->dev);
		goto found;
	/* Don't log an error when called from regulator_get_optional() */
	} else if (!have_full_constraints() || exclusive) {
		dev_warn(dev, "dummy supplies not allowed\n");
	}
			break;

	return regulator;
		case EXCLUSIVE_GET:
			dev_warn(dev,
				 "dummy supplies not allowed for exclusive requests\n");
			/* fall through */

		default:
			return ERR_PTR(-ENODEV);
		}
	}

found:
	if (rdev->exclusive) {
		regulator = ERR_PTR(-EPERM);
		put_device(&rdev->dev);
		return regulator;
	}

	if (exclusive && rdev->open_count) {
	if (get_type == EXCLUSIVE_GET && rdev->open_count) {
		regulator = ERR_PTR(-EBUSY);
		put_device(&rdev->dev);
		return regulator;
@@ -1656,6 +1662,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
	}

	if (!try_module_get(rdev->owner)) {
		regulator = ERR_PTR(-EPROBE_DEFER);
		put_device(&rdev->dev);
		return regulator;
	}
@@ -1669,7 +1676,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
	}

	rdev->open_count++;
	if (exclusive) {
	if (get_type == EXCLUSIVE_GET) {
		rdev->exclusive = 1;

		ret = _regulator_is_enabled(rdev);
@@ -1697,7 +1704,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
 */
struct regulator *regulator_get(struct device *dev, const char *id)
{
	return _regulator_get(dev, id, false, true);
	return _regulator_get(dev, id, NORMAL_GET);
}
EXPORT_SYMBOL_GPL(regulator_get);

@@ -1724,7 +1731,7 @@ EXPORT_SYMBOL_GPL(regulator_get);
 */
struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
{
	return _regulator_get(dev, id, true, false);
	return _regulator_get(dev, id, EXCLUSIVE_GET);
}
EXPORT_SYMBOL_GPL(regulator_get_exclusive);

@@ -1750,7 +1757,7 @@ EXPORT_SYMBOL_GPL(regulator_get_exclusive);
 */
struct regulator *regulator_get_optional(struct device *dev, const char *id)
{
	return _regulator_get(dev, id, false, false);
	return _regulator_get(dev, id, OPTIONAL_GET);
}
EXPORT_SYMBOL_GPL(regulator_get_optional);

@@ -3660,7 +3667,7 @@ int regulator_bulk_disable(int num_consumers,
	for (++i; i < num_consumers; ++i) {
		r = regulator_enable(consumers[i].consumer);
		if (r != 0)
			pr_err("Failed to reename %s: %d\n",
			pr_err("Failed to re-enable %s: %d\n",
			       consumers[i].supply, r);
	}

@@ -3686,21 +3693,17 @@ int regulator_bulk_force_disable(int num_consumers,
			   struct regulator_bulk_data *consumers)
{
	int i;
	int ret;
	int ret = 0;

	for (i = 0; i < num_consumers; i++)
	for (i = 0; i < num_consumers; i++) {
		consumers[i].ret =
			    regulator_force_disable(consumers[i].consumer);

	for (i = 0; i < num_consumers; i++) {
		if (consumers[i].ret != 0) {
		/* Store first error for reporting */
		if (consumers[i].ret && !ret)
			ret = consumers[i].ret;
			goto out;
		}
	}

	return 0;
out:
	return ret;
}
EXPORT_SYMBOL_GPL(regulator_bulk_force_disable);
+26 −40
Original line number Diff line number Diff line
@@ -19,12 +19,6 @@

#include "internal.h"

enum {
	NORMAL_GET,
	EXCLUSIVE_GET,
	OPTIONAL_GET,
};

static void devm_regulator_release(struct device *dev, void *res)
{
	regulator_put(*(struct regulator **)res);
@@ -39,20 +33,7 @@ static struct regulator *_devm_regulator_get(struct device *dev, const char *id,
	if (!ptr)
		return ERR_PTR(-ENOMEM);

	switch (get_type) {
	case NORMAL_GET:
		regulator = regulator_get(dev, id);
		break;
	case EXCLUSIVE_GET:
		regulator = regulator_get_exclusive(dev, id);
		break;
	case OPTIONAL_GET:
		regulator = regulator_get_optional(dev, id);
		break;
	default:
		regulator = ERR_PTR(-EINVAL);
	}

	regulator = _regulator_get(dev, id, get_type);
	if (!IS_ERR(regulator)) {
		*ptr = regulator;
		devres_add(dev, ptr);
@@ -139,6 +120,18 @@ void devm_regulator_put(struct regulator *regulator)
}
EXPORT_SYMBOL_GPL(devm_regulator_put);

struct regulator_bulk_devres {
	struct regulator_bulk_data *consumers;
	int num_consumers;
};

static void devm_regulator_bulk_release(struct device *dev, void *res)
{
	struct regulator_bulk_devres *devres = res;

	regulator_bulk_free(devres->num_consumers, devres->consumers);
}

/**
 * devm_regulator_bulk_get - managed get multiple regulator consumers
 *
@@ -157,29 +150,22 @@ EXPORT_SYMBOL_GPL(devm_regulator_put);
int devm_regulator_bulk_get(struct device *dev, int num_consumers,
			    struct regulator_bulk_data *consumers)
{
	int i;
	struct regulator_bulk_devres *devres;
	int ret;

	for (i = 0; i < num_consumers; i++)
		consumers[i].consumer = NULL;

	for (i = 0; i < num_consumers; i++) {
		consumers[i].consumer = devm_regulator_get(dev,
							   consumers[i].supply);
		if (IS_ERR(consumers[i].consumer)) {
			ret = PTR_ERR(consumers[i].consumer);
			dev_err(dev, "Failed to get supply '%s': %d\n",
				consumers[i].supply, ret);
			consumers[i].consumer = NULL;
			goto err;
		}
	}

	return 0;
	devres = devres_alloc(devm_regulator_bulk_release,
			      sizeof(*devres), GFP_KERNEL);
	if (!devres)
		return -ENOMEM;

err:
	for (i = 0; i < num_consumers && consumers[i].consumer; i++)
		devm_regulator_put(consumers[i].consumer);
	ret = regulator_bulk_get(dev, num_consumers, consumers);
	if (!ret) {
		devres->consumers = consumers;
		devres->num_consumers = num_consumers;
		devres_add(dev, devres);
	} else {
		devres_free(devres);
	}

	return ret;
}
+10 −0
Original line number Diff line number Diff line
@@ -51,4 +51,14 @@ regulator_of_get_init_data(struct device *dev,
}
#endif

enum regulator_get_type {
	NORMAL_GET,
	EXCLUSIVE_GET,
	OPTIONAL_GET,
	MAX_GET_TYPE
};

struct regulator *_regulator_get(struct device *dev, const char *id,
				 enum regulator_get_type get_type);

#endif