Unverified Commit dc16594d authored by Mark Brown's avatar Mark Brown
Browse files

Add of_regulator_get_optional() and Fix MTK Power

Merge series from Chen-Yu Tsai <wenst@chromium.org>:

At ELCE, Sebastian told me about his recent work on adding regulator
supply support to the Rockchip power domain driver [2], how the MediaTek
driver has been using the existing devm_regulator_get() API and
reassigning different device nodes to the device doing the lookup, and
how the new of_regulator_get_optional() is the proper fit for this.

Patch 1 adds a new of_regulator_get_optional() function to look up
regulator supplies using device tree nodes.

Patch 2 adds a devres version of the aforementioned function at
Sebastian's request for the two power domain drivers.
parents 18be43ac 36ec3f43
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1959,8 +1959,8 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
	regulator_supply_alias(&dev, &supply);

	/* first do a dt based lookup */
	if (dev && dev->of_node) {
		r = of_regulator_dev_lookup(dev, supply);
	if (dev_of_node(dev)) {
		r = of_regulator_dev_lookup(dev, dev_of_node(dev), supply);
		if (!IS_ERR(r))
			return r;
		if (PTR_ERR(r) == -EPROBE_DEFER)
+39 −0
Original line number Diff line number Diff line
@@ -749,3 +749,42 @@ void *devm_regulator_irq_helper(struct device *dev,
	return ptr;
}
EXPORT_SYMBOL_GPL(devm_regulator_irq_helper);

#if IS_ENABLED(CONFIG_OF)
static struct regulator *_devm_of_regulator_get(struct device *dev, struct device_node *node,
						const char *id, int get_type)
{
	struct regulator **ptr, *regulator;

	ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
	if (!ptr)
		return ERR_PTR(-ENOMEM);

	regulator = _of_regulator_get(dev, node, id, get_type);
	if (!IS_ERR(regulator)) {
		*ptr = regulator;
		devres_add(dev, ptr);
	} else {
		devres_free(ptr);
	}

	return regulator;
}

/**
 * devm_of_regulator_get_optional - Resource managed of_regulator_get_optional()
 * @dev: device used for dev_printk() messages and resource lifetime management
 * @node: device node for regulator "consumer"
 * @id:  supply name or regulator ID.
 *
 * Managed regulator_get_optional(). Regulators returned from this
 * function are automatically regulator_put() on driver detach. See
 * of_regulator_get_optional() for more information.
 */
struct regulator *devm_of_regulator_get_optional(struct device *dev, struct device_node *node,
						 const char *id)
{
	return _devm_of_regulator_get(dev, node, id, OPTIONAL_GET);
}
EXPORT_SYMBOL_GPL(devm_of_regulator_get_optional);
#endif
+12 −6
Original line number Diff line number Diff line
@@ -65,14 +65,25 @@ static inline struct regulator_dev *dev_to_rdev(struct device *dev)
	return container_of(dev, struct regulator_dev, dev);
}

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

#ifdef CONFIG_OF
struct regulator_dev *of_regulator_dev_lookup(struct device *dev,
					      struct device_node *np,
					      const char *supply);
struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
			         const struct regulator_desc *desc,
				 struct regulator_config *config,
				 struct device_node **node);

struct regulator *_of_regulator_get(struct device *dev, struct device_node *node,
				    const char *id, enum regulator_get_type get_type);

struct regulator_dev *of_parse_coupled_regulator(struct regulator_dev *rdev,
						 int index);

@@ -82,6 +93,7 @@ bool of_check_coupling_data(struct regulator_dev *rdev);

#else
static inline struct regulator_dev *of_regulator_dev_lookup(struct device *dev,
							    struct device_node *np,
							    const char *supply)
{
	return ERR_PTR(-ENODEV);
@@ -114,12 +126,6 @@ static inline bool of_check_coupling_data(struct regulator_dev *rdev)
}

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

int _regulator_get_common_check(struct device *dev, const char *id,
				enum regulator_get_type get_type);
+45 −6
Original line number Diff line number Diff line
@@ -588,7 +588,8 @@ static struct device_node *of_get_child_regulator(struct device_node *parent,

/**
 * of_get_regulator - get a regulator device node based on supply name
 * @dev: Device pointer for the consumer (of regulator) device
 * @dev: Device pointer for dev_printk() messages
 * @node: Device node pointer for supply property lookup
 * @supply: regulator supply name
 *
 * Extract the regulator device node corresponding to the supply name.
@@ -596,15 +597,16 @@ static struct device_node *of_get_child_regulator(struct device_node *parent,
 * Return: Pointer to the &struct device_node corresponding to the regulator
 *	   if found, or %NULL if not found.
 */
static struct device_node *of_get_regulator(struct device *dev, const char *supply)
static struct device_node *of_get_regulator(struct device *dev, struct device_node *node,
					    const char *supply)
{
	struct device_node *regnode = NULL;
	char prop_name[64]; /* 64 is max size of property name */

	dev_dbg(dev, "Looking up %s-supply from device tree\n", supply);
	dev_dbg(dev, "Looking up %s-supply from device node %pOF\n", supply, node);

	snprintf(prop_name, 64, "%s-supply", supply);
	regnode = of_parse_phandle(dev->of_node, prop_name, 0);
	regnode = of_parse_phandle(node, prop_name, 0);
	if (regnode)
		return regnode;

@@ -628,6 +630,7 @@ static struct regulator_dev *of_find_regulator_by_node(struct device_node *np)
/**
 * of_regulator_dev_lookup - lookup a regulator device with device tree only
 * @dev: Device pointer for regulator supply lookup.
 * @np: Device node pointer for regulator supply lookup.
 * @supply: Supply name or regulator ID.
 *
 * Return: Pointer to the &struct regulator_dev on success, or ERR_PTR()
@@ -642,13 +645,13 @@ static struct regulator_dev *of_find_regulator_by_node(struct device_node *np)
 * * -%ENODEV if lookup fails permanently.
 * * -%EPROBE_DEFER if lookup could succeed in the future.
 */
struct regulator_dev *of_regulator_dev_lookup(struct device *dev,
struct regulator_dev *of_regulator_dev_lookup(struct device *dev, struct device_node *np,
					      const char *supply)
{
	struct regulator_dev *r;
	struct device_node *node;

	node = of_get_regulator(dev, supply);
	node = of_get_regulator(dev, np, supply);
	if (node) {
		r = of_find_regulator_by_node(node);
		of_node_put(node);
@@ -665,6 +668,42 @@ struct regulator_dev *of_regulator_dev_lookup(struct device *dev,
	return ERR_PTR(-ENODEV);
}

struct regulator *_of_regulator_get(struct device *dev, struct device_node *node,
				    const char *id, enum regulator_get_type get_type)
{
	struct regulator_dev *r;
	int ret;

	ret = _regulator_get_common_check(dev, id, get_type);
	if (ret)
		return ERR_PTR(ret);

	r = of_regulator_dev_lookup(dev, node, id);
	return _regulator_get_common(r, dev, id, get_type);
}

/**
 * of_regulator_get_optional - get optional regulator via device tree lookup
 * @dev: device used for dev_printk() messages
 * @node: device node for regulator "consumer"
 * @id: Supply name
 *
 * Return: pointer to struct regulator corresponding to the regulator producer,
 *	   or PTR_ERR() encoded error number.
 *
 * This is intended for use by consumers that want to get a regulator
 * supply directly from a device node, and can and want to deal with
 * absence of such supplies. This will _not_ consider supply aliases.
 * See regulator_dev_lookup().
 */
struct regulator *of_regulator_get_optional(struct device *dev,
					    struct device_node *node,
					    const char *id)
{
	return _of_regulator_get(dev, node, id, OPTIONAL_GET);
}
EXPORT_SYMBOL_GPL(of_regulator_get_optional);

/*
 * Returns number of regulators coupled with rdev.
 */
+37 −0
Original line number Diff line number Diff line
@@ -168,6 +168,29 @@ int devm_regulator_get_enable_read_voltage(struct device *dev, const char *id);
void regulator_put(struct regulator *regulator);
void devm_regulator_put(struct regulator *regulator);

#if IS_ENABLED(CONFIG_OF)
struct regulator *__must_check of_regulator_get_optional(struct device *dev,
							 struct device_node *node,
							 const char *id);
struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev,
							      struct device_node *node,
							      const char *id);
#else
static inline struct regulator *__must_check of_regulator_get_optional(struct device *dev,
								       struct device_node *node,
								       const char *id)
{
	return ERR_PTR(-ENODEV);
}

static inline struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev,
									    struct device_node *node,
									    const char *id)
{
	return ERR_PTR(-ENODEV);
}
#endif

int regulator_register_supply_alias(struct device *dev, const char *id,
				    struct device *alias_dev,
				    const char *alias_id);
@@ -350,6 +373,20 @@ devm_regulator_get_optional(struct device *dev, const char *id)
	return ERR_PTR(-ENODEV);
}

static inline struct regulator *__must_check of_regulator_get_optional(struct device *dev,
								       struct device_node *node,
								       const char *id)
{
	return ERR_PTR(-ENODEV);
}

static inline struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev,
									    struct device_node *node,
									    const char *id)
{
	return ERR_PTR(-ENODEV);
}

static inline void regulator_put(struct regulator *regulator)
{
}