162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// core.c  --  Voltage/Current Regulator framework.
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Copyright 2007, 2008 Wolfson Microelectronics PLC.
662306a36Sopenharmony_ci// Copyright 2008 SlimLogic Ltd.
762306a36Sopenharmony_ci//
862306a36Sopenharmony_ci// Author: Liam Girdwood <lrg@slimlogic.co.uk>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/kernel.h>
1162306a36Sopenharmony_ci#include <linux/init.h>
1262306a36Sopenharmony_ci#include <linux/debugfs.h>
1362306a36Sopenharmony_ci#include <linux/device.h>
1462306a36Sopenharmony_ci#include <linux/slab.h>
1562306a36Sopenharmony_ci#include <linux/async.h>
1662306a36Sopenharmony_ci#include <linux/err.h>
1762306a36Sopenharmony_ci#include <linux/mutex.h>
1862306a36Sopenharmony_ci#include <linux/suspend.h>
1962306a36Sopenharmony_ci#include <linux/delay.h>
2062306a36Sopenharmony_ci#include <linux/gpio/consumer.h>
2162306a36Sopenharmony_ci#include <linux/of.h>
2262306a36Sopenharmony_ci#include <linux/regmap.h>
2362306a36Sopenharmony_ci#include <linux/regulator/of_regulator.h>
2462306a36Sopenharmony_ci#include <linux/regulator/consumer.h>
2562306a36Sopenharmony_ci#include <linux/regulator/coupler.h>
2662306a36Sopenharmony_ci#include <linux/regulator/driver.h>
2762306a36Sopenharmony_ci#include <linux/regulator/machine.h>
2862306a36Sopenharmony_ci#include <linux/module.h>
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#define CREATE_TRACE_POINTS
3162306a36Sopenharmony_ci#include <trace/events/regulator.h>
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#include "dummy.h"
3462306a36Sopenharmony_ci#include "internal.h"
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistatic DEFINE_WW_CLASS(regulator_ww_class);
3762306a36Sopenharmony_cistatic DEFINE_MUTEX(regulator_nesting_mutex);
3862306a36Sopenharmony_cistatic DEFINE_MUTEX(regulator_list_mutex);
3962306a36Sopenharmony_cistatic LIST_HEAD(regulator_map_list);
4062306a36Sopenharmony_cistatic LIST_HEAD(regulator_ena_gpio_list);
4162306a36Sopenharmony_cistatic LIST_HEAD(regulator_supply_alias_list);
4262306a36Sopenharmony_cistatic LIST_HEAD(regulator_coupler_list);
4362306a36Sopenharmony_cistatic bool has_full_constraints;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistatic struct dentry *debugfs_root;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/*
4862306a36Sopenharmony_ci * struct regulator_map
4962306a36Sopenharmony_ci *
5062306a36Sopenharmony_ci * Used to provide symbolic supply names to devices.
5162306a36Sopenharmony_ci */
5262306a36Sopenharmony_cistruct regulator_map {
5362306a36Sopenharmony_ci	struct list_head list;
5462306a36Sopenharmony_ci	const char *dev_name;   /* The dev_name() for the consumer */
5562306a36Sopenharmony_ci	const char *supply;
5662306a36Sopenharmony_ci	struct regulator_dev *regulator;
5762306a36Sopenharmony_ci};
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci/*
6062306a36Sopenharmony_ci * struct regulator_enable_gpio
6162306a36Sopenharmony_ci *
6262306a36Sopenharmony_ci * Management for shared enable GPIO pin
6362306a36Sopenharmony_ci */
6462306a36Sopenharmony_cistruct regulator_enable_gpio {
6562306a36Sopenharmony_ci	struct list_head list;
6662306a36Sopenharmony_ci	struct gpio_desc *gpiod;
6762306a36Sopenharmony_ci	u32 enable_count;	/* a number of enabled shared GPIO */
6862306a36Sopenharmony_ci	u32 request_count;	/* a number of requested shared GPIO */
6962306a36Sopenharmony_ci};
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/*
7262306a36Sopenharmony_ci * struct regulator_supply_alias
7362306a36Sopenharmony_ci *
7462306a36Sopenharmony_ci * Used to map lookups for a supply onto an alternative device.
7562306a36Sopenharmony_ci */
7662306a36Sopenharmony_cistruct regulator_supply_alias {
7762306a36Sopenharmony_ci	struct list_head list;
7862306a36Sopenharmony_ci	struct device *src_dev;
7962306a36Sopenharmony_ci	const char *src_supply;
8062306a36Sopenharmony_ci	struct device *alias_dev;
8162306a36Sopenharmony_ci	const char *alias_supply;
8262306a36Sopenharmony_ci};
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cistatic int _regulator_is_enabled(struct regulator_dev *rdev);
8562306a36Sopenharmony_cistatic int _regulator_disable(struct regulator *regulator);
8662306a36Sopenharmony_cistatic int _regulator_get_error_flags(struct regulator_dev *rdev, unsigned int *flags);
8762306a36Sopenharmony_cistatic int _regulator_get_current_limit(struct regulator_dev *rdev);
8862306a36Sopenharmony_cistatic unsigned int _regulator_get_mode(struct regulator_dev *rdev);
8962306a36Sopenharmony_cistatic int _notifier_call_chain(struct regulator_dev *rdev,
9062306a36Sopenharmony_ci				  unsigned long event, void *data);
9162306a36Sopenharmony_cistatic int _regulator_do_set_voltage(struct regulator_dev *rdev,
9262306a36Sopenharmony_ci				     int min_uV, int max_uV);
9362306a36Sopenharmony_cistatic int regulator_balance_voltage(struct regulator_dev *rdev,
9462306a36Sopenharmony_ci				     suspend_state_t state);
9562306a36Sopenharmony_cistatic struct regulator *create_regulator(struct regulator_dev *rdev,
9662306a36Sopenharmony_ci					  struct device *dev,
9762306a36Sopenharmony_ci					  const char *supply_name);
9862306a36Sopenharmony_cistatic void destroy_regulator(struct regulator *regulator);
9962306a36Sopenharmony_cistatic void _regulator_put(struct regulator *regulator);
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ciconst char *rdev_get_name(struct regulator_dev *rdev)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	if (rdev->constraints && rdev->constraints->name)
10462306a36Sopenharmony_ci		return rdev->constraints->name;
10562306a36Sopenharmony_ci	else if (rdev->desc->name)
10662306a36Sopenharmony_ci		return rdev->desc->name;
10762306a36Sopenharmony_ci	else
10862306a36Sopenharmony_ci		return "";
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rdev_get_name);
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistatic bool have_full_constraints(void)
11362306a36Sopenharmony_ci{
11462306a36Sopenharmony_ci	return has_full_constraints || of_have_populated_dt();
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic bool regulator_ops_is_valid(struct regulator_dev *rdev, int ops)
11862306a36Sopenharmony_ci{
11962306a36Sopenharmony_ci	if (!rdev->constraints) {
12062306a36Sopenharmony_ci		rdev_err(rdev, "no constraints\n");
12162306a36Sopenharmony_ci		return false;
12262306a36Sopenharmony_ci	}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	if (rdev->constraints->valid_ops_mask & ops)
12562306a36Sopenharmony_ci		return true;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	return false;
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci/**
13162306a36Sopenharmony_ci * regulator_lock_nested - lock a single regulator
13262306a36Sopenharmony_ci * @rdev:		regulator source
13362306a36Sopenharmony_ci * @ww_ctx:		w/w mutex acquire context
13462306a36Sopenharmony_ci *
13562306a36Sopenharmony_ci * This function can be called many times by one task on
13662306a36Sopenharmony_ci * a single regulator and its mutex will be locked only
13762306a36Sopenharmony_ci * once. If a task, which is calling this function is other
13862306a36Sopenharmony_ci * than the one, which initially locked the mutex, it will
13962306a36Sopenharmony_ci * wait on mutex.
14062306a36Sopenharmony_ci */
14162306a36Sopenharmony_cistatic inline int regulator_lock_nested(struct regulator_dev *rdev,
14262306a36Sopenharmony_ci					struct ww_acquire_ctx *ww_ctx)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	bool lock = false;
14562306a36Sopenharmony_ci	int ret = 0;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	mutex_lock(&regulator_nesting_mutex);
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	if (!ww_mutex_trylock(&rdev->mutex, ww_ctx)) {
15062306a36Sopenharmony_ci		if (rdev->mutex_owner == current)
15162306a36Sopenharmony_ci			rdev->ref_cnt++;
15262306a36Sopenharmony_ci		else
15362306a36Sopenharmony_ci			lock = true;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci		if (lock) {
15662306a36Sopenharmony_ci			mutex_unlock(&regulator_nesting_mutex);
15762306a36Sopenharmony_ci			ret = ww_mutex_lock(&rdev->mutex, ww_ctx);
15862306a36Sopenharmony_ci			mutex_lock(&regulator_nesting_mutex);
15962306a36Sopenharmony_ci		}
16062306a36Sopenharmony_ci	} else {
16162306a36Sopenharmony_ci		lock = true;
16262306a36Sopenharmony_ci	}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	if (lock && ret != -EDEADLK) {
16562306a36Sopenharmony_ci		rdev->ref_cnt++;
16662306a36Sopenharmony_ci		rdev->mutex_owner = current;
16762306a36Sopenharmony_ci	}
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	mutex_unlock(&regulator_nesting_mutex);
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	return ret;
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci/**
17562306a36Sopenharmony_ci * regulator_lock - lock a single regulator
17662306a36Sopenharmony_ci * @rdev:		regulator source
17762306a36Sopenharmony_ci *
17862306a36Sopenharmony_ci * This function can be called many times by one task on
17962306a36Sopenharmony_ci * a single regulator and its mutex will be locked only
18062306a36Sopenharmony_ci * once. If a task, which is calling this function is other
18162306a36Sopenharmony_ci * than the one, which initially locked the mutex, it will
18262306a36Sopenharmony_ci * wait on mutex.
18362306a36Sopenharmony_ci */
18462306a36Sopenharmony_cistatic void regulator_lock(struct regulator_dev *rdev)
18562306a36Sopenharmony_ci{
18662306a36Sopenharmony_ci	regulator_lock_nested(rdev, NULL);
18762306a36Sopenharmony_ci}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci/**
19062306a36Sopenharmony_ci * regulator_unlock - unlock a single regulator
19162306a36Sopenharmony_ci * @rdev:		regulator_source
19262306a36Sopenharmony_ci *
19362306a36Sopenharmony_ci * This function unlocks the mutex when the
19462306a36Sopenharmony_ci * reference counter reaches 0.
19562306a36Sopenharmony_ci */
19662306a36Sopenharmony_cistatic void regulator_unlock(struct regulator_dev *rdev)
19762306a36Sopenharmony_ci{
19862306a36Sopenharmony_ci	mutex_lock(&regulator_nesting_mutex);
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	if (--rdev->ref_cnt == 0) {
20162306a36Sopenharmony_ci		rdev->mutex_owner = NULL;
20262306a36Sopenharmony_ci		ww_mutex_unlock(&rdev->mutex);
20362306a36Sopenharmony_ci	}
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	WARN_ON_ONCE(rdev->ref_cnt < 0);
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	mutex_unlock(&regulator_nesting_mutex);
20862306a36Sopenharmony_ci}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci/**
21162306a36Sopenharmony_ci * regulator_lock_two - lock two regulators
21262306a36Sopenharmony_ci * @rdev1:		first regulator
21362306a36Sopenharmony_ci * @rdev2:		second regulator
21462306a36Sopenharmony_ci * @ww_ctx:		w/w mutex acquire context
21562306a36Sopenharmony_ci *
21662306a36Sopenharmony_ci * Locks both rdevs using the regulator_ww_class.
21762306a36Sopenharmony_ci */
21862306a36Sopenharmony_cistatic void regulator_lock_two(struct regulator_dev *rdev1,
21962306a36Sopenharmony_ci			       struct regulator_dev *rdev2,
22062306a36Sopenharmony_ci			       struct ww_acquire_ctx *ww_ctx)
22162306a36Sopenharmony_ci{
22262306a36Sopenharmony_ci	struct regulator_dev *held, *contended;
22362306a36Sopenharmony_ci	int ret;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	ww_acquire_init(ww_ctx, &regulator_ww_class);
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	/* Try to just grab both of them */
22862306a36Sopenharmony_ci	ret = regulator_lock_nested(rdev1, ww_ctx);
22962306a36Sopenharmony_ci	WARN_ON(ret);
23062306a36Sopenharmony_ci	ret = regulator_lock_nested(rdev2, ww_ctx);
23162306a36Sopenharmony_ci	if (ret != -EDEADLOCK) {
23262306a36Sopenharmony_ci		WARN_ON(ret);
23362306a36Sopenharmony_ci		goto exit;
23462306a36Sopenharmony_ci	}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	held = rdev1;
23762306a36Sopenharmony_ci	contended = rdev2;
23862306a36Sopenharmony_ci	while (true) {
23962306a36Sopenharmony_ci		regulator_unlock(held);
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci		ww_mutex_lock_slow(&contended->mutex, ww_ctx);
24262306a36Sopenharmony_ci		contended->ref_cnt++;
24362306a36Sopenharmony_ci		contended->mutex_owner = current;
24462306a36Sopenharmony_ci		swap(held, contended);
24562306a36Sopenharmony_ci		ret = regulator_lock_nested(contended, ww_ctx);
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci		if (ret != -EDEADLOCK) {
24862306a36Sopenharmony_ci			WARN_ON(ret);
24962306a36Sopenharmony_ci			break;
25062306a36Sopenharmony_ci		}
25162306a36Sopenharmony_ci	}
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ciexit:
25462306a36Sopenharmony_ci	ww_acquire_done(ww_ctx);
25562306a36Sopenharmony_ci}
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci/**
25862306a36Sopenharmony_ci * regulator_unlock_two - unlock two regulators
25962306a36Sopenharmony_ci * @rdev1:		first regulator
26062306a36Sopenharmony_ci * @rdev2:		second regulator
26162306a36Sopenharmony_ci * @ww_ctx:		w/w mutex acquire context
26262306a36Sopenharmony_ci *
26362306a36Sopenharmony_ci * The inverse of regulator_lock_two().
26462306a36Sopenharmony_ci */
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_cistatic void regulator_unlock_two(struct regulator_dev *rdev1,
26762306a36Sopenharmony_ci				 struct regulator_dev *rdev2,
26862306a36Sopenharmony_ci				 struct ww_acquire_ctx *ww_ctx)
26962306a36Sopenharmony_ci{
27062306a36Sopenharmony_ci	regulator_unlock(rdev2);
27162306a36Sopenharmony_ci	regulator_unlock(rdev1);
27262306a36Sopenharmony_ci	ww_acquire_fini(ww_ctx);
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_cistatic bool regulator_supply_is_couple(struct regulator_dev *rdev)
27662306a36Sopenharmony_ci{
27762306a36Sopenharmony_ci	struct regulator_dev *c_rdev;
27862306a36Sopenharmony_ci	int i;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	for (i = 1; i < rdev->coupling_desc.n_coupled; i++) {
28162306a36Sopenharmony_ci		c_rdev = rdev->coupling_desc.coupled_rdevs[i];
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci		if (rdev->supply->rdev == c_rdev)
28462306a36Sopenharmony_ci			return true;
28562306a36Sopenharmony_ci	}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	return false;
28862306a36Sopenharmony_ci}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_cistatic void regulator_unlock_recursive(struct regulator_dev *rdev,
29162306a36Sopenharmony_ci				       unsigned int n_coupled)
29262306a36Sopenharmony_ci{
29362306a36Sopenharmony_ci	struct regulator_dev *c_rdev, *supply_rdev;
29462306a36Sopenharmony_ci	int i, supply_n_coupled;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	for (i = n_coupled; i > 0; i--) {
29762306a36Sopenharmony_ci		c_rdev = rdev->coupling_desc.coupled_rdevs[i - 1];
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci		if (!c_rdev)
30062306a36Sopenharmony_ci			continue;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci		if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) {
30362306a36Sopenharmony_ci			supply_rdev = c_rdev->supply->rdev;
30462306a36Sopenharmony_ci			supply_n_coupled = supply_rdev->coupling_desc.n_coupled;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci			regulator_unlock_recursive(supply_rdev,
30762306a36Sopenharmony_ci						   supply_n_coupled);
30862306a36Sopenharmony_ci		}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci		regulator_unlock(c_rdev);
31162306a36Sopenharmony_ci	}
31262306a36Sopenharmony_ci}
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_cistatic int regulator_lock_recursive(struct regulator_dev *rdev,
31562306a36Sopenharmony_ci				    struct regulator_dev **new_contended_rdev,
31662306a36Sopenharmony_ci				    struct regulator_dev **old_contended_rdev,
31762306a36Sopenharmony_ci				    struct ww_acquire_ctx *ww_ctx)
31862306a36Sopenharmony_ci{
31962306a36Sopenharmony_ci	struct regulator_dev *c_rdev;
32062306a36Sopenharmony_ci	int i, err;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	for (i = 0; i < rdev->coupling_desc.n_coupled; i++) {
32362306a36Sopenharmony_ci		c_rdev = rdev->coupling_desc.coupled_rdevs[i];
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci		if (!c_rdev)
32662306a36Sopenharmony_ci			continue;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci		if (c_rdev != *old_contended_rdev) {
32962306a36Sopenharmony_ci			err = regulator_lock_nested(c_rdev, ww_ctx);
33062306a36Sopenharmony_ci			if (err) {
33162306a36Sopenharmony_ci				if (err == -EDEADLK) {
33262306a36Sopenharmony_ci					*new_contended_rdev = c_rdev;
33362306a36Sopenharmony_ci					goto err_unlock;
33462306a36Sopenharmony_ci				}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci				/* shouldn't happen */
33762306a36Sopenharmony_ci				WARN_ON_ONCE(err != -EALREADY);
33862306a36Sopenharmony_ci			}
33962306a36Sopenharmony_ci		} else {
34062306a36Sopenharmony_ci			*old_contended_rdev = NULL;
34162306a36Sopenharmony_ci		}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci		if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) {
34462306a36Sopenharmony_ci			err = regulator_lock_recursive(c_rdev->supply->rdev,
34562306a36Sopenharmony_ci						       new_contended_rdev,
34662306a36Sopenharmony_ci						       old_contended_rdev,
34762306a36Sopenharmony_ci						       ww_ctx);
34862306a36Sopenharmony_ci			if (err) {
34962306a36Sopenharmony_ci				regulator_unlock(c_rdev);
35062306a36Sopenharmony_ci				goto err_unlock;
35162306a36Sopenharmony_ci			}
35262306a36Sopenharmony_ci		}
35362306a36Sopenharmony_ci	}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	return 0;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_cierr_unlock:
35862306a36Sopenharmony_ci	regulator_unlock_recursive(rdev, i);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	return err;
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci/**
36462306a36Sopenharmony_ci * regulator_unlock_dependent - unlock regulator's suppliers and coupled
36562306a36Sopenharmony_ci *				regulators
36662306a36Sopenharmony_ci * @rdev:			regulator source
36762306a36Sopenharmony_ci * @ww_ctx:			w/w mutex acquire context
36862306a36Sopenharmony_ci *
36962306a36Sopenharmony_ci * Unlock all regulators related with rdev by coupling or supplying.
37062306a36Sopenharmony_ci */
37162306a36Sopenharmony_cistatic void regulator_unlock_dependent(struct regulator_dev *rdev,
37262306a36Sopenharmony_ci				       struct ww_acquire_ctx *ww_ctx)
37362306a36Sopenharmony_ci{
37462306a36Sopenharmony_ci	regulator_unlock_recursive(rdev, rdev->coupling_desc.n_coupled);
37562306a36Sopenharmony_ci	ww_acquire_fini(ww_ctx);
37662306a36Sopenharmony_ci}
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci/**
37962306a36Sopenharmony_ci * regulator_lock_dependent - lock regulator's suppliers and coupled regulators
38062306a36Sopenharmony_ci * @rdev:			regulator source
38162306a36Sopenharmony_ci * @ww_ctx:			w/w mutex acquire context
38262306a36Sopenharmony_ci *
38362306a36Sopenharmony_ci * This function as a wrapper on regulator_lock_recursive(), which locks
38462306a36Sopenharmony_ci * all regulators related with rdev by coupling or supplying.
38562306a36Sopenharmony_ci */
38662306a36Sopenharmony_cistatic void regulator_lock_dependent(struct regulator_dev *rdev,
38762306a36Sopenharmony_ci				     struct ww_acquire_ctx *ww_ctx)
38862306a36Sopenharmony_ci{
38962306a36Sopenharmony_ci	struct regulator_dev *new_contended_rdev = NULL;
39062306a36Sopenharmony_ci	struct regulator_dev *old_contended_rdev = NULL;
39162306a36Sopenharmony_ci	int err;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci	ww_acquire_init(ww_ctx, &regulator_ww_class);
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	do {
39862306a36Sopenharmony_ci		if (new_contended_rdev) {
39962306a36Sopenharmony_ci			ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx);
40062306a36Sopenharmony_ci			old_contended_rdev = new_contended_rdev;
40162306a36Sopenharmony_ci			old_contended_rdev->ref_cnt++;
40262306a36Sopenharmony_ci			old_contended_rdev->mutex_owner = current;
40362306a36Sopenharmony_ci		}
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci		err = regulator_lock_recursive(rdev,
40662306a36Sopenharmony_ci					       &new_contended_rdev,
40762306a36Sopenharmony_ci					       &old_contended_rdev,
40862306a36Sopenharmony_ci					       ww_ctx);
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci		if (old_contended_rdev)
41162306a36Sopenharmony_ci			regulator_unlock(old_contended_rdev);
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	} while (err == -EDEADLK);
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	ww_acquire_done(ww_ctx);
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
41862306a36Sopenharmony_ci}
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci/**
42162306a36Sopenharmony_ci * of_get_child_regulator - get a child regulator device node
42262306a36Sopenharmony_ci * based on supply name
42362306a36Sopenharmony_ci * @parent: Parent device node
42462306a36Sopenharmony_ci * @prop_name: Combination regulator supply name and "-supply"
42562306a36Sopenharmony_ci *
42662306a36Sopenharmony_ci * Traverse all child nodes.
42762306a36Sopenharmony_ci * Extract the child regulator device node corresponding to the supply name.
42862306a36Sopenharmony_ci * returns the device node corresponding to the regulator if found, else
42962306a36Sopenharmony_ci * returns NULL.
43062306a36Sopenharmony_ci */
43162306a36Sopenharmony_cistatic struct device_node *of_get_child_regulator(struct device_node *parent,
43262306a36Sopenharmony_ci						  const char *prop_name)
43362306a36Sopenharmony_ci{
43462306a36Sopenharmony_ci	struct device_node *regnode = NULL;
43562306a36Sopenharmony_ci	struct device_node *child = NULL;
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	for_each_child_of_node(parent, child) {
43862306a36Sopenharmony_ci		regnode = of_parse_phandle(child, prop_name, 0);
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci		if (!regnode) {
44162306a36Sopenharmony_ci			regnode = of_get_child_regulator(child, prop_name);
44262306a36Sopenharmony_ci			if (regnode)
44362306a36Sopenharmony_ci				goto err_node_put;
44462306a36Sopenharmony_ci		} else {
44562306a36Sopenharmony_ci			goto err_node_put;
44662306a36Sopenharmony_ci		}
44762306a36Sopenharmony_ci	}
44862306a36Sopenharmony_ci	return NULL;
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_cierr_node_put:
45162306a36Sopenharmony_ci	of_node_put(child);
45262306a36Sopenharmony_ci	return regnode;
45362306a36Sopenharmony_ci}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci/**
45662306a36Sopenharmony_ci * of_get_regulator - get a regulator device node based on supply name
45762306a36Sopenharmony_ci * @dev: Device pointer for the consumer (of regulator) device
45862306a36Sopenharmony_ci * @supply: regulator supply name
45962306a36Sopenharmony_ci *
46062306a36Sopenharmony_ci * Extract the regulator device node corresponding to the supply name.
46162306a36Sopenharmony_ci * returns the device node corresponding to the regulator if found, else
46262306a36Sopenharmony_ci * returns NULL.
46362306a36Sopenharmony_ci */
46462306a36Sopenharmony_cistatic struct device_node *of_get_regulator(struct device *dev, const char *supply)
46562306a36Sopenharmony_ci{
46662306a36Sopenharmony_ci	struct device_node *regnode = NULL;
46762306a36Sopenharmony_ci	char prop_name[64]; /* 64 is max size of property name */
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	dev_dbg(dev, "Looking up %s-supply from device tree\n", supply);
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	snprintf(prop_name, 64, "%s-supply", supply);
47262306a36Sopenharmony_ci	regnode = of_parse_phandle(dev->of_node, prop_name, 0);
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	if (!regnode) {
47562306a36Sopenharmony_ci		regnode = of_get_child_regulator(dev->of_node, prop_name);
47662306a36Sopenharmony_ci		if (regnode)
47762306a36Sopenharmony_ci			return regnode;
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci		dev_dbg(dev, "Looking up %s property in node %pOF failed\n",
48062306a36Sopenharmony_ci				prop_name, dev->of_node);
48162306a36Sopenharmony_ci		return NULL;
48262306a36Sopenharmony_ci	}
48362306a36Sopenharmony_ci	return regnode;
48462306a36Sopenharmony_ci}
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci/* Platform voltage constraint check */
48762306a36Sopenharmony_ciint regulator_check_voltage(struct regulator_dev *rdev,
48862306a36Sopenharmony_ci			    int *min_uV, int *max_uV)
48962306a36Sopenharmony_ci{
49062306a36Sopenharmony_ci	BUG_ON(*min_uV > *max_uV);
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
49362306a36Sopenharmony_ci		rdev_err(rdev, "voltage operation not allowed\n");
49462306a36Sopenharmony_ci		return -EPERM;
49562306a36Sopenharmony_ci	}
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	if (*max_uV > rdev->constraints->max_uV)
49862306a36Sopenharmony_ci		*max_uV = rdev->constraints->max_uV;
49962306a36Sopenharmony_ci	if (*min_uV < rdev->constraints->min_uV)
50062306a36Sopenharmony_ci		*min_uV = rdev->constraints->min_uV;
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	if (*min_uV > *max_uV) {
50362306a36Sopenharmony_ci		rdev_err(rdev, "unsupportable voltage range: %d-%duV\n",
50462306a36Sopenharmony_ci			 *min_uV, *max_uV);
50562306a36Sopenharmony_ci		return -EINVAL;
50662306a36Sopenharmony_ci	}
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	return 0;
50962306a36Sopenharmony_ci}
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci/* return 0 if the state is valid */
51262306a36Sopenharmony_cistatic int regulator_check_states(suspend_state_t state)
51362306a36Sopenharmony_ci{
51462306a36Sopenharmony_ci	return (state > PM_SUSPEND_MAX || state == PM_SUSPEND_TO_IDLE);
51562306a36Sopenharmony_ci}
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci/* Make sure we select a voltage that suits the needs of all
51862306a36Sopenharmony_ci * regulator consumers
51962306a36Sopenharmony_ci */
52062306a36Sopenharmony_ciint regulator_check_consumers(struct regulator_dev *rdev,
52162306a36Sopenharmony_ci			      int *min_uV, int *max_uV,
52262306a36Sopenharmony_ci			      suspend_state_t state)
52362306a36Sopenharmony_ci{
52462306a36Sopenharmony_ci	struct regulator *regulator;
52562306a36Sopenharmony_ci	struct regulator_voltage *voltage;
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	list_for_each_entry(regulator, &rdev->consumer_list, list) {
52862306a36Sopenharmony_ci		voltage = &regulator->voltage[state];
52962306a36Sopenharmony_ci		/*
53062306a36Sopenharmony_ci		 * Assume consumers that didn't say anything are OK
53162306a36Sopenharmony_ci		 * with anything in the constraint range.
53262306a36Sopenharmony_ci		 */
53362306a36Sopenharmony_ci		if (!voltage->min_uV && !voltage->max_uV)
53462306a36Sopenharmony_ci			continue;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci		if (*max_uV > voltage->max_uV)
53762306a36Sopenharmony_ci			*max_uV = voltage->max_uV;
53862306a36Sopenharmony_ci		if (*min_uV < voltage->min_uV)
53962306a36Sopenharmony_ci			*min_uV = voltage->min_uV;
54062306a36Sopenharmony_ci	}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	if (*min_uV > *max_uV) {
54362306a36Sopenharmony_ci		rdev_err(rdev, "Restricting voltage, %u-%uuV\n",
54462306a36Sopenharmony_ci			*min_uV, *max_uV);
54562306a36Sopenharmony_ci		return -EINVAL;
54662306a36Sopenharmony_ci	}
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	return 0;
54962306a36Sopenharmony_ci}
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci/* current constraint check */
55262306a36Sopenharmony_cistatic int regulator_check_current_limit(struct regulator_dev *rdev,
55362306a36Sopenharmony_ci					int *min_uA, int *max_uA)
55462306a36Sopenharmony_ci{
55562306a36Sopenharmony_ci	BUG_ON(*min_uA > *max_uA);
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_CURRENT)) {
55862306a36Sopenharmony_ci		rdev_err(rdev, "current operation not allowed\n");
55962306a36Sopenharmony_ci		return -EPERM;
56062306a36Sopenharmony_ci	}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	if (*max_uA > rdev->constraints->max_uA)
56362306a36Sopenharmony_ci		*max_uA = rdev->constraints->max_uA;
56462306a36Sopenharmony_ci	if (*min_uA < rdev->constraints->min_uA)
56562306a36Sopenharmony_ci		*min_uA = rdev->constraints->min_uA;
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	if (*min_uA > *max_uA) {
56862306a36Sopenharmony_ci		rdev_err(rdev, "unsupportable current range: %d-%duA\n",
56962306a36Sopenharmony_ci			 *min_uA, *max_uA);
57062306a36Sopenharmony_ci		return -EINVAL;
57162306a36Sopenharmony_ci	}
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	return 0;
57462306a36Sopenharmony_ci}
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci/* operating mode constraint check */
57762306a36Sopenharmony_cistatic int regulator_mode_constrain(struct regulator_dev *rdev,
57862306a36Sopenharmony_ci				    unsigned int *mode)
57962306a36Sopenharmony_ci{
58062306a36Sopenharmony_ci	switch (*mode) {
58162306a36Sopenharmony_ci	case REGULATOR_MODE_FAST:
58262306a36Sopenharmony_ci	case REGULATOR_MODE_NORMAL:
58362306a36Sopenharmony_ci	case REGULATOR_MODE_IDLE:
58462306a36Sopenharmony_ci	case REGULATOR_MODE_STANDBY:
58562306a36Sopenharmony_ci		break;
58662306a36Sopenharmony_ci	default:
58762306a36Sopenharmony_ci		rdev_err(rdev, "invalid mode %x specified\n", *mode);
58862306a36Sopenharmony_ci		return -EINVAL;
58962306a36Sopenharmony_ci	}
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_MODE)) {
59262306a36Sopenharmony_ci		rdev_err(rdev, "mode operation not allowed\n");
59362306a36Sopenharmony_ci		return -EPERM;
59462306a36Sopenharmony_ci	}
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	/* The modes are bitmasks, the most power hungry modes having
59762306a36Sopenharmony_ci	 * the lowest values. If the requested mode isn't supported
59862306a36Sopenharmony_ci	 * try higher modes.
59962306a36Sopenharmony_ci	 */
60062306a36Sopenharmony_ci	while (*mode) {
60162306a36Sopenharmony_ci		if (rdev->constraints->valid_modes_mask & *mode)
60262306a36Sopenharmony_ci			return 0;
60362306a36Sopenharmony_ci		*mode /= 2;
60462306a36Sopenharmony_ci	}
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci	return -EINVAL;
60762306a36Sopenharmony_ci}
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_cistatic inline struct regulator_state *
61062306a36Sopenharmony_ciregulator_get_suspend_state(struct regulator_dev *rdev, suspend_state_t state)
61162306a36Sopenharmony_ci{
61262306a36Sopenharmony_ci	if (rdev->constraints == NULL)
61362306a36Sopenharmony_ci		return NULL;
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci	switch (state) {
61662306a36Sopenharmony_ci	case PM_SUSPEND_STANDBY:
61762306a36Sopenharmony_ci		return &rdev->constraints->state_standby;
61862306a36Sopenharmony_ci	case PM_SUSPEND_MEM:
61962306a36Sopenharmony_ci		return &rdev->constraints->state_mem;
62062306a36Sopenharmony_ci	case PM_SUSPEND_MAX:
62162306a36Sopenharmony_ci		return &rdev->constraints->state_disk;
62262306a36Sopenharmony_ci	default:
62362306a36Sopenharmony_ci		return NULL;
62462306a36Sopenharmony_ci	}
62562306a36Sopenharmony_ci}
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_cistatic const struct regulator_state *
62862306a36Sopenharmony_ciregulator_get_suspend_state_check(struct regulator_dev *rdev, suspend_state_t state)
62962306a36Sopenharmony_ci{
63062306a36Sopenharmony_ci	const struct regulator_state *rstate;
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	rstate = regulator_get_suspend_state(rdev, state);
63362306a36Sopenharmony_ci	if (rstate == NULL)
63462306a36Sopenharmony_ci		return NULL;
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	/* If we have no suspend mode configuration don't set anything;
63762306a36Sopenharmony_ci	 * only warn if the driver implements set_suspend_voltage or
63862306a36Sopenharmony_ci	 * set_suspend_mode callback.
63962306a36Sopenharmony_ci	 */
64062306a36Sopenharmony_ci	if (rstate->enabled != ENABLE_IN_SUSPEND &&
64162306a36Sopenharmony_ci	    rstate->enabled != DISABLE_IN_SUSPEND) {
64262306a36Sopenharmony_ci		if (rdev->desc->ops->set_suspend_voltage ||
64362306a36Sopenharmony_ci		    rdev->desc->ops->set_suspend_mode)
64462306a36Sopenharmony_ci			rdev_warn(rdev, "No configuration\n");
64562306a36Sopenharmony_ci		return NULL;
64662306a36Sopenharmony_ci	}
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	return rstate;
64962306a36Sopenharmony_ci}
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_cistatic ssize_t microvolts_show(struct device *dev,
65262306a36Sopenharmony_ci			       struct device_attribute *attr, char *buf)
65362306a36Sopenharmony_ci{
65462306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
65562306a36Sopenharmony_ci	int uV;
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	regulator_lock(rdev);
65862306a36Sopenharmony_ci	uV = regulator_get_voltage_rdev(rdev);
65962306a36Sopenharmony_ci	regulator_unlock(rdev);
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	if (uV < 0)
66262306a36Sopenharmony_ci		return uV;
66362306a36Sopenharmony_ci	return sprintf(buf, "%d\n", uV);
66462306a36Sopenharmony_ci}
66562306a36Sopenharmony_cistatic DEVICE_ATTR_RO(microvolts);
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_cistatic ssize_t microamps_show(struct device *dev,
66862306a36Sopenharmony_ci			      struct device_attribute *attr, char *buf)
66962306a36Sopenharmony_ci{
67062306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev));
67362306a36Sopenharmony_ci}
67462306a36Sopenharmony_cistatic DEVICE_ATTR_RO(microamps);
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_cistatic ssize_t name_show(struct device *dev, struct device_attribute *attr,
67762306a36Sopenharmony_ci			 char *buf)
67862306a36Sopenharmony_ci{
67962306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	return sprintf(buf, "%s\n", rdev_get_name(rdev));
68262306a36Sopenharmony_ci}
68362306a36Sopenharmony_cistatic DEVICE_ATTR_RO(name);
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_cistatic const char *regulator_opmode_to_str(int mode)
68662306a36Sopenharmony_ci{
68762306a36Sopenharmony_ci	switch (mode) {
68862306a36Sopenharmony_ci	case REGULATOR_MODE_FAST:
68962306a36Sopenharmony_ci		return "fast";
69062306a36Sopenharmony_ci	case REGULATOR_MODE_NORMAL:
69162306a36Sopenharmony_ci		return "normal";
69262306a36Sopenharmony_ci	case REGULATOR_MODE_IDLE:
69362306a36Sopenharmony_ci		return "idle";
69462306a36Sopenharmony_ci	case REGULATOR_MODE_STANDBY:
69562306a36Sopenharmony_ci		return "standby";
69662306a36Sopenharmony_ci	}
69762306a36Sopenharmony_ci	return "unknown";
69862306a36Sopenharmony_ci}
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_cistatic ssize_t regulator_print_opmode(char *buf, int mode)
70162306a36Sopenharmony_ci{
70262306a36Sopenharmony_ci	return sprintf(buf, "%s\n", regulator_opmode_to_str(mode));
70362306a36Sopenharmony_ci}
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_cistatic ssize_t opmode_show(struct device *dev,
70662306a36Sopenharmony_ci			   struct device_attribute *attr, char *buf)
70762306a36Sopenharmony_ci{
70862306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci	return regulator_print_opmode(buf, _regulator_get_mode(rdev));
71162306a36Sopenharmony_ci}
71262306a36Sopenharmony_cistatic DEVICE_ATTR_RO(opmode);
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_cistatic ssize_t regulator_print_state(char *buf, int state)
71562306a36Sopenharmony_ci{
71662306a36Sopenharmony_ci	if (state > 0)
71762306a36Sopenharmony_ci		return sprintf(buf, "enabled\n");
71862306a36Sopenharmony_ci	else if (state == 0)
71962306a36Sopenharmony_ci		return sprintf(buf, "disabled\n");
72062306a36Sopenharmony_ci	else
72162306a36Sopenharmony_ci		return sprintf(buf, "unknown\n");
72262306a36Sopenharmony_ci}
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_cistatic ssize_t state_show(struct device *dev,
72562306a36Sopenharmony_ci			  struct device_attribute *attr, char *buf)
72662306a36Sopenharmony_ci{
72762306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
72862306a36Sopenharmony_ci	ssize_t ret;
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci	regulator_lock(rdev);
73162306a36Sopenharmony_ci	ret = regulator_print_state(buf, _regulator_is_enabled(rdev));
73262306a36Sopenharmony_ci	regulator_unlock(rdev);
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci	return ret;
73562306a36Sopenharmony_ci}
73662306a36Sopenharmony_cistatic DEVICE_ATTR_RO(state);
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_cistatic ssize_t status_show(struct device *dev,
73962306a36Sopenharmony_ci			   struct device_attribute *attr, char *buf)
74062306a36Sopenharmony_ci{
74162306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
74262306a36Sopenharmony_ci	int status;
74362306a36Sopenharmony_ci	char *label;
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	status = rdev->desc->ops->get_status(rdev);
74662306a36Sopenharmony_ci	if (status < 0)
74762306a36Sopenharmony_ci		return status;
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci	switch (status) {
75062306a36Sopenharmony_ci	case REGULATOR_STATUS_OFF:
75162306a36Sopenharmony_ci		label = "off";
75262306a36Sopenharmony_ci		break;
75362306a36Sopenharmony_ci	case REGULATOR_STATUS_ON:
75462306a36Sopenharmony_ci		label = "on";
75562306a36Sopenharmony_ci		break;
75662306a36Sopenharmony_ci	case REGULATOR_STATUS_ERROR:
75762306a36Sopenharmony_ci		label = "error";
75862306a36Sopenharmony_ci		break;
75962306a36Sopenharmony_ci	case REGULATOR_STATUS_FAST:
76062306a36Sopenharmony_ci		label = "fast";
76162306a36Sopenharmony_ci		break;
76262306a36Sopenharmony_ci	case REGULATOR_STATUS_NORMAL:
76362306a36Sopenharmony_ci		label = "normal";
76462306a36Sopenharmony_ci		break;
76562306a36Sopenharmony_ci	case REGULATOR_STATUS_IDLE:
76662306a36Sopenharmony_ci		label = "idle";
76762306a36Sopenharmony_ci		break;
76862306a36Sopenharmony_ci	case REGULATOR_STATUS_STANDBY:
76962306a36Sopenharmony_ci		label = "standby";
77062306a36Sopenharmony_ci		break;
77162306a36Sopenharmony_ci	case REGULATOR_STATUS_BYPASS:
77262306a36Sopenharmony_ci		label = "bypass";
77362306a36Sopenharmony_ci		break;
77462306a36Sopenharmony_ci	case REGULATOR_STATUS_UNDEFINED:
77562306a36Sopenharmony_ci		label = "undefined";
77662306a36Sopenharmony_ci		break;
77762306a36Sopenharmony_ci	default:
77862306a36Sopenharmony_ci		return -ERANGE;
77962306a36Sopenharmony_ci	}
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci	return sprintf(buf, "%s\n", label);
78262306a36Sopenharmony_ci}
78362306a36Sopenharmony_cistatic DEVICE_ATTR_RO(status);
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_cistatic ssize_t min_microamps_show(struct device *dev,
78662306a36Sopenharmony_ci				  struct device_attribute *attr, char *buf)
78762306a36Sopenharmony_ci{
78862306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci	if (!rdev->constraints)
79162306a36Sopenharmony_ci		return sprintf(buf, "constraint not defined\n");
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci	return sprintf(buf, "%d\n", rdev->constraints->min_uA);
79462306a36Sopenharmony_ci}
79562306a36Sopenharmony_cistatic DEVICE_ATTR_RO(min_microamps);
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_cistatic ssize_t max_microamps_show(struct device *dev,
79862306a36Sopenharmony_ci				  struct device_attribute *attr, char *buf)
79962306a36Sopenharmony_ci{
80062306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	if (!rdev->constraints)
80362306a36Sopenharmony_ci		return sprintf(buf, "constraint not defined\n");
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	return sprintf(buf, "%d\n", rdev->constraints->max_uA);
80662306a36Sopenharmony_ci}
80762306a36Sopenharmony_cistatic DEVICE_ATTR_RO(max_microamps);
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_cistatic ssize_t min_microvolts_show(struct device *dev,
81062306a36Sopenharmony_ci				   struct device_attribute *attr, char *buf)
81162306a36Sopenharmony_ci{
81262306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	if (!rdev->constraints)
81562306a36Sopenharmony_ci		return sprintf(buf, "constraint not defined\n");
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	return sprintf(buf, "%d\n", rdev->constraints->min_uV);
81862306a36Sopenharmony_ci}
81962306a36Sopenharmony_cistatic DEVICE_ATTR_RO(min_microvolts);
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_cistatic ssize_t max_microvolts_show(struct device *dev,
82262306a36Sopenharmony_ci				   struct device_attribute *attr, char *buf)
82362306a36Sopenharmony_ci{
82462306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	if (!rdev->constraints)
82762306a36Sopenharmony_ci		return sprintf(buf, "constraint not defined\n");
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	return sprintf(buf, "%d\n", rdev->constraints->max_uV);
83062306a36Sopenharmony_ci}
83162306a36Sopenharmony_cistatic DEVICE_ATTR_RO(max_microvolts);
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_cistatic ssize_t requested_microamps_show(struct device *dev,
83462306a36Sopenharmony_ci					struct device_attribute *attr, char *buf)
83562306a36Sopenharmony_ci{
83662306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
83762306a36Sopenharmony_ci	struct regulator *regulator;
83862306a36Sopenharmony_ci	int uA = 0;
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_ci	regulator_lock(rdev);
84162306a36Sopenharmony_ci	list_for_each_entry(regulator, &rdev->consumer_list, list) {
84262306a36Sopenharmony_ci		if (regulator->enable_count)
84362306a36Sopenharmony_ci			uA += regulator->uA_load;
84462306a36Sopenharmony_ci	}
84562306a36Sopenharmony_ci	regulator_unlock(rdev);
84662306a36Sopenharmony_ci	return sprintf(buf, "%d\n", uA);
84762306a36Sopenharmony_ci}
84862306a36Sopenharmony_cistatic DEVICE_ATTR_RO(requested_microamps);
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_cistatic ssize_t num_users_show(struct device *dev, struct device_attribute *attr,
85162306a36Sopenharmony_ci			      char *buf)
85262306a36Sopenharmony_ci{
85362306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
85462306a36Sopenharmony_ci	return sprintf(buf, "%d\n", rdev->use_count);
85562306a36Sopenharmony_ci}
85662306a36Sopenharmony_cistatic DEVICE_ATTR_RO(num_users);
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_cistatic ssize_t type_show(struct device *dev, struct device_attribute *attr,
85962306a36Sopenharmony_ci			 char *buf)
86062306a36Sopenharmony_ci{
86162306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci	switch (rdev->desc->type) {
86462306a36Sopenharmony_ci	case REGULATOR_VOLTAGE:
86562306a36Sopenharmony_ci		return sprintf(buf, "voltage\n");
86662306a36Sopenharmony_ci	case REGULATOR_CURRENT:
86762306a36Sopenharmony_ci		return sprintf(buf, "current\n");
86862306a36Sopenharmony_ci	}
86962306a36Sopenharmony_ci	return sprintf(buf, "unknown\n");
87062306a36Sopenharmony_ci}
87162306a36Sopenharmony_cistatic DEVICE_ATTR_RO(type);
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_cistatic ssize_t suspend_mem_microvolts_show(struct device *dev,
87462306a36Sopenharmony_ci					   struct device_attribute *attr, char *buf)
87562306a36Sopenharmony_ci{
87662306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci	return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV);
87962306a36Sopenharmony_ci}
88062306a36Sopenharmony_cistatic DEVICE_ATTR_RO(suspend_mem_microvolts);
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_cistatic ssize_t suspend_disk_microvolts_show(struct device *dev,
88362306a36Sopenharmony_ci					    struct device_attribute *attr, char *buf)
88462306a36Sopenharmony_ci{
88562306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV);
88862306a36Sopenharmony_ci}
88962306a36Sopenharmony_cistatic DEVICE_ATTR_RO(suspend_disk_microvolts);
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_cistatic ssize_t suspend_standby_microvolts_show(struct device *dev,
89262306a36Sopenharmony_ci					       struct device_attribute *attr, char *buf)
89362306a36Sopenharmony_ci{
89462306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci	return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV);
89762306a36Sopenharmony_ci}
89862306a36Sopenharmony_cistatic DEVICE_ATTR_RO(suspend_standby_microvolts);
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_cistatic ssize_t suspend_mem_mode_show(struct device *dev,
90162306a36Sopenharmony_ci				     struct device_attribute *attr, char *buf)
90262306a36Sopenharmony_ci{
90362306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	return regulator_print_opmode(buf,
90662306a36Sopenharmony_ci		rdev->constraints->state_mem.mode);
90762306a36Sopenharmony_ci}
90862306a36Sopenharmony_cistatic DEVICE_ATTR_RO(suspend_mem_mode);
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_cistatic ssize_t suspend_disk_mode_show(struct device *dev,
91162306a36Sopenharmony_ci				      struct device_attribute *attr, char *buf)
91262306a36Sopenharmony_ci{
91362306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	return regulator_print_opmode(buf,
91662306a36Sopenharmony_ci		rdev->constraints->state_disk.mode);
91762306a36Sopenharmony_ci}
91862306a36Sopenharmony_cistatic DEVICE_ATTR_RO(suspend_disk_mode);
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_cistatic ssize_t suspend_standby_mode_show(struct device *dev,
92162306a36Sopenharmony_ci					 struct device_attribute *attr, char *buf)
92262306a36Sopenharmony_ci{
92362306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci	return regulator_print_opmode(buf,
92662306a36Sopenharmony_ci		rdev->constraints->state_standby.mode);
92762306a36Sopenharmony_ci}
92862306a36Sopenharmony_cistatic DEVICE_ATTR_RO(suspend_standby_mode);
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_cistatic ssize_t suspend_mem_state_show(struct device *dev,
93162306a36Sopenharmony_ci				      struct device_attribute *attr, char *buf)
93262306a36Sopenharmony_ci{
93362306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci	return regulator_print_state(buf,
93662306a36Sopenharmony_ci			rdev->constraints->state_mem.enabled);
93762306a36Sopenharmony_ci}
93862306a36Sopenharmony_cistatic DEVICE_ATTR_RO(suspend_mem_state);
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_cistatic ssize_t suspend_disk_state_show(struct device *dev,
94162306a36Sopenharmony_ci				       struct device_attribute *attr, char *buf)
94262306a36Sopenharmony_ci{
94362306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci	return regulator_print_state(buf,
94662306a36Sopenharmony_ci			rdev->constraints->state_disk.enabled);
94762306a36Sopenharmony_ci}
94862306a36Sopenharmony_cistatic DEVICE_ATTR_RO(suspend_disk_state);
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_cistatic ssize_t suspend_standby_state_show(struct device *dev,
95162306a36Sopenharmony_ci					  struct device_attribute *attr, char *buf)
95262306a36Sopenharmony_ci{
95362306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_ci	return regulator_print_state(buf,
95662306a36Sopenharmony_ci			rdev->constraints->state_standby.enabled);
95762306a36Sopenharmony_ci}
95862306a36Sopenharmony_cistatic DEVICE_ATTR_RO(suspend_standby_state);
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_cistatic ssize_t bypass_show(struct device *dev,
96162306a36Sopenharmony_ci			   struct device_attribute *attr, char *buf)
96262306a36Sopenharmony_ci{
96362306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
96462306a36Sopenharmony_ci	const char *report;
96562306a36Sopenharmony_ci	bool bypass;
96662306a36Sopenharmony_ci	int ret;
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	ret = rdev->desc->ops->get_bypass(rdev, &bypass);
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci	if (ret != 0)
97162306a36Sopenharmony_ci		report = "unknown";
97262306a36Sopenharmony_ci	else if (bypass)
97362306a36Sopenharmony_ci		report = "enabled";
97462306a36Sopenharmony_ci	else
97562306a36Sopenharmony_ci		report = "disabled";
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	return sprintf(buf, "%s\n", report);
97862306a36Sopenharmony_ci}
97962306a36Sopenharmony_cistatic DEVICE_ATTR_RO(bypass);
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci#define REGULATOR_ERROR_ATTR(name, bit)							\
98262306a36Sopenharmony_ci	static ssize_t name##_show(struct device *dev, struct device_attribute *attr,	\
98362306a36Sopenharmony_ci				   char *buf)						\
98462306a36Sopenharmony_ci	{										\
98562306a36Sopenharmony_ci		int ret;								\
98662306a36Sopenharmony_ci		unsigned int flags;							\
98762306a36Sopenharmony_ci		struct regulator_dev *rdev = dev_get_drvdata(dev);			\
98862306a36Sopenharmony_ci		ret = _regulator_get_error_flags(rdev, &flags);				\
98962306a36Sopenharmony_ci		if (ret)								\
99062306a36Sopenharmony_ci			return ret;							\
99162306a36Sopenharmony_ci		return sysfs_emit(buf, "%d\n", !!(flags & (bit)));			\
99262306a36Sopenharmony_ci	}										\
99362306a36Sopenharmony_ci	static DEVICE_ATTR_RO(name)
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ciREGULATOR_ERROR_ATTR(under_voltage, REGULATOR_ERROR_UNDER_VOLTAGE);
99662306a36Sopenharmony_ciREGULATOR_ERROR_ATTR(over_current, REGULATOR_ERROR_OVER_CURRENT);
99762306a36Sopenharmony_ciREGULATOR_ERROR_ATTR(regulation_out, REGULATOR_ERROR_REGULATION_OUT);
99862306a36Sopenharmony_ciREGULATOR_ERROR_ATTR(fail, REGULATOR_ERROR_FAIL);
99962306a36Sopenharmony_ciREGULATOR_ERROR_ATTR(over_temp, REGULATOR_ERROR_OVER_TEMP);
100062306a36Sopenharmony_ciREGULATOR_ERROR_ATTR(under_voltage_warn, REGULATOR_ERROR_UNDER_VOLTAGE_WARN);
100162306a36Sopenharmony_ciREGULATOR_ERROR_ATTR(over_current_warn, REGULATOR_ERROR_OVER_CURRENT_WARN);
100262306a36Sopenharmony_ciREGULATOR_ERROR_ATTR(over_voltage_warn, REGULATOR_ERROR_OVER_VOLTAGE_WARN);
100362306a36Sopenharmony_ciREGULATOR_ERROR_ATTR(over_temp_warn, REGULATOR_ERROR_OVER_TEMP_WARN);
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_ci/* Calculate the new optimum regulator operating mode based on the new total
100662306a36Sopenharmony_ci * consumer load. All locks held by caller
100762306a36Sopenharmony_ci */
100862306a36Sopenharmony_cistatic int drms_uA_update(struct regulator_dev *rdev)
100962306a36Sopenharmony_ci{
101062306a36Sopenharmony_ci	struct regulator *sibling;
101162306a36Sopenharmony_ci	int current_uA = 0, output_uV, input_uV, err;
101262306a36Sopenharmony_ci	unsigned int mode;
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci	/*
101562306a36Sopenharmony_ci	 * first check to see if we can set modes at all, otherwise just
101662306a36Sopenharmony_ci	 * tell the consumer everything is OK.
101762306a36Sopenharmony_ci	 */
101862306a36Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) {
101962306a36Sopenharmony_ci		rdev_dbg(rdev, "DRMS operation not allowed\n");
102062306a36Sopenharmony_ci		return 0;
102162306a36Sopenharmony_ci	}
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_ci	if (!rdev->desc->ops->get_optimum_mode &&
102462306a36Sopenharmony_ci	    !rdev->desc->ops->set_load)
102562306a36Sopenharmony_ci		return 0;
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci	if (!rdev->desc->ops->set_mode &&
102862306a36Sopenharmony_ci	    !rdev->desc->ops->set_load)
102962306a36Sopenharmony_ci		return -EINVAL;
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci	/* calc total requested load */
103262306a36Sopenharmony_ci	list_for_each_entry(sibling, &rdev->consumer_list, list) {
103362306a36Sopenharmony_ci		if (sibling->enable_count)
103462306a36Sopenharmony_ci			current_uA += sibling->uA_load;
103562306a36Sopenharmony_ci	}
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci	current_uA += rdev->constraints->system_load;
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	if (rdev->desc->ops->set_load) {
104062306a36Sopenharmony_ci		/* set the optimum mode for our new total regulator load */
104162306a36Sopenharmony_ci		err = rdev->desc->ops->set_load(rdev, current_uA);
104262306a36Sopenharmony_ci		if (err < 0)
104362306a36Sopenharmony_ci			rdev_err(rdev, "failed to set load %d: %pe\n",
104462306a36Sopenharmony_ci				 current_uA, ERR_PTR(err));
104562306a36Sopenharmony_ci	} else {
104662306a36Sopenharmony_ci		/*
104762306a36Sopenharmony_ci		 * Unfortunately in some cases the constraints->valid_ops has
104862306a36Sopenharmony_ci		 * REGULATOR_CHANGE_DRMS but there are no valid modes listed.
104962306a36Sopenharmony_ci		 * That's not really legit but we won't consider it a fatal
105062306a36Sopenharmony_ci		 * error here. We'll treat it as if REGULATOR_CHANGE_DRMS
105162306a36Sopenharmony_ci		 * wasn't set.
105262306a36Sopenharmony_ci		 */
105362306a36Sopenharmony_ci		if (!rdev->constraints->valid_modes_mask) {
105462306a36Sopenharmony_ci			rdev_dbg(rdev, "Can change modes; but no valid mode\n");
105562306a36Sopenharmony_ci			return 0;
105662306a36Sopenharmony_ci		}
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci		/* get output voltage */
105962306a36Sopenharmony_ci		output_uV = regulator_get_voltage_rdev(rdev);
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci		/*
106262306a36Sopenharmony_ci		 * Don't return an error; if regulator driver cares about
106362306a36Sopenharmony_ci		 * output_uV then it's up to the driver to validate.
106462306a36Sopenharmony_ci		 */
106562306a36Sopenharmony_ci		if (output_uV <= 0)
106662306a36Sopenharmony_ci			rdev_dbg(rdev, "invalid output voltage found\n");
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci		/* get input voltage */
106962306a36Sopenharmony_ci		input_uV = 0;
107062306a36Sopenharmony_ci		if (rdev->supply)
107162306a36Sopenharmony_ci			input_uV = regulator_get_voltage_rdev(rdev->supply->rdev);
107262306a36Sopenharmony_ci		if (input_uV <= 0)
107362306a36Sopenharmony_ci			input_uV = rdev->constraints->input_uV;
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci		/*
107662306a36Sopenharmony_ci		 * Don't return an error; if regulator driver cares about
107762306a36Sopenharmony_ci		 * input_uV then it's up to the driver to validate.
107862306a36Sopenharmony_ci		 */
107962306a36Sopenharmony_ci		if (input_uV <= 0)
108062306a36Sopenharmony_ci			rdev_dbg(rdev, "invalid input voltage found\n");
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci		/* now get the optimum mode for our new total regulator load */
108362306a36Sopenharmony_ci		mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV,
108462306a36Sopenharmony_ci							 output_uV, current_uA);
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci		/* check the new mode is allowed */
108762306a36Sopenharmony_ci		err = regulator_mode_constrain(rdev, &mode);
108862306a36Sopenharmony_ci		if (err < 0) {
108962306a36Sopenharmony_ci			rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV: %pe\n",
109062306a36Sopenharmony_ci				 current_uA, input_uV, output_uV, ERR_PTR(err));
109162306a36Sopenharmony_ci			return err;
109262306a36Sopenharmony_ci		}
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_ci		err = rdev->desc->ops->set_mode(rdev, mode);
109562306a36Sopenharmony_ci		if (err < 0)
109662306a36Sopenharmony_ci			rdev_err(rdev, "failed to set optimum mode %x: %pe\n",
109762306a36Sopenharmony_ci				 mode, ERR_PTR(err));
109862306a36Sopenharmony_ci	}
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	return err;
110162306a36Sopenharmony_ci}
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_cistatic int __suspend_set_state(struct regulator_dev *rdev,
110462306a36Sopenharmony_ci			       const struct regulator_state *rstate)
110562306a36Sopenharmony_ci{
110662306a36Sopenharmony_ci	int ret = 0;
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_ci	if (rstate->enabled == ENABLE_IN_SUSPEND &&
110962306a36Sopenharmony_ci		rdev->desc->ops->set_suspend_enable)
111062306a36Sopenharmony_ci		ret = rdev->desc->ops->set_suspend_enable(rdev);
111162306a36Sopenharmony_ci	else if (rstate->enabled == DISABLE_IN_SUSPEND &&
111262306a36Sopenharmony_ci		rdev->desc->ops->set_suspend_disable)
111362306a36Sopenharmony_ci		ret = rdev->desc->ops->set_suspend_disable(rdev);
111462306a36Sopenharmony_ci	else /* OK if set_suspend_enable or set_suspend_disable is NULL */
111562306a36Sopenharmony_ci		ret = 0;
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_ci	if (ret < 0) {
111862306a36Sopenharmony_ci		rdev_err(rdev, "failed to enabled/disable: %pe\n", ERR_PTR(ret));
111962306a36Sopenharmony_ci		return ret;
112062306a36Sopenharmony_ci	}
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci	if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) {
112362306a36Sopenharmony_ci		ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV);
112462306a36Sopenharmony_ci		if (ret < 0) {
112562306a36Sopenharmony_ci			rdev_err(rdev, "failed to set voltage: %pe\n", ERR_PTR(ret));
112662306a36Sopenharmony_ci			return ret;
112762306a36Sopenharmony_ci		}
112862306a36Sopenharmony_ci	}
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) {
113162306a36Sopenharmony_ci		ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode);
113262306a36Sopenharmony_ci		if (ret < 0) {
113362306a36Sopenharmony_ci			rdev_err(rdev, "failed to set mode: %pe\n", ERR_PTR(ret));
113462306a36Sopenharmony_ci			return ret;
113562306a36Sopenharmony_ci		}
113662306a36Sopenharmony_ci	}
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	return ret;
113962306a36Sopenharmony_ci}
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_cistatic int suspend_set_initial_state(struct regulator_dev *rdev)
114262306a36Sopenharmony_ci{
114362306a36Sopenharmony_ci	const struct regulator_state *rstate;
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	rstate = regulator_get_suspend_state_check(rdev,
114662306a36Sopenharmony_ci			rdev->constraints->initial_state);
114762306a36Sopenharmony_ci	if (!rstate)
114862306a36Sopenharmony_ci		return 0;
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci	return __suspend_set_state(rdev, rstate);
115162306a36Sopenharmony_ci}
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
115462306a36Sopenharmony_cistatic void print_constraints_debug(struct regulator_dev *rdev)
115562306a36Sopenharmony_ci{
115662306a36Sopenharmony_ci	struct regulation_constraints *constraints = rdev->constraints;
115762306a36Sopenharmony_ci	char buf[160] = "";
115862306a36Sopenharmony_ci	size_t len = sizeof(buf) - 1;
115962306a36Sopenharmony_ci	int count = 0;
116062306a36Sopenharmony_ci	int ret;
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci	if (constraints->min_uV && constraints->max_uV) {
116362306a36Sopenharmony_ci		if (constraints->min_uV == constraints->max_uV)
116462306a36Sopenharmony_ci			count += scnprintf(buf + count, len - count, "%d mV ",
116562306a36Sopenharmony_ci					   constraints->min_uV / 1000);
116662306a36Sopenharmony_ci		else
116762306a36Sopenharmony_ci			count += scnprintf(buf + count, len - count,
116862306a36Sopenharmony_ci					   "%d <--> %d mV ",
116962306a36Sopenharmony_ci					   constraints->min_uV / 1000,
117062306a36Sopenharmony_ci					   constraints->max_uV / 1000);
117162306a36Sopenharmony_ci	}
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci	if (!constraints->min_uV ||
117462306a36Sopenharmony_ci	    constraints->min_uV != constraints->max_uV) {
117562306a36Sopenharmony_ci		ret = regulator_get_voltage_rdev(rdev);
117662306a36Sopenharmony_ci		if (ret > 0)
117762306a36Sopenharmony_ci			count += scnprintf(buf + count, len - count,
117862306a36Sopenharmony_ci					   "at %d mV ", ret / 1000);
117962306a36Sopenharmony_ci	}
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_ci	if (constraints->uV_offset)
118262306a36Sopenharmony_ci		count += scnprintf(buf + count, len - count, "%dmV offset ",
118362306a36Sopenharmony_ci				   constraints->uV_offset / 1000);
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_ci	if (constraints->min_uA && constraints->max_uA) {
118662306a36Sopenharmony_ci		if (constraints->min_uA == constraints->max_uA)
118762306a36Sopenharmony_ci			count += scnprintf(buf + count, len - count, "%d mA ",
118862306a36Sopenharmony_ci					   constraints->min_uA / 1000);
118962306a36Sopenharmony_ci		else
119062306a36Sopenharmony_ci			count += scnprintf(buf + count, len - count,
119162306a36Sopenharmony_ci					   "%d <--> %d mA ",
119262306a36Sopenharmony_ci					   constraints->min_uA / 1000,
119362306a36Sopenharmony_ci					   constraints->max_uA / 1000);
119462306a36Sopenharmony_ci	}
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci	if (!constraints->min_uA ||
119762306a36Sopenharmony_ci	    constraints->min_uA != constraints->max_uA) {
119862306a36Sopenharmony_ci		ret = _regulator_get_current_limit(rdev);
119962306a36Sopenharmony_ci		if (ret > 0)
120062306a36Sopenharmony_ci			count += scnprintf(buf + count, len - count,
120162306a36Sopenharmony_ci					   "at %d mA ", ret / 1000);
120262306a36Sopenharmony_ci	}
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci	if (constraints->valid_modes_mask & REGULATOR_MODE_FAST)
120562306a36Sopenharmony_ci		count += scnprintf(buf + count, len - count, "fast ");
120662306a36Sopenharmony_ci	if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL)
120762306a36Sopenharmony_ci		count += scnprintf(buf + count, len - count, "normal ");
120862306a36Sopenharmony_ci	if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE)
120962306a36Sopenharmony_ci		count += scnprintf(buf + count, len - count, "idle ");
121062306a36Sopenharmony_ci	if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY)
121162306a36Sopenharmony_ci		count += scnprintf(buf + count, len - count, "standby ");
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci	if (!count)
121462306a36Sopenharmony_ci		count = scnprintf(buf, len, "no parameters");
121562306a36Sopenharmony_ci	else
121662306a36Sopenharmony_ci		--count;
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_ci	count += scnprintf(buf + count, len - count, ", %s",
121962306a36Sopenharmony_ci		_regulator_is_enabled(rdev) ? "enabled" : "disabled");
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_ci	rdev_dbg(rdev, "%s\n", buf);
122262306a36Sopenharmony_ci}
122362306a36Sopenharmony_ci#else /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */
122462306a36Sopenharmony_cistatic inline void print_constraints_debug(struct regulator_dev *rdev) {}
122562306a36Sopenharmony_ci#endif /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_cistatic void print_constraints(struct regulator_dev *rdev)
122862306a36Sopenharmony_ci{
122962306a36Sopenharmony_ci	struct regulation_constraints *constraints = rdev->constraints;
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ci	print_constraints_debug(rdev);
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci	if ((constraints->min_uV != constraints->max_uV) &&
123462306a36Sopenharmony_ci	    !regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE))
123562306a36Sopenharmony_ci		rdev_warn(rdev,
123662306a36Sopenharmony_ci			  "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n");
123762306a36Sopenharmony_ci}
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_cistatic int machine_constraints_voltage(struct regulator_dev *rdev,
124062306a36Sopenharmony_ci	struct regulation_constraints *constraints)
124162306a36Sopenharmony_ci{
124262306a36Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
124362306a36Sopenharmony_ci	int ret;
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_ci	/* do we need to apply the constraint voltage */
124662306a36Sopenharmony_ci	if (rdev->constraints->apply_uV &&
124762306a36Sopenharmony_ci	    rdev->constraints->min_uV && rdev->constraints->max_uV) {
124862306a36Sopenharmony_ci		int target_min, target_max;
124962306a36Sopenharmony_ci		int current_uV = regulator_get_voltage_rdev(rdev);
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_ci		if (current_uV == -ENOTRECOVERABLE) {
125262306a36Sopenharmony_ci			/* This regulator can't be read and must be initialized */
125362306a36Sopenharmony_ci			rdev_info(rdev, "Setting %d-%duV\n",
125462306a36Sopenharmony_ci				  rdev->constraints->min_uV,
125562306a36Sopenharmony_ci				  rdev->constraints->max_uV);
125662306a36Sopenharmony_ci			_regulator_do_set_voltage(rdev,
125762306a36Sopenharmony_ci						  rdev->constraints->min_uV,
125862306a36Sopenharmony_ci						  rdev->constraints->max_uV);
125962306a36Sopenharmony_ci			current_uV = regulator_get_voltage_rdev(rdev);
126062306a36Sopenharmony_ci		}
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ci		if (current_uV < 0) {
126362306a36Sopenharmony_ci			if (current_uV != -EPROBE_DEFER)
126462306a36Sopenharmony_ci				rdev_err(rdev,
126562306a36Sopenharmony_ci					 "failed to get the current voltage: %pe\n",
126662306a36Sopenharmony_ci					 ERR_PTR(current_uV));
126762306a36Sopenharmony_ci			return current_uV;
126862306a36Sopenharmony_ci		}
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_ci		/*
127162306a36Sopenharmony_ci		 * If we're below the minimum voltage move up to the
127262306a36Sopenharmony_ci		 * minimum voltage, if we're above the maximum voltage
127362306a36Sopenharmony_ci		 * then move down to the maximum.
127462306a36Sopenharmony_ci		 */
127562306a36Sopenharmony_ci		target_min = current_uV;
127662306a36Sopenharmony_ci		target_max = current_uV;
127762306a36Sopenharmony_ci
127862306a36Sopenharmony_ci		if (current_uV < rdev->constraints->min_uV) {
127962306a36Sopenharmony_ci			target_min = rdev->constraints->min_uV;
128062306a36Sopenharmony_ci			target_max = rdev->constraints->min_uV;
128162306a36Sopenharmony_ci		}
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci		if (current_uV > rdev->constraints->max_uV) {
128462306a36Sopenharmony_ci			target_min = rdev->constraints->max_uV;
128562306a36Sopenharmony_ci			target_max = rdev->constraints->max_uV;
128662306a36Sopenharmony_ci		}
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci		if (target_min != current_uV || target_max != current_uV) {
128962306a36Sopenharmony_ci			rdev_info(rdev, "Bringing %duV into %d-%duV\n",
129062306a36Sopenharmony_ci				  current_uV, target_min, target_max);
129162306a36Sopenharmony_ci			ret = _regulator_do_set_voltage(
129262306a36Sopenharmony_ci				rdev, target_min, target_max);
129362306a36Sopenharmony_ci			if (ret < 0) {
129462306a36Sopenharmony_ci				rdev_err(rdev,
129562306a36Sopenharmony_ci					"failed to apply %d-%duV constraint: %pe\n",
129662306a36Sopenharmony_ci					target_min, target_max, ERR_PTR(ret));
129762306a36Sopenharmony_ci				return ret;
129862306a36Sopenharmony_ci			}
129962306a36Sopenharmony_ci		}
130062306a36Sopenharmony_ci	}
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	/* constrain machine-level voltage specs to fit
130362306a36Sopenharmony_ci	 * the actual range supported by this regulator.
130462306a36Sopenharmony_ci	 */
130562306a36Sopenharmony_ci	if (ops->list_voltage && rdev->desc->n_voltages) {
130662306a36Sopenharmony_ci		int	count = rdev->desc->n_voltages;
130762306a36Sopenharmony_ci		int	i;
130862306a36Sopenharmony_ci		int	min_uV = INT_MAX;
130962306a36Sopenharmony_ci		int	max_uV = INT_MIN;
131062306a36Sopenharmony_ci		int	cmin = constraints->min_uV;
131162306a36Sopenharmony_ci		int	cmax = constraints->max_uV;
131262306a36Sopenharmony_ci
131362306a36Sopenharmony_ci		/* it's safe to autoconfigure fixed-voltage supplies
131462306a36Sopenharmony_ci		 * and the constraints are used by list_voltage.
131562306a36Sopenharmony_ci		 */
131662306a36Sopenharmony_ci		if (count == 1 && !cmin) {
131762306a36Sopenharmony_ci			cmin = 1;
131862306a36Sopenharmony_ci			cmax = INT_MAX;
131962306a36Sopenharmony_ci			constraints->min_uV = cmin;
132062306a36Sopenharmony_ci			constraints->max_uV = cmax;
132162306a36Sopenharmony_ci		}
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci		/* voltage constraints are optional */
132462306a36Sopenharmony_ci		if ((cmin == 0) && (cmax == 0))
132562306a36Sopenharmony_ci			return 0;
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci		/* else require explicit machine-level constraints */
132862306a36Sopenharmony_ci		if (cmin <= 0 || cmax <= 0 || cmax < cmin) {
132962306a36Sopenharmony_ci			rdev_err(rdev, "invalid voltage constraints\n");
133062306a36Sopenharmony_ci			return -EINVAL;
133162306a36Sopenharmony_ci		}
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ci		/* no need to loop voltages if range is continuous */
133462306a36Sopenharmony_ci		if (rdev->desc->continuous_voltage_range)
133562306a36Sopenharmony_ci			return 0;
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_ci		/* initial: [cmin..cmax] valid, [min_uV..max_uV] not */
133862306a36Sopenharmony_ci		for (i = 0; i < count; i++) {
133962306a36Sopenharmony_ci			int	value;
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci			value = ops->list_voltage(rdev, i);
134262306a36Sopenharmony_ci			if (value <= 0)
134362306a36Sopenharmony_ci				continue;
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci			/* maybe adjust [min_uV..max_uV] */
134662306a36Sopenharmony_ci			if (value >= cmin && value < min_uV)
134762306a36Sopenharmony_ci				min_uV = value;
134862306a36Sopenharmony_ci			if (value <= cmax && value > max_uV)
134962306a36Sopenharmony_ci				max_uV = value;
135062306a36Sopenharmony_ci		}
135162306a36Sopenharmony_ci
135262306a36Sopenharmony_ci		/* final: [min_uV..max_uV] valid iff constraints valid */
135362306a36Sopenharmony_ci		if (max_uV < min_uV) {
135462306a36Sopenharmony_ci			rdev_err(rdev,
135562306a36Sopenharmony_ci				 "unsupportable voltage constraints %u-%uuV\n",
135662306a36Sopenharmony_ci				 min_uV, max_uV);
135762306a36Sopenharmony_ci			return -EINVAL;
135862306a36Sopenharmony_ci		}
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci		/* use regulator's subset of machine constraints */
136162306a36Sopenharmony_ci		if (constraints->min_uV < min_uV) {
136262306a36Sopenharmony_ci			rdev_dbg(rdev, "override min_uV, %d -> %d\n",
136362306a36Sopenharmony_ci				 constraints->min_uV, min_uV);
136462306a36Sopenharmony_ci			constraints->min_uV = min_uV;
136562306a36Sopenharmony_ci		}
136662306a36Sopenharmony_ci		if (constraints->max_uV > max_uV) {
136762306a36Sopenharmony_ci			rdev_dbg(rdev, "override max_uV, %d -> %d\n",
136862306a36Sopenharmony_ci				 constraints->max_uV, max_uV);
136962306a36Sopenharmony_ci			constraints->max_uV = max_uV;
137062306a36Sopenharmony_ci		}
137162306a36Sopenharmony_ci	}
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_ci	return 0;
137462306a36Sopenharmony_ci}
137562306a36Sopenharmony_ci
137662306a36Sopenharmony_cistatic int machine_constraints_current(struct regulator_dev *rdev,
137762306a36Sopenharmony_ci	struct regulation_constraints *constraints)
137862306a36Sopenharmony_ci{
137962306a36Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
138062306a36Sopenharmony_ci	int ret;
138162306a36Sopenharmony_ci
138262306a36Sopenharmony_ci	if (!constraints->min_uA && !constraints->max_uA)
138362306a36Sopenharmony_ci		return 0;
138462306a36Sopenharmony_ci
138562306a36Sopenharmony_ci	if (constraints->min_uA > constraints->max_uA) {
138662306a36Sopenharmony_ci		rdev_err(rdev, "Invalid current constraints\n");
138762306a36Sopenharmony_ci		return -EINVAL;
138862306a36Sopenharmony_ci	}
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	if (!ops->set_current_limit || !ops->get_current_limit) {
139162306a36Sopenharmony_ci		rdev_warn(rdev, "Operation of current configuration missing\n");
139262306a36Sopenharmony_ci		return 0;
139362306a36Sopenharmony_ci	}
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ci	/* Set regulator current in constraints range */
139662306a36Sopenharmony_ci	ret = ops->set_current_limit(rdev, constraints->min_uA,
139762306a36Sopenharmony_ci			constraints->max_uA);
139862306a36Sopenharmony_ci	if (ret < 0) {
139962306a36Sopenharmony_ci		rdev_err(rdev, "Failed to set current constraint, %d\n", ret);
140062306a36Sopenharmony_ci		return ret;
140162306a36Sopenharmony_ci	}
140262306a36Sopenharmony_ci
140362306a36Sopenharmony_ci	return 0;
140462306a36Sopenharmony_ci}
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_cistatic int _regulator_do_enable(struct regulator_dev *rdev);
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_cistatic int notif_set_limit(struct regulator_dev *rdev,
140962306a36Sopenharmony_ci			   int (*set)(struct regulator_dev *, int, int, bool),
141062306a36Sopenharmony_ci			   int limit, int severity)
141162306a36Sopenharmony_ci{
141262306a36Sopenharmony_ci	bool enable;
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_ci	if (limit == REGULATOR_NOTIF_LIMIT_DISABLE) {
141562306a36Sopenharmony_ci		enable = false;
141662306a36Sopenharmony_ci		limit = 0;
141762306a36Sopenharmony_ci	} else {
141862306a36Sopenharmony_ci		enable = true;
141962306a36Sopenharmony_ci	}
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_ci	if (limit == REGULATOR_NOTIF_LIMIT_ENABLE)
142262306a36Sopenharmony_ci		limit = 0;
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_ci	return set(rdev, limit, severity, enable);
142562306a36Sopenharmony_ci}
142662306a36Sopenharmony_ci
142762306a36Sopenharmony_cistatic int handle_notify_limits(struct regulator_dev *rdev,
142862306a36Sopenharmony_ci			int (*set)(struct regulator_dev *, int, int, bool),
142962306a36Sopenharmony_ci			struct notification_limit *limits)
143062306a36Sopenharmony_ci{
143162306a36Sopenharmony_ci	int ret = 0;
143262306a36Sopenharmony_ci
143362306a36Sopenharmony_ci	if (!set)
143462306a36Sopenharmony_ci		return -EOPNOTSUPP;
143562306a36Sopenharmony_ci
143662306a36Sopenharmony_ci	if (limits->prot)
143762306a36Sopenharmony_ci		ret = notif_set_limit(rdev, set, limits->prot,
143862306a36Sopenharmony_ci				      REGULATOR_SEVERITY_PROT);
143962306a36Sopenharmony_ci	if (ret)
144062306a36Sopenharmony_ci		return ret;
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_ci	if (limits->err)
144362306a36Sopenharmony_ci		ret = notif_set_limit(rdev, set, limits->err,
144462306a36Sopenharmony_ci				      REGULATOR_SEVERITY_ERR);
144562306a36Sopenharmony_ci	if (ret)
144662306a36Sopenharmony_ci		return ret;
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_ci	if (limits->warn)
144962306a36Sopenharmony_ci		ret = notif_set_limit(rdev, set, limits->warn,
145062306a36Sopenharmony_ci				      REGULATOR_SEVERITY_WARN);
145162306a36Sopenharmony_ci
145262306a36Sopenharmony_ci	return ret;
145362306a36Sopenharmony_ci}
145462306a36Sopenharmony_ci/**
145562306a36Sopenharmony_ci * set_machine_constraints - sets regulator constraints
145662306a36Sopenharmony_ci * @rdev: regulator source
145762306a36Sopenharmony_ci *
145862306a36Sopenharmony_ci * Allows platform initialisation code to define and constrain
145962306a36Sopenharmony_ci * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
146062306a36Sopenharmony_ci * Constraints *must* be set by platform code in order for some
146162306a36Sopenharmony_ci * regulator operations to proceed i.e. set_voltage, set_current_limit,
146262306a36Sopenharmony_ci * set_mode.
146362306a36Sopenharmony_ci */
146462306a36Sopenharmony_cistatic int set_machine_constraints(struct regulator_dev *rdev)
146562306a36Sopenharmony_ci{
146662306a36Sopenharmony_ci	int ret = 0;
146762306a36Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci	ret = machine_constraints_voltage(rdev, rdev->constraints);
147062306a36Sopenharmony_ci	if (ret != 0)
147162306a36Sopenharmony_ci		return ret;
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_ci	ret = machine_constraints_current(rdev, rdev->constraints);
147462306a36Sopenharmony_ci	if (ret != 0)
147562306a36Sopenharmony_ci		return ret;
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_ci	if (rdev->constraints->ilim_uA && ops->set_input_current_limit) {
147862306a36Sopenharmony_ci		ret = ops->set_input_current_limit(rdev,
147962306a36Sopenharmony_ci						   rdev->constraints->ilim_uA);
148062306a36Sopenharmony_ci		if (ret < 0) {
148162306a36Sopenharmony_ci			rdev_err(rdev, "failed to set input limit: %pe\n", ERR_PTR(ret));
148262306a36Sopenharmony_ci			return ret;
148362306a36Sopenharmony_ci		}
148462306a36Sopenharmony_ci	}
148562306a36Sopenharmony_ci
148662306a36Sopenharmony_ci	/* do we need to setup our suspend state */
148762306a36Sopenharmony_ci	if (rdev->constraints->initial_state) {
148862306a36Sopenharmony_ci		ret = suspend_set_initial_state(rdev);
148962306a36Sopenharmony_ci		if (ret < 0) {
149062306a36Sopenharmony_ci			rdev_err(rdev, "failed to set suspend state: %pe\n", ERR_PTR(ret));
149162306a36Sopenharmony_ci			return ret;
149262306a36Sopenharmony_ci		}
149362306a36Sopenharmony_ci	}
149462306a36Sopenharmony_ci
149562306a36Sopenharmony_ci	if (rdev->constraints->initial_mode) {
149662306a36Sopenharmony_ci		if (!ops->set_mode) {
149762306a36Sopenharmony_ci			rdev_err(rdev, "no set_mode operation\n");
149862306a36Sopenharmony_ci			return -EINVAL;
149962306a36Sopenharmony_ci		}
150062306a36Sopenharmony_ci
150162306a36Sopenharmony_ci		ret = ops->set_mode(rdev, rdev->constraints->initial_mode);
150262306a36Sopenharmony_ci		if (ret < 0) {
150362306a36Sopenharmony_ci			rdev_err(rdev, "failed to set initial mode: %pe\n", ERR_PTR(ret));
150462306a36Sopenharmony_ci			return ret;
150562306a36Sopenharmony_ci		}
150662306a36Sopenharmony_ci	} else if (rdev->constraints->system_load) {
150762306a36Sopenharmony_ci		/*
150862306a36Sopenharmony_ci		 * We'll only apply the initial system load if an
150962306a36Sopenharmony_ci		 * initial mode wasn't specified.
151062306a36Sopenharmony_ci		 */
151162306a36Sopenharmony_ci		drms_uA_update(rdev);
151262306a36Sopenharmony_ci	}
151362306a36Sopenharmony_ci
151462306a36Sopenharmony_ci	if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable)
151562306a36Sopenharmony_ci		&& ops->set_ramp_delay) {
151662306a36Sopenharmony_ci		ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay);
151762306a36Sopenharmony_ci		if (ret < 0) {
151862306a36Sopenharmony_ci			rdev_err(rdev, "failed to set ramp_delay: %pe\n", ERR_PTR(ret));
151962306a36Sopenharmony_ci			return ret;
152062306a36Sopenharmony_ci		}
152162306a36Sopenharmony_ci	}
152262306a36Sopenharmony_ci
152362306a36Sopenharmony_ci	if (rdev->constraints->pull_down && ops->set_pull_down) {
152462306a36Sopenharmony_ci		ret = ops->set_pull_down(rdev);
152562306a36Sopenharmony_ci		if (ret < 0) {
152662306a36Sopenharmony_ci			rdev_err(rdev, "failed to set pull down: %pe\n", ERR_PTR(ret));
152762306a36Sopenharmony_ci			return ret;
152862306a36Sopenharmony_ci		}
152962306a36Sopenharmony_ci	}
153062306a36Sopenharmony_ci
153162306a36Sopenharmony_ci	if (rdev->constraints->soft_start && ops->set_soft_start) {
153262306a36Sopenharmony_ci		ret = ops->set_soft_start(rdev);
153362306a36Sopenharmony_ci		if (ret < 0) {
153462306a36Sopenharmony_ci			rdev_err(rdev, "failed to set soft start: %pe\n", ERR_PTR(ret));
153562306a36Sopenharmony_ci			return ret;
153662306a36Sopenharmony_ci		}
153762306a36Sopenharmony_ci	}
153862306a36Sopenharmony_ci
153962306a36Sopenharmony_ci	/*
154062306a36Sopenharmony_ci	 * Existing logic does not warn if over_current_protection is given as
154162306a36Sopenharmony_ci	 * a constraint but driver does not support that. I think we should
154262306a36Sopenharmony_ci	 * warn about this type of issues as it is possible someone changes
154362306a36Sopenharmony_ci	 * PMIC on board to another type - and the another PMIC's driver does
154462306a36Sopenharmony_ci	 * not support setting protection. Board composer may happily believe
154562306a36Sopenharmony_ci	 * the DT limits are respected - especially if the new PMIC HW also
154662306a36Sopenharmony_ci	 * supports protection but the driver does not. I won't change the logic
154762306a36Sopenharmony_ci	 * without hearing more experienced opinion on this though.
154862306a36Sopenharmony_ci	 *
154962306a36Sopenharmony_ci	 * If warning is seen as a good idea then we can merge handling the
155062306a36Sopenharmony_ci	 * over-curret protection and detection and get rid of this special
155162306a36Sopenharmony_ci	 * handling.
155262306a36Sopenharmony_ci	 */
155362306a36Sopenharmony_ci	if (rdev->constraints->over_current_protection
155462306a36Sopenharmony_ci		&& ops->set_over_current_protection) {
155562306a36Sopenharmony_ci		int lim = rdev->constraints->over_curr_limits.prot;
155662306a36Sopenharmony_ci
155762306a36Sopenharmony_ci		ret = ops->set_over_current_protection(rdev, lim,
155862306a36Sopenharmony_ci						       REGULATOR_SEVERITY_PROT,
155962306a36Sopenharmony_ci						       true);
156062306a36Sopenharmony_ci		if (ret < 0) {
156162306a36Sopenharmony_ci			rdev_err(rdev, "failed to set over current protection: %pe\n",
156262306a36Sopenharmony_ci				 ERR_PTR(ret));
156362306a36Sopenharmony_ci			return ret;
156462306a36Sopenharmony_ci		}
156562306a36Sopenharmony_ci	}
156662306a36Sopenharmony_ci
156762306a36Sopenharmony_ci	if (rdev->constraints->over_current_detection)
156862306a36Sopenharmony_ci		ret = handle_notify_limits(rdev,
156962306a36Sopenharmony_ci					   ops->set_over_current_protection,
157062306a36Sopenharmony_ci					   &rdev->constraints->over_curr_limits);
157162306a36Sopenharmony_ci	if (ret) {
157262306a36Sopenharmony_ci		if (ret != -EOPNOTSUPP) {
157362306a36Sopenharmony_ci			rdev_err(rdev, "failed to set over current limits: %pe\n",
157462306a36Sopenharmony_ci				 ERR_PTR(ret));
157562306a36Sopenharmony_ci			return ret;
157662306a36Sopenharmony_ci		}
157762306a36Sopenharmony_ci		rdev_warn(rdev,
157862306a36Sopenharmony_ci			  "IC does not support requested over-current limits\n");
157962306a36Sopenharmony_ci	}
158062306a36Sopenharmony_ci
158162306a36Sopenharmony_ci	if (rdev->constraints->over_voltage_detection)
158262306a36Sopenharmony_ci		ret = handle_notify_limits(rdev,
158362306a36Sopenharmony_ci					   ops->set_over_voltage_protection,
158462306a36Sopenharmony_ci					   &rdev->constraints->over_voltage_limits);
158562306a36Sopenharmony_ci	if (ret) {
158662306a36Sopenharmony_ci		if (ret != -EOPNOTSUPP) {
158762306a36Sopenharmony_ci			rdev_err(rdev, "failed to set over voltage limits %pe\n",
158862306a36Sopenharmony_ci				 ERR_PTR(ret));
158962306a36Sopenharmony_ci			return ret;
159062306a36Sopenharmony_ci		}
159162306a36Sopenharmony_ci		rdev_warn(rdev,
159262306a36Sopenharmony_ci			  "IC does not support requested over voltage limits\n");
159362306a36Sopenharmony_ci	}
159462306a36Sopenharmony_ci
159562306a36Sopenharmony_ci	if (rdev->constraints->under_voltage_detection)
159662306a36Sopenharmony_ci		ret = handle_notify_limits(rdev,
159762306a36Sopenharmony_ci					   ops->set_under_voltage_protection,
159862306a36Sopenharmony_ci					   &rdev->constraints->under_voltage_limits);
159962306a36Sopenharmony_ci	if (ret) {
160062306a36Sopenharmony_ci		if (ret != -EOPNOTSUPP) {
160162306a36Sopenharmony_ci			rdev_err(rdev, "failed to set under voltage limits %pe\n",
160262306a36Sopenharmony_ci				 ERR_PTR(ret));
160362306a36Sopenharmony_ci			return ret;
160462306a36Sopenharmony_ci		}
160562306a36Sopenharmony_ci		rdev_warn(rdev,
160662306a36Sopenharmony_ci			  "IC does not support requested under voltage limits\n");
160762306a36Sopenharmony_ci	}
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_ci	if (rdev->constraints->over_temp_detection)
161062306a36Sopenharmony_ci		ret = handle_notify_limits(rdev,
161162306a36Sopenharmony_ci					   ops->set_thermal_protection,
161262306a36Sopenharmony_ci					   &rdev->constraints->temp_limits);
161362306a36Sopenharmony_ci	if (ret) {
161462306a36Sopenharmony_ci		if (ret != -EOPNOTSUPP) {
161562306a36Sopenharmony_ci			rdev_err(rdev, "failed to set temperature limits %pe\n",
161662306a36Sopenharmony_ci				 ERR_PTR(ret));
161762306a36Sopenharmony_ci			return ret;
161862306a36Sopenharmony_ci		}
161962306a36Sopenharmony_ci		rdev_warn(rdev,
162062306a36Sopenharmony_ci			  "IC does not support requested temperature limits\n");
162162306a36Sopenharmony_ci	}
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_ci	if (rdev->constraints->active_discharge && ops->set_active_discharge) {
162462306a36Sopenharmony_ci		bool ad_state = (rdev->constraints->active_discharge ==
162562306a36Sopenharmony_ci			      REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false;
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_ci		ret = ops->set_active_discharge(rdev, ad_state);
162862306a36Sopenharmony_ci		if (ret < 0) {
162962306a36Sopenharmony_ci			rdev_err(rdev, "failed to set active discharge: %pe\n", ERR_PTR(ret));
163062306a36Sopenharmony_ci			return ret;
163162306a36Sopenharmony_ci		}
163262306a36Sopenharmony_ci	}
163362306a36Sopenharmony_ci
163462306a36Sopenharmony_ci	/*
163562306a36Sopenharmony_ci	 * If there is no mechanism for controlling the regulator then
163662306a36Sopenharmony_ci	 * flag it as always_on so we don't end up duplicating checks
163762306a36Sopenharmony_ci	 * for this so much.  Note that we could control the state of
163862306a36Sopenharmony_ci	 * a supply to control the output on a regulator that has no
163962306a36Sopenharmony_ci	 * direct control.
164062306a36Sopenharmony_ci	 */
164162306a36Sopenharmony_ci	if (!rdev->ena_pin && !ops->enable) {
164262306a36Sopenharmony_ci		if (rdev->supply_name && !rdev->supply)
164362306a36Sopenharmony_ci			return -EPROBE_DEFER;
164462306a36Sopenharmony_ci
164562306a36Sopenharmony_ci		if (rdev->supply)
164662306a36Sopenharmony_ci			rdev->constraints->always_on =
164762306a36Sopenharmony_ci				rdev->supply->rdev->constraints->always_on;
164862306a36Sopenharmony_ci		else
164962306a36Sopenharmony_ci			rdev->constraints->always_on = true;
165062306a36Sopenharmony_ci	}
165162306a36Sopenharmony_ci
165262306a36Sopenharmony_ci	/* If the constraints say the regulator should be on at this point
165362306a36Sopenharmony_ci	 * and we have control then make sure it is enabled.
165462306a36Sopenharmony_ci	 */
165562306a36Sopenharmony_ci	if (rdev->constraints->always_on || rdev->constraints->boot_on) {
165662306a36Sopenharmony_ci		/* If we want to enable this regulator, make sure that we know
165762306a36Sopenharmony_ci		 * the supplying regulator.
165862306a36Sopenharmony_ci		 */
165962306a36Sopenharmony_ci		if (rdev->supply_name && !rdev->supply)
166062306a36Sopenharmony_ci			return -EPROBE_DEFER;
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_ci		/* If supplying regulator has already been enabled,
166362306a36Sopenharmony_ci		 * it's not intended to have use_count increment
166462306a36Sopenharmony_ci		 * when rdev is only boot-on.
166562306a36Sopenharmony_ci		 */
166662306a36Sopenharmony_ci		if (rdev->supply &&
166762306a36Sopenharmony_ci		    (rdev->constraints->always_on ||
166862306a36Sopenharmony_ci		     !regulator_is_enabled(rdev->supply))) {
166962306a36Sopenharmony_ci			ret = regulator_enable(rdev->supply);
167062306a36Sopenharmony_ci			if (ret < 0) {
167162306a36Sopenharmony_ci				_regulator_put(rdev->supply);
167262306a36Sopenharmony_ci				rdev->supply = NULL;
167362306a36Sopenharmony_ci				return ret;
167462306a36Sopenharmony_ci			}
167562306a36Sopenharmony_ci		}
167662306a36Sopenharmony_ci
167762306a36Sopenharmony_ci		ret = _regulator_do_enable(rdev);
167862306a36Sopenharmony_ci		if (ret < 0 && ret != -EINVAL) {
167962306a36Sopenharmony_ci			rdev_err(rdev, "failed to enable: %pe\n", ERR_PTR(ret));
168062306a36Sopenharmony_ci			return ret;
168162306a36Sopenharmony_ci		}
168262306a36Sopenharmony_ci
168362306a36Sopenharmony_ci		if (rdev->constraints->always_on)
168462306a36Sopenharmony_ci			rdev->use_count++;
168562306a36Sopenharmony_ci	} else if (rdev->desc->off_on_delay) {
168662306a36Sopenharmony_ci		rdev->last_off = ktime_get();
168762306a36Sopenharmony_ci	}
168862306a36Sopenharmony_ci
168962306a36Sopenharmony_ci	print_constraints(rdev);
169062306a36Sopenharmony_ci	return 0;
169162306a36Sopenharmony_ci}
169262306a36Sopenharmony_ci
169362306a36Sopenharmony_ci/**
169462306a36Sopenharmony_ci * set_supply - set regulator supply regulator
169562306a36Sopenharmony_ci * @rdev: regulator (locked)
169662306a36Sopenharmony_ci * @supply_rdev: supply regulator (locked))
169762306a36Sopenharmony_ci *
169862306a36Sopenharmony_ci * Called by platform initialisation code to set the supply regulator for this
169962306a36Sopenharmony_ci * regulator. This ensures that a regulators supply will also be enabled by the
170062306a36Sopenharmony_ci * core if it's child is enabled.
170162306a36Sopenharmony_ci */
170262306a36Sopenharmony_cistatic int set_supply(struct regulator_dev *rdev,
170362306a36Sopenharmony_ci		      struct regulator_dev *supply_rdev)
170462306a36Sopenharmony_ci{
170562306a36Sopenharmony_ci	int err;
170662306a36Sopenharmony_ci
170762306a36Sopenharmony_ci	rdev_dbg(rdev, "supplied by %s\n", rdev_get_name(supply_rdev));
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci	if (!try_module_get(supply_rdev->owner))
171062306a36Sopenharmony_ci		return -ENODEV;
171162306a36Sopenharmony_ci
171262306a36Sopenharmony_ci	rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY");
171362306a36Sopenharmony_ci	if (rdev->supply == NULL) {
171462306a36Sopenharmony_ci		module_put(supply_rdev->owner);
171562306a36Sopenharmony_ci		err = -ENOMEM;
171662306a36Sopenharmony_ci		return err;
171762306a36Sopenharmony_ci	}
171862306a36Sopenharmony_ci	supply_rdev->open_count++;
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci	return 0;
172162306a36Sopenharmony_ci}
172262306a36Sopenharmony_ci
172362306a36Sopenharmony_ci/**
172462306a36Sopenharmony_ci * set_consumer_device_supply - Bind a regulator to a symbolic supply
172562306a36Sopenharmony_ci * @rdev:         regulator source
172662306a36Sopenharmony_ci * @consumer_dev_name: dev_name() string for device supply applies to
172762306a36Sopenharmony_ci * @supply:       symbolic name for supply
172862306a36Sopenharmony_ci *
172962306a36Sopenharmony_ci * Allows platform initialisation code to map physical regulator
173062306a36Sopenharmony_ci * sources to symbolic names for supplies for use by devices.  Devices
173162306a36Sopenharmony_ci * should use these symbolic names to request regulators, avoiding the
173262306a36Sopenharmony_ci * need to provide board-specific regulator names as platform data.
173362306a36Sopenharmony_ci */
173462306a36Sopenharmony_cistatic int set_consumer_device_supply(struct regulator_dev *rdev,
173562306a36Sopenharmony_ci				      const char *consumer_dev_name,
173662306a36Sopenharmony_ci				      const char *supply)
173762306a36Sopenharmony_ci{
173862306a36Sopenharmony_ci	struct regulator_map *node, *new_node;
173962306a36Sopenharmony_ci	int has_dev;
174062306a36Sopenharmony_ci
174162306a36Sopenharmony_ci	if (supply == NULL)
174262306a36Sopenharmony_ci		return -EINVAL;
174362306a36Sopenharmony_ci
174462306a36Sopenharmony_ci	if (consumer_dev_name != NULL)
174562306a36Sopenharmony_ci		has_dev = 1;
174662306a36Sopenharmony_ci	else
174762306a36Sopenharmony_ci		has_dev = 0;
174862306a36Sopenharmony_ci
174962306a36Sopenharmony_ci	new_node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL);
175062306a36Sopenharmony_ci	if (new_node == NULL)
175162306a36Sopenharmony_ci		return -ENOMEM;
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	new_node->regulator = rdev;
175462306a36Sopenharmony_ci	new_node->supply = supply;
175562306a36Sopenharmony_ci
175662306a36Sopenharmony_ci	if (has_dev) {
175762306a36Sopenharmony_ci		new_node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL);
175862306a36Sopenharmony_ci		if (new_node->dev_name == NULL) {
175962306a36Sopenharmony_ci			kfree(new_node);
176062306a36Sopenharmony_ci			return -ENOMEM;
176162306a36Sopenharmony_ci		}
176262306a36Sopenharmony_ci	}
176362306a36Sopenharmony_ci
176462306a36Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
176562306a36Sopenharmony_ci	list_for_each_entry(node, &regulator_map_list, list) {
176662306a36Sopenharmony_ci		if (node->dev_name && consumer_dev_name) {
176762306a36Sopenharmony_ci			if (strcmp(node->dev_name, consumer_dev_name) != 0)
176862306a36Sopenharmony_ci				continue;
176962306a36Sopenharmony_ci		} else if (node->dev_name || consumer_dev_name) {
177062306a36Sopenharmony_ci			continue;
177162306a36Sopenharmony_ci		}
177262306a36Sopenharmony_ci
177362306a36Sopenharmony_ci		if (strcmp(node->supply, supply) != 0)
177462306a36Sopenharmony_ci			continue;
177562306a36Sopenharmony_ci
177662306a36Sopenharmony_ci		pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n",
177762306a36Sopenharmony_ci			 consumer_dev_name,
177862306a36Sopenharmony_ci			 dev_name(&node->regulator->dev),
177962306a36Sopenharmony_ci			 node->regulator->desc->name,
178062306a36Sopenharmony_ci			 supply,
178162306a36Sopenharmony_ci			 dev_name(&rdev->dev), rdev_get_name(rdev));
178262306a36Sopenharmony_ci		goto fail;
178362306a36Sopenharmony_ci	}
178462306a36Sopenharmony_ci
178562306a36Sopenharmony_ci	list_add(&new_node->list, &regulator_map_list);
178662306a36Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
178762306a36Sopenharmony_ci
178862306a36Sopenharmony_ci	return 0;
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_cifail:
179162306a36Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
179262306a36Sopenharmony_ci	kfree(new_node->dev_name);
179362306a36Sopenharmony_ci	kfree(new_node);
179462306a36Sopenharmony_ci	return -EBUSY;
179562306a36Sopenharmony_ci}
179662306a36Sopenharmony_ci
179762306a36Sopenharmony_cistatic void unset_regulator_supplies(struct regulator_dev *rdev)
179862306a36Sopenharmony_ci{
179962306a36Sopenharmony_ci	struct regulator_map *node, *n;
180062306a36Sopenharmony_ci
180162306a36Sopenharmony_ci	list_for_each_entry_safe(node, n, &regulator_map_list, list) {
180262306a36Sopenharmony_ci		if (rdev == node->regulator) {
180362306a36Sopenharmony_ci			list_del(&node->list);
180462306a36Sopenharmony_ci			kfree(node->dev_name);
180562306a36Sopenharmony_ci			kfree(node);
180662306a36Sopenharmony_ci		}
180762306a36Sopenharmony_ci	}
180862306a36Sopenharmony_ci}
180962306a36Sopenharmony_ci
181062306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
181162306a36Sopenharmony_cistatic ssize_t constraint_flags_read_file(struct file *file,
181262306a36Sopenharmony_ci					  char __user *user_buf,
181362306a36Sopenharmony_ci					  size_t count, loff_t *ppos)
181462306a36Sopenharmony_ci{
181562306a36Sopenharmony_ci	const struct regulator *regulator = file->private_data;
181662306a36Sopenharmony_ci	const struct regulation_constraints *c = regulator->rdev->constraints;
181762306a36Sopenharmony_ci	char *buf;
181862306a36Sopenharmony_ci	ssize_t ret;
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_ci	if (!c)
182162306a36Sopenharmony_ci		return 0;
182262306a36Sopenharmony_ci
182362306a36Sopenharmony_ci	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
182462306a36Sopenharmony_ci	if (!buf)
182562306a36Sopenharmony_ci		return -ENOMEM;
182662306a36Sopenharmony_ci
182762306a36Sopenharmony_ci	ret = snprintf(buf, PAGE_SIZE,
182862306a36Sopenharmony_ci			"always_on: %u\n"
182962306a36Sopenharmony_ci			"boot_on: %u\n"
183062306a36Sopenharmony_ci			"apply_uV: %u\n"
183162306a36Sopenharmony_ci			"ramp_disable: %u\n"
183262306a36Sopenharmony_ci			"soft_start: %u\n"
183362306a36Sopenharmony_ci			"pull_down: %u\n"
183462306a36Sopenharmony_ci			"over_current_protection: %u\n",
183562306a36Sopenharmony_ci			c->always_on,
183662306a36Sopenharmony_ci			c->boot_on,
183762306a36Sopenharmony_ci			c->apply_uV,
183862306a36Sopenharmony_ci			c->ramp_disable,
183962306a36Sopenharmony_ci			c->soft_start,
184062306a36Sopenharmony_ci			c->pull_down,
184162306a36Sopenharmony_ci			c->over_current_protection);
184262306a36Sopenharmony_ci
184362306a36Sopenharmony_ci	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
184462306a36Sopenharmony_ci	kfree(buf);
184562306a36Sopenharmony_ci
184662306a36Sopenharmony_ci	return ret;
184762306a36Sopenharmony_ci}
184862306a36Sopenharmony_ci
184962306a36Sopenharmony_ci#endif
185062306a36Sopenharmony_ci
185162306a36Sopenharmony_cistatic const struct file_operations constraint_flags_fops = {
185262306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
185362306a36Sopenharmony_ci	.open = simple_open,
185462306a36Sopenharmony_ci	.read = constraint_flags_read_file,
185562306a36Sopenharmony_ci	.llseek = default_llseek,
185662306a36Sopenharmony_ci#endif
185762306a36Sopenharmony_ci};
185862306a36Sopenharmony_ci
185962306a36Sopenharmony_ci#define REG_STR_SIZE	64
186062306a36Sopenharmony_ci
186162306a36Sopenharmony_cistatic struct regulator *create_regulator(struct regulator_dev *rdev,
186262306a36Sopenharmony_ci					  struct device *dev,
186362306a36Sopenharmony_ci					  const char *supply_name)
186462306a36Sopenharmony_ci{
186562306a36Sopenharmony_ci	struct regulator *regulator;
186662306a36Sopenharmony_ci	int err = 0;
186762306a36Sopenharmony_ci
186862306a36Sopenharmony_ci	lockdep_assert_held_once(&rdev->mutex.base);
186962306a36Sopenharmony_ci
187062306a36Sopenharmony_ci	if (dev) {
187162306a36Sopenharmony_ci		char buf[REG_STR_SIZE];
187262306a36Sopenharmony_ci		int size;
187362306a36Sopenharmony_ci
187462306a36Sopenharmony_ci		size = snprintf(buf, REG_STR_SIZE, "%s-%s",
187562306a36Sopenharmony_ci				dev->kobj.name, supply_name);
187662306a36Sopenharmony_ci		if (size >= REG_STR_SIZE)
187762306a36Sopenharmony_ci			return NULL;
187862306a36Sopenharmony_ci
187962306a36Sopenharmony_ci		supply_name = kstrdup(buf, GFP_KERNEL);
188062306a36Sopenharmony_ci		if (supply_name == NULL)
188162306a36Sopenharmony_ci			return NULL;
188262306a36Sopenharmony_ci	} else {
188362306a36Sopenharmony_ci		supply_name = kstrdup_const(supply_name, GFP_KERNEL);
188462306a36Sopenharmony_ci		if (supply_name == NULL)
188562306a36Sopenharmony_ci			return NULL;
188662306a36Sopenharmony_ci	}
188762306a36Sopenharmony_ci
188862306a36Sopenharmony_ci	regulator = kzalloc(sizeof(*regulator), GFP_KERNEL);
188962306a36Sopenharmony_ci	if (regulator == NULL) {
189062306a36Sopenharmony_ci		kfree_const(supply_name);
189162306a36Sopenharmony_ci		return NULL;
189262306a36Sopenharmony_ci	}
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_ci	regulator->rdev = rdev;
189562306a36Sopenharmony_ci	regulator->supply_name = supply_name;
189662306a36Sopenharmony_ci
189762306a36Sopenharmony_ci	list_add(&regulator->list, &rdev->consumer_list);
189862306a36Sopenharmony_ci
189962306a36Sopenharmony_ci	if (dev) {
190062306a36Sopenharmony_ci		regulator->dev = dev;
190162306a36Sopenharmony_ci
190262306a36Sopenharmony_ci		/* Add a link to the device sysfs entry */
190362306a36Sopenharmony_ci		err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj,
190462306a36Sopenharmony_ci					       supply_name);
190562306a36Sopenharmony_ci		if (err) {
190662306a36Sopenharmony_ci			rdev_dbg(rdev, "could not add device link %s: %pe\n",
190762306a36Sopenharmony_ci				  dev->kobj.name, ERR_PTR(err));
190862306a36Sopenharmony_ci			/* non-fatal */
190962306a36Sopenharmony_ci		}
191062306a36Sopenharmony_ci	}
191162306a36Sopenharmony_ci
191262306a36Sopenharmony_ci	if (err != -EEXIST)
191362306a36Sopenharmony_ci		regulator->debugfs = debugfs_create_dir(supply_name, rdev->debugfs);
191462306a36Sopenharmony_ci	if (IS_ERR(regulator->debugfs))
191562306a36Sopenharmony_ci		rdev_dbg(rdev, "Failed to create debugfs directory\n");
191662306a36Sopenharmony_ci
191762306a36Sopenharmony_ci	debugfs_create_u32("uA_load", 0444, regulator->debugfs,
191862306a36Sopenharmony_ci			   &regulator->uA_load);
191962306a36Sopenharmony_ci	debugfs_create_u32("min_uV", 0444, regulator->debugfs,
192062306a36Sopenharmony_ci			   &regulator->voltage[PM_SUSPEND_ON].min_uV);
192162306a36Sopenharmony_ci	debugfs_create_u32("max_uV", 0444, regulator->debugfs,
192262306a36Sopenharmony_ci			   &regulator->voltage[PM_SUSPEND_ON].max_uV);
192362306a36Sopenharmony_ci	debugfs_create_file("constraint_flags", 0444, regulator->debugfs,
192462306a36Sopenharmony_ci			    regulator, &constraint_flags_fops);
192562306a36Sopenharmony_ci
192662306a36Sopenharmony_ci	/*
192762306a36Sopenharmony_ci	 * Check now if the regulator is an always on regulator - if
192862306a36Sopenharmony_ci	 * it is then we don't need to do nearly so much work for
192962306a36Sopenharmony_ci	 * enable/disable calls.
193062306a36Sopenharmony_ci	 */
193162306a36Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS) &&
193262306a36Sopenharmony_ci	    _regulator_is_enabled(rdev))
193362306a36Sopenharmony_ci		regulator->always_on = true;
193462306a36Sopenharmony_ci
193562306a36Sopenharmony_ci	return regulator;
193662306a36Sopenharmony_ci}
193762306a36Sopenharmony_ci
193862306a36Sopenharmony_cistatic int _regulator_get_enable_time(struct regulator_dev *rdev)
193962306a36Sopenharmony_ci{
194062306a36Sopenharmony_ci	if (rdev->constraints && rdev->constraints->enable_time)
194162306a36Sopenharmony_ci		return rdev->constraints->enable_time;
194262306a36Sopenharmony_ci	if (rdev->desc->ops->enable_time)
194362306a36Sopenharmony_ci		return rdev->desc->ops->enable_time(rdev);
194462306a36Sopenharmony_ci	return rdev->desc->enable_time;
194562306a36Sopenharmony_ci}
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_cistatic struct regulator_supply_alias *regulator_find_supply_alias(
194862306a36Sopenharmony_ci		struct device *dev, const char *supply)
194962306a36Sopenharmony_ci{
195062306a36Sopenharmony_ci	struct regulator_supply_alias *map;
195162306a36Sopenharmony_ci
195262306a36Sopenharmony_ci	list_for_each_entry(map, &regulator_supply_alias_list, list)
195362306a36Sopenharmony_ci		if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0)
195462306a36Sopenharmony_ci			return map;
195562306a36Sopenharmony_ci
195662306a36Sopenharmony_ci	return NULL;
195762306a36Sopenharmony_ci}
195862306a36Sopenharmony_ci
195962306a36Sopenharmony_cistatic void regulator_supply_alias(struct device **dev, const char **supply)
196062306a36Sopenharmony_ci{
196162306a36Sopenharmony_ci	struct regulator_supply_alias *map;
196262306a36Sopenharmony_ci
196362306a36Sopenharmony_ci	map = regulator_find_supply_alias(*dev, *supply);
196462306a36Sopenharmony_ci	if (map) {
196562306a36Sopenharmony_ci		dev_dbg(*dev, "Mapping supply %s to %s,%s\n",
196662306a36Sopenharmony_ci				*supply, map->alias_supply,
196762306a36Sopenharmony_ci				dev_name(map->alias_dev));
196862306a36Sopenharmony_ci		*dev = map->alias_dev;
196962306a36Sopenharmony_ci		*supply = map->alias_supply;
197062306a36Sopenharmony_ci	}
197162306a36Sopenharmony_ci}
197262306a36Sopenharmony_ci
197362306a36Sopenharmony_cistatic int regulator_match(struct device *dev, const void *data)
197462306a36Sopenharmony_ci{
197562306a36Sopenharmony_ci	struct regulator_dev *r = dev_to_rdev(dev);
197662306a36Sopenharmony_ci
197762306a36Sopenharmony_ci	return strcmp(rdev_get_name(r), data) == 0;
197862306a36Sopenharmony_ci}
197962306a36Sopenharmony_ci
198062306a36Sopenharmony_cistatic struct regulator_dev *regulator_lookup_by_name(const char *name)
198162306a36Sopenharmony_ci{
198262306a36Sopenharmony_ci	struct device *dev;
198362306a36Sopenharmony_ci
198462306a36Sopenharmony_ci	dev = class_find_device(&regulator_class, NULL, name, regulator_match);
198562306a36Sopenharmony_ci
198662306a36Sopenharmony_ci	return dev ? dev_to_rdev(dev) : NULL;
198762306a36Sopenharmony_ci}
198862306a36Sopenharmony_ci
198962306a36Sopenharmony_ci/**
199062306a36Sopenharmony_ci * regulator_dev_lookup - lookup a regulator device.
199162306a36Sopenharmony_ci * @dev: device for regulator "consumer".
199262306a36Sopenharmony_ci * @supply: Supply name or regulator ID.
199362306a36Sopenharmony_ci *
199462306a36Sopenharmony_ci * If successful, returns a struct regulator_dev that corresponds to the name
199562306a36Sopenharmony_ci * @supply and with the embedded struct device refcount incremented by one.
199662306a36Sopenharmony_ci * The refcount must be dropped by calling put_device().
199762306a36Sopenharmony_ci * On failure one of the following ERR-PTR-encoded values is returned:
199862306a36Sopenharmony_ci * -ENODEV if lookup fails permanently, -EPROBE_DEFER if lookup could succeed
199962306a36Sopenharmony_ci * in the future.
200062306a36Sopenharmony_ci */
200162306a36Sopenharmony_cistatic struct regulator_dev *regulator_dev_lookup(struct device *dev,
200262306a36Sopenharmony_ci						  const char *supply)
200362306a36Sopenharmony_ci{
200462306a36Sopenharmony_ci	struct regulator_dev *r = NULL;
200562306a36Sopenharmony_ci	struct device_node *node;
200662306a36Sopenharmony_ci	struct regulator_map *map;
200762306a36Sopenharmony_ci	const char *devname = NULL;
200862306a36Sopenharmony_ci
200962306a36Sopenharmony_ci	regulator_supply_alias(&dev, &supply);
201062306a36Sopenharmony_ci
201162306a36Sopenharmony_ci	/* first do a dt based lookup */
201262306a36Sopenharmony_ci	if (dev && dev->of_node) {
201362306a36Sopenharmony_ci		node = of_get_regulator(dev, supply);
201462306a36Sopenharmony_ci		if (node) {
201562306a36Sopenharmony_ci			r = of_find_regulator_by_node(node);
201662306a36Sopenharmony_ci			of_node_put(node);
201762306a36Sopenharmony_ci			if (r)
201862306a36Sopenharmony_ci				return r;
201962306a36Sopenharmony_ci
202062306a36Sopenharmony_ci			/*
202162306a36Sopenharmony_ci			 * We have a node, but there is no device.
202262306a36Sopenharmony_ci			 * assume it has not registered yet.
202362306a36Sopenharmony_ci			 */
202462306a36Sopenharmony_ci			return ERR_PTR(-EPROBE_DEFER);
202562306a36Sopenharmony_ci		}
202662306a36Sopenharmony_ci	}
202762306a36Sopenharmony_ci
202862306a36Sopenharmony_ci	/* if not found, try doing it non-dt way */
202962306a36Sopenharmony_ci	if (dev)
203062306a36Sopenharmony_ci		devname = dev_name(dev);
203162306a36Sopenharmony_ci
203262306a36Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
203362306a36Sopenharmony_ci	list_for_each_entry(map, &regulator_map_list, list) {
203462306a36Sopenharmony_ci		/* If the mapping has a device set up it must match */
203562306a36Sopenharmony_ci		if (map->dev_name &&
203662306a36Sopenharmony_ci		    (!devname || strcmp(map->dev_name, devname)))
203762306a36Sopenharmony_ci			continue;
203862306a36Sopenharmony_ci
203962306a36Sopenharmony_ci		if (strcmp(map->supply, supply) == 0 &&
204062306a36Sopenharmony_ci		    get_device(&map->regulator->dev)) {
204162306a36Sopenharmony_ci			r = map->regulator;
204262306a36Sopenharmony_ci			break;
204362306a36Sopenharmony_ci		}
204462306a36Sopenharmony_ci	}
204562306a36Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
204662306a36Sopenharmony_ci
204762306a36Sopenharmony_ci	if (r)
204862306a36Sopenharmony_ci		return r;
204962306a36Sopenharmony_ci
205062306a36Sopenharmony_ci	r = regulator_lookup_by_name(supply);
205162306a36Sopenharmony_ci	if (r)
205262306a36Sopenharmony_ci		return r;
205362306a36Sopenharmony_ci
205462306a36Sopenharmony_ci	return ERR_PTR(-ENODEV);
205562306a36Sopenharmony_ci}
205662306a36Sopenharmony_ci
205762306a36Sopenharmony_cistatic int regulator_resolve_supply(struct regulator_dev *rdev)
205862306a36Sopenharmony_ci{
205962306a36Sopenharmony_ci	struct regulator_dev *r;
206062306a36Sopenharmony_ci	struct device *dev = rdev->dev.parent;
206162306a36Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
206262306a36Sopenharmony_ci	int ret = 0;
206362306a36Sopenharmony_ci
206462306a36Sopenharmony_ci	/* No supply to resolve? */
206562306a36Sopenharmony_ci	if (!rdev->supply_name)
206662306a36Sopenharmony_ci		return 0;
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_ci	/* Supply already resolved? (fast-path without locking contention) */
206962306a36Sopenharmony_ci	if (rdev->supply)
207062306a36Sopenharmony_ci		return 0;
207162306a36Sopenharmony_ci
207262306a36Sopenharmony_ci	r = regulator_dev_lookup(dev, rdev->supply_name);
207362306a36Sopenharmony_ci	if (IS_ERR(r)) {
207462306a36Sopenharmony_ci		ret = PTR_ERR(r);
207562306a36Sopenharmony_ci
207662306a36Sopenharmony_ci		/* Did the lookup explicitly defer for us? */
207762306a36Sopenharmony_ci		if (ret == -EPROBE_DEFER)
207862306a36Sopenharmony_ci			goto out;
207962306a36Sopenharmony_ci
208062306a36Sopenharmony_ci		if (have_full_constraints()) {
208162306a36Sopenharmony_ci			r = dummy_regulator_rdev;
208262306a36Sopenharmony_ci			get_device(&r->dev);
208362306a36Sopenharmony_ci		} else {
208462306a36Sopenharmony_ci			dev_err(dev, "Failed to resolve %s-supply for %s\n",
208562306a36Sopenharmony_ci				rdev->supply_name, rdev->desc->name);
208662306a36Sopenharmony_ci			ret = -EPROBE_DEFER;
208762306a36Sopenharmony_ci			goto out;
208862306a36Sopenharmony_ci		}
208962306a36Sopenharmony_ci	}
209062306a36Sopenharmony_ci
209162306a36Sopenharmony_ci	if (r == rdev) {
209262306a36Sopenharmony_ci		dev_err(dev, "Supply for %s (%s) resolved to itself\n",
209362306a36Sopenharmony_ci			rdev->desc->name, rdev->supply_name);
209462306a36Sopenharmony_ci		if (!have_full_constraints()) {
209562306a36Sopenharmony_ci			ret = -EINVAL;
209662306a36Sopenharmony_ci			goto out;
209762306a36Sopenharmony_ci		}
209862306a36Sopenharmony_ci		r = dummy_regulator_rdev;
209962306a36Sopenharmony_ci		get_device(&r->dev);
210062306a36Sopenharmony_ci	}
210162306a36Sopenharmony_ci
210262306a36Sopenharmony_ci	/*
210362306a36Sopenharmony_ci	 * If the supply's parent device is not the same as the
210462306a36Sopenharmony_ci	 * regulator's parent device, then ensure the parent device
210562306a36Sopenharmony_ci	 * is bound before we resolve the supply, in case the parent
210662306a36Sopenharmony_ci	 * device get probe deferred and unregisters the supply.
210762306a36Sopenharmony_ci	 */
210862306a36Sopenharmony_ci	if (r->dev.parent && r->dev.parent != rdev->dev.parent) {
210962306a36Sopenharmony_ci		if (!device_is_bound(r->dev.parent)) {
211062306a36Sopenharmony_ci			put_device(&r->dev);
211162306a36Sopenharmony_ci			ret = -EPROBE_DEFER;
211262306a36Sopenharmony_ci			goto out;
211362306a36Sopenharmony_ci		}
211462306a36Sopenharmony_ci	}
211562306a36Sopenharmony_ci
211662306a36Sopenharmony_ci	/* Recursively resolve the supply of the supply */
211762306a36Sopenharmony_ci	ret = regulator_resolve_supply(r);
211862306a36Sopenharmony_ci	if (ret < 0) {
211962306a36Sopenharmony_ci		put_device(&r->dev);
212062306a36Sopenharmony_ci		goto out;
212162306a36Sopenharmony_ci	}
212262306a36Sopenharmony_ci
212362306a36Sopenharmony_ci	/*
212462306a36Sopenharmony_ci	 * Recheck rdev->supply with rdev->mutex lock held to avoid a race
212562306a36Sopenharmony_ci	 * between rdev->supply null check and setting rdev->supply in
212662306a36Sopenharmony_ci	 * set_supply() from concurrent tasks.
212762306a36Sopenharmony_ci	 */
212862306a36Sopenharmony_ci	regulator_lock_two(rdev, r, &ww_ctx);
212962306a36Sopenharmony_ci
213062306a36Sopenharmony_ci	/* Supply just resolved by a concurrent task? */
213162306a36Sopenharmony_ci	if (rdev->supply) {
213262306a36Sopenharmony_ci		regulator_unlock_two(rdev, r, &ww_ctx);
213362306a36Sopenharmony_ci		put_device(&r->dev);
213462306a36Sopenharmony_ci		goto out;
213562306a36Sopenharmony_ci	}
213662306a36Sopenharmony_ci
213762306a36Sopenharmony_ci	ret = set_supply(rdev, r);
213862306a36Sopenharmony_ci	if (ret < 0) {
213962306a36Sopenharmony_ci		regulator_unlock_two(rdev, r, &ww_ctx);
214062306a36Sopenharmony_ci		put_device(&r->dev);
214162306a36Sopenharmony_ci		goto out;
214262306a36Sopenharmony_ci	}
214362306a36Sopenharmony_ci
214462306a36Sopenharmony_ci	regulator_unlock_two(rdev, r, &ww_ctx);
214562306a36Sopenharmony_ci
214662306a36Sopenharmony_ci	/*
214762306a36Sopenharmony_ci	 * In set_machine_constraints() we may have turned this regulator on
214862306a36Sopenharmony_ci	 * but we couldn't propagate to the supply if it hadn't been resolved
214962306a36Sopenharmony_ci	 * yet.  Do it now.
215062306a36Sopenharmony_ci	 */
215162306a36Sopenharmony_ci	if (rdev->use_count) {
215262306a36Sopenharmony_ci		ret = regulator_enable(rdev->supply);
215362306a36Sopenharmony_ci		if (ret < 0) {
215462306a36Sopenharmony_ci			_regulator_put(rdev->supply);
215562306a36Sopenharmony_ci			rdev->supply = NULL;
215662306a36Sopenharmony_ci			goto out;
215762306a36Sopenharmony_ci		}
215862306a36Sopenharmony_ci	}
215962306a36Sopenharmony_ci
216062306a36Sopenharmony_ciout:
216162306a36Sopenharmony_ci	return ret;
216262306a36Sopenharmony_ci}
216362306a36Sopenharmony_ci
216462306a36Sopenharmony_ci/* Internal regulator request function */
216562306a36Sopenharmony_cistruct regulator *_regulator_get(struct device *dev, const char *id,
216662306a36Sopenharmony_ci				 enum regulator_get_type get_type)
216762306a36Sopenharmony_ci{
216862306a36Sopenharmony_ci	struct regulator_dev *rdev;
216962306a36Sopenharmony_ci	struct regulator *regulator;
217062306a36Sopenharmony_ci	struct device_link *link;
217162306a36Sopenharmony_ci	int ret;
217262306a36Sopenharmony_ci
217362306a36Sopenharmony_ci	if (get_type >= MAX_GET_TYPE) {
217462306a36Sopenharmony_ci		dev_err(dev, "invalid type %d in %s\n", get_type, __func__);
217562306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
217662306a36Sopenharmony_ci	}
217762306a36Sopenharmony_ci
217862306a36Sopenharmony_ci	if (id == NULL) {
217962306a36Sopenharmony_ci		pr_err("get() with no identifier\n");
218062306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
218162306a36Sopenharmony_ci	}
218262306a36Sopenharmony_ci
218362306a36Sopenharmony_ci	rdev = regulator_dev_lookup(dev, id);
218462306a36Sopenharmony_ci	if (IS_ERR(rdev)) {
218562306a36Sopenharmony_ci		ret = PTR_ERR(rdev);
218662306a36Sopenharmony_ci
218762306a36Sopenharmony_ci		/*
218862306a36Sopenharmony_ci		 * If regulator_dev_lookup() fails with error other
218962306a36Sopenharmony_ci		 * than -ENODEV our job here is done, we simply return it.
219062306a36Sopenharmony_ci		 */
219162306a36Sopenharmony_ci		if (ret != -ENODEV)
219262306a36Sopenharmony_ci			return ERR_PTR(ret);
219362306a36Sopenharmony_ci
219462306a36Sopenharmony_ci		if (!have_full_constraints()) {
219562306a36Sopenharmony_ci			dev_warn(dev,
219662306a36Sopenharmony_ci				 "incomplete constraints, dummy supplies not allowed\n");
219762306a36Sopenharmony_ci			return ERR_PTR(-ENODEV);
219862306a36Sopenharmony_ci		}
219962306a36Sopenharmony_ci
220062306a36Sopenharmony_ci		switch (get_type) {
220162306a36Sopenharmony_ci		case NORMAL_GET:
220262306a36Sopenharmony_ci			/*
220362306a36Sopenharmony_ci			 * Assume that a regulator is physically present and
220462306a36Sopenharmony_ci			 * enabled, even if it isn't hooked up, and just
220562306a36Sopenharmony_ci			 * provide a dummy.
220662306a36Sopenharmony_ci			 */
220762306a36Sopenharmony_ci			dev_warn(dev, "supply %s not found, using dummy regulator\n", id);
220862306a36Sopenharmony_ci			rdev = dummy_regulator_rdev;
220962306a36Sopenharmony_ci			get_device(&rdev->dev);
221062306a36Sopenharmony_ci			break;
221162306a36Sopenharmony_ci
221262306a36Sopenharmony_ci		case EXCLUSIVE_GET:
221362306a36Sopenharmony_ci			dev_warn(dev,
221462306a36Sopenharmony_ci				 "dummy supplies not allowed for exclusive requests\n");
221562306a36Sopenharmony_ci			fallthrough;
221662306a36Sopenharmony_ci
221762306a36Sopenharmony_ci		default:
221862306a36Sopenharmony_ci			return ERR_PTR(-ENODEV);
221962306a36Sopenharmony_ci		}
222062306a36Sopenharmony_ci	}
222162306a36Sopenharmony_ci
222262306a36Sopenharmony_ci	if (rdev->exclusive) {
222362306a36Sopenharmony_ci		regulator = ERR_PTR(-EPERM);
222462306a36Sopenharmony_ci		put_device(&rdev->dev);
222562306a36Sopenharmony_ci		return regulator;
222662306a36Sopenharmony_ci	}
222762306a36Sopenharmony_ci
222862306a36Sopenharmony_ci	if (get_type == EXCLUSIVE_GET && rdev->open_count) {
222962306a36Sopenharmony_ci		regulator = ERR_PTR(-EBUSY);
223062306a36Sopenharmony_ci		put_device(&rdev->dev);
223162306a36Sopenharmony_ci		return regulator;
223262306a36Sopenharmony_ci	}
223362306a36Sopenharmony_ci
223462306a36Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
223562306a36Sopenharmony_ci	ret = (rdev->coupling_desc.n_resolved != rdev->coupling_desc.n_coupled);
223662306a36Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
223762306a36Sopenharmony_ci
223862306a36Sopenharmony_ci	if (ret != 0) {
223962306a36Sopenharmony_ci		regulator = ERR_PTR(-EPROBE_DEFER);
224062306a36Sopenharmony_ci		put_device(&rdev->dev);
224162306a36Sopenharmony_ci		return regulator;
224262306a36Sopenharmony_ci	}
224362306a36Sopenharmony_ci
224462306a36Sopenharmony_ci	ret = regulator_resolve_supply(rdev);
224562306a36Sopenharmony_ci	if (ret < 0) {
224662306a36Sopenharmony_ci		regulator = ERR_PTR(ret);
224762306a36Sopenharmony_ci		put_device(&rdev->dev);
224862306a36Sopenharmony_ci		return regulator;
224962306a36Sopenharmony_ci	}
225062306a36Sopenharmony_ci
225162306a36Sopenharmony_ci	if (!try_module_get(rdev->owner)) {
225262306a36Sopenharmony_ci		regulator = ERR_PTR(-EPROBE_DEFER);
225362306a36Sopenharmony_ci		put_device(&rdev->dev);
225462306a36Sopenharmony_ci		return regulator;
225562306a36Sopenharmony_ci	}
225662306a36Sopenharmony_ci
225762306a36Sopenharmony_ci	regulator_lock(rdev);
225862306a36Sopenharmony_ci	regulator = create_regulator(rdev, dev, id);
225962306a36Sopenharmony_ci	regulator_unlock(rdev);
226062306a36Sopenharmony_ci	if (regulator == NULL) {
226162306a36Sopenharmony_ci		regulator = ERR_PTR(-ENOMEM);
226262306a36Sopenharmony_ci		module_put(rdev->owner);
226362306a36Sopenharmony_ci		put_device(&rdev->dev);
226462306a36Sopenharmony_ci		return regulator;
226562306a36Sopenharmony_ci	}
226662306a36Sopenharmony_ci
226762306a36Sopenharmony_ci	rdev->open_count++;
226862306a36Sopenharmony_ci	if (get_type == EXCLUSIVE_GET) {
226962306a36Sopenharmony_ci		rdev->exclusive = 1;
227062306a36Sopenharmony_ci
227162306a36Sopenharmony_ci		ret = _regulator_is_enabled(rdev);
227262306a36Sopenharmony_ci		if (ret > 0) {
227362306a36Sopenharmony_ci			rdev->use_count = 1;
227462306a36Sopenharmony_ci			regulator->enable_count = 1;
227562306a36Sopenharmony_ci		} else {
227662306a36Sopenharmony_ci			rdev->use_count = 0;
227762306a36Sopenharmony_ci			regulator->enable_count = 0;
227862306a36Sopenharmony_ci		}
227962306a36Sopenharmony_ci	}
228062306a36Sopenharmony_ci
228162306a36Sopenharmony_ci	link = device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS);
228262306a36Sopenharmony_ci	if (!IS_ERR_OR_NULL(link))
228362306a36Sopenharmony_ci		regulator->device_link = true;
228462306a36Sopenharmony_ci
228562306a36Sopenharmony_ci	return regulator;
228662306a36Sopenharmony_ci}
228762306a36Sopenharmony_ci
228862306a36Sopenharmony_ci/**
228962306a36Sopenharmony_ci * regulator_get - lookup and obtain a reference to a regulator.
229062306a36Sopenharmony_ci * @dev: device for regulator "consumer"
229162306a36Sopenharmony_ci * @id: Supply name or regulator ID.
229262306a36Sopenharmony_ci *
229362306a36Sopenharmony_ci * Returns a struct regulator corresponding to the regulator producer,
229462306a36Sopenharmony_ci * or IS_ERR() condition containing errno.
229562306a36Sopenharmony_ci *
229662306a36Sopenharmony_ci * Use of supply names configured via set_consumer_device_supply() is
229762306a36Sopenharmony_ci * strongly encouraged.  It is recommended that the supply name used
229862306a36Sopenharmony_ci * should match the name used for the supply and/or the relevant
229962306a36Sopenharmony_ci * device pins in the datasheet.
230062306a36Sopenharmony_ci */
230162306a36Sopenharmony_cistruct regulator *regulator_get(struct device *dev, const char *id)
230262306a36Sopenharmony_ci{
230362306a36Sopenharmony_ci	return _regulator_get(dev, id, NORMAL_GET);
230462306a36Sopenharmony_ci}
230562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get);
230662306a36Sopenharmony_ci
230762306a36Sopenharmony_ci/**
230862306a36Sopenharmony_ci * regulator_get_exclusive - obtain exclusive access to a regulator.
230962306a36Sopenharmony_ci * @dev: device for regulator "consumer"
231062306a36Sopenharmony_ci * @id: Supply name or regulator ID.
231162306a36Sopenharmony_ci *
231262306a36Sopenharmony_ci * Returns a struct regulator corresponding to the regulator producer,
231362306a36Sopenharmony_ci * or IS_ERR() condition containing errno.  Other consumers will be
231462306a36Sopenharmony_ci * unable to obtain this regulator while this reference is held and the
231562306a36Sopenharmony_ci * use count for the regulator will be initialised to reflect the current
231662306a36Sopenharmony_ci * state of the regulator.
231762306a36Sopenharmony_ci *
231862306a36Sopenharmony_ci * This is intended for use by consumers which cannot tolerate shared
231962306a36Sopenharmony_ci * use of the regulator such as those which need to force the
232062306a36Sopenharmony_ci * regulator off for correct operation of the hardware they are
232162306a36Sopenharmony_ci * controlling.
232262306a36Sopenharmony_ci *
232362306a36Sopenharmony_ci * Use of supply names configured via set_consumer_device_supply() is
232462306a36Sopenharmony_ci * strongly encouraged.  It is recommended that the supply name used
232562306a36Sopenharmony_ci * should match the name used for the supply and/or the relevant
232662306a36Sopenharmony_ci * device pins in the datasheet.
232762306a36Sopenharmony_ci */
232862306a36Sopenharmony_cistruct regulator *regulator_get_exclusive(struct device *dev, const char *id)
232962306a36Sopenharmony_ci{
233062306a36Sopenharmony_ci	return _regulator_get(dev, id, EXCLUSIVE_GET);
233162306a36Sopenharmony_ci}
233262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_exclusive);
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_ci/**
233562306a36Sopenharmony_ci * regulator_get_optional - obtain optional access to a regulator.
233662306a36Sopenharmony_ci * @dev: device for regulator "consumer"
233762306a36Sopenharmony_ci * @id: Supply name or regulator ID.
233862306a36Sopenharmony_ci *
233962306a36Sopenharmony_ci * Returns a struct regulator corresponding to the regulator producer,
234062306a36Sopenharmony_ci * or IS_ERR() condition containing errno.
234162306a36Sopenharmony_ci *
234262306a36Sopenharmony_ci * This is intended for use by consumers for devices which can have
234362306a36Sopenharmony_ci * some supplies unconnected in normal use, such as some MMC devices.
234462306a36Sopenharmony_ci * It can allow the regulator core to provide stub supplies for other
234562306a36Sopenharmony_ci * supplies requested using normal regulator_get() calls without
234662306a36Sopenharmony_ci * disrupting the operation of drivers that can handle absent
234762306a36Sopenharmony_ci * supplies.
234862306a36Sopenharmony_ci *
234962306a36Sopenharmony_ci * Use of supply names configured via set_consumer_device_supply() is
235062306a36Sopenharmony_ci * strongly encouraged.  It is recommended that the supply name used
235162306a36Sopenharmony_ci * should match the name used for the supply and/or the relevant
235262306a36Sopenharmony_ci * device pins in the datasheet.
235362306a36Sopenharmony_ci */
235462306a36Sopenharmony_cistruct regulator *regulator_get_optional(struct device *dev, const char *id)
235562306a36Sopenharmony_ci{
235662306a36Sopenharmony_ci	return _regulator_get(dev, id, OPTIONAL_GET);
235762306a36Sopenharmony_ci}
235862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_optional);
235962306a36Sopenharmony_ci
236062306a36Sopenharmony_cistatic void destroy_regulator(struct regulator *regulator)
236162306a36Sopenharmony_ci{
236262306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
236362306a36Sopenharmony_ci
236462306a36Sopenharmony_ci	debugfs_remove_recursive(regulator->debugfs);
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_ci	if (regulator->dev) {
236762306a36Sopenharmony_ci		if (regulator->device_link)
236862306a36Sopenharmony_ci			device_link_remove(regulator->dev, &rdev->dev);
236962306a36Sopenharmony_ci
237062306a36Sopenharmony_ci		/* remove any sysfs entries */
237162306a36Sopenharmony_ci		sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
237262306a36Sopenharmony_ci	}
237362306a36Sopenharmony_ci
237462306a36Sopenharmony_ci	regulator_lock(rdev);
237562306a36Sopenharmony_ci	list_del(&regulator->list);
237662306a36Sopenharmony_ci
237762306a36Sopenharmony_ci	rdev->open_count--;
237862306a36Sopenharmony_ci	rdev->exclusive = 0;
237962306a36Sopenharmony_ci	regulator_unlock(rdev);
238062306a36Sopenharmony_ci
238162306a36Sopenharmony_ci	kfree_const(regulator->supply_name);
238262306a36Sopenharmony_ci	kfree(regulator);
238362306a36Sopenharmony_ci}
238462306a36Sopenharmony_ci
238562306a36Sopenharmony_ci/* regulator_list_mutex lock held by regulator_put() */
238662306a36Sopenharmony_cistatic void _regulator_put(struct regulator *regulator)
238762306a36Sopenharmony_ci{
238862306a36Sopenharmony_ci	struct regulator_dev *rdev;
238962306a36Sopenharmony_ci
239062306a36Sopenharmony_ci	if (IS_ERR_OR_NULL(regulator))
239162306a36Sopenharmony_ci		return;
239262306a36Sopenharmony_ci
239362306a36Sopenharmony_ci	lockdep_assert_held_once(&regulator_list_mutex);
239462306a36Sopenharmony_ci
239562306a36Sopenharmony_ci	/* Docs say you must disable before calling regulator_put() */
239662306a36Sopenharmony_ci	WARN_ON(regulator->enable_count);
239762306a36Sopenharmony_ci
239862306a36Sopenharmony_ci	rdev = regulator->rdev;
239962306a36Sopenharmony_ci
240062306a36Sopenharmony_ci	destroy_regulator(regulator);
240162306a36Sopenharmony_ci
240262306a36Sopenharmony_ci	module_put(rdev->owner);
240362306a36Sopenharmony_ci	put_device(&rdev->dev);
240462306a36Sopenharmony_ci}
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci/**
240762306a36Sopenharmony_ci * regulator_put - "free" the regulator source
240862306a36Sopenharmony_ci * @regulator: regulator source
240962306a36Sopenharmony_ci *
241062306a36Sopenharmony_ci * Note: drivers must ensure that all regulator_enable calls made on this
241162306a36Sopenharmony_ci * regulator source are balanced by regulator_disable calls prior to calling
241262306a36Sopenharmony_ci * this function.
241362306a36Sopenharmony_ci */
241462306a36Sopenharmony_civoid regulator_put(struct regulator *regulator)
241562306a36Sopenharmony_ci{
241662306a36Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
241762306a36Sopenharmony_ci	_regulator_put(regulator);
241862306a36Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
241962306a36Sopenharmony_ci}
242062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_put);
242162306a36Sopenharmony_ci
242262306a36Sopenharmony_ci/**
242362306a36Sopenharmony_ci * regulator_register_supply_alias - Provide device alias for supply lookup
242462306a36Sopenharmony_ci *
242562306a36Sopenharmony_ci * @dev: device that will be given as the regulator "consumer"
242662306a36Sopenharmony_ci * @id: Supply name or regulator ID
242762306a36Sopenharmony_ci * @alias_dev: device that should be used to lookup the supply
242862306a36Sopenharmony_ci * @alias_id: Supply name or regulator ID that should be used to lookup the
242962306a36Sopenharmony_ci * supply
243062306a36Sopenharmony_ci *
243162306a36Sopenharmony_ci * All lookups for id on dev will instead be conducted for alias_id on
243262306a36Sopenharmony_ci * alias_dev.
243362306a36Sopenharmony_ci */
243462306a36Sopenharmony_ciint regulator_register_supply_alias(struct device *dev, const char *id,
243562306a36Sopenharmony_ci				    struct device *alias_dev,
243662306a36Sopenharmony_ci				    const char *alias_id)
243762306a36Sopenharmony_ci{
243862306a36Sopenharmony_ci	struct regulator_supply_alias *map;
243962306a36Sopenharmony_ci
244062306a36Sopenharmony_ci	map = regulator_find_supply_alias(dev, id);
244162306a36Sopenharmony_ci	if (map)
244262306a36Sopenharmony_ci		return -EEXIST;
244362306a36Sopenharmony_ci
244462306a36Sopenharmony_ci	map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL);
244562306a36Sopenharmony_ci	if (!map)
244662306a36Sopenharmony_ci		return -ENOMEM;
244762306a36Sopenharmony_ci
244862306a36Sopenharmony_ci	map->src_dev = dev;
244962306a36Sopenharmony_ci	map->src_supply = id;
245062306a36Sopenharmony_ci	map->alias_dev = alias_dev;
245162306a36Sopenharmony_ci	map->alias_supply = alias_id;
245262306a36Sopenharmony_ci
245362306a36Sopenharmony_ci	list_add(&map->list, &regulator_supply_alias_list);
245462306a36Sopenharmony_ci
245562306a36Sopenharmony_ci	pr_info("Adding alias for supply %s,%s -> %s,%s\n",
245662306a36Sopenharmony_ci		id, dev_name(dev), alias_id, dev_name(alias_dev));
245762306a36Sopenharmony_ci
245862306a36Sopenharmony_ci	return 0;
245962306a36Sopenharmony_ci}
246062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_register_supply_alias);
246162306a36Sopenharmony_ci
246262306a36Sopenharmony_ci/**
246362306a36Sopenharmony_ci * regulator_unregister_supply_alias - Remove device alias
246462306a36Sopenharmony_ci *
246562306a36Sopenharmony_ci * @dev: device that will be given as the regulator "consumer"
246662306a36Sopenharmony_ci * @id: Supply name or regulator ID
246762306a36Sopenharmony_ci *
246862306a36Sopenharmony_ci * Remove a lookup alias if one exists for id on dev.
246962306a36Sopenharmony_ci */
247062306a36Sopenharmony_civoid regulator_unregister_supply_alias(struct device *dev, const char *id)
247162306a36Sopenharmony_ci{
247262306a36Sopenharmony_ci	struct regulator_supply_alias *map;
247362306a36Sopenharmony_ci
247462306a36Sopenharmony_ci	map = regulator_find_supply_alias(dev, id);
247562306a36Sopenharmony_ci	if (map) {
247662306a36Sopenharmony_ci		list_del(&map->list);
247762306a36Sopenharmony_ci		kfree(map);
247862306a36Sopenharmony_ci	}
247962306a36Sopenharmony_ci}
248062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_unregister_supply_alias);
248162306a36Sopenharmony_ci
248262306a36Sopenharmony_ci/**
248362306a36Sopenharmony_ci * regulator_bulk_register_supply_alias - register multiple aliases
248462306a36Sopenharmony_ci *
248562306a36Sopenharmony_ci * @dev: device that will be given as the regulator "consumer"
248662306a36Sopenharmony_ci * @id: List of supply names or regulator IDs
248762306a36Sopenharmony_ci * @alias_dev: device that should be used to lookup the supply
248862306a36Sopenharmony_ci * @alias_id: List of supply names or regulator IDs that should be used to
248962306a36Sopenharmony_ci * lookup the supply
249062306a36Sopenharmony_ci * @num_id: Number of aliases to register
249162306a36Sopenharmony_ci *
249262306a36Sopenharmony_ci * @return 0 on success, an errno on failure.
249362306a36Sopenharmony_ci *
249462306a36Sopenharmony_ci * This helper function allows drivers to register several supply
249562306a36Sopenharmony_ci * aliases in one operation.  If any of the aliases cannot be
249662306a36Sopenharmony_ci * registered any aliases that were registered will be removed
249762306a36Sopenharmony_ci * before returning to the caller.
249862306a36Sopenharmony_ci */
249962306a36Sopenharmony_ciint regulator_bulk_register_supply_alias(struct device *dev,
250062306a36Sopenharmony_ci					 const char *const *id,
250162306a36Sopenharmony_ci					 struct device *alias_dev,
250262306a36Sopenharmony_ci					 const char *const *alias_id,
250362306a36Sopenharmony_ci					 int num_id)
250462306a36Sopenharmony_ci{
250562306a36Sopenharmony_ci	int i;
250662306a36Sopenharmony_ci	int ret;
250762306a36Sopenharmony_ci
250862306a36Sopenharmony_ci	for (i = 0; i < num_id; ++i) {
250962306a36Sopenharmony_ci		ret = regulator_register_supply_alias(dev, id[i], alias_dev,
251062306a36Sopenharmony_ci						      alias_id[i]);
251162306a36Sopenharmony_ci		if (ret < 0)
251262306a36Sopenharmony_ci			goto err;
251362306a36Sopenharmony_ci	}
251462306a36Sopenharmony_ci
251562306a36Sopenharmony_ci	return 0;
251662306a36Sopenharmony_ci
251762306a36Sopenharmony_cierr:
251862306a36Sopenharmony_ci	dev_err(dev,
251962306a36Sopenharmony_ci		"Failed to create supply alias %s,%s -> %s,%s\n",
252062306a36Sopenharmony_ci		id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
252162306a36Sopenharmony_ci
252262306a36Sopenharmony_ci	while (--i >= 0)
252362306a36Sopenharmony_ci		regulator_unregister_supply_alias(dev, id[i]);
252462306a36Sopenharmony_ci
252562306a36Sopenharmony_ci	return ret;
252662306a36Sopenharmony_ci}
252762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias);
252862306a36Sopenharmony_ci
252962306a36Sopenharmony_ci/**
253062306a36Sopenharmony_ci * regulator_bulk_unregister_supply_alias - unregister multiple aliases
253162306a36Sopenharmony_ci *
253262306a36Sopenharmony_ci * @dev: device that will be given as the regulator "consumer"
253362306a36Sopenharmony_ci * @id: List of supply names or regulator IDs
253462306a36Sopenharmony_ci * @num_id: Number of aliases to unregister
253562306a36Sopenharmony_ci *
253662306a36Sopenharmony_ci * This helper function allows drivers to unregister several supply
253762306a36Sopenharmony_ci * aliases in one operation.
253862306a36Sopenharmony_ci */
253962306a36Sopenharmony_civoid regulator_bulk_unregister_supply_alias(struct device *dev,
254062306a36Sopenharmony_ci					    const char *const *id,
254162306a36Sopenharmony_ci					    int num_id)
254262306a36Sopenharmony_ci{
254362306a36Sopenharmony_ci	int i;
254462306a36Sopenharmony_ci
254562306a36Sopenharmony_ci	for (i = 0; i < num_id; ++i)
254662306a36Sopenharmony_ci		regulator_unregister_supply_alias(dev, id[i]);
254762306a36Sopenharmony_ci}
254862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias);
254962306a36Sopenharmony_ci
255062306a36Sopenharmony_ci
255162306a36Sopenharmony_ci/* Manage enable GPIO list. Same GPIO pin can be shared among regulators */
255262306a36Sopenharmony_cistatic int regulator_ena_gpio_request(struct regulator_dev *rdev,
255362306a36Sopenharmony_ci				const struct regulator_config *config)
255462306a36Sopenharmony_ci{
255562306a36Sopenharmony_ci	struct regulator_enable_gpio *pin, *new_pin;
255662306a36Sopenharmony_ci	struct gpio_desc *gpiod;
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci	gpiod = config->ena_gpiod;
255962306a36Sopenharmony_ci	new_pin = kzalloc(sizeof(*new_pin), GFP_KERNEL);
256062306a36Sopenharmony_ci
256162306a36Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
256262306a36Sopenharmony_ci
256362306a36Sopenharmony_ci	list_for_each_entry(pin, &regulator_ena_gpio_list, list) {
256462306a36Sopenharmony_ci		if (pin->gpiod == gpiod) {
256562306a36Sopenharmony_ci			rdev_dbg(rdev, "GPIO is already used\n");
256662306a36Sopenharmony_ci			goto update_ena_gpio_to_rdev;
256762306a36Sopenharmony_ci		}
256862306a36Sopenharmony_ci	}
256962306a36Sopenharmony_ci
257062306a36Sopenharmony_ci	if (new_pin == NULL) {
257162306a36Sopenharmony_ci		mutex_unlock(&regulator_list_mutex);
257262306a36Sopenharmony_ci		return -ENOMEM;
257362306a36Sopenharmony_ci	}
257462306a36Sopenharmony_ci
257562306a36Sopenharmony_ci	pin = new_pin;
257662306a36Sopenharmony_ci	new_pin = NULL;
257762306a36Sopenharmony_ci
257862306a36Sopenharmony_ci	pin->gpiod = gpiod;
257962306a36Sopenharmony_ci	list_add(&pin->list, &regulator_ena_gpio_list);
258062306a36Sopenharmony_ci
258162306a36Sopenharmony_ciupdate_ena_gpio_to_rdev:
258262306a36Sopenharmony_ci	pin->request_count++;
258362306a36Sopenharmony_ci	rdev->ena_pin = pin;
258462306a36Sopenharmony_ci
258562306a36Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
258662306a36Sopenharmony_ci	kfree(new_pin);
258762306a36Sopenharmony_ci
258862306a36Sopenharmony_ci	return 0;
258962306a36Sopenharmony_ci}
259062306a36Sopenharmony_ci
259162306a36Sopenharmony_cistatic void regulator_ena_gpio_free(struct regulator_dev *rdev)
259262306a36Sopenharmony_ci{
259362306a36Sopenharmony_ci	struct regulator_enable_gpio *pin, *n;
259462306a36Sopenharmony_ci
259562306a36Sopenharmony_ci	if (!rdev->ena_pin)
259662306a36Sopenharmony_ci		return;
259762306a36Sopenharmony_ci
259862306a36Sopenharmony_ci	/* Free the GPIO only in case of no use */
259962306a36Sopenharmony_ci	list_for_each_entry_safe(pin, n, &regulator_ena_gpio_list, list) {
260062306a36Sopenharmony_ci		if (pin != rdev->ena_pin)
260162306a36Sopenharmony_ci			continue;
260262306a36Sopenharmony_ci
260362306a36Sopenharmony_ci		if (--pin->request_count)
260462306a36Sopenharmony_ci			break;
260562306a36Sopenharmony_ci
260662306a36Sopenharmony_ci		gpiod_put(pin->gpiod);
260762306a36Sopenharmony_ci		list_del(&pin->list);
260862306a36Sopenharmony_ci		kfree(pin);
260962306a36Sopenharmony_ci		break;
261062306a36Sopenharmony_ci	}
261162306a36Sopenharmony_ci
261262306a36Sopenharmony_ci	rdev->ena_pin = NULL;
261362306a36Sopenharmony_ci}
261462306a36Sopenharmony_ci
261562306a36Sopenharmony_ci/**
261662306a36Sopenharmony_ci * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control
261762306a36Sopenharmony_ci * @rdev: regulator_dev structure
261862306a36Sopenharmony_ci * @enable: enable GPIO at initial use?
261962306a36Sopenharmony_ci *
262062306a36Sopenharmony_ci * GPIO is enabled in case of initial use. (enable_count is 0)
262162306a36Sopenharmony_ci * GPIO is disabled when it is not shared any more. (enable_count <= 1)
262262306a36Sopenharmony_ci */
262362306a36Sopenharmony_cistatic int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
262462306a36Sopenharmony_ci{
262562306a36Sopenharmony_ci	struct regulator_enable_gpio *pin = rdev->ena_pin;
262662306a36Sopenharmony_ci
262762306a36Sopenharmony_ci	if (!pin)
262862306a36Sopenharmony_ci		return -EINVAL;
262962306a36Sopenharmony_ci
263062306a36Sopenharmony_ci	if (enable) {
263162306a36Sopenharmony_ci		/* Enable GPIO at initial use */
263262306a36Sopenharmony_ci		if (pin->enable_count == 0)
263362306a36Sopenharmony_ci			gpiod_set_value_cansleep(pin->gpiod, 1);
263462306a36Sopenharmony_ci
263562306a36Sopenharmony_ci		pin->enable_count++;
263662306a36Sopenharmony_ci	} else {
263762306a36Sopenharmony_ci		if (pin->enable_count > 1) {
263862306a36Sopenharmony_ci			pin->enable_count--;
263962306a36Sopenharmony_ci			return 0;
264062306a36Sopenharmony_ci		}
264162306a36Sopenharmony_ci
264262306a36Sopenharmony_ci		/* Disable GPIO if not used */
264362306a36Sopenharmony_ci		if (pin->enable_count <= 1) {
264462306a36Sopenharmony_ci			gpiod_set_value_cansleep(pin->gpiod, 0);
264562306a36Sopenharmony_ci			pin->enable_count = 0;
264662306a36Sopenharmony_ci		}
264762306a36Sopenharmony_ci	}
264862306a36Sopenharmony_ci
264962306a36Sopenharmony_ci	return 0;
265062306a36Sopenharmony_ci}
265162306a36Sopenharmony_ci
265262306a36Sopenharmony_ci/**
265362306a36Sopenharmony_ci * _regulator_delay_helper - a delay helper function
265462306a36Sopenharmony_ci * @delay: time to delay in microseconds
265562306a36Sopenharmony_ci *
265662306a36Sopenharmony_ci * Delay for the requested amount of time as per the guidelines in:
265762306a36Sopenharmony_ci *
265862306a36Sopenharmony_ci *     Documentation/timers/timers-howto.rst
265962306a36Sopenharmony_ci *
266062306a36Sopenharmony_ci * The assumption here is that these regulator operations will never used in
266162306a36Sopenharmony_ci * atomic context and therefore sleeping functions can be used.
266262306a36Sopenharmony_ci */
266362306a36Sopenharmony_cistatic void _regulator_delay_helper(unsigned int delay)
266462306a36Sopenharmony_ci{
266562306a36Sopenharmony_ci	unsigned int ms = delay / 1000;
266662306a36Sopenharmony_ci	unsigned int us = delay % 1000;
266762306a36Sopenharmony_ci
266862306a36Sopenharmony_ci	if (ms > 0) {
266962306a36Sopenharmony_ci		/*
267062306a36Sopenharmony_ci		 * For small enough values, handle super-millisecond
267162306a36Sopenharmony_ci		 * delays in the usleep_range() call below.
267262306a36Sopenharmony_ci		 */
267362306a36Sopenharmony_ci		if (ms < 20)
267462306a36Sopenharmony_ci			us += ms * 1000;
267562306a36Sopenharmony_ci		else
267662306a36Sopenharmony_ci			msleep(ms);
267762306a36Sopenharmony_ci	}
267862306a36Sopenharmony_ci
267962306a36Sopenharmony_ci	/*
268062306a36Sopenharmony_ci	 * Give the scheduler some room to coalesce with any other
268162306a36Sopenharmony_ci	 * wakeup sources. For delays shorter than 10 us, don't even
268262306a36Sopenharmony_ci	 * bother setting up high-resolution timers and just busy-
268362306a36Sopenharmony_ci	 * loop.
268462306a36Sopenharmony_ci	 */
268562306a36Sopenharmony_ci	if (us >= 10)
268662306a36Sopenharmony_ci		usleep_range(us, us + 100);
268762306a36Sopenharmony_ci	else
268862306a36Sopenharmony_ci		udelay(us);
268962306a36Sopenharmony_ci}
269062306a36Sopenharmony_ci
269162306a36Sopenharmony_ci/**
269262306a36Sopenharmony_ci * _regulator_check_status_enabled
269362306a36Sopenharmony_ci *
269462306a36Sopenharmony_ci * A helper function to check if the regulator status can be interpreted
269562306a36Sopenharmony_ci * as 'regulator is enabled'.
269662306a36Sopenharmony_ci * @rdev: the regulator device to check
269762306a36Sopenharmony_ci *
269862306a36Sopenharmony_ci * Return:
269962306a36Sopenharmony_ci * * 1			- if status shows regulator is in enabled state
270062306a36Sopenharmony_ci * * 0			- if not enabled state
270162306a36Sopenharmony_ci * * Error Value	- as received from ops->get_status()
270262306a36Sopenharmony_ci */
270362306a36Sopenharmony_cistatic inline int _regulator_check_status_enabled(struct regulator_dev *rdev)
270462306a36Sopenharmony_ci{
270562306a36Sopenharmony_ci	int ret = rdev->desc->ops->get_status(rdev);
270662306a36Sopenharmony_ci
270762306a36Sopenharmony_ci	if (ret < 0) {
270862306a36Sopenharmony_ci		rdev_info(rdev, "get_status returned error: %d\n", ret);
270962306a36Sopenharmony_ci		return ret;
271062306a36Sopenharmony_ci	}
271162306a36Sopenharmony_ci
271262306a36Sopenharmony_ci	switch (ret) {
271362306a36Sopenharmony_ci	case REGULATOR_STATUS_OFF:
271462306a36Sopenharmony_ci	case REGULATOR_STATUS_ERROR:
271562306a36Sopenharmony_ci	case REGULATOR_STATUS_UNDEFINED:
271662306a36Sopenharmony_ci		return 0;
271762306a36Sopenharmony_ci	default:
271862306a36Sopenharmony_ci		return 1;
271962306a36Sopenharmony_ci	}
272062306a36Sopenharmony_ci}
272162306a36Sopenharmony_ci
272262306a36Sopenharmony_cistatic int _regulator_do_enable(struct regulator_dev *rdev)
272362306a36Sopenharmony_ci{
272462306a36Sopenharmony_ci	int ret, delay;
272562306a36Sopenharmony_ci
272662306a36Sopenharmony_ci	/* Query before enabling in case configuration dependent.  */
272762306a36Sopenharmony_ci	ret = _regulator_get_enable_time(rdev);
272862306a36Sopenharmony_ci	if (ret >= 0) {
272962306a36Sopenharmony_ci		delay = ret;
273062306a36Sopenharmony_ci	} else {
273162306a36Sopenharmony_ci		rdev_warn(rdev, "enable_time() failed: %pe\n", ERR_PTR(ret));
273262306a36Sopenharmony_ci		delay = 0;
273362306a36Sopenharmony_ci	}
273462306a36Sopenharmony_ci
273562306a36Sopenharmony_ci	trace_regulator_enable(rdev_get_name(rdev));
273662306a36Sopenharmony_ci
273762306a36Sopenharmony_ci	if (rdev->desc->off_on_delay) {
273862306a36Sopenharmony_ci		/* if needed, keep a distance of off_on_delay from last time
273962306a36Sopenharmony_ci		 * this regulator was disabled.
274062306a36Sopenharmony_ci		 */
274162306a36Sopenharmony_ci		ktime_t end = ktime_add_us(rdev->last_off, rdev->desc->off_on_delay);
274262306a36Sopenharmony_ci		s64 remaining = ktime_us_delta(end, ktime_get_boottime());
274362306a36Sopenharmony_ci
274462306a36Sopenharmony_ci		if (remaining > 0)
274562306a36Sopenharmony_ci			_regulator_delay_helper(remaining);
274662306a36Sopenharmony_ci	}
274762306a36Sopenharmony_ci
274862306a36Sopenharmony_ci	if (rdev->ena_pin) {
274962306a36Sopenharmony_ci		if (!rdev->ena_gpio_state) {
275062306a36Sopenharmony_ci			ret = regulator_ena_gpio_ctrl(rdev, true);
275162306a36Sopenharmony_ci			if (ret < 0)
275262306a36Sopenharmony_ci				return ret;
275362306a36Sopenharmony_ci			rdev->ena_gpio_state = 1;
275462306a36Sopenharmony_ci		}
275562306a36Sopenharmony_ci	} else if (rdev->desc->ops->enable) {
275662306a36Sopenharmony_ci		ret = rdev->desc->ops->enable(rdev);
275762306a36Sopenharmony_ci		if (ret < 0)
275862306a36Sopenharmony_ci			return ret;
275962306a36Sopenharmony_ci	} else {
276062306a36Sopenharmony_ci		return -EINVAL;
276162306a36Sopenharmony_ci	}
276262306a36Sopenharmony_ci
276362306a36Sopenharmony_ci	/* Allow the regulator to ramp; it would be useful to extend
276462306a36Sopenharmony_ci	 * this for bulk operations so that the regulators can ramp
276562306a36Sopenharmony_ci	 * together.
276662306a36Sopenharmony_ci	 */
276762306a36Sopenharmony_ci	trace_regulator_enable_delay(rdev_get_name(rdev));
276862306a36Sopenharmony_ci
276962306a36Sopenharmony_ci	/* If poll_enabled_time is set, poll upto the delay calculated
277062306a36Sopenharmony_ci	 * above, delaying poll_enabled_time uS to check if the regulator
277162306a36Sopenharmony_ci	 * actually got enabled.
277262306a36Sopenharmony_ci	 * If the regulator isn't enabled after our delay helper has expired,
277362306a36Sopenharmony_ci	 * return -ETIMEDOUT.
277462306a36Sopenharmony_ci	 */
277562306a36Sopenharmony_ci	if (rdev->desc->poll_enabled_time) {
277662306a36Sopenharmony_ci		int time_remaining = delay;
277762306a36Sopenharmony_ci
277862306a36Sopenharmony_ci		while (time_remaining > 0) {
277962306a36Sopenharmony_ci			_regulator_delay_helper(rdev->desc->poll_enabled_time);
278062306a36Sopenharmony_ci
278162306a36Sopenharmony_ci			if (rdev->desc->ops->get_status) {
278262306a36Sopenharmony_ci				ret = _regulator_check_status_enabled(rdev);
278362306a36Sopenharmony_ci				if (ret < 0)
278462306a36Sopenharmony_ci					return ret;
278562306a36Sopenharmony_ci				else if (ret)
278662306a36Sopenharmony_ci					break;
278762306a36Sopenharmony_ci			} else if (rdev->desc->ops->is_enabled(rdev))
278862306a36Sopenharmony_ci				break;
278962306a36Sopenharmony_ci
279062306a36Sopenharmony_ci			time_remaining -= rdev->desc->poll_enabled_time;
279162306a36Sopenharmony_ci		}
279262306a36Sopenharmony_ci
279362306a36Sopenharmony_ci		if (time_remaining <= 0) {
279462306a36Sopenharmony_ci			rdev_err(rdev, "Enabled check timed out\n");
279562306a36Sopenharmony_ci			return -ETIMEDOUT;
279662306a36Sopenharmony_ci		}
279762306a36Sopenharmony_ci	} else {
279862306a36Sopenharmony_ci		_regulator_delay_helper(delay);
279962306a36Sopenharmony_ci	}
280062306a36Sopenharmony_ci
280162306a36Sopenharmony_ci	trace_regulator_enable_complete(rdev_get_name(rdev));
280262306a36Sopenharmony_ci
280362306a36Sopenharmony_ci	return 0;
280462306a36Sopenharmony_ci}
280562306a36Sopenharmony_ci
280662306a36Sopenharmony_ci/**
280762306a36Sopenharmony_ci * _regulator_handle_consumer_enable - handle that a consumer enabled
280862306a36Sopenharmony_ci * @regulator: regulator source
280962306a36Sopenharmony_ci *
281062306a36Sopenharmony_ci * Some things on a regulator consumer (like the contribution towards total
281162306a36Sopenharmony_ci * load on the regulator) only have an effect when the consumer wants the
281262306a36Sopenharmony_ci * regulator enabled.  Explained in example with two consumers of the same
281362306a36Sopenharmony_ci * regulator:
281462306a36Sopenharmony_ci *   consumer A: set_load(100);       => total load = 0
281562306a36Sopenharmony_ci *   consumer A: regulator_enable();  => total load = 100
281662306a36Sopenharmony_ci *   consumer B: set_load(1000);      => total load = 100
281762306a36Sopenharmony_ci *   consumer B: regulator_enable();  => total load = 1100
281862306a36Sopenharmony_ci *   consumer A: regulator_disable(); => total_load = 1000
281962306a36Sopenharmony_ci *
282062306a36Sopenharmony_ci * This function (together with _regulator_handle_consumer_disable) is
282162306a36Sopenharmony_ci * responsible for keeping track of the refcount for a given regulator consumer
282262306a36Sopenharmony_ci * and applying / unapplying these things.
282362306a36Sopenharmony_ci *
282462306a36Sopenharmony_ci * Returns 0 upon no error; -error upon error.
282562306a36Sopenharmony_ci */
282662306a36Sopenharmony_cistatic int _regulator_handle_consumer_enable(struct regulator *regulator)
282762306a36Sopenharmony_ci{
282862306a36Sopenharmony_ci	int ret;
282962306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
283062306a36Sopenharmony_ci
283162306a36Sopenharmony_ci	lockdep_assert_held_once(&rdev->mutex.base);
283262306a36Sopenharmony_ci
283362306a36Sopenharmony_ci	regulator->enable_count++;
283462306a36Sopenharmony_ci	if (regulator->uA_load && regulator->enable_count == 1) {
283562306a36Sopenharmony_ci		ret = drms_uA_update(rdev);
283662306a36Sopenharmony_ci		if (ret)
283762306a36Sopenharmony_ci			regulator->enable_count--;
283862306a36Sopenharmony_ci		return ret;
283962306a36Sopenharmony_ci	}
284062306a36Sopenharmony_ci
284162306a36Sopenharmony_ci	return 0;
284262306a36Sopenharmony_ci}
284362306a36Sopenharmony_ci
284462306a36Sopenharmony_ci/**
284562306a36Sopenharmony_ci * _regulator_handle_consumer_disable - handle that a consumer disabled
284662306a36Sopenharmony_ci * @regulator: regulator source
284762306a36Sopenharmony_ci *
284862306a36Sopenharmony_ci * The opposite of _regulator_handle_consumer_enable().
284962306a36Sopenharmony_ci *
285062306a36Sopenharmony_ci * Returns 0 upon no error; -error upon error.
285162306a36Sopenharmony_ci */
285262306a36Sopenharmony_cistatic int _regulator_handle_consumer_disable(struct regulator *regulator)
285362306a36Sopenharmony_ci{
285462306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
285562306a36Sopenharmony_ci
285662306a36Sopenharmony_ci	lockdep_assert_held_once(&rdev->mutex.base);
285762306a36Sopenharmony_ci
285862306a36Sopenharmony_ci	if (!regulator->enable_count) {
285962306a36Sopenharmony_ci		rdev_err(rdev, "Underflow of regulator enable count\n");
286062306a36Sopenharmony_ci		return -EINVAL;
286162306a36Sopenharmony_ci	}
286262306a36Sopenharmony_ci
286362306a36Sopenharmony_ci	regulator->enable_count--;
286462306a36Sopenharmony_ci	if (regulator->uA_load && regulator->enable_count == 0)
286562306a36Sopenharmony_ci		return drms_uA_update(rdev);
286662306a36Sopenharmony_ci
286762306a36Sopenharmony_ci	return 0;
286862306a36Sopenharmony_ci}
286962306a36Sopenharmony_ci
287062306a36Sopenharmony_ci/* locks held by regulator_enable() */
287162306a36Sopenharmony_cistatic int _regulator_enable(struct regulator *regulator)
287262306a36Sopenharmony_ci{
287362306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
287462306a36Sopenharmony_ci	int ret;
287562306a36Sopenharmony_ci
287662306a36Sopenharmony_ci	lockdep_assert_held_once(&rdev->mutex.base);
287762306a36Sopenharmony_ci
287862306a36Sopenharmony_ci	if (rdev->use_count == 0 && rdev->supply) {
287962306a36Sopenharmony_ci		ret = _regulator_enable(rdev->supply);
288062306a36Sopenharmony_ci		if (ret < 0)
288162306a36Sopenharmony_ci			return ret;
288262306a36Sopenharmony_ci	}
288362306a36Sopenharmony_ci
288462306a36Sopenharmony_ci	/* balance only if there are regulators coupled */
288562306a36Sopenharmony_ci	if (rdev->coupling_desc.n_coupled > 1) {
288662306a36Sopenharmony_ci		ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
288762306a36Sopenharmony_ci		if (ret < 0)
288862306a36Sopenharmony_ci			goto err_disable_supply;
288962306a36Sopenharmony_ci	}
289062306a36Sopenharmony_ci
289162306a36Sopenharmony_ci	ret = _regulator_handle_consumer_enable(regulator);
289262306a36Sopenharmony_ci	if (ret < 0)
289362306a36Sopenharmony_ci		goto err_disable_supply;
289462306a36Sopenharmony_ci
289562306a36Sopenharmony_ci	if (rdev->use_count == 0) {
289662306a36Sopenharmony_ci		/*
289762306a36Sopenharmony_ci		 * The regulator may already be enabled if it's not switchable
289862306a36Sopenharmony_ci		 * or was left on
289962306a36Sopenharmony_ci		 */
290062306a36Sopenharmony_ci		ret = _regulator_is_enabled(rdev);
290162306a36Sopenharmony_ci		if (ret == -EINVAL || ret == 0) {
290262306a36Sopenharmony_ci			if (!regulator_ops_is_valid(rdev,
290362306a36Sopenharmony_ci					REGULATOR_CHANGE_STATUS)) {
290462306a36Sopenharmony_ci				ret = -EPERM;
290562306a36Sopenharmony_ci				goto err_consumer_disable;
290662306a36Sopenharmony_ci			}
290762306a36Sopenharmony_ci
290862306a36Sopenharmony_ci			ret = _regulator_do_enable(rdev);
290962306a36Sopenharmony_ci			if (ret < 0)
291062306a36Sopenharmony_ci				goto err_consumer_disable;
291162306a36Sopenharmony_ci
291262306a36Sopenharmony_ci			_notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE,
291362306a36Sopenharmony_ci					     NULL);
291462306a36Sopenharmony_ci		} else if (ret < 0) {
291562306a36Sopenharmony_ci			rdev_err(rdev, "is_enabled() failed: %pe\n", ERR_PTR(ret));
291662306a36Sopenharmony_ci			goto err_consumer_disable;
291762306a36Sopenharmony_ci		}
291862306a36Sopenharmony_ci		/* Fallthrough on positive return values - already enabled */
291962306a36Sopenharmony_ci	}
292062306a36Sopenharmony_ci
292162306a36Sopenharmony_ci	if (regulator->enable_count == 1)
292262306a36Sopenharmony_ci		rdev->use_count++;
292362306a36Sopenharmony_ci
292462306a36Sopenharmony_ci	return 0;
292562306a36Sopenharmony_ci
292662306a36Sopenharmony_cierr_consumer_disable:
292762306a36Sopenharmony_ci	_regulator_handle_consumer_disable(regulator);
292862306a36Sopenharmony_ci
292962306a36Sopenharmony_cierr_disable_supply:
293062306a36Sopenharmony_ci	if (rdev->use_count == 0 && rdev->supply)
293162306a36Sopenharmony_ci		_regulator_disable(rdev->supply);
293262306a36Sopenharmony_ci
293362306a36Sopenharmony_ci	return ret;
293462306a36Sopenharmony_ci}
293562306a36Sopenharmony_ci
293662306a36Sopenharmony_ci/**
293762306a36Sopenharmony_ci * regulator_enable - enable regulator output
293862306a36Sopenharmony_ci * @regulator: regulator source
293962306a36Sopenharmony_ci *
294062306a36Sopenharmony_ci * Request that the regulator be enabled with the regulator output at
294162306a36Sopenharmony_ci * the predefined voltage or current value.  Calls to regulator_enable()
294262306a36Sopenharmony_ci * must be balanced with calls to regulator_disable().
294362306a36Sopenharmony_ci *
294462306a36Sopenharmony_ci * NOTE: the output value can be set by other drivers, boot loader or may be
294562306a36Sopenharmony_ci * hardwired in the regulator.
294662306a36Sopenharmony_ci */
294762306a36Sopenharmony_ciint regulator_enable(struct regulator *regulator)
294862306a36Sopenharmony_ci{
294962306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
295062306a36Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
295162306a36Sopenharmony_ci	int ret;
295262306a36Sopenharmony_ci
295362306a36Sopenharmony_ci	regulator_lock_dependent(rdev, &ww_ctx);
295462306a36Sopenharmony_ci	ret = _regulator_enable(regulator);
295562306a36Sopenharmony_ci	regulator_unlock_dependent(rdev, &ww_ctx);
295662306a36Sopenharmony_ci
295762306a36Sopenharmony_ci	return ret;
295862306a36Sopenharmony_ci}
295962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_enable);
296062306a36Sopenharmony_ci
296162306a36Sopenharmony_cistatic int _regulator_do_disable(struct regulator_dev *rdev)
296262306a36Sopenharmony_ci{
296362306a36Sopenharmony_ci	int ret;
296462306a36Sopenharmony_ci
296562306a36Sopenharmony_ci	trace_regulator_disable(rdev_get_name(rdev));
296662306a36Sopenharmony_ci
296762306a36Sopenharmony_ci	if (rdev->ena_pin) {
296862306a36Sopenharmony_ci		if (rdev->ena_gpio_state) {
296962306a36Sopenharmony_ci			ret = regulator_ena_gpio_ctrl(rdev, false);
297062306a36Sopenharmony_ci			if (ret < 0)
297162306a36Sopenharmony_ci				return ret;
297262306a36Sopenharmony_ci			rdev->ena_gpio_state = 0;
297362306a36Sopenharmony_ci		}
297462306a36Sopenharmony_ci
297562306a36Sopenharmony_ci	} else if (rdev->desc->ops->disable) {
297662306a36Sopenharmony_ci		ret = rdev->desc->ops->disable(rdev);
297762306a36Sopenharmony_ci		if (ret != 0)
297862306a36Sopenharmony_ci			return ret;
297962306a36Sopenharmony_ci	}
298062306a36Sopenharmony_ci
298162306a36Sopenharmony_ci	if (rdev->desc->off_on_delay)
298262306a36Sopenharmony_ci		rdev->last_off = ktime_get_boottime();
298362306a36Sopenharmony_ci
298462306a36Sopenharmony_ci	trace_regulator_disable_complete(rdev_get_name(rdev));
298562306a36Sopenharmony_ci
298662306a36Sopenharmony_ci	return 0;
298762306a36Sopenharmony_ci}
298862306a36Sopenharmony_ci
298962306a36Sopenharmony_ci/* locks held by regulator_disable() */
299062306a36Sopenharmony_cistatic int _regulator_disable(struct regulator *regulator)
299162306a36Sopenharmony_ci{
299262306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
299362306a36Sopenharmony_ci	int ret = 0;
299462306a36Sopenharmony_ci
299562306a36Sopenharmony_ci	lockdep_assert_held_once(&rdev->mutex.base);
299662306a36Sopenharmony_ci
299762306a36Sopenharmony_ci	if (WARN(regulator->enable_count == 0,
299862306a36Sopenharmony_ci		 "unbalanced disables for %s\n", rdev_get_name(rdev)))
299962306a36Sopenharmony_ci		return -EIO;
300062306a36Sopenharmony_ci
300162306a36Sopenharmony_ci	if (regulator->enable_count == 1) {
300262306a36Sopenharmony_ci	/* disabling last enable_count from this regulator */
300362306a36Sopenharmony_ci		/* are we the last user and permitted to disable ? */
300462306a36Sopenharmony_ci		if (rdev->use_count == 1 &&
300562306a36Sopenharmony_ci		    (rdev->constraints && !rdev->constraints->always_on)) {
300662306a36Sopenharmony_ci
300762306a36Sopenharmony_ci			/* we are last user */
300862306a36Sopenharmony_ci			if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) {
300962306a36Sopenharmony_ci				ret = _notifier_call_chain(rdev,
301062306a36Sopenharmony_ci							   REGULATOR_EVENT_PRE_DISABLE,
301162306a36Sopenharmony_ci							   NULL);
301262306a36Sopenharmony_ci				if (ret & NOTIFY_STOP_MASK)
301362306a36Sopenharmony_ci					return -EINVAL;
301462306a36Sopenharmony_ci
301562306a36Sopenharmony_ci				ret = _regulator_do_disable(rdev);
301662306a36Sopenharmony_ci				if (ret < 0) {
301762306a36Sopenharmony_ci					rdev_err(rdev, "failed to disable: %pe\n", ERR_PTR(ret));
301862306a36Sopenharmony_ci					_notifier_call_chain(rdev,
301962306a36Sopenharmony_ci							REGULATOR_EVENT_ABORT_DISABLE,
302062306a36Sopenharmony_ci							NULL);
302162306a36Sopenharmony_ci					return ret;
302262306a36Sopenharmony_ci				}
302362306a36Sopenharmony_ci				_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
302462306a36Sopenharmony_ci						NULL);
302562306a36Sopenharmony_ci			}
302662306a36Sopenharmony_ci
302762306a36Sopenharmony_ci			rdev->use_count = 0;
302862306a36Sopenharmony_ci		} else if (rdev->use_count > 1) {
302962306a36Sopenharmony_ci			rdev->use_count--;
303062306a36Sopenharmony_ci		}
303162306a36Sopenharmony_ci	}
303262306a36Sopenharmony_ci
303362306a36Sopenharmony_ci	if (ret == 0)
303462306a36Sopenharmony_ci		ret = _regulator_handle_consumer_disable(regulator);
303562306a36Sopenharmony_ci
303662306a36Sopenharmony_ci	if (ret == 0 && rdev->coupling_desc.n_coupled > 1)
303762306a36Sopenharmony_ci		ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
303862306a36Sopenharmony_ci
303962306a36Sopenharmony_ci	if (ret == 0 && rdev->use_count == 0 && rdev->supply)
304062306a36Sopenharmony_ci		ret = _regulator_disable(rdev->supply);
304162306a36Sopenharmony_ci
304262306a36Sopenharmony_ci	return ret;
304362306a36Sopenharmony_ci}
304462306a36Sopenharmony_ci
304562306a36Sopenharmony_ci/**
304662306a36Sopenharmony_ci * regulator_disable - disable regulator output
304762306a36Sopenharmony_ci * @regulator: regulator source
304862306a36Sopenharmony_ci *
304962306a36Sopenharmony_ci * Disable the regulator output voltage or current.  Calls to
305062306a36Sopenharmony_ci * regulator_enable() must be balanced with calls to
305162306a36Sopenharmony_ci * regulator_disable().
305262306a36Sopenharmony_ci *
305362306a36Sopenharmony_ci * NOTE: this will only disable the regulator output if no other consumer
305462306a36Sopenharmony_ci * devices have it enabled, the regulator device supports disabling and
305562306a36Sopenharmony_ci * machine constraints permit this operation.
305662306a36Sopenharmony_ci */
305762306a36Sopenharmony_ciint regulator_disable(struct regulator *regulator)
305862306a36Sopenharmony_ci{
305962306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
306062306a36Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
306162306a36Sopenharmony_ci	int ret;
306262306a36Sopenharmony_ci
306362306a36Sopenharmony_ci	regulator_lock_dependent(rdev, &ww_ctx);
306462306a36Sopenharmony_ci	ret = _regulator_disable(regulator);
306562306a36Sopenharmony_ci	regulator_unlock_dependent(rdev, &ww_ctx);
306662306a36Sopenharmony_ci
306762306a36Sopenharmony_ci	return ret;
306862306a36Sopenharmony_ci}
306962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_disable);
307062306a36Sopenharmony_ci
307162306a36Sopenharmony_ci/* locks held by regulator_force_disable() */
307262306a36Sopenharmony_cistatic int _regulator_force_disable(struct regulator_dev *rdev)
307362306a36Sopenharmony_ci{
307462306a36Sopenharmony_ci	int ret = 0;
307562306a36Sopenharmony_ci
307662306a36Sopenharmony_ci	lockdep_assert_held_once(&rdev->mutex.base);
307762306a36Sopenharmony_ci
307862306a36Sopenharmony_ci	ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
307962306a36Sopenharmony_ci			REGULATOR_EVENT_PRE_DISABLE, NULL);
308062306a36Sopenharmony_ci	if (ret & NOTIFY_STOP_MASK)
308162306a36Sopenharmony_ci		return -EINVAL;
308262306a36Sopenharmony_ci
308362306a36Sopenharmony_ci	ret = _regulator_do_disable(rdev);
308462306a36Sopenharmony_ci	if (ret < 0) {
308562306a36Sopenharmony_ci		rdev_err(rdev, "failed to force disable: %pe\n", ERR_PTR(ret));
308662306a36Sopenharmony_ci		_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
308762306a36Sopenharmony_ci				REGULATOR_EVENT_ABORT_DISABLE, NULL);
308862306a36Sopenharmony_ci		return ret;
308962306a36Sopenharmony_ci	}
309062306a36Sopenharmony_ci
309162306a36Sopenharmony_ci	_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
309262306a36Sopenharmony_ci			REGULATOR_EVENT_DISABLE, NULL);
309362306a36Sopenharmony_ci
309462306a36Sopenharmony_ci	return 0;
309562306a36Sopenharmony_ci}
309662306a36Sopenharmony_ci
309762306a36Sopenharmony_ci/**
309862306a36Sopenharmony_ci * regulator_force_disable - force disable regulator output
309962306a36Sopenharmony_ci * @regulator: regulator source
310062306a36Sopenharmony_ci *
310162306a36Sopenharmony_ci * Forcibly disable the regulator output voltage or current.
310262306a36Sopenharmony_ci * NOTE: this *will* disable the regulator output even if other consumer
310362306a36Sopenharmony_ci * devices have it enabled. This should be used for situations when device
310462306a36Sopenharmony_ci * damage will likely occur if the regulator is not disabled (e.g. over temp).
310562306a36Sopenharmony_ci */
310662306a36Sopenharmony_ciint regulator_force_disable(struct regulator *regulator)
310762306a36Sopenharmony_ci{
310862306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
310962306a36Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
311062306a36Sopenharmony_ci	int ret;
311162306a36Sopenharmony_ci
311262306a36Sopenharmony_ci	regulator_lock_dependent(rdev, &ww_ctx);
311362306a36Sopenharmony_ci
311462306a36Sopenharmony_ci	ret = _regulator_force_disable(regulator->rdev);
311562306a36Sopenharmony_ci
311662306a36Sopenharmony_ci	if (rdev->coupling_desc.n_coupled > 1)
311762306a36Sopenharmony_ci		regulator_balance_voltage(rdev, PM_SUSPEND_ON);
311862306a36Sopenharmony_ci
311962306a36Sopenharmony_ci	if (regulator->uA_load) {
312062306a36Sopenharmony_ci		regulator->uA_load = 0;
312162306a36Sopenharmony_ci		ret = drms_uA_update(rdev);
312262306a36Sopenharmony_ci	}
312362306a36Sopenharmony_ci
312462306a36Sopenharmony_ci	if (rdev->use_count != 0 && rdev->supply)
312562306a36Sopenharmony_ci		_regulator_disable(rdev->supply);
312662306a36Sopenharmony_ci
312762306a36Sopenharmony_ci	regulator_unlock_dependent(rdev, &ww_ctx);
312862306a36Sopenharmony_ci
312962306a36Sopenharmony_ci	return ret;
313062306a36Sopenharmony_ci}
313162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_force_disable);
313262306a36Sopenharmony_ci
313362306a36Sopenharmony_cistatic void regulator_disable_work(struct work_struct *work)
313462306a36Sopenharmony_ci{
313562306a36Sopenharmony_ci	struct regulator_dev *rdev = container_of(work, struct regulator_dev,
313662306a36Sopenharmony_ci						  disable_work.work);
313762306a36Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
313862306a36Sopenharmony_ci	int count, i, ret;
313962306a36Sopenharmony_ci	struct regulator *regulator;
314062306a36Sopenharmony_ci	int total_count = 0;
314162306a36Sopenharmony_ci
314262306a36Sopenharmony_ci	regulator_lock_dependent(rdev, &ww_ctx);
314362306a36Sopenharmony_ci
314462306a36Sopenharmony_ci	/*
314562306a36Sopenharmony_ci	 * Workqueue functions queue the new work instance while the previous
314662306a36Sopenharmony_ci	 * work instance is being processed. Cancel the queued work instance
314762306a36Sopenharmony_ci	 * as the work instance under processing does the job of the queued
314862306a36Sopenharmony_ci	 * work instance.
314962306a36Sopenharmony_ci	 */
315062306a36Sopenharmony_ci	cancel_delayed_work(&rdev->disable_work);
315162306a36Sopenharmony_ci
315262306a36Sopenharmony_ci	list_for_each_entry(regulator, &rdev->consumer_list, list) {
315362306a36Sopenharmony_ci		count = regulator->deferred_disables;
315462306a36Sopenharmony_ci
315562306a36Sopenharmony_ci		if (!count)
315662306a36Sopenharmony_ci			continue;
315762306a36Sopenharmony_ci
315862306a36Sopenharmony_ci		total_count += count;
315962306a36Sopenharmony_ci		regulator->deferred_disables = 0;
316062306a36Sopenharmony_ci
316162306a36Sopenharmony_ci		for (i = 0; i < count; i++) {
316262306a36Sopenharmony_ci			ret = _regulator_disable(regulator);
316362306a36Sopenharmony_ci			if (ret != 0)
316462306a36Sopenharmony_ci				rdev_err(rdev, "Deferred disable failed: %pe\n",
316562306a36Sopenharmony_ci					 ERR_PTR(ret));
316662306a36Sopenharmony_ci		}
316762306a36Sopenharmony_ci	}
316862306a36Sopenharmony_ci	WARN_ON(!total_count);
316962306a36Sopenharmony_ci
317062306a36Sopenharmony_ci	if (rdev->coupling_desc.n_coupled > 1)
317162306a36Sopenharmony_ci		regulator_balance_voltage(rdev, PM_SUSPEND_ON);
317262306a36Sopenharmony_ci
317362306a36Sopenharmony_ci	regulator_unlock_dependent(rdev, &ww_ctx);
317462306a36Sopenharmony_ci}
317562306a36Sopenharmony_ci
317662306a36Sopenharmony_ci/**
317762306a36Sopenharmony_ci * regulator_disable_deferred - disable regulator output with delay
317862306a36Sopenharmony_ci * @regulator: regulator source
317962306a36Sopenharmony_ci * @ms: milliseconds until the regulator is disabled
318062306a36Sopenharmony_ci *
318162306a36Sopenharmony_ci * Execute regulator_disable() on the regulator after a delay.  This
318262306a36Sopenharmony_ci * is intended for use with devices that require some time to quiesce.
318362306a36Sopenharmony_ci *
318462306a36Sopenharmony_ci * NOTE: this will only disable the regulator output if no other consumer
318562306a36Sopenharmony_ci * devices have it enabled, the regulator device supports disabling and
318662306a36Sopenharmony_ci * machine constraints permit this operation.
318762306a36Sopenharmony_ci */
318862306a36Sopenharmony_ciint regulator_disable_deferred(struct regulator *regulator, int ms)
318962306a36Sopenharmony_ci{
319062306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
319162306a36Sopenharmony_ci
319262306a36Sopenharmony_ci	if (!ms)
319362306a36Sopenharmony_ci		return regulator_disable(regulator);
319462306a36Sopenharmony_ci
319562306a36Sopenharmony_ci	regulator_lock(rdev);
319662306a36Sopenharmony_ci	regulator->deferred_disables++;
319762306a36Sopenharmony_ci	mod_delayed_work(system_power_efficient_wq, &rdev->disable_work,
319862306a36Sopenharmony_ci			 msecs_to_jiffies(ms));
319962306a36Sopenharmony_ci	regulator_unlock(rdev);
320062306a36Sopenharmony_ci
320162306a36Sopenharmony_ci	return 0;
320262306a36Sopenharmony_ci}
320362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_disable_deferred);
320462306a36Sopenharmony_ci
320562306a36Sopenharmony_cistatic int _regulator_is_enabled(struct regulator_dev *rdev)
320662306a36Sopenharmony_ci{
320762306a36Sopenharmony_ci	/* A GPIO control always takes precedence */
320862306a36Sopenharmony_ci	if (rdev->ena_pin)
320962306a36Sopenharmony_ci		return rdev->ena_gpio_state;
321062306a36Sopenharmony_ci
321162306a36Sopenharmony_ci	/* If we don't know then assume that the regulator is always on */
321262306a36Sopenharmony_ci	if (!rdev->desc->ops->is_enabled)
321362306a36Sopenharmony_ci		return 1;
321462306a36Sopenharmony_ci
321562306a36Sopenharmony_ci	return rdev->desc->ops->is_enabled(rdev);
321662306a36Sopenharmony_ci}
321762306a36Sopenharmony_ci
321862306a36Sopenharmony_cistatic int _regulator_list_voltage(struct regulator_dev *rdev,
321962306a36Sopenharmony_ci				   unsigned selector, int lock)
322062306a36Sopenharmony_ci{
322162306a36Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
322262306a36Sopenharmony_ci	int ret;
322362306a36Sopenharmony_ci
322462306a36Sopenharmony_ci	if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector)
322562306a36Sopenharmony_ci		return rdev->desc->fixed_uV;
322662306a36Sopenharmony_ci
322762306a36Sopenharmony_ci	if (ops->list_voltage) {
322862306a36Sopenharmony_ci		if (selector >= rdev->desc->n_voltages)
322962306a36Sopenharmony_ci			return -EINVAL;
323062306a36Sopenharmony_ci		if (selector < rdev->desc->linear_min_sel)
323162306a36Sopenharmony_ci			return 0;
323262306a36Sopenharmony_ci		if (lock)
323362306a36Sopenharmony_ci			regulator_lock(rdev);
323462306a36Sopenharmony_ci		ret = ops->list_voltage(rdev, selector);
323562306a36Sopenharmony_ci		if (lock)
323662306a36Sopenharmony_ci			regulator_unlock(rdev);
323762306a36Sopenharmony_ci	} else if (rdev->is_switch && rdev->supply) {
323862306a36Sopenharmony_ci		ret = _regulator_list_voltage(rdev->supply->rdev,
323962306a36Sopenharmony_ci					      selector, lock);
324062306a36Sopenharmony_ci	} else {
324162306a36Sopenharmony_ci		return -EINVAL;
324262306a36Sopenharmony_ci	}
324362306a36Sopenharmony_ci
324462306a36Sopenharmony_ci	if (ret > 0) {
324562306a36Sopenharmony_ci		if (ret < rdev->constraints->min_uV)
324662306a36Sopenharmony_ci			ret = 0;
324762306a36Sopenharmony_ci		else if (ret > rdev->constraints->max_uV)
324862306a36Sopenharmony_ci			ret = 0;
324962306a36Sopenharmony_ci	}
325062306a36Sopenharmony_ci
325162306a36Sopenharmony_ci	return ret;
325262306a36Sopenharmony_ci}
325362306a36Sopenharmony_ci
325462306a36Sopenharmony_ci/**
325562306a36Sopenharmony_ci * regulator_is_enabled - is the regulator output enabled
325662306a36Sopenharmony_ci * @regulator: regulator source
325762306a36Sopenharmony_ci *
325862306a36Sopenharmony_ci * Returns positive if the regulator driver backing the source/client
325962306a36Sopenharmony_ci * has requested that the device be enabled, zero if it hasn't, else a
326062306a36Sopenharmony_ci * negative errno code.
326162306a36Sopenharmony_ci *
326262306a36Sopenharmony_ci * Note that the device backing this regulator handle can have multiple
326362306a36Sopenharmony_ci * users, so it might be enabled even if regulator_enable() was never
326462306a36Sopenharmony_ci * called for this particular source.
326562306a36Sopenharmony_ci */
326662306a36Sopenharmony_ciint regulator_is_enabled(struct regulator *regulator)
326762306a36Sopenharmony_ci{
326862306a36Sopenharmony_ci	int ret;
326962306a36Sopenharmony_ci
327062306a36Sopenharmony_ci	if (regulator->always_on)
327162306a36Sopenharmony_ci		return 1;
327262306a36Sopenharmony_ci
327362306a36Sopenharmony_ci	regulator_lock(regulator->rdev);
327462306a36Sopenharmony_ci	ret = _regulator_is_enabled(regulator->rdev);
327562306a36Sopenharmony_ci	regulator_unlock(regulator->rdev);
327662306a36Sopenharmony_ci
327762306a36Sopenharmony_ci	return ret;
327862306a36Sopenharmony_ci}
327962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_is_enabled);
328062306a36Sopenharmony_ci
328162306a36Sopenharmony_ci/**
328262306a36Sopenharmony_ci * regulator_count_voltages - count regulator_list_voltage() selectors
328362306a36Sopenharmony_ci * @regulator: regulator source
328462306a36Sopenharmony_ci *
328562306a36Sopenharmony_ci * Returns number of selectors, or negative errno.  Selectors are
328662306a36Sopenharmony_ci * numbered starting at zero, and typically correspond to bitfields
328762306a36Sopenharmony_ci * in hardware registers.
328862306a36Sopenharmony_ci */
328962306a36Sopenharmony_ciint regulator_count_voltages(struct regulator *regulator)
329062306a36Sopenharmony_ci{
329162306a36Sopenharmony_ci	struct regulator_dev	*rdev = regulator->rdev;
329262306a36Sopenharmony_ci
329362306a36Sopenharmony_ci	if (rdev->desc->n_voltages)
329462306a36Sopenharmony_ci		return rdev->desc->n_voltages;
329562306a36Sopenharmony_ci
329662306a36Sopenharmony_ci	if (!rdev->is_switch || !rdev->supply)
329762306a36Sopenharmony_ci		return -EINVAL;
329862306a36Sopenharmony_ci
329962306a36Sopenharmony_ci	return regulator_count_voltages(rdev->supply);
330062306a36Sopenharmony_ci}
330162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_count_voltages);
330262306a36Sopenharmony_ci
330362306a36Sopenharmony_ci/**
330462306a36Sopenharmony_ci * regulator_list_voltage - enumerate supported voltages
330562306a36Sopenharmony_ci * @regulator: regulator source
330662306a36Sopenharmony_ci * @selector: identify voltage to list
330762306a36Sopenharmony_ci * Context: can sleep
330862306a36Sopenharmony_ci *
330962306a36Sopenharmony_ci * Returns a voltage that can be passed to @regulator_set_voltage(),
331062306a36Sopenharmony_ci * zero if this selector code can't be used on this system, or a
331162306a36Sopenharmony_ci * negative errno.
331262306a36Sopenharmony_ci */
331362306a36Sopenharmony_ciint regulator_list_voltage(struct regulator *regulator, unsigned selector)
331462306a36Sopenharmony_ci{
331562306a36Sopenharmony_ci	return _regulator_list_voltage(regulator->rdev, selector, 1);
331662306a36Sopenharmony_ci}
331762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_list_voltage);
331862306a36Sopenharmony_ci
331962306a36Sopenharmony_ci/**
332062306a36Sopenharmony_ci * regulator_get_regmap - get the regulator's register map
332162306a36Sopenharmony_ci * @regulator: regulator source
332262306a36Sopenharmony_ci *
332362306a36Sopenharmony_ci * Returns the register map for the given regulator, or an ERR_PTR value
332462306a36Sopenharmony_ci * if the regulator doesn't use regmap.
332562306a36Sopenharmony_ci */
332662306a36Sopenharmony_cistruct regmap *regulator_get_regmap(struct regulator *regulator)
332762306a36Sopenharmony_ci{
332862306a36Sopenharmony_ci	struct regmap *map = regulator->rdev->regmap;
332962306a36Sopenharmony_ci
333062306a36Sopenharmony_ci	return map ? map : ERR_PTR(-EOPNOTSUPP);
333162306a36Sopenharmony_ci}
333262306a36Sopenharmony_ci
333362306a36Sopenharmony_ci/**
333462306a36Sopenharmony_ci * regulator_get_hardware_vsel_register - get the HW voltage selector register
333562306a36Sopenharmony_ci * @regulator: regulator source
333662306a36Sopenharmony_ci * @vsel_reg: voltage selector register, output parameter
333762306a36Sopenharmony_ci * @vsel_mask: mask for voltage selector bitfield, output parameter
333862306a36Sopenharmony_ci *
333962306a36Sopenharmony_ci * Returns the hardware register offset and bitmask used for setting the
334062306a36Sopenharmony_ci * regulator voltage. This might be useful when configuring voltage-scaling
334162306a36Sopenharmony_ci * hardware or firmware that can make I2C requests behind the kernel's back,
334262306a36Sopenharmony_ci * for example.
334362306a36Sopenharmony_ci *
334462306a36Sopenharmony_ci * On success, the output parameters @vsel_reg and @vsel_mask are filled in
334562306a36Sopenharmony_ci * and 0 is returned, otherwise a negative errno is returned.
334662306a36Sopenharmony_ci */
334762306a36Sopenharmony_ciint regulator_get_hardware_vsel_register(struct regulator *regulator,
334862306a36Sopenharmony_ci					 unsigned *vsel_reg,
334962306a36Sopenharmony_ci					 unsigned *vsel_mask)
335062306a36Sopenharmony_ci{
335162306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
335262306a36Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
335362306a36Sopenharmony_ci
335462306a36Sopenharmony_ci	if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap)
335562306a36Sopenharmony_ci		return -EOPNOTSUPP;
335662306a36Sopenharmony_ci
335762306a36Sopenharmony_ci	*vsel_reg = rdev->desc->vsel_reg;
335862306a36Sopenharmony_ci	*vsel_mask = rdev->desc->vsel_mask;
335962306a36Sopenharmony_ci
336062306a36Sopenharmony_ci	return 0;
336162306a36Sopenharmony_ci}
336262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register);
336362306a36Sopenharmony_ci
336462306a36Sopenharmony_ci/**
336562306a36Sopenharmony_ci * regulator_list_hardware_vsel - get the HW-specific register value for a selector
336662306a36Sopenharmony_ci * @regulator: regulator source
336762306a36Sopenharmony_ci * @selector: identify voltage to list
336862306a36Sopenharmony_ci *
336962306a36Sopenharmony_ci * Converts the selector to a hardware-specific voltage selector that can be
337062306a36Sopenharmony_ci * directly written to the regulator registers. The address of the voltage
337162306a36Sopenharmony_ci * register can be determined by calling @regulator_get_hardware_vsel_register.
337262306a36Sopenharmony_ci *
337362306a36Sopenharmony_ci * On error a negative errno is returned.
337462306a36Sopenharmony_ci */
337562306a36Sopenharmony_ciint regulator_list_hardware_vsel(struct regulator *regulator,
337662306a36Sopenharmony_ci				 unsigned selector)
337762306a36Sopenharmony_ci{
337862306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
337962306a36Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
338062306a36Sopenharmony_ci
338162306a36Sopenharmony_ci	if (selector >= rdev->desc->n_voltages)
338262306a36Sopenharmony_ci		return -EINVAL;
338362306a36Sopenharmony_ci	if (selector < rdev->desc->linear_min_sel)
338462306a36Sopenharmony_ci		return 0;
338562306a36Sopenharmony_ci	if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap)
338662306a36Sopenharmony_ci		return -EOPNOTSUPP;
338762306a36Sopenharmony_ci
338862306a36Sopenharmony_ci	return selector;
338962306a36Sopenharmony_ci}
339062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_list_hardware_vsel);
339162306a36Sopenharmony_ci
339262306a36Sopenharmony_ci/**
339362306a36Sopenharmony_ci * regulator_get_linear_step - return the voltage step size between VSEL values
339462306a36Sopenharmony_ci * @regulator: regulator source
339562306a36Sopenharmony_ci *
339662306a36Sopenharmony_ci * Returns the voltage step size between VSEL values for linear
339762306a36Sopenharmony_ci * regulators, or return 0 if the regulator isn't a linear regulator.
339862306a36Sopenharmony_ci */
339962306a36Sopenharmony_ciunsigned int regulator_get_linear_step(struct regulator *regulator)
340062306a36Sopenharmony_ci{
340162306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
340262306a36Sopenharmony_ci
340362306a36Sopenharmony_ci	return rdev->desc->uV_step;
340462306a36Sopenharmony_ci}
340562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_linear_step);
340662306a36Sopenharmony_ci
340762306a36Sopenharmony_ci/**
340862306a36Sopenharmony_ci * regulator_is_supported_voltage - check if a voltage range can be supported
340962306a36Sopenharmony_ci *
341062306a36Sopenharmony_ci * @regulator: Regulator to check.
341162306a36Sopenharmony_ci * @min_uV: Minimum required voltage in uV.
341262306a36Sopenharmony_ci * @max_uV: Maximum required voltage in uV.
341362306a36Sopenharmony_ci *
341462306a36Sopenharmony_ci * Returns a boolean.
341562306a36Sopenharmony_ci */
341662306a36Sopenharmony_ciint regulator_is_supported_voltage(struct regulator *regulator,
341762306a36Sopenharmony_ci				   int min_uV, int max_uV)
341862306a36Sopenharmony_ci{
341962306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
342062306a36Sopenharmony_ci	int i, voltages, ret;
342162306a36Sopenharmony_ci
342262306a36Sopenharmony_ci	/* If we can't change voltage check the current voltage */
342362306a36Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
342462306a36Sopenharmony_ci		ret = regulator_get_voltage(regulator);
342562306a36Sopenharmony_ci		if (ret >= 0)
342662306a36Sopenharmony_ci			return min_uV <= ret && ret <= max_uV;
342762306a36Sopenharmony_ci		else
342862306a36Sopenharmony_ci			return ret;
342962306a36Sopenharmony_ci	}
343062306a36Sopenharmony_ci
343162306a36Sopenharmony_ci	/* Any voltage within constrains range is fine? */
343262306a36Sopenharmony_ci	if (rdev->desc->continuous_voltage_range)
343362306a36Sopenharmony_ci		return min_uV >= rdev->constraints->min_uV &&
343462306a36Sopenharmony_ci				max_uV <= rdev->constraints->max_uV;
343562306a36Sopenharmony_ci
343662306a36Sopenharmony_ci	ret = regulator_count_voltages(regulator);
343762306a36Sopenharmony_ci	if (ret < 0)
343862306a36Sopenharmony_ci		return 0;
343962306a36Sopenharmony_ci	voltages = ret;
344062306a36Sopenharmony_ci
344162306a36Sopenharmony_ci	for (i = 0; i < voltages; i++) {
344262306a36Sopenharmony_ci		ret = regulator_list_voltage(regulator, i);
344362306a36Sopenharmony_ci
344462306a36Sopenharmony_ci		if (ret >= min_uV && ret <= max_uV)
344562306a36Sopenharmony_ci			return 1;
344662306a36Sopenharmony_ci	}
344762306a36Sopenharmony_ci
344862306a36Sopenharmony_ci	return 0;
344962306a36Sopenharmony_ci}
345062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_is_supported_voltage);
345162306a36Sopenharmony_ci
345262306a36Sopenharmony_cistatic int regulator_map_voltage(struct regulator_dev *rdev, int min_uV,
345362306a36Sopenharmony_ci				 int max_uV)
345462306a36Sopenharmony_ci{
345562306a36Sopenharmony_ci	const struct regulator_desc *desc = rdev->desc;
345662306a36Sopenharmony_ci
345762306a36Sopenharmony_ci	if (desc->ops->map_voltage)
345862306a36Sopenharmony_ci		return desc->ops->map_voltage(rdev, min_uV, max_uV);
345962306a36Sopenharmony_ci
346062306a36Sopenharmony_ci	if (desc->ops->list_voltage == regulator_list_voltage_linear)
346162306a36Sopenharmony_ci		return regulator_map_voltage_linear(rdev, min_uV, max_uV);
346262306a36Sopenharmony_ci
346362306a36Sopenharmony_ci	if (desc->ops->list_voltage == regulator_list_voltage_linear_range)
346462306a36Sopenharmony_ci		return regulator_map_voltage_linear_range(rdev, min_uV, max_uV);
346562306a36Sopenharmony_ci
346662306a36Sopenharmony_ci	if (desc->ops->list_voltage ==
346762306a36Sopenharmony_ci		regulator_list_voltage_pickable_linear_range)
346862306a36Sopenharmony_ci		return regulator_map_voltage_pickable_linear_range(rdev,
346962306a36Sopenharmony_ci							min_uV, max_uV);
347062306a36Sopenharmony_ci
347162306a36Sopenharmony_ci	return regulator_map_voltage_iterate(rdev, min_uV, max_uV);
347262306a36Sopenharmony_ci}
347362306a36Sopenharmony_ci
347462306a36Sopenharmony_cistatic int _regulator_call_set_voltage(struct regulator_dev *rdev,
347562306a36Sopenharmony_ci				       int min_uV, int max_uV,
347662306a36Sopenharmony_ci				       unsigned *selector)
347762306a36Sopenharmony_ci{
347862306a36Sopenharmony_ci	struct pre_voltage_change_data data;
347962306a36Sopenharmony_ci	int ret;
348062306a36Sopenharmony_ci
348162306a36Sopenharmony_ci	data.old_uV = regulator_get_voltage_rdev(rdev);
348262306a36Sopenharmony_ci	data.min_uV = min_uV;
348362306a36Sopenharmony_ci	data.max_uV = max_uV;
348462306a36Sopenharmony_ci	ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE,
348562306a36Sopenharmony_ci				   &data);
348662306a36Sopenharmony_ci	if (ret & NOTIFY_STOP_MASK)
348762306a36Sopenharmony_ci		return -EINVAL;
348862306a36Sopenharmony_ci
348962306a36Sopenharmony_ci	ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector);
349062306a36Sopenharmony_ci	if (ret >= 0)
349162306a36Sopenharmony_ci		return ret;
349262306a36Sopenharmony_ci
349362306a36Sopenharmony_ci	_notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE,
349462306a36Sopenharmony_ci			     (void *)data.old_uV);
349562306a36Sopenharmony_ci
349662306a36Sopenharmony_ci	return ret;
349762306a36Sopenharmony_ci}
349862306a36Sopenharmony_ci
349962306a36Sopenharmony_cistatic int _regulator_call_set_voltage_sel(struct regulator_dev *rdev,
350062306a36Sopenharmony_ci					   int uV, unsigned selector)
350162306a36Sopenharmony_ci{
350262306a36Sopenharmony_ci	struct pre_voltage_change_data data;
350362306a36Sopenharmony_ci	int ret;
350462306a36Sopenharmony_ci
350562306a36Sopenharmony_ci	data.old_uV = regulator_get_voltage_rdev(rdev);
350662306a36Sopenharmony_ci	data.min_uV = uV;
350762306a36Sopenharmony_ci	data.max_uV = uV;
350862306a36Sopenharmony_ci	ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE,
350962306a36Sopenharmony_ci				   &data);
351062306a36Sopenharmony_ci	if (ret & NOTIFY_STOP_MASK)
351162306a36Sopenharmony_ci		return -EINVAL;
351262306a36Sopenharmony_ci
351362306a36Sopenharmony_ci	ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
351462306a36Sopenharmony_ci	if (ret >= 0)
351562306a36Sopenharmony_ci		return ret;
351662306a36Sopenharmony_ci
351762306a36Sopenharmony_ci	_notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE,
351862306a36Sopenharmony_ci			     (void *)data.old_uV);
351962306a36Sopenharmony_ci
352062306a36Sopenharmony_ci	return ret;
352162306a36Sopenharmony_ci}
352262306a36Sopenharmony_ci
352362306a36Sopenharmony_cistatic int _regulator_set_voltage_sel_step(struct regulator_dev *rdev,
352462306a36Sopenharmony_ci					   int uV, int new_selector)
352562306a36Sopenharmony_ci{
352662306a36Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
352762306a36Sopenharmony_ci	int diff, old_sel, curr_sel, ret;
352862306a36Sopenharmony_ci
352962306a36Sopenharmony_ci	/* Stepping is only needed if the regulator is enabled. */
353062306a36Sopenharmony_ci	if (!_regulator_is_enabled(rdev))
353162306a36Sopenharmony_ci		goto final_set;
353262306a36Sopenharmony_ci
353362306a36Sopenharmony_ci	if (!ops->get_voltage_sel)
353462306a36Sopenharmony_ci		return -EINVAL;
353562306a36Sopenharmony_ci
353662306a36Sopenharmony_ci	old_sel = ops->get_voltage_sel(rdev);
353762306a36Sopenharmony_ci	if (old_sel < 0)
353862306a36Sopenharmony_ci		return old_sel;
353962306a36Sopenharmony_ci
354062306a36Sopenharmony_ci	diff = new_selector - old_sel;
354162306a36Sopenharmony_ci	if (diff == 0)
354262306a36Sopenharmony_ci		return 0; /* No change needed. */
354362306a36Sopenharmony_ci
354462306a36Sopenharmony_ci	if (diff > 0) {
354562306a36Sopenharmony_ci		/* Stepping up. */
354662306a36Sopenharmony_ci		for (curr_sel = old_sel + rdev->desc->vsel_step;
354762306a36Sopenharmony_ci		     curr_sel < new_selector;
354862306a36Sopenharmony_ci		     curr_sel += rdev->desc->vsel_step) {
354962306a36Sopenharmony_ci			/*
355062306a36Sopenharmony_ci			 * Call the callback directly instead of using
355162306a36Sopenharmony_ci			 * _regulator_call_set_voltage_sel() as we don't
355262306a36Sopenharmony_ci			 * want to notify anyone yet. Same in the branch
355362306a36Sopenharmony_ci			 * below.
355462306a36Sopenharmony_ci			 */
355562306a36Sopenharmony_ci			ret = ops->set_voltage_sel(rdev, curr_sel);
355662306a36Sopenharmony_ci			if (ret)
355762306a36Sopenharmony_ci				goto try_revert;
355862306a36Sopenharmony_ci		}
355962306a36Sopenharmony_ci	} else {
356062306a36Sopenharmony_ci		/* Stepping down. */
356162306a36Sopenharmony_ci		for (curr_sel = old_sel - rdev->desc->vsel_step;
356262306a36Sopenharmony_ci		     curr_sel > new_selector;
356362306a36Sopenharmony_ci		     curr_sel -= rdev->desc->vsel_step) {
356462306a36Sopenharmony_ci			ret = ops->set_voltage_sel(rdev, curr_sel);
356562306a36Sopenharmony_ci			if (ret)
356662306a36Sopenharmony_ci				goto try_revert;
356762306a36Sopenharmony_ci		}
356862306a36Sopenharmony_ci	}
356962306a36Sopenharmony_ci
357062306a36Sopenharmony_cifinal_set:
357162306a36Sopenharmony_ci	/* The final selector will trigger the notifiers. */
357262306a36Sopenharmony_ci	return _regulator_call_set_voltage_sel(rdev, uV, new_selector);
357362306a36Sopenharmony_ci
357462306a36Sopenharmony_citry_revert:
357562306a36Sopenharmony_ci	/*
357662306a36Sopenharmony_ci	 * At least try to return to the previous voltage if setting a new
357762306a36Sopenharmony_ci	 * one failed.
357862306a36Sopenharmony_ci	 */
357962306a36Sopenharmony_ci	(void)ops->set_voltage_sel(rdev, old_sel);
358062306a36Sopenharmony_ci	return ret;
358162306a36Sopenharmony_ci}
358262306a36Sopenharmony_ci
358362306a36Sopenharmony_cistatic int _regulator_set_voltage_time(struct regulator_dev *rdev,
358462306a36Sopenharmony_ci				       int old_uV, int new_uV)
358562306a36Sopenharmony_ci{
358662306a36Sopenharmony_ci	unsigned int ramp_delay = 0;
358762306a36Sopenharmony_ci
358862306a36Sopenharmony_ci	if (rdev->constraints->ramp_delay)
358962306a36Sopenharmony_ci		ramp_delay = rdev->constraints->ramp_delay;
359062306a36Sopenharmony_ci	else if (rdev->desc->ramp_delay)
359162306a36Sopenharmony_ci		ramp_delay = rdev->desc->ramp_delay;
359262306a36Sopenharmony_ci	else if (rdev->constraints->settling_time)
359362306a36Sopenharmony_ci		return rdev->constraints->settling_time;
359462306a36Sopenharmony_ci	else if (rdev->constraints->settling_time_up &&
359562306a36Sopenharmony_ci		 (new_uV > old_uV))
359662306a36Sopenharmony_ci		return rdev->constraints->settling_time_up;
359762306a36Sopenharmony_ci	else if (rdev->constraints->settling_time_down &&
359862306a36Sopenharmony_ci		 (new_uV < old_uV))
359962306a36Sopenharmony_ci		return rdev->constraints->settling_time_down;
360062306a36Sopenharmony_ci
360162306a36Sopenharmony_ci	if (ramp_delay == 0)
360262306a36Sopenharmony_ci		return 0;
360362306a36Sopenharmony_ci
360462306a36Sopenharmony_ci	return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay);
360562306a36Sopenharmony_ci}
360662306a36Sopenharmony_ci
360762306a36Sopenharmony_cistatic int _regulator_do_set_voltage(struct regulator_dev *rdev,
360862306a36Sopenharmony_ci				     int min_uV, int max_uV)
360962306a36Sopenharmony_ci{
361062306a36Sopenharmony_ci	int ret;
361162306a36Sopenharmony_ci	int delay = 0;
361262306a36Sopenharmony_ci	int best_val = 0;
361362306a36Sopenharmony_ci	unsigned int selector;
361462306a36Sopenharmony_ci	int old_selector = -1;
361562306a36Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
361662306a36Sopenharmony_ci	int old_uV = regulator_get_voltage_rdev(rdev);
361762306a36Sopenharmony_ci
361862306a36Sopenharmony_ci	trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
361962306a36Sopenharmony_ci
362062306a36Sopenharmony_ci	min_uV += rdev->constraints->uV_offset;
362162306a36Sopenharmony_ci	max_uV += rdev->constraints->uV_offset;
362262306a36Sopenharmony_ci
362362306a36Sopenharmony_ci	/*
362462306a36Sopenharmony_ci	 * If we can't obtain the old selector there is not enough
362562306a36Sopenharmony_ci	 * info to call set_voltage_time_sel().
362662306a36Sopenharmony_ci	 */
362762306a36Sopenharmony_ci	if (_regulator_is_enabled(rdev) &&
362862306a36Sopenharmony_ci	    ops->set_voltage_time_sel && ops->get_voltage_sel) {
362962306a36Sopenharmony_ci		old_selector = ops->get_voltage_sel(rdev);
363062306a36Sopenharmony_ci		if (old_selector < 0)
363162306a36Sopenharmony_ci			return old_selector;
363262306a36Sopenharmony_ci	}
363362306a36Sopenharmony_ci
363462306a36Sopenharmony_ci	if (ops->set_voltage) {
363562306a36Sopenharmony_ci		ret = _regulator_call_set_voltage(rdev, min_uV, max_uV,
363662306a36Sopenharmony_ci						  &selector);
363762306a36Sopenharmony_ci
363862306a36Sopenharmony_ci		if (ret >= 0) {
363962306a36Sopenharmony_ci			if (ops->list_voltage)
364062306a36Sopenharmony_ci				best_val = ops->list_voltage(rdev,
364162306a36Sopenharmony_ci							     selector);
364262306a36Sopenharmony_ci			else
364362306a36Sopenharmony_ci				best_val = regulator_get_voltage_rdev(rdev);
364462306a36Sopenharmony_ci		}
364562306a36Sopenharmony_ci
364662306a36Sopenharmony_ci	} else if (ops->set_voltage_sel) {
364762306a36Sopenharmony_ci		ret = regulator_map_voltage(rdev, min_uV, max_uV);
364862306a36Sopenharmony_ci		if (ret >= 0) {
364962306a36Sopenharmony_ci			best_val = ops->list_voltage(rdev, ret);
365062306a36Sopenharmony_ci			if (min_uV <= best_val && max_uV >= best_val) {
365162306a36Sopenharmony_ci				selector = ret;
365262306a36Sopenharmony_ci				if (old_selector == selector)
365362306a36Sopenharmony_ci					ret = 0;
365462306a36Sopenharmony_ci				else if (rdev->desc->vsel_step)
365562306a36Sopenharmony_ci					ret = _regulator_set_voltage_sel_step(
365662306a36Sopenharmony_ci						rdev, best_val, selector);
365762306a36Sopenharmony_ci				else
365862306a36Sopenharmony_ci					ret = _regulator_call_set_voltage_sel(
365962306a36Sopenharmony_ci						rdev, best_val, selector);
366062306a36Sopenharmony_ci			} else {
366162306a36Sopenharmony_ci				ret = -EINVAL;
366262306a36Sopenharmony_ci			}
366362306a36Sopenharmony_ci		}
366462306a36Sopenharmony_ci	} else {
366562306a36Sopenharmony_ci		ret = -EINVAL;
366662306a36Sopenharmony_ci	}
366762306a36Sopenharmony_ci
366862306a36Sopenharmony_ci	if (ret)
366962306a36Sopenharmony_ci		goto out;
367062306a36Sopenharmony_ci
367162306a36Sopenharmony_ci	if (ops->set_voltage_time_sel) {
367262306a36Sopenharmony_ci		/*
367362306a36Sopenharmony_ci		 * Call set_voltage_time_sel if successfully obtained
367462306a36Sopenharmony_ci		 * old_selector
367562306a36Sopenharmony_ci		 */
367662306a36Sopenharmony_ci		if (old_selector >= 0 && old_selector != selector)
367762306a36Sopenharmony_ci			delay = ops->set_voltage_time_sel(rdev, old_selector,
367862306a36Sopenharmony_ci							  selector);
367962306a36Sopenharmony_ci	} else {
368062306a36Sopenharmony_ci		if (old_uV != best_val) {
368162306a36Sopenharmony_ci			if (ops->set_voltage_time)
368262306a36Sopenharmony_ci				delay = ops->set_voltage_time(rdev, old_uV,
368362306a36Sopenharmony_ci							      best_val);
368462306a36Sopenharmony_ci			else
368562306a36Sopenharmony_ci				delay = _regulator_set_voltage_time(rdev,
368662306a36Sopenharmony_ci								    old_uV,
368762306a36Sopenharmony_ci								    best_val);
368862306a36Sopenharmony_ci		}
368962306a36Sopenharmony_ci	}
369062306a36Sopenharmony_ci
369162306a36Sopenharmony_ci	if (delay < 0) {
369262306a36Sopenharmony_ci		rdev_warn(rdev, "failed to get delay: %pe\n", ERR_PTR(delay));
369362306a36Sopenharmony_ci		delay = 0;
369462306a36Sopenharmony_ci	}
369562306a36Sopenharmony_ci
369662306a36Sopenharmony_ci	/* Insert any necessary delays */
369762306a36Sopenharmony_ci	_regulator_delay_helper(delay);
369862306a36Sopenharmony_ci
369962306a36Sopenharmony_ci	if (best_val >= 0) {
370062306a36Sopenharmony_ci		unsigned long data = best_val;
370162306a36Sopenharmony_ci
370262306a36Sopenharmony_ci		_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
370362306a36Sopenharmony_ci				     (void *)data);
370462306a36Sopenharmony_ci	}
370562306a36Sopenharmony_ci
370662306a36Sopenharmony_ciout:
370762306a36Sopenharmony_ci	trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
370862306a36Sopenharmony_ci
370962306a36Sopenharmony_ci	return ret;
371062306a36Sopenharmony_ci}
371162306a36Sopenharmony_ci
371262306a36Sopenharmony_cistatic int _regulator_do_set_suspend_voltage(struct regulator_dev *rdev,
371362306a36Sopenharmony_ci				  int min_uV, int max_uV, suspend_state_t state)
371462306a36Sopenharmony_ci{
371562306a36Sopenharmony_ci	struct regulator_state *rstate;
371662306a36Sopenharmony_ci	int uV, sel;
371762306a36Sopenharmony_ci
371862306a36Sopenharmony_ci	rstate = regulator_get_suspend_state(rdev, state);
371962306a36Sopenharmony_ci	if (rstate == NULL)
372062306a36Sopenharmony_ci		return -EINVAL;
372162306a36Sopenharmony_ci
372262306a36Sopenharmony_ci	if (min_uV < rstate->min_uV)
372362306a36Sopenharmony_ci		min_uV = rstate->min_uV;
372462306a36Sopenharmony_ci	if (max_uV > rstate->max_uV)
372562306a36Sopenharmony_ci		max_uV = rstate->max_uV;
372662306a36Sopenharmony_ci
372762306a36Sopenharmony_ci	sel = regulator_map_voltage(rdev, min_uV, max_uV);
372862306a36Sopenharmony_ci	if (sel < 0)
372962306a36Sopenharmony_ci		return sel;
373062306a36Sopenharmony_ci
373162306a36Sopenharmony_ci	uV = rdev->desc->ops->list_voltage(rdev, sel);
373262306a36Sopenharmony_ci	if (uV >= min_uV && uV <= max_uV)
373362306a36Sopenharmony_ci		rstate->uV = uV;
373462306a36Sopenharmony_ci
373562306a36Sopenharmony_ci	return 0;
373662306a36Sopenharmony_ci}
373762306a36Sopenharmony_ci
373862306a36Sopenharmony_cistatic int regulator_set_voltage_unlocked(struct regulator *regulator,
373962306a36Sopenharmony_ci					  int min_uV, int max_uV,
374062306a36Sopenharmony_ci					  suspend_state_t state)
374162306a36Sopenharmony_ci{
374262306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
374362306a36Sopenharmony_ci	struct regulator_voltage *voltage = &regulator->voltage[state];
374462306a36Sopenharmony_ci	int ret = 0;
374562306a36Sopenharmony_ci	int old_min_uV, old_max_uV;
374662306a36Sopenharmony_ci	int current_uV;
374762306a36Sopenharmony_ci
374862306a36Sopenharmony_ci	/* If we're setting the same range as last time the change
374962306a36Sopenharmony_ci	 * should be a noop (some cpufreq implementations use the same
375062306a36Sopenharmony_ci	 * voltage for multiple frequencies, for example).
375162306a36Sopenharmony_ci	 */
375262306a36Sopenharmony_ci	if (voltage->min_uV == min_uV && voltage->max_uV == max_uV)
375362306a36Sopenharmony_ci		goto out;
375462306a36Sopenharmony_ci
375562306a36Sopenharmony_ci	/* If we're trying to set a range that overlaps the current voltage,
375662306a36Sopenharmony_ci	 * return successfully even though the regulator does not support
375762306a36Sopenharmony_ci	 * changing the voltage.
375862306a36Sopenharmony_ci	 */
375962306a36Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
376062306a36Sopenharmony_ci		current_uV = regulator_get_voltage_rdev(rdev);
376162306a36Sopenharmony_ci		if (min_uV <= current_uV && current_uV <= max_uV) {
376262306a36Sopenharmony_ci			voltage->min_uV = min_uV;
376362306a36Sopenharmony_ci			voltage->max_uV = max_uV;
376462306a36Sopenharmony_ci			goto out;
376562306a36Sopenharmony_ci		}
376662306a36Sopenharmony_ci	}
376762306a36Sopenharmony_ci
376862306a36Sopenharmony_ci	/* sanity check */
376962306a36Sopenharmony_ci	if (!rdev->desc->ops->set_voltage &&
377062306a36Sopenharmony_ci	    !rdev->desc->ops->set_voltage_sel) {
377162306a36Sopenharmony_ci		ret = -EINVAL;
377262306a36Sopenharmony_ci		goto out;
377362306a36Sopenharmony_ci	}
377462306a36Sopenharmony_ci
377562306a36Sopenharmony_ci	/* constraints check */
377662306a36Sopenharmony_ci	ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
377762306a36Sopenharmony_ci	if (ret < 0)
377862306a36Sopenharmony_ci		goto out;
377962306a36Sopenharmony_ci
378062306a36Sopenharmony_ci	/* restore original values in case of error */
378162306a36Sopenharmony_ci	old_min_uV = voltage->min_uV;
378262306a36Sopenharmony_ci	old_max_uV = voltage->max_uV;
378362306a36Sopenharmony_ci	voltage->min_uV = min_uV;
378462306a36Sopenharmony_ci	voltage->max_uV = max_uV;
378562306a36Sopenharmony_ci
378662306a36Sopenharmony_ci	/* for not coupled regulators this will just set the voltage */
378762306a36Sopenharmony_ci	ret = regulator_balance_voltage(rdev, state);
378862306a36Sopenharmony_ci	if (ret < 0) {
378962306a36Sopenharmony_ci		voltage->min_uV = old_min_uV;
379062306a36Sopenharmony_ci		voltage->max_uV = old_max_uV;
379162306a36Sopenharmony_ci	}
379262306a36Sopenharmony_ci
379362306a36Sopenharmony_ciout:
379462306a36Sopenharmony_ci	return ret;
379562306a36Sopenharmony_ci}
379662306a36Sopenharmony_ci
379762306a36Sopenharmony_ciint regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV,
379862306a36Sopenharmony_ci			       int max_uV, suspend_state_t state)
379962306a36Sopenharmony_ci{
380062306a36Sopenharmony_ci	int best_supply_uV = 0;
380162306a36Sopenharmony_ci	int supply_change_uV = 0;
380262306a36Sopenharmony_ci	int ret;
380362306a36Sopenharmony_ci
380462306a36Sopenharmony_ci	if (rdev->supply &&
380562306a36Sopenharmony_ci	    regulator_ops_is_valid(rdev->supply->rdev,
380662306a36Sopenharmony_ci				   REGULATOR_CHANGE_VOLTAGE) &&
380762306a36Sopenharmony_ci	    (rdev->desc->min_dropout_uV || !(rdev->desc->ops->get_voltage ||
380862306a36Sopenharmony_ci					   rdev->desc->ops->get_voltage_sel))) {
380962306a36Sopenharmony_ci		int current_supply_uV;
381062306a36Sopenharmony_ci		int selector;
381162306a36Sopenharmony_ci
381262306a36Sopenharmony_ci		selector = regulator_map_voltage(rdev, min_uV, max_uV);
381362306a36Sopenharmony_ci		if (selector < 0) {
381462306a36Sopenharmony_ci			ret = selector;
381562306a36Sopenharmony_ci			goto out;
381662306a36Sopenharmony_ci		}
381762306a36Sopenharmony_ci
381862306a36Sopenharmony_ci		best_supply_uV = _regulator_list_voltage(rdev, selector, 0);
381962306a36Sopenharmony_ci		if (best_supply_uV < 0) {
382062306a36Sopenharmony_ci			ret = best_supply_uV;
382162306a36Sopenharmony_ci			goto out;
382262306a36Sopenharmony_ci		}
382362306a36Sopenharmony_ci
382462306a36Sopenharmony_ci		best_supply_uV += rdev->desc->min_dropout_uV;
382562306a36Sopenharmony_ci
382662306a36Sopenharmony_ci		current_supply_uV = regulator_get_voltage_rdev(rdev->supply->rdev);
382762306a36Sopenharmony_ci		if (current_supply_uV < 0) {
382862306a36Sopenharmony_ci			ret = current_supply_uV;
382962306a36Sopenharmony_ci			goto out;
383062306a36Sopenharmony_ci		}
383162306a36Sopenharmony_ci
383262306a36Sopenharmony_ci		supply_change_uV = best_supply_uV - current_supply_uV;
383362306a36Sopenharmony_ci	}
383462306a36Sopenharmony_ci
383562306a36Sopenharmony_ci	if (supply_change_uV > 0) {
383662306a36Sopenharmony_ci		ret = regulator_set_voltage_unlocked(rdev->supply,
383762306a36Sopenharmony_ci				best_supply_uV, INT_MAX, state);
383862306a36Sopenharmony_ci		if (ret) {
383962306a36Sopenharmony_ci			dev_err(&rdev->dev, "Failed to increase supply voltage: %pe\n",
384062306a36Sopenharmony_ci				ERR_PTR(ret));
384162306a36Sopenharmony_ci			goto out;
384262306a36Sopenharmony_ci		}
384362306a36Sopenharmony_ci	}
384462306a36Sopenharmony_ci
384562306a36Sopenharmony_ci	if (state == PM_SUSPEND_ON)
384662306a36Sopenharmony_ci		ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
384762306a36Sopenharmony_ci	else
384862306a36Sopenharmony_ci		ret = _regulator_do_set_suspend_voltage(rdev, min_uV,
384962306a36Sopenharmony_ci							max_uV, state);
385062306a36Sopenharmony_ci	if (ret < 0)
385162306a36Sopenharmony_ci		goto out;
385262306a36Sopenharmony_ci
385362306a36Sopenharmony_ci	if (supply_change_uV < 0) {
385462306a36Sopenharmony_ci		ret = regulator_set_voltage_unlocked(rdev->supply,
385562306a36Sopenharmony_ci				best_supply_uV, INT_MAX, state);
385662306a36Sopenharmony_ci		if (ret)
385762306a36Sopenharmony_ci			dev_warn(&rdev->dev, "Failed to decrease supply voltage: %pe\n",
385862306a36Sopenharmony_ci				 ERR_PTR(ret));
385962306a36Sopenharmony_ci		/* No need to fail here */
386062306a36Sopenharmony_ci		ret = 0;
386162306a36Sopenharmony_ci	}
386262306a36Sopenharmony_ci
386362306a36Sopenharmony_ciout:
386462306a36Sopenharmony_ci	return ret;
386562306a36Sopenharmony_ci}
386662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_voltage_rdev);
386762306a36Sopenharmony_ci
386862306a36Sopenharmony_cistatic int regulator_limit_voltage_step(struct regulator_dev *rdev,
386962306a36Sopenharmony_ci					int *current_uV, int *min_uV)
387062306a36Sopenharmony_ci{
387162306a36Sopenharmony_ci	struct regulation_constraints *constraints = rdev->constraints;
387262306a36Sopenharmony_ci
387362306a36Sopenharmony_ci	/* Limit voltage change only if necessary */
387462306a36Sopenharmony_ci	if (!constraints->max_uV_step || !_regulator_is_enabled(rdev))
387562306a36Sopenharmony_ci		return 1;
387662306a36Sopenharmony_ci
387762306a36Sopenharmony_ci	if (*current_uV < 0) {
387862306a36Sopenharmony_ci		*current_uV = regulator_get_voltage_rdev(rdev);
387962306a36Sopenharmony_ci
388062306a36Sopenharmony_ci		if (*current_uV < 0)
388162306a36Sopenharmony_ci			return *current_uV;
388262306a36Sopenharmony_ci	}
388362306a36Sopenharmony_ci
388462306a36Sopenharmony_ci	if (abs(*current_uV - *min_uV) <= constraints->max_uV_step)
388562306a36Sopenharmony_ci		return 1;
388662306a36Sopenharmony_ci
388762306a36Sopenharmony_ci	/* Clamp target voltage within the given step */
388862306a36Sopenharmony_ci	if (*current_uV < *min_uV)
388962306a36Sopenharmony_ci		*min_uV = min(*current_uV + constraints->max_uV_step,
389062306a36Sopenharmony_ci			      *min_uV);
389162306a36Sopenharmony_ci	else
389262306a36Sopenharmony_ci		*min_uV = max(*current_uV - constraints->max_uV_step,
389362306a36Sopenharmony_ci			      *min_uV);
389462306a36Sopenharmony_ci
389562306a36Sopenharmony_ci	return 0;
389662306a36Sopenharmony_ci}
389762306a36Sopenharmony_ci
389862306a36Sopenharmony_cistatic int regulator_get_optimal_voltage(struct regulator_dev *rdev,
389962306a36Sopenharmony_ci					 int *current_uV,
390062306a36Sopenharmony_ci					 int *min_uV, int *max_uV,
390162306a36Sopenharmony_ci					 suspend_state_t state,
390262306a36Sopenharmony_ci					 int n_coupled)
390362306a36Sopenharmony_ci{
390462306a36Sopenharmony_ci	struct coupling_desc *c_desc = &rdev->coupling_desc;
390562306a36Sopenharmony_ci	struct regulator_dev **c_rdevs = c_desc->coupled_rdevs;
390662306a36Sopenharmony_ci	struct regulation_constraints *constraints = rdev->constraints;
390762306a36Sopenharmony_ci	int desired_min_uV = 0, desired_max_uV = INT_MAX;
390862306a36Sopenharmony_ci	int max_current_uV = 0, min_current_uV = INT_MAX;
390962306a36Sopenharmony_ci	int highest_min_uV = 0, target_uV, possible_uV;
391062306a36Sopenharmony_ci	int i, ret, max_spread;
391162306a36Sopenharmony_ci	bool done;
391262306a36Sopenharmony_ci
391362306a36Sopenharmony_ci	*current_uV = -1;
391462306a36Sopenharmony_ci
391562306a36Sopenharmony_ci	/*
391662306a36Sopenharmony_ci	 * If there are no coupled regulators, simply set the voltage
391762306a36Sopenharmony_ci	 * demanded by consumers.
391862306a36Sopenharmony_ci	 */
391962306a36Sopenharmony_ci	if (n_coupled == 1) {
392062306a36Sopenharmony_ci		/*
392162306a36Sopenharmony_ci		 * If consumers don't provide any demands, set voltage
392262306a36Sopenharmony_ci		 * to min_uV
392362306a36Sopenharmony_ci		 */
392462306a36Sopenharmony_ci		desired_min_uV = constraints->min_uV;
392562306a36Sopenharmony_ci		desired_max_uV = constraints->max_uV;
392662306a36Sopenharmony_ci
392762306a36Sopenharmony_ci		ret = regulator_check_consumers(rdev,
392862306a36Sopenharmony_ci						&desired_min_uV,
392962306a36Sopenharmony_ci						&desired_max_uV, state);
393062306a36Sopenharmony_ci		if (ret < 0)
393162306a36Sopenharmony_ci			return ret;
393262306a36Sopenharmony_ci
393362306a36Sopenharmony_ci		possible_uV = desired_min_uV;
393462306a36Sopenharmony_ci		done = true;
393562306a36Sopenharmony_ci
393662306a36Sopenharmony_ci		goto finish;
393762306a36Sopenharmony_ci	}
393862306a36Sopenharmony_ci
393962306a36Sopenharmony_ci	/* Find highest min desired voltage */
394062306a36Sopenharmony_ci	for (i = 0; i < n_coupled; i++) {
394162306a36Sopenharmony_ci		int tmp_min = 0;
394262306a36Sopenharmony_ci		int tmp_max = INT_MAX;
394362306a36Sopenharmony_ci
394462306a36Sopenharmony_ci		lockdep_assert_held_once(&c_rdevs[i]->mutex.base);
394562306a36Sopenharmony_ci
394662306a36Sopenharmony_ci		ret = regulator_check_consumers(c_rdevs[i],
394762306a36Sopenharmony_ci						&tmp_min,
394862306a36Sopenharmony_ci						&tmp_max, state);
394962306a36Sopenharmony_ci		if (ret < 0)
395062306a36Sopenharmony_ci			return ret;
395162306a36Sopenharmony_ci
395262306a36Sopenharmony_ci		ret = regulator_check_voltage(c_rdevs[i], &tmp_min, &tmp_max);
395362306a36Sopenharmony_ci		if (ret < 0)
395462306a36Sopenharmony_ci			return ret;
395562306a36Sopenharmony_ci
395662306a36Sopenharmony_ci		highest_min_uV = max(highest_min_uV, tmp_min);
395762306a36Sopenharmony_ci
395862306a36Sopenharmony_ci		if (i == 0) {
395962306a36Sopenharmony_ci			desired_min_uV = tmp_min;
396062306a36Sopenharmony_ci			desired_max_uV = tmp_max;
396162306a36Sopenharmony_ci		}
396262306a36Sopenharmony_ci	}
396362306a36Sopenharmony_ci
396462306a36Sopenharmony_ci	max_spread = constraints->max_spread[0];
396562306a36Sopenharmony_ci
396662306a36Sopenharmony_ci	/*
396762306a36Sopenharmony_ci	 * Let target_uV be equal to the desired one if possible.
396862306a36Sopenharmony_ci	 * If not, set it to minimum voltage, allowed by other coupled
396962306a36Sopenharmony_ci	 * regulators.
397062306a36Sopenharmony_ci	 */
397162306a36Sopenharmony_ci	target_uV = max(desired_min_uV, highest_min_uV - max_spread);
397262306a36Sopenharmony_ci
397362306a36Sopenharmony_ci	/*
397462306a36Sopenharmony_ci	 * Find min and max voltages, which currently aren't violating
397562306a36Sopenharmony_ci	 * max_spread.
397662306a36Sopenharmony_ci	 */
397762306a36Sopenharmony_ci	for (i = 1; i < n_coupled; i++) {
397862306a36Sopenharmony_ci		int tmp_act;
397962306a36Sopenharmony_ci
398062306a36Sopenharmony_ci		if (!_regulator_is_enabled(c_rdevs[i]))
398162306a36Sopenharmony_ci			continue;
398262306a36Sopenharmony_ci
398362306a36Sopenharmony_ci		tmp_act = regulator_get_voltage_rdev(c_rdevs[i]);
398462306a36Sopenharmony_ci		if (tmp_act < 0)
398562306a36Sopenharmony_ci			return tmp_act;
398662306a36Sopenharmony_ci
398762306a36Sopenharmony_ci		min_current_uV = min(tmp_act, min_current_uV);
398862306a36Sopenharmony_ci		max_current_uV = max(tmp_act, max_current_uV);
398962306a36Sopenharmony_ci	}
399062306a36Sopenharmony_ci
399162306a36Sopenharmony_ci	/* There aren't any other regulators enabled */
399262306a36Sopenharmony_ci	if (max_current_uV == 0) {
399362306a36Sopenharmony_ci		possible_uV = target_uV;
399462306a36Sopenharmony_ci	} else {
399562306a36Sopenharmony_ci		/*
399662306a36Sopenharmony_ci		 * Correct target voltage, so as it currently isn't
399762306a36Sopenharmony_ci		 * violating max_spread
399862306a36Sopenharmony_ci		 */
399962306a36Sopenharmony_ci		possible_uV = max(target_uV, max_current_uV - max_spread);
400062306a36Sopenharmony_ci		possible_uV = min(possible_uV, min_current_uV + max_spread);
400162306a36Sopenharmony_ci	}
400262306a36Sopenharmony_ci
400362306a36Sopenharmony_ci	if (possible_uV > desired_max_uV)
400462306a36Sopenharmony_ci		return -EINVAL;
400562306a36Sopenharmony_ci
400662306a36Sopenharmony_ci	done = (possible_uV == target_uV);
400762306a36Sopenharmony_ci	desired_min_uV = possible_uV;
400862306a36Sopenharmony_ci
400962306a36Sopenharmony_cifinish:
401062306a36Sopenharmony_ci	/* Apply max_uV_step constraint if necessary */
401162306a36Sopenharmony_ci	if (state == PM_SUSPEND_ON) {
401262306a36Sopenharmony_ci		ret = regulator_limit_voltage_step(rdev, current_uV,
401362306a36Sopenharmony_ci						   &desired_min_uV);
401462306a36Sopenharmony_ci		if (ret < 0)
401562306a36Sopenharmony_ci			return ret;
401662306a36Sopenharmony_ci
401762306a36Sopenharmony_ci		if (ret == 0)
401862306a36Sopenharmony_ci			done = false;
401962306a36Sopenharmony_ci	}
402062306a36Sopenharmony_ci
402162306a36Sopenharmony_ci	/* Set current_uV if wasn't done earlier in the code and if necessary */
402262306a36Sopenharmony_ci	if (n_coupled > 1 && *current_uV == -1) {
402362306a36Sopenharmony_ci
402462306a36Sopenharmony_ci		if (_regulator_is_enabled(rdev)) {
402562306a36Sopenharmony_ci			ret = regulator_get_voltage_rdev(rdev);
402662306a36Sopenharmony_ci			if (ret < 0)
402762306a36Sopenharmony_ci				return ret;
402862306a36Sopenharmony_ci
402962306a36Sopenharmony_ci			*current_uV = ret;
403062306a36Sopenharmony_ci		} else {
403162306a36Sopenharmony_ci			*current_uV = desired_min_uV;
403262306a36Sopenharmony_ci		}
403362306a36Sopenharmony_ci	}
403462306a36Sopenharmony_ci
403562306a36Sopenharmony_ci	*min_uV = desired_min_uV;
403662306a36Sopenharmony_ci	*max_uV = desired_max_uV;
403762306a36Sopenharmony_ci
403862306a36Sopenharmony_ci	return done;
403962306a36Sopenharmony_ci}
404062306a36Sopenharmony_ci
404162306a36Sopenharmony_ciint regulator_do_balance_voltage(struct regulator_dev *rdev,
404262306a36Sopenharmony_ci				 suspend_state_t state, bool skip_coupled)
404362306a36Sopenharmony_ci{
404462306a36Sopenharmony_ci	struct regulator_dev **c_rdevs;
404562306a36Sopenharmony_ci	struct regulator_dev *best_rdev;
404662306a36Sopenharmony_ci	struct coupling_desc *c_desc = &rdev->coupling_desc;
404762306a36Sopenharmony_ci	int i, ret, n_coupled, best_min_uV, best_max_uV, best_c_rdev;
404862306a36Sopenharmony_ci	unsigned int delta, best_delta;
404962306a36Sopenharmony_ci	unsigned long c_rdev_done = 0;
405062306a36Sopenharmony_ci	bool best_c_rdev_done;
405162306a36Sopenharmony_ci
405262306a36Sopenharmony_ci	c_rdevs = c_desc->coupled_rdevs;
405362306a36Sopenharmony_ci	n_coupled = skip_coupled ? 1 : c_desc->n_coupled;
405462306a36Sopenharmony_ci
405562306a36Sopenharmony_ci	/*
405662306a36Sopenharmony_ci	 * Find the best possible voltage change on each loop. Leave the loop
405762306a36Sopenharmony_ci	 * if there isn't any possible change.
405862306a36Sopenharmony_ci	 */
405962306a36Sopenharmony_ci	do {
406062306a36Sopenharmony_ci		best_c_rdev_done = false;
406162306a36Sopenharmony_ci		best_delta = 0;
406262306a36Sopenharmony_ci		best_min_uV = 0;
406362306a36Sopenharmony_ci		best_max_uV = 0;
406462306a36Sopenharmony_ci		best_c_rdev = 0;
406562306a36Sopenharmony_ci		best_rdev = NULL;
406662306a36Sopenharmony_ci
406762306a36Sopenharmony_ci		/*
406862306a36Sopenharmony_ci		 * Find highest difference between optimal voltage
406962306a36Sopenharmony_ci		 * and current voltage.
407062306a36Sopenharmony_ci		 */
407162306a36Sopenharmony_ci		for (i = 0; i < n_coupled; i++) {
407262306a36Sopenharmony_ci			/*
407362306a36Sopenharmony_ci			 * optimal_uV is the best voltage that can be set for
407462306a36Sopenharmony_ci			 * i-th regulator at the moment without violating
407562306a36Sopenharmony_ci			 * max_spread constraint in order to balance
407662306a36Sopenharmony_ci			 * the coupled voltages.
407762306a36Sopenharmony_ci			 */
407862306a36Sopenharmony_ci			int optimal_uV = 0, optimal_max_uV = 0, current_uV = 0;
407962306a36Sopenharmony_ci
408062306a36Sopenharmony_ci			if (test_bit(i, &c_rdev_done))
408162306a36Sopenharmony_ci				continue;
408262306a36Sopenharmony_ci
408362306a36Sopenharmony_ci			ret = regulator_get_optimal_voltage(c_rdevs[i],
408462306a36Sopenharmony_ci							    &current_uV,
408562306a36Sopenharmony_ci							    &optimal_uV,
408662306a36Sopenharmony_ci							    &optimal_max_uV,
408762306a36Sopenharmony_ci							    state, n_coupled);
408862306a36Sopenharmony_ci			if (ret < 0)
408962306a36Sopenharmony_ci				goto out;
409062306a36Sopenharmony_ci
409162306a36Sopenharmony_ci			delta = abs(optimal_uV - current_uV);
409262306a36Sopenharmony_ci
409362306a36Sopenharmony_ci			if (delta && best_delta <= delta) {
409462306a36Sopenharmony_ci				best_c_rdev_done = ret;
409562306a36Sopenharmony_ci				best_delta = delta;
409662306a36Sopenharmony_ci				best_rdev = c_rdevs[i];
409762306a36Sopenharmony_ci				best_min_uV = optimal_uV;
409862306a36Sopenharmony_ci				best_max_uV = optimal_max_uV;
409962306a36Sopenharmony_ci				best_c_rdev = i;
410062306a36Sopenharmony_ci			}
410162306a36Sopenharmony_ci		}
410262306a36Sopenharmony_ci
410362306a36Sopenharmony_ci		/* Nothing to change, return successfully */
410462306a36Sopenharmony_ci		if (!best_rdev) {
410562306a36Sopenharmony_ci			ret = 0;
410662306a36Sopenharmony_ci			goto out;
410762306a36Sopenharmony_ci		}
410862306a36Sopenharmony_ci
410962306a36Sopenharmony_ci		ret = regulator_set_voltage_rdev(best_rdev, best_min_uV,
411062306a36Sopenharmony_ci						 best_max_uV, state);
411162306a36Sopenharmony_ci
411262306a36Sopenharmony_ci		if (ret < 0)
411362306a36Sopenharmony_ci			goto out;
411462306a36Sopenharmony_ci
411562306a36Sopenharmony_ci		if (best_c_rdev_done)
411662306a36Sopenharmony_ci			set_bit(best_c_rdev, &c_rdev_done);
411762306a36Sopenharmony_ci
411862306a36Sopenharmony_ci	} while (n_coupled > 1);
411962306a36Sopenharmony_ci
412062306a36Sopenharmony_ciout:
412162306a36Sopenharmony_ci	return ret;
412262306a36Sopenharmony_ci}
412362306a36Sopenharmony_ci
412462306a36Sopenharmony_cistatic int regulator_balance_voltage(struct regulator_dev *rdev,
412562306a36Sopenharmony_ci				     suspend_state_t state)
412662306a36Sopenharmony_ci{
412762306a36Sopenharmony_ci	struct coupling_desc *c_desc = &rdev->coupling_desc;
412862306a36Sopenharmony_ci	struct regulator_coupler *coupler = c_desc->coupler;
412962306a36Sopenharmony_ci	bool skip_coupled = false;
413062306a36Sopenharmony_ci
413162306a36Sopenharmony_ci	/*
413262306a36Sopenharmony_ci	 * If system is in a state other than PM_SUSPEND_ON, don't check
413362306a36Sopenharmony_ci	 * other coupled regulators.
413462306a36Sopenharmony_ci	 */
413562306a36Sopenharmony_ci	if (state != PM_SUSPEND_ON)
413662306a36Sopenharmony_ci		skip_coupled = true;
413762306a36Sopenharmony_ci
413862306a36Sopenharmony_ci	if (c_desc->n_resolved < c_desc->n_coupled) {
413962306a36Sopenharmony_ci		rdev_err(rdev, "Not all coupled regulators registered\n");
414062306a36Sopenharmony_ci		return -EPERM;
414162306a36Sopenharmony_ci	}
414262306a36Sopenharmony_ci
414362306a36Sopenharmony_ci	/* Invoke custom balancer for customized couplers */
414462306a36Sopenharmony_ci	if (coupler && coupler->balance_voltage)
414562306a36Sopenharmony_ci		return coupler->balance_voltage(coupler, rdev, state);
414662306a36Sopenharmony_ci
414762306a36Sopenharmony_ci	return regulator_do_balance_voltage(rdev, state, skip_coupled);
414862306a36Sopenharmony_ci}
414962306a36Sopenharmony_ci
415062306a36Sopenharmony_ci/**
415162306a36Sopenharmony_ci * regulator_set_voltage - set regulator output voltage
415262306a36Sopenharmony_ci * @regulator: regulator source
415362306a36Sopenharmony_ci * @min_uV: Minimum required voltage in uV
415462306a36Sopenharmony_ci * @max_uV: Maximum acceptable voltage in uV
415562306a36Sopenharmony_ci *
415662306a36Sopenharmony_ci * Sets a voltage regulator to the desired output voltage. This can be set
415762306a36Sopenharmony_ci * during any regulator state. IOW, regulator can be disabled or enabled.
415862306a36Sopenharmony_ci *
415962306a36Sopenharmony_ci * If the regulator is enabled then the voltage will change to the new value
416062306a36Sopenharmony_ci * immediately otherwise if the regulator is disabled the regulator will
416162306a36Sopenharmony_ci * output at the new voltage when enabled.
416262306a36Sopenharmony_ci *
416362306a36Sopenharmony_ci * NOTE: If the regulator is shared between several devices then the lowest
416462306a36Sopenharmony_ci * request voltage that meets the system constraints will be used.
416562306a36Sopenharmony_ci * Regulator system constraints must be set for this regulator before
416662306a36Sopenharmony_ci * calling this function otherwise this call will fail.
416762306a36Sopenharmony_ci */
416862306a36Sopenharmony_ciint regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
416962306a36Sopenharmony_ci{
417062306a36Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
417162306a36Sopenharmony_ci	int ret;
417262306a36Sopenharmony_ci
417362306a36Sopenharmony_ci	regulator_lock_dependent(regulator->rdev, &ww_ctx);
417462306a36Sopenharmony_ci
417562306a36Sopenharmony_ci	ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV,
417662306a36Sopenharmony_ci					     PM_SUSPEND_ON);
417762306a36Sopenharmony_ci
417862306a36Sopenharmony_ci	regulator_unlock_dependent(regulator->rdev, &ww_ctx);
417962306a36Sopenharmony_ci
418062306a36Sopenharmony_ci	return ret;
418162306a36Sopenharmony_ci}
418262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_voltage);
418362306a36Sopenharmony_ci
418462306a36Sopenharmony_cistatic inline int regulator_suspend_toggle(struct regulator_dev *rdev,
418562306a36Sopenharmony_ci					   suspend_state_t state, bool en)
418662306a36Sopenharmony_ci{
418762306a36Sopenharmony_ci	struct regulator_state *rstate;
418862306a36Sopenharmony_ci
418962306a36Sopenharmony_ci	rstate = regulator_get_suspend_state(rdev, state);
419062306a36Sopenharmony_ci	if (rstate == NULL)
419162306a36Sopenharmony_ci		return -EINVAL;
419262306a36Sopenharmony_ci
419362306a36Sopenharmony_ci	if (!rstate->changeable)
419462306a36Sopenharmony_ci		return -EPERM;
419562306a36Sopenharmony_ci
419662306a36Sopenharmony_ci	rstate->enabled = (en) ? ENABLE_IN_SUSPEND : DISABLE_IN_SUSPEND;
419762306a36Sopenharmony_ci
419862306a36Sopenharmony_ci	return 0;
419962306a36Sopenharmony_ci}
420062306a36Sopenharmony_ci
420162306a36Sopenharmony_ciint regulator_suspend_enable(struct regulator_dev *rdev,
420262306a36Sopenharmony_ci				    suspend_state_t state)
420362306a36Sopenharmony_ci{
420462306a36Sopenharmony_ci	return regulator_suspend_toggle(rdev, state, true);
420562306a36Sopenharmony_ci}
420662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_suspend_enable);
420762306a36Sopenharmony_ci
420862306a36Sopenharmony_ciint regulator_suspend_disable(struct regulator_dev *rdev,
420962306a36Sopenharmony_ci				     suspend_state_t state)
421062306a36Sopenharmony_ci{
421162306a36Sopenharmony_ci	struct regulator *regulator;
421262306a36Sopenharmony_ci	struct regulator_voltage *voltage;
421362306a36Sopenharmony_ci
421462306a36Sopenharmony_ci	/*
421562306a36Sopenharmony_ci	 * if any consumer wants this regulator device keeping on in
421662306a36Sopenharmony_ci	 * suspend states, don't set it as disabled.
421762306a36Sopenharmony_ci	 */
421862306a36Sopenharmony_ci	list_for_each_entry(regulator, &rdev->consumer_list, list) {
421962306a36Sopenharmony_ci		voltage = &regulator->voltage[state];
422062306a36Sopenharmony_ci		if (voltage->min_uV || voltage->max_uV)
422162306a36Sopenharmony_ci			return 0;
422262306a36Sopenharmony_ci	}
422362306a36Sopenharmony_ci
422462306a36Sopenharmony_ci	return regulator_suspend_toggle(rdev, state, false);
422562306a36Sopenharmony_ci}
422662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_suspend_disable);
422762306a36Sopenharmony_ci
422862306a36Sopenharmony_cistatic int _regulator_set_suspend_voltage(struct regulator *regulator,
422962306a36Sopenharmony_ci					  int min_uV, int max_uV,
423062306a36Sopenharmony_ci					  suspend_state_t state)
423162306a36Sopenharmony_ci{
423262306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
423362306a36Sopenharmony_ci	struct regulator_state *rstate;
423462306a36Sopenharmony_ci
423562306a36Sopenharmony_ci	rstate = regulator_get_suspend_state(rdev, state);
423662306a36Sopenharmony_ci	if (rstate == NULL)
423762306a36Sopenharmony_ci		return -EINVAL;
423862306a36Sopenharmony_ci
423962306a36Sopenharmony_ci	if (rstate->min_uV == rstate->max_uV) {
424062306a36Sopenharmony_ci		rdev_err(rdev, "The suspend voltage can't be changed!\n");
424162306a36Sopenharmony_ci		return -EPERM;
424262306a36Sopenharmony_ci	}
424362306a36Sopenharmony_ci
424462306a36Sopenharmony_ci	return regulator_set_voltage_unlocked(regulator, min_uV, max_uV, state);
424562306a36Sopenharmony_ci}
424662306a36Sopenharmony_ci
424762306a36Sopenharmony_ciint regulator_set_suspend_voltage(struct regulator *regulator, int min_uV,
424862306a36Sopenharmony_ci				  int max_uV, suspend_state_t state)
424962306a36Sopenharmony_ci{
425062306a36Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
425162306a36Sopenharmony_ci	int ret;
425262306a36Sopenharmony_ci
425362306a36Sopenharmony_ci	/* PM_SUSPEND_ON is handled by regulator_set_voltage() */
425462306a36Sopenharmony_ci	if (regulator_check_states(state) || state == PM_SUSPEND_ON)
425562306a36Sopenharmony_ci		return -EINVAL;
425662306a36Sopenharmony_ci
425762306a36Sopenharmony_ci	regulator_lock_dependent(regulator->rdev, &ww_ctx);
425862306a36Sopenharmony_ci
425962306a36Sopenharmony_ci	ret = _regulator_set_suspend_voltage(regulator, min_uV,
426062306a36Sopenharmony_ci					     max_uV, state);
426162306a36Sopenharmony_ci
426262306a36Sopenharmony_ci	regulator_unlock_dependent(regulator->rdev, &ww_ctx);
426362306a36Sopenharmony_ci
426462306a36Sopenharmony_ci	return ret;
426562306a36Sopenharmony_ci}
426662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_suspend_voltage);
426762306a36Sopenharmony_ci
426862306a36Sopenharmony_ci/**
426962306a36Sopenharmony_ci * regulator_set_voltage_time - get raise/fall time
427062306a36Sopenharmony_ci * @regulator: regulator source
427162306a36Sopenharmony_ci * @old_uV: starting voltage in microvolts
427262306a36Sopenharmony_ci * @new_uV: target voltage in microvolts
427362306a36Sopenharmony_ci *
427462306a36Sopenharmony_ci * Provided with the starting and ending voltage, this function attempts to
427562306a36Sopenharmony_ci * calculate the time in microseconds required to rise or fall to this new
427662306a36Sopenharmony_ci * voltage.
427762306a36Sopenharmony_ci */
427862306a36Sopenharmony_ciint regulator_set_voltage_time(struct regulator *regulator,
427962306a36Sopenharmony_ci			       int old_uV, int new_uV)
428062306a36Sopenharmony_ci{
428162306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
428262306a36Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
428362306a36Sopenharmony_ci	int old_sel = -1;
428462306a36Sopenharmony_ci	int new_sel = -1;
428562306a36Sopenharmony_ci	int voltage;
428662306a36Sopenharmony_ci	int i;
428762306a36Sopenharmony_ci
428862306a36Sopenharmony_ci	if (ops->set_voltage_time)
428962306a36Sopenharmony_ci		return ops->set_voltage_time(rdev, old_uV, new_uV);
429062306a36Sopenharmony_ci	else if (!ops->set_voltage_time_sel)
429162306a36Sopenharmony_ci		return _regulator_set_voltage_time(rdev, old_uV, new_uV);
429262306a36Sopenharmony_ci
429362306a36Sopenharmony_ci	/* Currently requires operations to do this */
429462306a36Sopenharmony_ci	if (!ops->list_voltage || !rdev->desc->n_voltages)
429562306a36Sopenharmony_ci		return -EINVAL;
429662306a36Sopenharmony_ci
429762306a36Sopenharmony_ci	for (i = 0; i < rdev->desc->n_voltages; i++) {
429862306a36Sopenharmony_ci		/* We only look for exact voltage matches here */
429962306a36Sopenharmony_ci		if (i < rdev->desc->linear_min_sel)
430062306a36Sopenharmony_ci			continue;
430162306a36Sopenharmony_ci
430262306a36Sopenharmony_ci		if (old_sel >= 0 && new_sel >= 0)
430362306a36Sopenharmony_ci			break;
430462306a36Sopenharmony_ci
430562306a36Sopenharmony_ci		voltage = regulator_list_voltage(regulator, i);
430662306a36Sopenharmony_ci		if (voltage < 0)
430762306a36Sopenharmony_ci			return -EINVAL;
430862306a36Sopenharmony_ci		if (voltage == 0)
430962306a36Sopenharmony_ci			continue;
431062306a36Sopenharmony_ci		if (voltage == old_uV)
431162306a36Sopenharmony_ci			old_sel = i;
431262306a36Sopenharmony_ci		if (voltage == new_uV)
431362306a36Sopenharmony_ci			new_sel = i;
431462306a36Sopenharmony_ci	}
431562306a36Sopenharmony_ci
431662306a36Sopenharmony_ci	if (old_sel < 0 || new_sel < 0)
431762306a36Sopenharmony_ci		return -EINVAL;
431862306a36Sopenharmony_ci
431962306a36Sopenharmony_ci	return ops->set_voltage_time_sel(rdev, old_sel, new_sel);
432062306a36Sopenharmony_ci}
432162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_voltage_time);
432262306a36Sopenharmony_ci
432362306a36Sopenharmony_ci/**
432462306a36Sopenharmony_ci * regulator_set_voltage_time_sel - get raise/fall time
432562306a36Sopenharmony_ci * @rdev: regulator source device
432662306a36Sopenharmony_ci * @old_selector: selector for starting voltage
432762306a36Sopenharmony_ci * @new_selector: selector for target voltage
432862306a36Sopenharmony_ci *
432962306a36Sopenharmony_ci * Provided with the starting and target voltage selectors, this function
433062306a36Sopenharmony_ci * returns time in microseconds required to rise or fall to this new voltage
433162306a36Sopenharmony_ci *
433262306a36Sopenharmony_ci * Drivers providing ramp_delay in regulation_constraints can use this as their
433362306a36Sopenharmony_ci * set_voltage_time_sel() operation.
433462306a36Sopenharmony_ci */
433562306a36Sopenharmony_ciint regulator_set_voltage_time_sel(struct regulator_dev *rdev,
433662306a36Sopenharmony_ci				   unsigned int old_selector,
433762306a36Sopenharmony_ci				   unsigned int new_selector)
433862306a36Sopenharmony_ci{
433962306a36Sopenharmony_ci	int old_volt, new_volt;
434062306a36Sopenharmony_ci
434162306a36Sopenharmony_ci	/* sanity check */
434262306a36Sopenharmony_ci	if (!rdev->desc->ops->list_voltage)
434362306a36Sopenharmony_ci		return -EINVAL;
434462306a36Sopenharmony_ci
434562306a36Sopenharmony_ci	old_volt = rdev->desc->ops->list_voltage(rdev, old_selector);
434662306a36Sopenharmony_ci	new_volt = rdev->desc->ops->list_voltage(rdev, new_selector);
434762306a36Sopenharmony_ci
434862306a36Sopenharmony_ci	if (rdev->desc->ops->set_voltage_time)
434962306a36Sopenharmony_ci		return rdev->desc->ops->set_voltage_time(rdev, old_volt,
435062306a36Sopenharmony_ci							 new_volt);
435162306a36Sopenharmony_ci	else
435262306a36Sopenharmony_ci		return _regulator_set_voltage_time(rdev, old_volt, new_volt);
435362306a36Sopenharmony_ci}
435462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel);
435562306a36Sopenharmony_ci
435662306a36Sopenharmony_ciint regulator_sync_voltage_rdev(struct regulator_dev *rdev)
435762306a36Sopenharmony_ci{
435862306a36Sopenharmony_ci	int ret;
435962306a36Sopenharmony_ci
436062306a36Sopenharmony_ci	regulator_lock(rdev);
436162306a36Sopenharmony_ci
436262306a36Sopenharmony_ci	if (!rdev->desc->ops->set_voltage &&
436362306a36Sopenharmony_ci	    !rdev->desc->ops->set_voltage_sel) {
436462306a36Sopenharmony_ci		ret = -EINVAL;
436562306a36Sopenharmony_ci		goto out;
436662306a36Sopenharmony_ci	}
436762306a36Sopenharmony_ci
436862306a36Sopenharmony_ci	/* balance only, if regulator is coupled */
436962306a36Sopenharmony_ci	if (rdev->coupling_desc.n_coupled > 1)
437062306a36Sopenharmony_ci		ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
437162306a36Sopenharmony_ci	else
437262306a36Sopenharmony_ci		ret = -EOPNOTSUPP;
437362306a36Sopenharmony_ci
437462306a36Sopenharmony_ciout:
437562306a36Sopenharmony_ci	regulator_unlock(rdev);
437662306a36Sopenharmony_ci	return ret;
437762306a36Sopenharmony_ci}
437862306a36Sopenharmony_ci
437962306a36Sopenharmony_ci/**
438062306a36Sopenharmony_ci * regulator_sync_voltage - re-apply last regulator output voltage
438162306a36Sopenharmony_ci * @regulator: regulator source
438262306a36Sopenharmony_ci *
438362306a36Sopenharmony_ci * Re-apply the last configured voltage.  This is intended to be used
438462306a36Sopenharmony_ci * where some external control source the consumer is cooperating with
438562306a36Sopenharmony_ci * has caused the configured voltage to change.
438662306a36Sopenharmony_ci */
438762306a36Sopenharmony_ciint regulator_sync_voltage(struct regulator *regulator)
438862306a36Sopenharmony_ci{
438962306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
439062306a36Sopenharmony_ci	struct regulator_voltage *voltage = &regulator->voltage[PM_SUSPEND_ON];
439162306a36Sopenharmony_ci	int ret, min_uV, max_uV;
439262306a36Sopenharmony_ci
439362306a36Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE))
439462306a36Sopenharmony_ci		return 0;
439562306a36Sopenharmony_ci
439662306a36Sopenharmony_ci	regulator_lock(rdev);
439762306a36Sopenharmony_ci
439862306a36Sopenharmony_ci	if (!rdev->desc->ops->set_voltage &&
439962306a36Sopenharmony_ci	    !rdev->desc->ops->set_voltage_sel) {
440062306a36Sopenharmony_ci		ret = -EINVAL;
440162306a36Sopenharmony_ci		goto out;
440262306a36Sopenharmony_ci	}
440362306a36Sopenharmony_ci
440462306a36Sopenharmony_ci	/* This is only going to work if we've had a voltage configured. */
440562306a36Sopenharmony_ci	if (!voltage->min_uV && !voltage->max_uV) {
440662306a36Sopenharmony_ci		ret = -EINVAL;
440762306a36Sopenharmony_ci		goto out;
440862306a36Sopenharmony_ci	}
440962306a36Sopenharmony_ci
441062306a36Sopenharmony_ci	min_uV = voltage->min_uV;
441162306a36Sopenharmony_ci	max_uV = voltage->max_uV;
441262306a36Sopenharmony_ci
441362306a36Sopenharmony_ci	/* This should be a paranoia check... */
441462306a36Sopenharmony_ci	ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
441562306a36Sopenharmony_ci	if (ret < 0)
441662306a36Sopenharmony_ci		goto out;
441762306a36Sopenharmony_ci
441862306a36Sopenharmony_ci	ret = regulator_check_consumers(rdev, &min_uV, &max_uV, 0);
441962306a36Sopenharmony_ci	if (ret < 0)
442062306a36Sopenharmony_ci		goto out;
442162306a36Sopenharmony_ci
442262306a36Sopenharmony_ci	/* balance only, if regulator is coupled */
442362306a36Sopenharmony_ci	if (rdev->coupling_desc.n_coupled > 1)
442462306a36Sopenharmony_ci		ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
442562306a36Sopenharmony_ci	else
442662306a36Sopenharmony_ci		ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
442762306a36Sopenharmony_ci
442862306a36Sopenharmony_ciout:
442962306a36Sopenharmony_ci	regulator_unlock(rdev);
443062306a36Sopenharmony_ci	return ret;
443162306a36Sopenharmony_ci}
443262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_sync_voltage);
443362306a36Sopenharmony_ci
443462306a36Sopenharmony_ciint regulator_get_voltage_rdev(struct regulator_dev *rdev)
443562306a36Sopenharmony_ci{
443662306a36Sopenharmony_ci	int sel, ret;
443762306a36Sopenharmony_ci	bool bypassed;
443862306a36Sopenharmony_ci
443962306a36Sopenharmony_ci	if (rdev->desc->ops->get_bypass) {
444062306a36Sopenharmony_ci		ret = rdev->desc->ops->get_bypass(rdev, &bypassed);
444162306a36Sopenharmony_ci		if (ret < 0)
444262306a36Sopenharmony_ci			return ret;
444362306a36Sopenharmony_ci		if (bypassed) {
444462306a36Sopenharmony_ci			/* if bypassed the regulator must have a supply */
444562306a36Sopenharmony_ci			if (!rdev->supply) {
444662306a36Sopenharmony_ci				rdev_err(rdev,
444762306a36Sopenharmony_ci					 "bypassed regulator has no supply!\n");
444862306a36Sopenharmony_ci				return -EPROBE_DEFER;
444962306a36Sopenharmony_ci			}
445062306a36Sopenharmony_ci
445162306a36Sopenharmony_ci			return regulator_get_voltage_rdev(rdev->supply->rdev);
445262306a36Sopenharmony_ci		}
445362306a36Sopenharmony_ci	}
445462306a36Sopenharmony_ci
445562306a36Sopenharmony_ci	if (rdev->desc->ops->get_voltage_sel) {
445662306a36Sopenharmony_ci		sel = rdev->desc->ops->get_voltage_sel(rdev);
445762306a36Sopenharmony_ci		if (sel < 0)
445862306a36Sopenharmony_ci			return sel;
445962306a36Sopenharmony_ci		ret = rdev->desc->ops->list_voltage(rdev, sel);
446062306a36Sopenharmony_ci	} else if (rdev->desc->ops->get_voltage) {
446162306a36Sopenharmony_ci		ret = rdev->desc->ops->get_voltage(rdev);
446262306a36Sopenharmony_ci	} else if (rdev->desc->ops->list_voltage) {
446362306a36Sopenharmony_ci		ret = rdev->desc->ops->list_voltage(rdev, 0);
446462306a36Sopenharmony_ci	} else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) {
446562306a36Sopenharmony_ci		ret = rdev->desc->fixed_uV;
446662306a36Sopenharmony_ci	} else if (rdev->supply) {
446762306a36Sopenharmony_ci		ret = regulator_get_voltage_rdev(rdev->supply->rdev);
446862306a36Sopenharmony_ci	} else if (rdev->supply_name) {
446962306a36Sopenharmony_ci		return -EPROBE_DEFER;
447062306a36Sopenharmony_ci	} else {
447162306a36Sopenharmony_ci		return -EINVAL;
447262306a36Sopenharmony_ci	}
447362306a36Sopenharmony_ci
447462306a36Sopenharmony_ci	if (ret < 0)
447562306a36Sopenharmony_ci		return ret;
447662306a36Sopenharmony_ci	return ret - rdev->constraints->uV_offset;
447762306a36Sopenharmony_ci}
447862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_voltage_rdev);
447962306a36Sopenharmony_ci
448062306a36Sopenharmony_ci/**
448162306a36Sopenharmony_ci * regulator_get_voltage - get regulator output voltage
448262306a36Sopenharmony_ci * @regulator: regulator source
448362306a36Sopenharmony_ci *
448462306a36Sopenharmony_ci * This returns the current regulator voltage in uV.
448562306a36Sopenharmony_ci *
448662306a36Sopenharmony_ci * NOTE: If the regulator is disabled it will return the voltage value. This
448762306a36Sopenharmony_ci * function should not be used to determine regulator state.
448862306a36Sopenharmony_ci */
448962306a36Sopenharmony_ciint regulator_get_voltage(struct regulator *regulator)
449062306a36Sopenharmony_ci{
449162306a36Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
449262306a36Sopenharmony_ci	int ret;
449362306a36Sopenharmony_ci
449462306a36Sopenharmony_ci	regulator_lock_dependent(regulator->rdev, &ww_ctx);
449562306a36Sopenharmony_ci	ret = regulator_get_voltage_rdev(regulator->rdev);
449662306a36Sopenharmony_ci	regulator_unlock_dependent(regulator->rdev, &ww_ctx);
449762306a36Sopenharmony_ci
449862306a36Sopenharmony_ci	return ret;
449962306a36Sopenharmony_ci}
450062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_voltage);
450162306a36Sopenharmony_ci
450262306a36Sopenharmony_ci/**
450362306a36Sopenharmony_ci * regulator_set_current_limit - set regulator output current limit
450462306a36Sopenharmony_ci * @regulator: regulator source
450562306a36Sopenharmony_ci * @min_uA: Minimum supported current in uA
450662306a36Sopenharmony_ci * @max_uA: Maximum supported current in uA
450762306a36Sopenharmony_ci *
450862306a36Sopenharmony_ci * Sets current sink to the desired output current. This can be set during
450962306a36Sopenharmony_ci * any regulator state. IOW, regulator can be disabled or enabled.
451062306a36Sopenharmony_ci *
451162306a36Sopenharmony_ci * If the regulator is enabled then the current will change to the new value
451262306a36Sopenharmony_ci * immediately otherwise if the regulator is disabled the regulator will
451362306a36Sopenharmony_ci * output at the new current when enabled.
451462306a36Sopenharmony_ci *
451562306a36Sopenharmony_ci * NOTE: Regulator system constraints must be set for this regulator before
451662306a36Sopenharmony_ci * calling this function otherwise this call will fail.
451762306a36Sopenharmony_ci */
451862306a36Sopenharmony_ciint regulator_set_current_limit(struct regulator *regulator,
451962306a36Sopenharmony_ci			       int min_uA, int max_uA)
452062306a36Sopenharmony_ci{
452162306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
452262306a36Sopenharmony_ci	int ret;
452362306a36Sopenharmony_ci
452462306a36Sopenharmony_ci	regulator_lock(rdev);
452562306a36Sopenharmony_ci
452662306a36Sopenharmony_ci	/* sanity check */
452762306a36Sopenharmony_ci	if (!rdev->desc->ops->set_current_limit) {
452862306a36Sopenharmony_ci		ret = -EINVAL;
452962306a36Sopenharmony_ci		goto out;
453062306a36Sopenharmony_ci	}
453162306a36Sopenharmony_ci
453262306a36Sopenharmony_ci	/* constraints check */
453362306a36Sopenharmony_ci	ret = regulator_check_current_limit(rdev, &min_uA, &max_uA);
453462306a36Sopenharmony_ci	if (ret < 0)
453562306a36Sopenharmony_ci		goto out;
453662306a36Sopenharmony_ci
453762306a36Sopenharmony_ci	ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA);
453862306a36Sopenharmony_ciout:
453962306a36Sopenharmony_ci	regulator_unlock(rdev);
454062306a36Sopenharmony_ci	return ret;
454162306a36Sopenharmony_ci}
454262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_current_limit);
454362306a36Sopenharmony_ci
454462306a36Sopenharmony_cistatic int _regulator_get_current_limit_unlocked(struct regulator_dev *rdev)
454562306a36Sopenharmony_ci{
454662306a36Sopenharmony_ci	/* sanity check */
454762306a36Sopenharmony_ci	if (!rdev->desc->ops->get_current_limit)
454862306a36Sopenharmony_ci		return -EINVAL;
454962306a36Sopenharmony_ci
455062306a36Sopenharmony_ci	return rdev->desc->ops->get_current_limit(rdev);
455162306a36Sopenharmony_ci}
455262306a36Sopenharmony_ci
455362306a36Sopenharmony_cistatic int _regulator_get_current_limit(struct regulator_dev *rdev)
455462306a36Sopenharmony_ci{
455562306a36Sopenharmony_ci	int ret;
455662306a36Sopenharmony_ci
455762306a36Sopenharmony_ci	regulator_lock(rdev);
455862306a36Sopenharmony_ci	ret = _regulator_get_current_limit_unlocked(rdev);
455962306a36Sopenharmony_ci	regulator_unlock(rdev);
456062306a36Sopenharmony_ci
456162306a36Sopenharmony_ci	return ret;
456262306a36Sopenharmony_ci}
456362306a36Sopenharmony_ci
456462306a36Sopenharmony_ci/**
456562306a36Sopenharmony_ci * regulator_get_current_limit - get regulator output current
456662306a36Sopenharmony_ci * @regulator: regulator source
456762306a36Sopenharmony_ci *
456862306a36Sopenharmony_ci * This returns the current supplied by the specified current sink in uA.
456962306a36Sopenharmony_ci *
457062306a36Sopenharmony_ci * NOTE: If the regulator is disabled it will return the current value. This
457162306a36Sopenharmony_ci * function should not be used to determine regulator state.
457262306a36Sopenharmony_ci */
457362306a36Sopenharmony_ciint regulator_get_current_limit(struct regulator *regulator)
457462306a36Sopenharmony_ci{
457562306a36Sopenharmony_ci	return _regulator_get_current_limit(regulator->rdev);
457662306a36Sopenharmony_ci}
457762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_current_limit);
457862306a36Sopenharmony_ci
457962306a36Sopenharmony_ci/**
458062306a36Sopenharmony_ci * regulator_set_mode - set regulator operating mode
458162306a36Sopenharmony_ci * @regulator: regulator source
458262306a36Sopenharmony_ci * @mode: operating mode - one of the REGULATOR_MODE constants
458362306a36Sopenharmony_ci *
458462306a36Sopenharmony_ci * Set regulator operating mode to increase regulator efficiency or improve
458562306a36Sopenharmony_ci * regulation performance.
458662306a36Sopenharmony_ci *
458762306a36Sopenharmony_ci * NOTE: Regulator system constraints must be set for this regulator before
458862306a36Sopenharmony_ci * calling this function otherwise this call will fail.
458962306a36Sopenharmony_ci */
459062306a36Sopenharmony_ciint regulator_set_mode(struct regulator *regulator, unsigned int mode)
459162306a36Sopenharmony_ci{
459262306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
459362306a36Sopenharmony_ci	int ret;
459462306a36Sopenharmony_ci	int regulator_curr_mode;
459562306a36Sopenharmony_ci
459662306a36Sopenharmony_ci	regulator_lock(rdev);
459762306a36Sopenharmony_ci
459862306a36Sopenharmony_ci	/* sanity check */
459962306a36Sopenharmony_ci	if (!rdev->desc->ops->set_mode) {
460062306a36Sopenharmony_ci		ret = -EINVAL;
460162306a36Sopenharmony_ci		goto out;
460262306a36Sopenharmony_ci	}
460362306a36Sopenharmony_ci
460462306a36Sopenharmony_ci	/* return if the same mode is requested */
460562306a36Sopenharmony_ci	if (rdev->desc->ops->get_mode) {
460662306a36Sopenharmony_ci		regulator_curr_mode = rdev->desc->ops->get_mode(rdev);
460762306a36Sopenharmony_ci		if (regulator_curr_mode == mode) {
460862306a36Sopenharmony_ci			ret = 0;
460962306a36Sopenharmony_ci			goto out;
461062306a36Sopenharmony_ci		}
461162306a36Sopenharmony_ci	}
461262306a36Sopenharmony_ci
461362306a36Sopenharmony_ci	/* constraints check */
461462306a36Sopenharmony_ci	ret = regulator_mode_constrain(rdev, &mode);
461562306a36Sopenharmony_ci	if (ret < 0)
461662306a36Sopenharmony_ci		goto out;
461762306a36Sopenharmony_ci
461862306a36Sopenharmony_ci	ret = rdev->desc->ops->set_mode(rdev, mode);
461962306a36Sopenharmony_ciout:
462062306a36Sopenharmony_ci	regulator_unlock(rdev);
462162306a36Sopenharmony_ci	return ret;
462262306a36Sopenharmony_ci}
462362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_mode);
462462306a36Sopenharmony_ci
462562306a36Sopenharmony_cistatic unsigned int _regulator_get_mode_unlocked(struct regulator_dev *rdev)
462662306a36Sopenharmony_ci{
462762306a36Sopenharmony_ci	/* sanity check */
462862306a36Sopenharmony_ci	if (!rdev->desc->ops->get_mode)
462962306a36Sopenharmony_ci		return -EINVAL;
463062306a36Sopenharmony_ci
463162306a36Sopenharmony_ci	return rdev->desc->ops->get_mode(rdev);
463262306a36Sopenharmony_ci}
463362306a36Sopenharmony_ci
463462306a36Sopenharmony_cistatic unsigned int _regulator_get_mode(struct regulator_dev *rdev)
463562306a36Sopenharmony_ci{
463662306a36Sopenharmony_ci	int ret;
463762306a36Sopenharmony_ci
463862306a36Sopenharmony_ci	regulator_lock(rdev);
463962306a36Sopenharmony_ci	ret = _regulator_get_mode_unlocked(rdev);
464062306a36Sopenharmony_ci	regulator_unlock(rdev);
464162306a36Sopenharmony_ci
464262306a36Sopenharmony_ci	return ret;
464362306a36Sopenharmony_ci}
464462306a36Sopenharmony_ci
464562306a36Sopenharmony_ci/**
464662306a36Sopenharmony_ci * regulator_get_mode - get regulator operating mode
464762306a36Sopenharmony_ci * @regulator: regulator source
464862306a36Sopenharmony_ci *
464962306a36Sopenharmony_ci * Get the current regulator operating mode.
465062306a36Sopenharmony_ci */
465162306a36Sopenharmony_ciunsigned int regulator_get_mode(struct regulator *regulator)
465262306a36Sopenharmony_ci{
465362306a36Sopenharmony_ci	return _regulator_get_mode(regulator->rdev);
465462306a36Sopenharmony_ci}
465562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_mode);
465662306a36Sopenharmony_ci
465762306a36Sopenharmony_cistatic int rdev_get_cached_err_flags(struct regulator_dev *rdev)
465862306a36Sopenharmony_ci{
465962306a36Sopenharmony_ci	int ret = 0;
466062306a36Sopenharmony_ci
466162306a36Sopenharmony_ci	if (rdev->use_cached_err) {
466262306a36Sopenharmony_ci		spin_lock(&rdev->err_lock);
466362306a36Sopenharmony_ci		ret = rdev->cached_err;
466462306a36Sopenharmony_ci		spin_unlock(&rdev->err_lock);
466562306a36Sopenharmony_ci	}
466662306a36Sopenharmony_ci	return ret;
466762306a36Sopenharmony_ci}
466862306a36Sopenharmony_ci
466962306a36Sopenharmony_cistatic int _regulator_get_error_flags(struct regulator_dev *rdev,
467062306a36Sopenharmony_ci					unsigned int *flags)
467162306a36Sopenharmony_ci{
467262306a36Sopenharmony_ci	int cached_flags, ret = 0;
467362306a36Sopenharmony_ci
467462306a36Sopenharmony_ci	regulator_lock(rdev);
467562306a36Sopenharmony_ci
467662306a36Sopenharmony_ci	cached_flags = rdev_get_cached_err_flags(rdev);
467762306a36Sopenharmony_ci
467862306a36Sopenharmony_ci	if (rdev->desc->ops->get_error_flags)
467962306a36Sopenharmony_ci		ret = rdev->desc->ops->get_error_flags(rdev, flags);
468062306a36Sopenharmony_ci	else if (!rdev->use_cached_err)
468162306a36Sopenharmony_ci		ret = -EINVAL;
468262306a36Sopenharmony_ci
468362306a36Sopenharmony_ci	*flags |= cached_flags;
468462306a36Sopenharmony_ci
468562306a36Sopenharmony_ci	regulator_unlock(rdev);
468662306a36Sopenharmony_ci
468762306a36Sopenharmony_ci	return ret;
468862306a36Sopenharmony_ci}
468962306a36Sopenharmony_ci
469062306a36Sopenharmony_ci/**
469162306a36Sopenharmony_ci * regulator_get_error_flags - get regulator error information
469262306a36Sopenharmony_ci * @regulator: regulator source
469362306a36Sopenharmony_ci * @flags: pointer to store error flags
469462306a36Sopenharmony_ci *
469562306a36Sopenharmony_ci * Get the current regulator error information.
469662306a36Sopenharmony_ci */
469762306a36Sopenharmony_ciint regulator_get_error_flags(struct regulator *regulator,
469862306a36Sopenharmony_ci				unsigned int *flags)
469962306a36Sopenharmony_ci{
470062306a36Sopenharmony_ci	return _regulator_get_error_flags(regulator->rdev, flags);
470162306a36Sopenharmony_ci}
470262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_error_flags);
470362306a36Sopenharmony_ci
470462306a36Sopenharmony_ci/**
470562306a36Sopenharmony_ci * regulator_set_load - set regulator load
470662306a36Sopenharmony_ci * @regulator: regulator source
470762306a36Sopenharmony_ci * @uA_load: load current
470862306a36Sopenharmony_ci *
470962306a36Sopenharmony_ci * Notifies the regulator core of a new device load. This is then used by
471062306a36Sopenharmony_ci * DRMS (if enabled by constraints) to set the most efficient regulator
471162306a36Sopenharmony_ci * operating mode for the new regulator loading.
471262306a36Sopenharmony_ci *
471362306a36Sopenharmony_ci * Consumer devices notify their supply regulator of the maximum power
471462306a36Sopenharmony_ci * they will require (can be taken from device datasheet in the power
471562306a36Sopenharmony_ci * consumption tables) when they change operational status and hence power
471662306a36Sopenharmony_ci * state. Examples of operational state changes that can affect power
471762306a36Sopenharmony_ci * consumption are :-
471862306a36Sopenharmony_ci *
471962306a36Sopenharmony_ci *    o Device is opened / closed.
472062306a36Sopenharmony_ci *    o Device I/O is about to begin or has just finished.
472162306a36Sopenharmony_ci *    o Device is idling in between work.
472262306a36Sopenharmony_ci *
472362306a36Sopenharmony_ci * This information is also exported via sysfs to userspace.
472462306a36Sopenharmony_ci *
472562306a36Sopenharmony_ci * DRMS will sum the total requested load on the regulator and change
472662306a36Sopenharmony_ci * to the most efficient operating mode if platform constraints allow.
472762306a36Sopenharmony_ci *
472862306a36Sopenharmony_ci * NOTE: when a regulator consumer requests to have a regulator
472962306a36Sopenharmony_ci * disabled then any load that consumer requested no longer counts
473062306a36Sopenharmony_ci * toward the total requested load.  If the regulator is re-enabled
473162306a36Sopenharmony_ci * then the previously requested load will start counting again.
473262306a36Sopenharmony_ci *
473362306a36Sopenharmony_ci * If a regulator is an always-on regulator then an individual consumer's
473462306a36Sopenharmony_ci * load will still be removed if that consumer is fully disabled.
473562306a36Sopenharmony_ci *
473662306a36Sopenharmony_ci * On error a negative errno is returned.
473762306a36Sopenharmony_ci */
473862306a36Sopenharmony_ciint regulator_set_load(struct regulator *regulator, int uA_load)
473962306a36Sopenharmony_ci{
474062306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
474162306a36Sopenharmony_ci	int old_uA_load;
474262306a36Sopenharmony_ci	int ret = 0;
474362306a36Sopenharmony_ci
474462306a36Sopenharmony_ci	regulator_lock(rdev);
474562306a36Sopenharmony_ci	old_uA_load = regulator->uA_load;
474662306a36Sopenharmony_ci	regulator->uA_load = uA_load;
474762306a36Sopenharmony_ci	if (regulator->enable_count && old_uA_load != uA_load) {
474862306a36Sopenharmony_ci		ret = drms_uA_update(rdev);
474962306a36Sopenharmony_ci		if (ret < 0)
475062306a36Sopenharmony_ci			regulator->uA_load = old_uA_load;
475162306a36Sopenharmony_ci	}
475262306a36Sopenharmony_ci	regulator_unlock(rdev);
475362306a36Sopenharmony_ci
475462306a36Sopenharmony_ci	return ret;
475562306a36Sopenharmony_ci}
475662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_load);
475762306a36Sopenharmony_ci
475862306a36Sopenharmony_ci/**
475962306a36Sopenharmony_ci * regulator_allow_bypass - allow the regulator to go into bypass mode
476062306a36Sopenharmony_ci *
476162306a36Sopenharmony_ci * @regulator: Regulator to configure
476262306a36Sopenharmony_ci * @enable: enable or disable bypass mode
476362306a36Sopenharmony_ci *
476462306a36Sopenharmony_ci * Allow the regulator to go into bypass mode if all other consumers
476562306a36Sopenharmony_ci * for the regulator also enable bypass mode and the machine
476662306a36Sopenharmony_ci * constraints allow this.  Bypass mode means that the regulator is
476762306a36Sopenharmony_ci * simply passing the input directly to the output with no regulation.
476862306a36Sopenharmony_ci */
476962306a36Sopenharmony_ciint regulator_allow_bypass(struct regulator *regulator, bool enable)
477062306a36Sopenharmony_ci{
477162306a36Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
477262306a36Sopenharmony_ci	const char *name = rdev_get_name(rdev);
477362306a36Sopenharmony_ci	int ret = 0;
477462306a36Sopenharmony_ci
477562306a36Sopenharmony_ci	if (!rdev->desc->ops->set_bypass)
477662306a36Sopenharmony_ci		return 0;
477762306a36Sopenharmony_ci
477862306a36Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_BYPASS))
477962306a36Sopenharmony_ci		return 0;
478062306a36Sopenharmony_ci
478162306a36Sopenharmony_ci	regulator_lock(rdev);
478262306a36Sopenharmony_ci
478362306a36Sopenharmony_ci	if (enable && !regulator->bypass) {
478462306a36Sopenharmony_ci		rdev->bypass_count++;
478562306a36Sopenharmony_ci
478662306a36Sopenharmony_ci		if (rdev->bypass_count == rdev->open_count) {
478762306a36Sopenharmony_ci			trace_regulator_bypass_enable(name);
478862306a36Sopenharmony_ci
478962306a36Sopenharmony_ci			ret = rdev->desc->ops->set_bypass(rdev, enable);
479062306a36Sopenharmony_ci			if (ret != 0)
479162306a36Sopenharmony_ci				rdev->bypass_count--;
479262306a36Sopenharmony_ci			else
479362306a36Sopenharmony_ci				trace_regulator_bypass_enable_complete(name);
479462306a36Sopenharmony_ci		}
479562306a36Sopenharmony_ci
479662306a36Sopenharmony_ci	} else if (!enable && regulator->bypass) {
479762306a36Sopenharmony_ci		rdev->bypass_count--;
479862306a36Sopenharmony_ci
479962306a36Sopenharmony_ci		if (rdev->bypass_count != rdev->open_count) {
480062306a36Sopenharmony_ci			trace_regulator_bypass_disable(name);
480162306a36Sopenharmony_ci
480262306a36Sopenharmony_ci			ret = rdev->desc->ops->set_bypass(rdev, enable);
480362306a36Sopenharmony_ci			if (ret != 0)
480462306a36Sopenharmony_ci				rdev->bypass_count++;
480562306a36Sopenharmony_ci			else
480662306a36Sopenharmony_ci				trace_regulator_bypass_disable_complete(name);
480762306a36Sopenharmony_ci		}
480862306a36Sopenharmony_ci	}
480962306a36Sopenharmony_ci
481062306a36Sopenharmony_ci	if (ret == 0)
481162306a36Sopenharmony_ci		regulator->bypass = enable;
481262306a36Sopenharmony_ci
481362306a36Sopenharmony_ci	regulator_unlock(rdev);
481462306a36Sopenharmony_ci
481562306a36Sopenharmony_ci	return ret;
481662306a36Sopenharmony_ci}
481762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_allow_bypass);
481862306a36Sopenharmony_ci
481962306a36Sopenharmony_ci/**
482062306a36Sopenharmony_ci * regulator_register_notifier - register regulator event notifier
482162306a36Sopenharmony_ci * @regulator: regulator source
482262306a36Sopenharmony_ci * @nb: notifier block
482362306a36Sopenharmony_ci *
482462306a36Sopenharmony_ci * Register notifier block to receive regulator events.
482562306a36Sopenharmony_ci */
482662306a36Sopenharmony_ciint regulator_register_notifier(struct regulator *regulator,
482762306a36Sopenharmony_ci			      struct notifier_block *nb)
482862306a36Sopenharmony_ci{
482962306a36Sopenharmony_ci	return blocking_notifier_chain_register(&regulator->rdev->notifier,
483062306a36Sopenharmony_ci						nb);
483162306a36Sopenharmony_ci}
483262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_register_notifier);
483362306a36Sopenharmony_ci
483462306a36Sopenharmony_ci/**
483562306a36Sopenharmony_ci * regulator_unregister_notifier - unregister regulator event notifier
483662306a36Sopenharmony_ci * @regulator: regulator source
483762306a36Sopenharmony_ci * @nb: notifier block
483862306a36Sopenharmony_ci *
483962306a36Sopenharmony_ci * Unregister regulator event notifier block.
484062306a36Sopenharmony_ci */
484162306a36Sopenharmony_ciint regulator_unregister_notifier(struct regulator *regulator,
484262306a36Sopenharmony_ci				struct notifier_block *nb)
484362306a36Sopenharmony_ci{
484462306a36Sopenharmony_ci	return blocking_notifier_chain_unregister(&regulator->rdev->notifier,
484562306a36Sopenharmony_ci						  nb);
484662306a36Sopenharmony_ci}
484762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_unregister_notifier);
484862306a36Sopenharmony_ci
484962306a36Sopenharmony_ci/* notify regulator consumers and downstream regulator consumers.
485062306a36Sopenharmony_ci * Note mutex must be held by caller.
485162306a36Sopenharmony_ci */
485262306a36Sopenharmony_cistatic int _notifier_call_chain(struct regulator_dev *rdev,
485362306a36Sopenharmony_ci				  unsigned long event, void *data)
485462306a36Sopenharmony_ci{
485562306a36Sopenharmony_ci	/* call rdev chain first */
485662306a36Sopenharmony_ci	return blocking_notifier_call_chain(&rdev->notifier, event, data);
485762306a36Sopenharmony_ci}
485862306a36Sopenharmony_ci
485962306a36Sopenharmony_ciint _regulator_bulk_get(struct device *dev, int num_consumers,
486062306a36Sopenharmony_ci			struct regulator_bulk_data *consumers, enum regulator_get_type get_type)
486162306a36Sopenharmony_ci{
486262306a36Sopenharmony_ci	int i;
486362306a36Sopenharmony_ci	int ret;
486462306a36Sopenharmony_ci
486562306a36Sopenharmony_ci	for (i = 0; i < num_consumers; i++)
486662306a36Sopenharmony_ci		consumers[i].consumer = NULL;
486762306a36Sopenharmony_ci
486862306a36Sopenharmony_ci	for (i = 0; i < num_consumers; i++) {
486962306a36Sopenharmony_ci		consumers[i].consumer = _regulator_get(dev,
487062306a36Sopenharmony_ci						       consumers[i].supply, get_type);
487162306a36Sopenharmony_ci		if (IS_ERR(consumers[i].consumer)) {
487262306a36Sopenharmony_ci			ret = dev_err_probe(dev, PTR_ERR(consumers[i].consumer),
487362306a36Sopenharmony_ci					    "Failed to get supply '%s'",
487462306a36Sopenharmony_ci					    consumers[i].supply);
487562306a36Sopenharmony_ci			consumers[i].consumer = NULL;
487662306a36Sopenharmony_ci			goto err;
487762306a36Sopenharmony_ci		}
487862306a36Sopenharmony_ci
487962306a36Sopenharmony_ci		if (consumers[i].init_load_uA > 0) {
488062306a36Sopenharmony_ci			ret = regulator_set_load(consumers[i].consumer,
488162306a36Sopenharmony_ci						 consumers[i].init_load_uA);
488262306a36Sopenharmony_ci			if (ret) {
488362306a36Sopenharmony_ci				i++;
488462306a36Sopenharmony_ci				goto err;
488562306a36Sopenharmony_ci			}
488662306a36Sopenharmony_ci		}
488762306a36Sopenharmony_ci	}
488862306a36Sopenharmony_ci
488962306a36Sopenharmony_ci	return 0;
489062306a36Sopenharmony_ci
489162306a36Sopenharmony_cierr:
489262306a36Sopenharmony_ci	while (--i >= 0)
489362306a36Sopenharmony_ci		regulator_put(consumers[i].consumer);
489462306a36Sopenharmony_ci
489562306a36Sopenharmony_ci	return ret;
489662306a36Sopenharmony_ci}
489762306a36Sopenharmony_ci
489862306a36Sopenharmony_ci/**
489962306a36Sopenharmony_ci * regulator_bulk_get - get multiple regulator consumers
490062306a36Sopenharmony_ci *
490162306a36Sopenharmony_ci * @dev:           Device to supply
490262306a36Sopenharmony_ci * @num_consumers: Number of consumers to register
490362306a36Sopenharmony_ci * @consumers:     Configuration of consumers; clients are stored here.
490462306a36Sopenharmony_ci *
490562306a36Sopenharmony_ci * @return 0 on success, an errno on failure.
490662306a36Sopenharmony_ci *
490762306a36Sopenharmony_ci * This helper function allows drivers to get several regulator
490862306a36Sopenharmony_ci * consumers in one operation.  If any of the regulators cannot be
490962306a36Sopenharmony_ci * acquired then any regulators that were allocated will be freed
491062306a36Sopenharmony_ci * before returning to the caller.
491162306a36Sopenharmony_ci */
491262306a36Sopenharmony_ciint regulator_bulk_get(struct device *dev, int num_consumers,
491362306a36Sopenharmony_ci		       struct regulator_bulk_data *consumers)
491462306a36Sopenharmony_ci{
491562306a36Sopenharmony_ci	return _regulator_bulk_get(dev, num_consumers, consumers, NORMAL_GET);
491662306a36Sopenharmony_ci}
491762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_bulk_get);
491862306a36Sopenharmony_ci
491962306a36Sopenharmony_cistatic void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
492062306a36Sopenharmony_ci{
492162306a36Sopenharmony_ci	struct regulator_bulk_data *bulk = data;
492262306a36Sopenharmony_ci
492362306a36Sopenharmony_ci	bulk->ret = regulator_enable(bulk->consumer);
492462306a36Sopenharmony_ci}
492562306a36Sopenharmony_ci
492662306a36Sopenharmony_ci/**
492762306a36Sopenharmony_ci * regulator_bulk_enable - enable multiple regulator consumers
492862306a36Sopenharmony_ci *
492962306a36Sopenharmony_ci * @num_consumers: Number of consumers
493062306a36Sopenharmony_ci * @consumers:     Consumer data; clients are stored here.
493162306a36Sopenharmony_ci * @return         0 on success, an errno on failure
493262306a36Sopenharmony_ci *
493362306a36Sopenharmony_ci * This convenience API allows consumers to enable multiple regulator
493462306a36Sopenharmony_ci * clients in a single API call.  If any consumers cannot be enabled
493562306a36Sopenharmony_ci * then any others that were enabled will be disabled again prior to
493662306a36Sopenharmony_ci * return.
493762306a36Sopenharmony_ci */
493862306a36Sopenharmony_ciint regulator_bulk_enable(int num_consumers,
493962306a36Sopenharmony_ci			  struct regulator_bulk_data *consumers)
494062306a36Sopenharmony_ci{
494162306a36Sopenharmony_ci	ASYNC_DOMAIN_EXCLUSIVE(async_domain);
494262306a36Sopenharmony_ci	int i;
494362306a36Sopenharmony_ci	int ret = 0;
494462306a36Sopenharmony_ci
494562306a36Sopenharmony_ci	for (i = 0; i < num_consumers; i++) {
494662306a36Sopenharmony_ci		async_schedule_domain(regulator_bulk_enable_async,
494762306a36Sopenharmony_ci				      &consumers[i], &async_domain);
494862306a36Sopenharmony_ci	}
494962306a36Sopenharmony_ci
495062306a36Sopenharmony_ci	async_synchronize_full_domain(&async_domain);
495162306a36Sopenharmony_ci
495262306a36Sopenharmony_ci	/* If any consumer failed we need to unwind any that succeeded */
495362306a36Sopenharmony_ci	for (i = 0; i < num_consumers; i++) {
495462306a36Sopenharmony_ci		if (consumers[i].ret != 0) {
495562306a36Sopenharmony_ci			ret = consumers[i].ret;
495662306a36Sopenharmony_ci			goto err;
495762306a36Sopenharmony_ci		}
495862306a36Sopenharmony_ci	}
495962306a36Sopenharmony_ci
496062306a36Sopenharmony_ci	return 0;
496162306a36Sopenharmony_ci
496262306a36Sopenharmony_cierr:
496362306a36Sopenharmony_ci	for (i = 0; i < num_consumers; i++) {
496462306a36Sopenharmony_ci		if (consumers[i].ret < 0)
496562306a36Sopenharmony_ci			pr_err("Failed to enable %s: %pe\n", consumers[i].supply,
496662306a36Sopenharmony_ci			       ERR_PTR(consumers[i].ret));
496762306a36Sopenharmony_ci		else
496862306a36Sopenharmony_ci			regulator_disable(consumers[i].consumer);
496962306a36Sopenharmony_ci	}
497062306a36Sopenharmony_ci
497162306a36Sopenharmony_ci	return ret;
497262306a36Sopenharmony_ci}
497362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_bulk_enable);
497462306a36Sopenharmony_ci
497562306a36Sopenharmony_ci/**
497662306a36Sopenharmony_ci * regulator_bulk_disable - disable multiple regulator consumers
497762306a36Sopenharmony_ci *
497862306a36Sopenharmony_ci * @num_consumers: Number of consumers
497962306a36Sopenharmony_ci * @consumers:     Consumer data; clients are stored here.
498062306a36Sopenharmony_ci * @return         0 on success, an errno on failure
498162306a36Sopenharmony_ci *
498262306a36Sopenharmony_ci * This convenience API allows consumers to disable multiple regulator
498362306a36Sopenharmony_ci * clients in a single API call.  If any consumers cannot be disabled
498462306a36Sopenharmony_ci * then any others that were disabled will be enabled again prior to
498562306a36Sopenharmony_ci * return.
498662306a36Sopenharmony_ci */
498762306a36Sopenharmony_ciint regulator_bulk_disable(int num_consumers,
498862306a36Sopenharmony_ci			   struct regulator_bulk_data *consumers)
498962306a36Sopenharmony_ci{
499062306a36Sopenharmony_ci	int i;
499162306a36Sopenharmony_ci	int ret, r;
499262306a36Sopenharmony_ci
499362306a36Sopenharmony_ci	for (i = num_consumers - 1; i >= 0; --i) {
499462306a36Sopenharmony_ci		ret = regulator_disable(consumers[i].consumer);
499562306a36Sopenharmony_ci		if (ret != 0)
499662306a36Sopenharmony_ci			goto err;
499762306a36Sopenharmony_ci	}
499862306a36Sopenharmony_ci
499962306a36Sopenharmony_ci	return 0;
500062306a36Sopenharmony_ci
500162306a36Sopenharmony_cierr:
500262306a36Sopenharmony_ci	pr_err("Failed to disable %s: %pe\n", consumers[i].supply, ERR_PTR(ret));
500362306a36Sopenharmony_ci	for (++i; i < num_consumers; ++i) {
500462306a36Sopenharmony_ci		r = regulator_enable(consumers[i].consumer);
500562306a36Sopenharmony_ci		if (r != 0)
500662306a36Sopenharmony_ci			pr_err("Failed to re-enable %s: %pe\n",
500762306a36Sopenharmony_ci			       consumers[i].supply, ERR_PTR(r));
500862306a36Sopenharmony_ci	}
500962306a36Sopenharmony_ci
501062306a36Sopenharmony_ci	return ret;
501162306a36Sopenharmony_ci}
501262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_bulk_disable);
501362306a36Sopenharmony_ci
501462306a36Sopenharmony_ci/**
501562306a36Sopenharmony_ci * regulator_bulk_force_disable - force disable multiple regulator consumers
501662306a36Sopenharmony_ci *
501762306a36Sopenharmony_ci * @num_consumers: Number of consumers
501862306a36Sopenharmony_ci * @consumers:     Consumer data; clients are stored here.
501962306a36Sopenharmony_ci * @return         0 on success, an errno on failure
502062306a36Sopenharmony_ci *
502162306a36Sopenharmony_ci * This convenience API allows consumers to forcibly disable multiple regulator
502262306a36Sopenharmony_ci * clients in a single API call.
502362306a36Sopenharmony_ci * NOTE: This should be used for situations when device damage will
502462306a36Sopenharmony_ci * likely occur if the regulators are not disabled (e.g. over temp).
502562306a36Sopenharmony_ci * Although regulator_force_disable function call for some consumers can
502662306a36Sopenharmony_ci * return error numbers, the function is called for all consumers.
502762306a36Sopenharmony_ci */
502862306a36Sopenharmony_ciint regulator_bulk_force_disable(int num_consumers,
502962306a36Sopenharmony_ci			   struct regulator_bulk_data *consumers)
503062306a36Sopenharmony_ci{
503162306a36Sopenharmony_ci	int i;
503262306a36Sopenharmony_ci	int ret = 0;
503362306a36Sopenharmony_ci
503462306a36Sopenharmony_ci	for (i = 0; i < num_consumers; i++) {
503562306a36Sopenharmony_ci		consumers[i].ret =
503662306a36Sopenharmony_ci			    regulator_force_disable(consumers[i].consumer);
503762306a36Sopenharmony_ci
503862306a36Sopenharmony_ci		/* Store first error for reporting */
503962306a36Sopenharmony_ci		if (consumers[i].ret && !ret)
504062306a36Sopenharmony_ci			ret = consumers[i].ret;
504162306a36Sopenharmony_ci	}
504262306a36Sopenharmony_ci
504362306a36Sopenharmony_ci	return ret;
504462306a36Sopenharmony_ci}
504562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_bulk_force_disable);
504662306a36Sopenharmony_ci
504762306a36Sopenharmony_ci/**
504862306a36Sopenharmony_ci * regulator_bulk_free - free multiple regulator consumers
504962306a36Sopenharmony_ci *
505062306a36Sopenharmony_ci * @num_consumers: Number of consumers
505162306a36Sopenharmony_ci * @consumers:     Consumer data; clients are stored here.
505262306a36Sopenharmony_ci *
505362306a36Sopenharmony_ci * This convenience API allows consumers to free multiple regulator
505462306a36Sopenharmony_ci * clients in a single API call.
505562306a36Sopenharmony_ci */
505662306a36Sopenharmony_civoid regulator_bulk_free(int num_consumers,
505762306a36Sopenharmony_ci			 struct regulator_bulk_data *consumers)
505862306a36Sopenharmony_ci{
505962306a36Sopenharmony_ci	int i;
506062306a36Sopenharmony_ci
506162306a36Sopenharmony_ci	for (i = 0; i < num_consumers; i++) {
506262306a36Sopenharmony_ci		regulator_put(consumers[i].consumer);
506362306a36Sopenharmony_ci		consumers[i].consumer = NULL;
506462306a36Sopenharmony_ci	}
506562306a36Sopenharmony_ci}
506662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_bulk_free);
506762306a36Sopenharmony_ci
506862306a36Sopenharmony_ci/**
506962306a36Sopenharmony_ci * regulator_notifier_call_chain - call regulator event notifier
507062306a36Sopenharmony_ci * @rdev: regulator source
507162306a36Sopenharmony_ci * @event: notifier block
507262306a36Sopenharmony_ci * @data: callback-specific data.
507362306a36Sopenharmony_ci *
507462306a36Sopenharmony_ci * Called by regulator drivers to notify clients a regulator event has
507562306a36Sopenharmony_ci * occurred.
507662306a36Sopenharmony_ci */
507762306a36Sopenharmony_ciint regulator_notifier_call_chain(struct regulator_dev *rdev,
507862306a36Sopenharmony_ci				  unsigned long event, void *data)
507962306a36Sopenharmony_ci{
508062306a36Sopenharmony_ci	_notifier_call_chain(rdev, event, data);
508162306a36Sopenharmony_ci	return NOTIFY_DONE;
508262306a36Sopenharmony_ci
508362306a36Sopenharmony_ci}
508462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_notifier_call_chain);
508562306a36Sopenharmony_ci
508662306a36Sopenharmony_ci/**
508762306a36Sopenharmony_ci * regulator_mode_to_status - convert a regulator mode into a status
508862306a36Sopenharmony_ci *
508962306a36Sopenharmony_ci * @mode: Mode to convert
509062306a36Sopenharmony_ci *
509162306a36Sopenharmony_ci * Convert a regulator mode into a status.
509262306a36Sopenharmony_ci */
509362306a36Sopenharmony_ciint regulator_mode_to_status(unsigned int mode)
509462306a36Sopenharmony_ci{
509562306a36Sopenharmony_ci	switch (mode) {
509662306a36Sopenharmony_ci	case REGULATOR_MODE_FAST:
509762306a36Sopenharmony_ci		return REGULATOR_STATUS_FAST;
509862306a36Sopenharmony_ci	case REGULATOR_MODE_NORMAL:
509962306a36Sopenharmony_ci		return REGULATOR_STATUS_NORMAL;
510062306a36Sopenharmony_ci	case REGULATOR_MODE_IDLE:
510162306a36Sopenharmony_ci		return REGULATOR_STATUS_IDLE;
510262306a36Sopenharmony_ci	case REGULATOR_MODE_STANDBY:
510362306a36Sopenharmony_ci		return REGULATOR_STATUS_STANDBY;
510462306a36Sopenharmony_ci	default:
510562306a36Sopenharmony_ci		return REGULATOR_STATUS_UNDEFINED;
510662306a36Sopenharmony_ci	}
510762306a36Sopenharmony_ci}
510862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_mode_to_status);
510962306a36Sopenharmony_ci
511062306a36Sopenharmony_cistatic struct attribute *regulator_dev_attrs[] = {
511162306a36Sopenharmony_ci	&dev_attr_name.attr,
511262306a36Sopenharmony_ci	&dev_attr_num_users.attr,
511362306a36Sopenharmony_ci	&dev_attr_type.attr,
511462306a36Sopenharmony_ci	&dev_attr_microvolts.attr,
511562306a36Sopenharmony_ci	&dev_attr_microamps.attr,
511662306a36Sopenharmony_ci	&dev_attr_opmode.attr,
511762306a36Sopenharmony_ci	&dev_attr_state.attr,
511862306a36Sopenharmony_ci	&dev_attr_status.attr,
511962306a36Sopenharmony_ci	&dev_attr_bypass.attr,
512062306a36Sopenharmony_ci	&dev_attr_requested_microamps.attr,
512162306a36Sopenharmony_ci	&dev_attr_min_microvolts.attr,
512262306a36Sopenharmony_ci	&dev_attr_max_microvolts.attr,
512362306a36Sopenharmony_ci	&dev_attr_min_microamps.attr,
512462306a36Sopenharmony_ci	&dev_attr_max_microamps.attr,
512562306a36Sopenharmony_ci	&dev_attr_under_voltage.attr,
512662306a36Sopenharmony_ci	&dev_attr_over_current.attr,
512762306a36Sopenharmony_ci	&dev_attr_regulation_out.attr,
512862306a36Sopenharmony_ci	&dev_attr_fail.attr,
512962306a36Sopenharmony_ci	&dev_attr_over_temp.attr,
513062306a36Sopenharmony_ci	&dev_attr_under_voltage_warn.attr,
513162306a36Sopenharmony_ci	&dev_attr_over_current_warn.attr,
513262306a36Sopenharmony_ci	&dev_attr_over_voltage_warn.attr,
513362306a36Sopenharmony_ci	&dev_attr_over_temp_warn.attr,
513462306a36Sopenharmony_ci	&dev_attr_suspend_standby_state.attr,
513562306a36Sopenharmony_ci	&dev_attr_suspend_mem_state.attr,
513662306a36Sopenharmony_ci	&dev_attr_suspend_disk_state.attr,
513762306a36Sopenharmony_ci	&dev_attr_suspend_standby_microvolts.attr,
513862306a36Sopenharmony_ci	&dev_attr_suspend_mem_microvolts.attr,
513962306a36Sopenharmony_ci	&dev_attr_suspend_disk_microvolts.attr,
514062306a36Sopenharmony_ci	&dev_attr_suspend_standby_mode.attr,
514162306a36Sopenharmony_ci	&dev_attr_suspend_mem_mode.attr,
514262306a36Sopenharmony_ci	&dev_attr_suspend_disk_mode.attr,
514362306a36Sopenharmony_ci	NULL
514462306a36Sopenharmony_ci};
514562306a36Sopenharmony_ci
514662306a36Sopenharmony_ci/*
514762306a36Sopenharmony_ci * To avoid cluttering sysfs (and memory) with useless state, only
514862306a36Sopenharmony_ci * create attributes that can be meaningfully displayed.
514962306a36Sopenharmony_ci */
515062306a36Sopenharmony_cistatic umode_t regulator_attr_is_visible(struct kobject *kobj,
515162306a36Sopenharmony_ci					 struct attribute *attr, int idx)
515262306a36Sopenharmony_ci{
515362306a36Sopenharmony_ci	struct device *dev = kobj_to_dev(kobj);
515462306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
515562306a36Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
515662306a36Sopenharmony_ci	umode_t mode = attr->mode;
515762306a36Sopenharmony_ci
515862306a36Sopenharmony_ci	/* these three are always present */
515962306a36Sopenharmony_ci	if (attr == &dev_attr_name.attr ||
516062306a36Sopenharmony_ci	    attr == &dev_attr_num_users.attr ||
516162306a36Sopenharmony_ci	    attr == &dev_attr_type.attr)
516262306a36Sopenharmony_ci		return mode;
516362306a36Sopenharmony_ci
516462306a36Sopenharmony_ci	/* some attributes need specific methods to be displayed */
516562306a36Sopenharmony_ci	if (attr == &dev_attr_microvolts.attr) {
516662306a36Sopenharmony_ci		if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) ||
516762306a36Sopenharmony_ci		    (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) ||
516862306a36Sopenharmony_ci		    (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) ||
516962306a36Sopenharmony_ci		    (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1))
517062306a36Sopenharmony_ci			return mode;
517162306a36Sopenharmony_ci		return 0;
517262306a36Sopenharmony_ci	}
517362306a36Sopenharmony_ci
517462306a36Sopenharmony_ci	if (attr == &dev_attr_microamps.attr)
517562306a36Sopenharmony_ci		return ops->get_current_limit ? mode : 0;
517662306a36Sopenharmony_ci
517762306a36Sopenharmony_ci	if (attr == &dev_attr_opmode.attr)
517862306a36Sopenharmony_ci		return ops->get_mode ? mode : 0;
517962306a36Sopenharmony_ci
518062306a36Sopenharmony_ci	if (attr == &dev_attr_state.attr)
518162306a36Sopenharmony_ci		return (rdev->ena_pin || ops->is_enabled) ? mode : 0;
518262306a36Sopenharmony_ci
518362306a36Sopenharmony_ci	if (attr == &dev_attr_status.attr)
518462306a36Sopenharmony_ci		return ops->get_status ? mode : 0;
518562306a36Sopenharmony_ci
518662306a36Sopenharmony_ci	if (attr == &dev_attr_bypass.attr)
518762306a36Sopenharmony_ci		return ops->get_bypass ? mode : 0;
518862306a36Sopenharmony_ci
518962306a36Sopenharmony_ci	if (attr == &dev_attr_under_voltage.attr ||
519062306a36Sopenharmony_ci	    attr == &dev_attr_over_current.attr ||
519162306a36Sopenharmony_ci	    attr == &dev_attr_regulation_out.attr ||
519262306a36Sopenharmony_ci	    attr == &dev_attr_fail.attr ||
519362306a36Sopenharmony_ci	    attr == &dev_attr_over_temp.attr ||
519462306a36Sopenharmony_ci	    attr == &dev_attr_under_voltage_warn.attr ||
519562306a36Sopenharmony_ci	    attr == &dev_attr_over_current_warn.attr ||
519662306a36Sopenharmony_ci	    attr == &dev_attr_over_voltage_warn.attr ||
519762306a36Sopenharmony_ci	    attr == &dev_attr_over_temp_warn.attr)
519862306a36Sopenharmony_ci		return ops->get_error_flags ? mode : 0;
519962306a36Sopenharmony_ci
520062306a36Sopenharmony_ci	/* constraints need specific supporting methods */
520162306a36Sopenharmony_ci	if (attr == &dev_attr_min_microvolts.attr ||
520262306a36Sopenharmony_ci	    attr == &dev_attr_max_microvolts.attr)
520362306a36Sopenharmony_ci		return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0;
520462306a36Sopenharmony_ci
520562306a36Sopenharmony_ci	if (attr == &dev_attr_min_microamps.attr ||
520662306a36Sopenharmony_ci	    attr == &dev_attr_max_microamps.attr)
520762306a36Sopenharmony_ci		return ops->set_current_limit ? mode : 0;
520862306a36Sopenharmony_ci
520962306a36Sopenharmony_ci	if (attr == &dev_attr_suspend_standby_state.attr ||
521062306a36Sopenharmony_ci	    attr == &dev_attr_suspend_mem_state.attr ||
521162306a36Sopenharmony_ci	    attr == &dev_attr_suspend_disk_state.attr)
521262306a36Sopenharmony_ci		return mode;
521362306a36Sopenharmony_ci
521462306a36Sopenharmony_ci	if (attr == &dev_attr_suspend_standby_microvolts.attr ||
521562306a36Sopenharmony_ci	    attr == &dev_attr_suspend_mem_microvolts.attr ||
521662306a36Sopenharmony_ci	    attr == &dev_attr_suspend_disk_microvolts.attr)
521762306a36Sopenharmony_ci		return ops->set_suspend_voltage ? mode : 0;
521862306a36Sopenharmony_ci
521962306a36Sopenharmony_ci	if (attr == &dev_attr_suspend_standby_mode.attr ||
522062306a36Sopenharmony_ci	    attr == &dev_attr_suspend_mem_mode.attr ||
522162306a36Sopenharmony_ci	    attr == &dev_attr_suspend_disk_mode.attr)
522262306a36Sopenharmony_ci		return ops->set_suspend_mode ? mode : 0;
522362306a36Sopenharmony_ci
522462306a36Sopenharmony_ci	return mode;
522562306a36Sopenharmony_ci}
522662306a36Sopenharmony_ci
522762306a36Sopenharmony_cistatic const struct attribute_group regulator_dev_group = {
522862306a36Sopenharmony_ci	.attrs = regulator_dev_attrs,
522962306a36Sopenharmony_ci	.is_visible = regulator_attr_is_visible,
523062306a36Sopenharmony_ci};
523162306a36Sopenharmony_ci
523262306a36Sopenharmony_cistatic const struct attribute_group *regulator_dev_groups[] = {
523362306a36Sopenharmony_ci	&regulator_dev_group,
523462306a36Sopenharmony_ci	NULL
523562306a36Sopenharmony_ci};
523662306a36Sopenharmony_ci
523762306a36Sopenharmony_cistatic void regulator_dev_release(struct device *dev)
523862306a36Sopenharmony_ci{
523962306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
524062306a36Sopenharmony_ci
524162306a36Sopenharmony_ci	debugfs_remove_recursive(rdev->debugfs);
524262306a36Sopenharmony_ci	kfree(rdev->constraints);
524362306a36Sopenharmony_ci	of_node_put(rdev->dev.of_node);
524462306a36Sopenharmony_ci	kfree(rdev);
524562306a36Sopenharmony_ci}
524662306a36Sopenharmony_ci
524762306a36Sopenharmony_cistatic void rdev_init_debugfs(struct regulator_dev *rdev)
524862306a36Sopenharmony_ci{
524962306a36Sopenharmony_ci	struct device *parent = rdev->dev.parent;
525062306a36Sopenharmony_ci	const char *rname = rdev_get_name(rdev);
525162306a36Sopenharmony_ci	char name[NAME_MAX];
525262306a36Sopenharmony_ci
525362306a36Sopenharmony_ci	/* Avoid duplicate debugfs directory names */
525462306a36Sopenharmony_ci	if (parent && rname == rdev->desc->name) {
525562306a36Sopenharmony_ci		snprintf(name, sizeof(name), "%s-%s", dev_name(parent),
525662306a36Sopenharmony_ci			 rname);
525762306a36Sopenharmony_ci		rname = name;
525862306a36Sopenharmony_ci	}
525962306a36Sopenharmony_ci
526062306a36Sopenharmony_ci	rdev->debugfs = debugfs_create_dir(rname, debugfs_root);
526162306a36Sopenharmony_ci	if (IS_ERR(rdev->debugfs))
526262306a36Sopenharmony_ci		rdev_dbg(rdev, "Failed to create debugfs directory\n");
526362306a36Sopenharmony_ci
526462306a36Sopenharmony_ci	debugfs_create_u32("use_count", 0444, rdev->debugfs,
526562306a36Sopenharmony_ci			   &rdev->use_count);
526662306a36Sopenharmony_ci	debugfs_create_u32("open_count", 0444, rdev->debugfs,
526762306a36Sopenharmony_ci			   &rdev->open_count);
526862306a36Sopenharmony_ci	debugfs_create_u32("bypass_count", 0444, rdev->debugfs,
526962306a36Sopenharmony_ci			   &rdev->bypass_count);
527062306a36Sopenharmony_ci}
527162306a36Sopenharmony_ci
527262306a36Sopenharmony_cistatic int regulator_register_resolve_supply(struct device *dev, void *data)
527362306a36Sopenharmony_ci{
527462306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
527562306a36Sopenharmony_ci
527662306a36Sopenharmony_ci	if (regulator_resolve_supply(rdev))
527762306a36Sopenharmony_ci		rdev_dbg(rdev, "unable to resolve supply\n");
527862306a36Sopenharmony_ci
527962306a36Sopenharmony_ci	return 0;
528062306a36Sopenharmony_ci}
528162306a36Sopenharmony_ci
528262306a36Sopenharmony_ciint regulator_coupler_register(struct regulator_coupler *coupler)
528362306a36Sopenharmony_ci{
528462306a36Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
528562306a36Sopenharmony_ci	list_add_tail(&coupler->list, &regulator_coupler_list);
528662306a36Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
528762306a36Sopenharmony_ci
528862306a36Sopenharmony_ci	return 0;
528962306a36Sopenharmony_ci}
529062306a36Sopenharmony_ci
529162306a36Sopenharmony_cistatic struct regulator_coupler *
529262306a36Sopenharmony_ciregulator_find_coupler(struct regulator_dev *rdev)
529362306a36Sopenharmony_ci{
529462306a36Sopenharmony_ci	struct regulator_coupler *coupler;
529562306a36Sopenharmony_ci	int err;
529662306a36Sopenharmony_ci
529762306a36Sopenharmony_ci	/*
529862306a36Sopenharmony_ci	 * Note that regulators are appended to the list and the generic
529962306a36Sopenharmony_ci	 * coupler is registered first, hence it will be attached at last
530062306a36Sopenharmony_ci	 * if nobody cared.
530162306a36Sopenharmony_ci	 */
530262306a36Sopenharmony_ci	list_for_each_entry_reverse(coupler, &regulator_coupler_list, list) {
530362306a36Sopenharmony_ci		err = coupler->attach_regulator(coupler, rdev);
530462306a36Sopenharmony_ci		if (!err) {
530562306a36Sopenharmony_ci			if (!coupler->balance_voltage &&
530662306a36Sopenharmony_ci			    rdev->coupling_desc.n_coupled > 2)
530762306a36Sopenharmony_ci				goto err_unsupported;
530862306a36Sopenharmony_ci
530962306a36Sopenharmony_ci			return coupler;
531062306a36Sopenharmony_ci		}
531162306a36Sopenharmony_ci
531262306a36Sopenharmony_ci		if (err < 0)
531362306a36Sopenharmony_ci			return ERR_PTR(err);
531462306a36Sopenharmony_ci
531562306a36Sopenharmony_ci		if (err == 1)
531662306a36Sopenharmony_ci			continue;
531762306a36Sopenharmony_ci
531862306a36Sopenharmony_ci		break;
531962306a36Sopenharmony_ci	}
532062306a36Sopenharmony_ci
532162306a36Sopenharmony_ci	return ERR_PTR(-EINVAL);
532262306a36Sopenharmony_ci
532362306a36Sopenharmony_cierr_unsupported:
532462306a36Sopenharmony_ci	if (coupler->detach_regulator)
532562306a36Sopenharmony_ci		coupler->detach_regulator(coupler, rdev);
532662306a36Sopenharmony_ci
532762306a36Sopenharmony_ci	rdev_err(rdev,
532862306a36Sopenharmony_ci		"Voltage balancing for multiple regulator couples is unimplemented\n");
532962306a36Sopenharmony_ci
533062306a36Sopenharmony_ci	return ERR_PTR(-EPERM);
533162306a36Sopenharmony_ci}
533262306a36Sopenharmony_ci
533362306a36Sopenharmony_cistatic void regulator_resolve_coupling(struct regulator_dev *rdev)
533462306a36Sopenharmony_ci{
533562306a36Sopenharmony_ci	struct regulator_coupler *coupler = rdev->coupling_desc.coupler;
533662306a36Sopenharmony_ci	struct coupling_desc *c_desc = &rdev->coupling_desc;
533762306a36Sopenharmony_ci	int n_coupled = c_desc->n_coupled;
533862306a36Sopenharmony_ci	struct regulator_dev *c_rdev;
533962306a36Sopenharmony_ci	int i;
534062306a36Sopenharmony_ci
534162306a36Sopenharmony_ci	for (i = 1; i < n_coupled; i++) {
534262306a36Sopenharmony_ci		/* already resolved */
534362306a36Sopenharmony_ci		if (c_desc->coupled_rdevs[i])
534462306a36Sopenharmony_ci			continue;
534562306a36Sopenharmony_ci
534662306a36Sopenharmony_ci		c_rdev = of_parse_coupled_regulator(rdev, i - 1);
534762306a36Sopenharmony_ci
534862306a36Sopenharmony_ci		if (!c_rdev)
534962306a36Sopenharmony_ci			continue;
535062306a36Sopenharmony_ci
535162306a36Sopenharmony_ci		if (c_rdev->coupling_desc.coupler != coupler) {
535262306a36Sopenharmony_ci			rdev_err(rdev, "coupler mismatch with %s\n",
535362306a36Sopenharmony_ci				 rdev_get_name(c_rdev));
535462306a36Sopenharmony_ci			return;
535562306a36Sopenharmony_ci		}
535662306a36Sopenharmony_ci
535762306a36Sopenharmony_ci		c_desc->coupled_rdevs[i] = c_rdev;
535862306a36Sopenharmony_ci		c_desc->n_resolved++;
535962306a36Sopenharmony_ci
536062306a36Sopenharmony_ci		regulator_resolve_coupling(c_rdev);
536162306a36Sopenharmony_ci	}
536262306a36Sopenharmony_ci}
536362306a36Sopenharmony_ci
536462306a36Sopenharmony_cistatic void regulator_remove_coupling(struct regulator_dev *rdev)
536562306a36Sopenharmony_ci{
536662306a36Sopenharmony_ci	struct regulator_coupler *coupler = rdev->coupling_desc.coupler;
536762306a36Sopenharmony_ci	struct coupling_desc *__c_desc, *c_desc = &rdev->coupling_desc;
536862306a36Sopenharmony_ci	struct regulator_dev *__c_rdev, *c_rdev;
536962306a36Sopenharmony_ci	unsigned int __n_coupled, n_coupled;
537062306a36Sopenharmony_ci	int i, k;
537162306a36Sopenharmony_ci	int err;
537262306a36Sopenharmony_ci
537362306a36Sopenharmony_ci	n_coupled = c_desc->n_coupled;
537462306a36Sopenharmony_ci
537562306a36Sopenharmony_ci	for (i = 1; i < n_coupled; i++) {
537662306a36Sopenharmony_ci		c_rdev = c_desc->coupled_rdevs[i];
537762306a36Sopenharmony_ci
537862306a36Sopenharmony_ci		if (!c_rdev)
537962306a36Sopenharmony_ci			continue;
538062306a36Sopenharmony_ci
538162306a36Sopenharmony_ci		regulator_lock(c_rdev);
538262306a36Sopenharmony_ci
538362306a36Sopenharmony_ci		__c_desc = &c_rdev->coupling_desc;
538462306a36Sopenharmony_ci		__n_coupled = __c_desc->n_coupled;
538562306a36Sopenharmony_ci
538662306a36Sopenharmony_ci		for (k = 1; k < __n_coupled; k++) {
538762306a36Sopenharmony_ci			__c_rdev = __c_desc->coupled_rdevs[k];
538862306a36Sopenharmony_ci
538962306a36Sopenharmony_ci			if (__c_rdev == rdev) {
539062306a36Sopenharmony_ci				__c_desc->coupled_rdevs[k] = NULL;
539162306a36Sopenharmony_ci				__c_desc->n_resolved--;
539262306a36Sopenharmony_ci				break;
539362306a36Sopenharmony_ci			}
539462306a36Sopenharmony_ci		}
539562306a36Sopenharmony_ci
539662306a36Sopenharmony_ci		regulator_unlock(c_rdev);
539762306a36Sopenharmony_ci
539862306a36Sopenharmony_ci		c_desc->coupled_rdevs[i] = NULL;
539962306a36Sopenharmony_ci		c_desc->n_resolved--;
540062306a36Sopenharmony_ci	}
540162306a36Sopenharmony_ci
540262306a36Sopenharmony_ci	if (coupler && coupler->detach_regulator) {
540362306a36Sopenharmony_ci		err = coupler->detach_regulator(coupler, rdev);
540462306a36Sopenharmony_ci		if (err)
540562306a36Sopenharmony_ci			rdev_err(rdev, "failed to detach from coupler: %pe\n",
540662306a36Sopenharmony_ci				 ERR_PTR(err));
540762306a36Sopenharmony_ci	}
540862306a36Sopenharmony_ci
540962306a36Sopenharmony_ci	kfree(rdev->coupling_desc.coupled_rdevs);
541062306a36Sopenharmony_ci	rdev->coupling_desc.coupled_rdevs = NULL;
541162306a36Sopenharmony_ci}
541262306a36Sopenharmony_ci
541362306a36Sopenharmony_cistatic int regulator_init_coupling(struct regulator_dev *rdev)
541462306a36Sopenharmony_ci{
541562306a36Sopenharmony_ci	struct regulator_dev **coupled;
541662306a36Sopenharmony_ci	int err, n_phandles;
541762306a36Sopenharmony_ci
541862306a36Sopenharmony_ci	if (!IS_ENABLED(CONFIG_OF))
541962306a36Sopenharmony_ci		n_phandles = 0;
542062306a36Sopenharmony_ci	else
542162306a36Sopenharmony_ci		n_phandles = of_get_n_coupled(rdev);
542262306a36Sopenharmony_ci
542362306a36Sopenharmony_ci	coupled = kcalloc(n_phandles + 1, sizeof(*coupled), GFP_KERNEL);
542462306a36Sopenharmony_ci	if (!coupled)
542562306a36Sopenharmony_ci		return -ENOMEM;
542662306a36Sopenharmony_ci
542762306a36Sopenharmony_ci	rdev->coupling_desc.coupled_rdevs = coupled;
542862306a36Sopenharmony_ci
542962306a36Sopenharmony_ci	/*
543062306a36Sopenharmony_ci	 * Every regulator should always have coupling descriptor filled with
543162306a36Sopenharmony_ci	 * at least pointer to itself.
543262306a36Sopenharmony_ci	 */
543362306a36Sopenharmony_ci	rdev->coupling_desc.coupled_rdevs[0] = rdev;
543462306a36Sopenharmony_ci	rdev->coupling_desc.n_coupled = n_phandles + 1;
543562306a36Sopenharmony_ci	rdev->coupling_desc.n_resolved++;
543662306a36Sopenharmony_ci
543762306a36Sopenharmony_ci	/* regulator isn't coupled */
543862306a36Sopenharmony_ci	if (n_phandles == 0)
543962306a36Sopenharmony_ci		return 0;
544062306a36Sopenharmony_ci
544162306a36Sopenharmony_ci	if (!of_check_coupling_data(rdev))
544262306a36Sopenharmony_ci		return -EPERM;
544362306a36Sopenharmony_ci
544462306a36Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
544562306a36Sopenharmony_ci	rdev->coupling_desc.coupler = regulator_find_coupler(rdev);
544662306a36Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
544762306a36Sopenharmony_ci
544862306a36Sopenharmony_ci	if (IS_ERR(rdev->coupling_desc.coupler)) {
544962306a36Sopenharmony_ci		err = PTR_ERR(rdev->coupling_desc.coupler);
545062306a36Sopenharmony_ci		rdev_err(rdev, "failed to get coupler: %pe\n", ERR_PTR(err));
545162306a36Sopenharmony_ci		return err;
545262306a36Sopenharmony_ci	}
545362306a36Sopenharmony_ci
545462306a36Sopenharmony_ci	return 0;
545562306a36Sopenharmony_ci}
545662306a36Sopenharmony_ci
545762306a36Sopenharmony_cistatic int generic_coupler_attach(struct regulator_coupler *coupler,
545862306a36Sopenharmony_ci				  struct regulator_dev *rdev)
545962306a36Sopenharmony_ci{
546062306a36Sopenharmony_ci	if (rdev->coupling_desc.n_coupled > 2) {
546162306a36Sopenharmony_ci		rdev_err(rdev,
546262306a36Sopenharmony_ci			 "Voltage balancing for multiple regulator couples is unimplemented\n");
546362306a36Sopenharmony_ci		return -EPERM;
546462306a36Sopenharmony_ci	}
546562306a36Sopenharmony_ci
546662306a36Sopenharmony_ci	if (!rdev->constraints->always_on) {
546762306a36Sopenharmony_ci		rdev_err(rdev,
546862306a36Sopenharmony_ci			 "Coupling of a non always-on regulator is unimplemented\n");
546962306a36Sopenharmony_ci		return -ENOTSUPP;
547062306a36Sopenharmony_ci	}
547162306a36Sopenharmony_ci
547262306a36Sopenharmony_ci	return 0;
547362306a36Sopenharmony_ci}
547462306a36Sopenharmony_ci
547562306a36Sopenharmony_cistatic struct regulator_coupler generic_regulator_coupler = {
547662306a36Sopenharmony_ci	.attach_regulator = generic_coupler_attach,
547762306a36Sopenharmony_ci};
547862306a36Sopenharmony_ci
547962306a36Sopenharmony_ci/**
548062306a36Sopenharmony_ci * regulator_register - register regulator
548162306a36Sopenharmony_ci * @dev: the device that drive the regulator
548262306a36Sopenharmony_ci * @regulator_desc: regulator to register
548362306a36Sopenharmony_ci * @cfg: runtime configuration for regulator
548462306a36Sopenharmony_ci *
548562306a36Sopenharmony_ci * Called by regulator drivers to register a regulator.
548662306a36Sopenharmony_ci * Returns a valid pointer to struct regulator_dev on success
548762306a36Sopenharmony_ci * or an ERR_PTR() on error.
548862306a36Sopenharmony_ci */
548962306a36Sopenharmony_cistruct regulator_dev *
549062306a36Sopenharmony_ciregulator_register(struct device *dev,
549162306a36Sopenharmony_ci		   const struct regulator_desc *regulator_desc,
549262306a36Sopenharmony_ci		   const struct regulator_config *cfg)
549362306a36Sopenharmony_ci{
549462306a36Sopenharmony_ci	const struct regulator_init_data *init_data;
549562306a36Sopenharmony_ci	struct regulator_config *config = NULL;
549662306a36Sopenharmony_ci	static atomic_t regulator_no = ATOMIC_INIT(-1);
549762306a36Sopenharmony_ci	struct regulator_dev *rdev;
549862306a36Sopenharmony_ci	bool dangling_cfg_gpiod = false;
549962306a36Sopenharmony_ci	bool dangling_of_gpiod = false;
550062306a36Sopenharmony_ci	int ret, i;
550162306a36Sopenharmony_ci	bool resolved_early = false;
550262306a36Sopenharmony_ci
550362306a36Sopenharmony_ci	if (cfg == NULL)
550462306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
550562306a36Sopenharmony_ci	if (cfg->ena_gpiod)
550662306a36Sopenharmony_ci		dangling_cfg_gpiod = true;
550762306a36Sopenharmony_ci	if (regulator_desc == NULL) {
550862306a36Sopenharmony_ci		ret = -EINVAL;
550962306a36Sopenharmony_ci		goto rinse;
551062306a36Sopenharmony_ci	}
551162306a36Sopenharmony_ci
551262306a36Sopenharmony_ci	WARN_ON(!dev || !cfg->dev);
551362306a36Sopenharmony_ci
551462306a36Sopenharmony_ci	if (regulator_desc->name == NULL || regulator_desc->ops == NULL) {
551562306a36Sopenharmony_ci		ret = -EINVAL;
551662306a36Sopenharmony_ci		goto rinse;
551762306a36Sopenharmony_ci	}
551862306a36Sopenharmony_ci
551962306a36Sopenharmony_ci	if (regulator_desc->type != REGULATOR_VOLTAGE &&
552062306a36Sopenharmony_ci	    regulator_desc->type != REGULATOR_CURRENT) {
552162306a36Sopenharmony_ci		ret = -EINVAL;
552262306a36Sopenharmony_ci		goto rinse;
552362306a36Sopenharmony_ci	}
552462306a36Sopenharmony_ci
552562306a36Sopenharmony_ci	/* Only one of each should be implemented */
552662306a36Sopenharmony_ci	WARN_ON(regulator_desc->ops->get_voltage &&
552762306a36Sopenharmony_ci		regulator_desc->ops->get_voltage_sel);
552862306a36Sopenharmony_ci	WARN_ON(regulator_desc->ops->set_voltage &&
552962306a36Sopenharmony_ci		regulator_desc->ops->set_voltage_sel);
553062306a36Sopenharmony_ci
553162306a36Sopenharmony_ci	/* If we're using selectors we must implement list_voltage. */
553262306a36Sopenharmony_ci	if (regulator_desc->ops->get_voltage_sel &&
553362306a36Sopenharmony_ci	    !regulator_desc->ops->list_voltage) {
553462306a36Sopenharmony_ci		ret = -EINVAL;
553562306a36Sopenharmony_ci		goto rinse;
553662306a36Sopenharmony_ci	}
553762306a36Sopenharmony_ci	if (regulator_desc->ops->set_voltage_sel &&
553862306a36Sopenharmony_ci	    !regulator_desc->ops->list_voltage) {
553962306a36Sopenharmony_ci		ret = -EINVAL;
554062306a36Sopenharmony_ci		goto rinse;
554162306a36Sopenharmony_ci	}
554262306a36Sopenharmony_ci
554362306a36Sopenharmony_ci	rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
554462306a36Sopenharmony_ci	if (rdev == NULL) {
554562306a36Sopenharmony_ci		ret = -ENOMEM;
554662306a36Sopenharmony_ci		goto rinse;
554762306a36Sopenharmony_ci	}
554862306a36Sopenharmony_ci	device_initialize(&rdev->dev);
554962306a36Sopenharmony_ci	dev_set_drvdata(&rdev->dev, rdev);
555062306a36Sopenharmony_ci	rdev->dev.class = &regulator_class;
555162306a36Sopenharmony_ci	spin_lock_init(&rdev->err_lock);
555262306a36Sopenharmony_ci
555362306a36Sopenharmony_ci	/*
555462306a36Sopenharmony_ci	 * Duplicate the config so the driver could override it after
555562306a36Sopenharmony_ci	 * parsing init data.
555662306a36Sopenharmony_ci	 */
555762306a36Sopenharmony_ci	config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL);
555862306a36Sopenharmony_ci	if (config == NULL) {
555962306a36Sopenharmony_ci		ret = -ENOMEM;
556062306a36Sopenharmony_ci		goto clean;
556162306a36Sopenharmony_ci	}
556262306a36Sopenharmony_ci
556362306a36Sopenharmony_ci	init_data = regulator_of_get_init_data(dev, regulator_desc, config,
556462306a36Sopenharmony_ci					       &rdev->dev.of_node);
556562306a36Sopenharmony_ci
556662306a36Sopenharmony_ci	/*
556762306a36Sopenharmony_ci	 * Sometimes not all resources are probed already so we need to take
556862306a36Sopenharmony_ci	 * that into account. This happens most the time if the ena_gpiod comes
556962306a36Sopenharmony_ci	 * from a gpio extender or something else.
557062306a36Sopenharmony_ci	 */
557162306a36Sopenharmony_ci	if (PTR_ERR(init_data) == -EPROBE_DEFER) {
557262306a36Sopenharmony_ci		ret = -EPROBE_DEFER;
557362306a36Sopenharmony_ci		goto clean;
557462306a36Sopenharmony_ci	}
557562306a36Sopenharmony_ci
557662306a36Sopenharmony_ci	/*
557762306a36Sopenharmony_ci	 * We need to keep track of any GPIO descriptor coming from the
557862306a36Sopenharmony_ci	 * device tree until we have handled it over to the core. If the
557962306a36Sopenharmony_ci	 * config that was passed in to this function DOES NOT contain
558062306a36Sopenharmony_ci	 * a descriptor, and the config after this call DOES contain
558162306a36Sopenharmony_ci	 * a descriptor, we definitely got one from parsing the device
558262306a36Sopenharmony_ci	 * tree.
558362306a36Sopenharmony_ci	 */
558462306a36Sopenharmony_ci	if (!cfg->ena_gpiod && config->ena_gpiod)
558562306a36Sopenharmony_ci		dangling_of_gpiod = true;
558662306a36Sopenharmony_ci	if (!init_data) {
558762306a36Sopenharmony_ci		init_data = config->init_data;
558862306a36Sopenharmony_ci		rdev->dev.of_node = of_node_get(config->of_node);
558962306a36Sopenharmony_ci	}
559062306a36Sopenharmony_ci
559162306a36Sopenharmony_ci	ww_mutex_init(&rdev->mutex, &regulator_ww_class);
559262306a36Sopenharmony_ci	rdev->reg_data = config->driver_data;
559362306a36Sopenharmony_ci	rdev->owner = regulator_desc->owner;
559462306a36Sopenharmony_ci	rdev->desc = regulator_desc;
559562306a36Sopenharmony_ci	if (config->regmap)
559662306a36Sopenharmony_ci		rdev->regmap = config->regmap;
559762306a36Sopenharmony_ci	else if (dev_get_regmap(dev, NULL))
559862306a36Sopenharmony_ci		rdev->regmap = dev_get_regmap(dev, NULL);
559962306a36Sopenharmony_ci	else if (dev->parent)
560062306a36Sopenharmony_ci		rdev->regmap = dev_get_regmap(dev->parent, NULL);
560162306a36Sopenharmony_ci	INIT_LIST_HEAD(&rdev->consumer_list);
560262306a36Sopenharmony_ci	INIT_LIST_HEAD(&rdev->list);
560362306a36Sopenharmony_ci	BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
560462306a36Sopenharmony_ci	INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work);
560562306a36Sopenharmony_ci
560662306a36Sopenharmony_ci	if (init_data && init_data->supply_regulator)
560762306a36Sopenharmony_ci		rdev->supply_name = init_data->supply_regulator;
560862306a36Sopenharmony_ci	else if (regulator_desc->supply_name)
560962306a36Sopenharmony_ci		rdev->supply_name = regulator_desc->supply_name;
561062306a36Sopenharmony_ci
561162306a36Sopenharmony_ci	/* register with sysfs */
561262306a36Sopenharmony_ci	rdev->dev.parent = config->dev;
561362306a36Sopenharmony_ci	dev_set_name(&rdev->dev, "regulator.%lu",
561462306a36Sopenharmony_ci		    (unsigned long) atomic_inc_return(&regulator_no));
561562306a36Sopenharmony_ci
561662306a36Sopenharmony_ci	/* set regulator constraints */
561762306a36Sopenharmony_ci	if (init_data)
561862306a36Sopenharmony_ci		rdev->constraints = kmemdup(&init_data->constraints,
561962306a36Sopenharmony_ci					    sizeof(*rdev->constraints),
562062306a36Sopenharmony_ci					    GFP_KERNEL);
562162306a36Sopenharmony_ci	else
562262306a36Sopenharmony_ci		rdev->constraints = kzalloc(sizeof(*rdev->constraints),
562362306a36Sopenharmony_ci					    GFP_KERNEL);
562462306a36Sopenharmony_ci	if (!rdev->constraints) {
562562306a36Sopenharmony_ci		ret = -ENOMEM;
562662306a36Sopenharmony_ci		goto wash;
562762306a36Sopenharmony_ci	}
562862306a36Sopenharmony_ci
562962306a36Sopenharmony_ci	if ((rdev->supply_name && !rdev->supply) &&
563062306a36Sopenharmony_ci		(rdev->constraints->always_on ||
563162306a36Sopenharmony_ci		 rdev->constraints->boot_on)) {
563262306a36Sopenharmony_ci		ret = regulator_resolve_supply(rdev);
563362306a36Sopenharmony_ci		if (ret)
563462306a36Sopenharmony_ci			rdev_dbg(rdev, "unable to resolve supply early: %pe\n",
563562306a36Sopenharmony_ci					 ERR_PTR(ret));
563662306a36Sopenharmony_ci
563762306a36Sopenharmony_ci		resolved_early = true;
563862306a36Sopenharmony_ci	}
563962306a36Sopenharmony_ci
564062306a36Sopenharmony_ci	/* perform any regulator specific init */
564162306a36Sopenharmony_ci	if (init_data && init_data->regulator_init) {
564262306a36Sopenharmony_ci		ret = init_data->regulator_init(rdev->reg_data);
564362306a36Sopenharmony_ci		if (ret < 0)
564462306a36Sopenharmony_ci			goto wash;
564562306a36Sopenharmony_ci	}
564662306a36Sopenharmony_ci
564762306a36Sopenharmony_ci	if (config->ena_gpiod) {
564862306a36Sopenharmony_ci		ret = regulator_ena_gpio_request(rdev, config);
564962306a36Sopenharmony_ci		if (ret != 0) {
565062306a36Sopenharmony_ci			rdev_err(rdev, "Failed to request enable GPIO: %pe\n",
565162306a36Sopenharmony_ci				 ERR_PTR(ret));
565262306a36Sopenharmony_ci			goto wash;
565362306a36Sopenharmony_ci		}
565462306a36Sopenharmony_ci		/* The regulator core took over the GPIO descriptor */
565562306a36Sopenharmony_ci		dangling_cfg_gpiod = false;
565662306a36Sopenharmony_ci		dangling_of_gpiod = false;
565762306a36Sopenharmony_ci	}
565862306a36Sopenharmony_ci
565962306a36Sopenharmony_ci	ret = set_machine_constraints(rdev);
566062306a36Sopenharmony_ci	if (ret == -EPROBE_DEFER && !resolved_early) {
566162306a36Sopenharmony_ci		/* Regulator might be in bypass mode and so needs its supply
566262306a36Sopenharmony_ci		 * to set the constraints
566362306a36Sopenharmony_ci		 */
566462306a36Sopenharmony_ci		/* FIXME: this currently triggers a chicken-and-egg problem
566562306a36Sopenharmony_ci		 * when creating -SUPPLY symlink in sysfs to a regulator
566662306a36Sopenharmony_ci		 * that is just being created
566762306a36Sopenharmony_ci		 */
566862306a36Sopenharmony_ci		rdev_dbg(rdev, "will resolve supply early: %s\n",
566962306a36Sopenharmony_ci			 rdev->supply_name);
567062306a36Sopenharmony_ci		ret = regulator_resolve_supply(rdev);
567162306a36Sopenharmony_ci		if (!ret)
567262306a36Sopenharmony_ci			ret = set_machine_constraints(rdev);
567362306a36Sopenharmony_ci		else
567462306a36Sopenharmony_ci			rdev_dbg(rdev, "unable to resolve supply early: %pe\n",
567562306a36Sopenharmony_ci				 ERR_PTR(ret));
567662306a36Sopenharmony_ci	}
567762306a36Sopenharmony_ci	if (ret < 0)
567862306a36Sopenharmony_ci		goto wash;
567962306a36Sopenharmony_ci
568062306a36Sopenharmony_ci	ret = regulator_init_coupling(rdev);
568162306a36Sopenharmony_ci	if (ret < 0)
568262306a36Sopenharmony_ci		goto wash;
568362306a36Sopenharmony_ci
568462306a36Sopenharmony_ci	/* add consumers devices */
568562306a36Sopenharmony_ci	if (init_data) {
568662306a36Sopenharmony_ci		for (i = 0; i < init_data->num_consumer_supplies; i++) {
568762306a36Sopenharmony_ci			ret = set_consumer_device_supply(rdev,
568862306a36Sopenharmony_ci				init_data->consumer_supplies[i].dev_name,
568962306a36Sopenharmony_ci				init_data->consumer_supplies[i].supply);
569062306a36Sopenharmony_ci			if (ret < 0) {
569162306a36Sopenharmony_ci				dev_err(dev, "Failed to set supply %s\n",
569262306a36Sopenharmony_ci					init_data->consumer_supplies[i].supply);
569362306a36Sopenharmony_ci				goto unset_supplies;
569462306a36Sopenharmony_ci			}
569562306a36Sopenharmony_ci		}
569662306a36Sopenharmony_ci	}
569762306a36Sopenharmony_ci
569862306a36Sopenharmony_ci	if (!rdev->desc->ops->get_voltage &&
569962306a36Sopenharmony_ci	    !rdev->desc->ops->list_voltage &&
570062306a36Sopenharmony_ci	    !rdev->desc->fixed_uV)
570162306a36Sopenharmony_ci		rdev->is_switch = true;
570262306a36Sopenharmony_ci
570362306a36Sopenharmony_ci	ret = device_add(&rdev->dev);
570462306a36Sopenharmony_ci	if (ret != 0)
570562306a36Sopenharmony_ci		goto unset_supplies;
570662306a36Sopenharmony_ci
570762306a36Sopenharmony_ci	rdev_init_debugfs(rdev);
570862306a36Sopenharmony_ci
570962306a36Sopenharmony_ci	/* try to resolve regulators coupling since a new one was registered */
571062306a36Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
571162306a36Sopenharmony_ci	regulator_resolve_coupling(rdev);
571262306a36Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
571362306a36Sopenharmony_ci
571462306a36Sopenharmony_ci	/* try to resolve regulators supply since a new one was registered */
571562306a36Sopenharmony_ci	class_for_each_device(&regulator_class, NULL, NULL,
571662306a36Sopenharmony_ci			      regulator_register_resolve_supply);
571762306a36Sopenharmony_ci	kfree(config);
571862306a36Sopenharmony_ci	return rdev;
571962306a36Sopenharmony_ci
572062306a36Sopenharmony_ciunset_supplies:
572162306a36Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
572262306a36Sopenharmony_ci	unset_regulator_supplies(rdev);
572362306a36Sopenharmony_ci	regulator_remove_coupling(rdev);
572462306a36Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
572562306a36Sopenharmony_ciwash:
572662306a36Sopenharmony_ci	regulator_put(rdev->supply);
572762306a36Sopenharmony_ci	kfree(rdev->coupling_desc.coupled_rdevs);
572862306a36Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
572962306a36Sopenharmony_ci	regulator_ena_gpio_free(rdev);
573062306a36Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
573162306a36Sopenharmony_ciclean:
573262306a36Sopenharmony_ci	if (dangling_of_gpiod)
573362306a36Sopenharmony_ci		gpiod_put(config->ena_gpiod);
573462306a36Sopenharmony_ci	kfree(config);
573562306a36Sopenharmony_ci	put_device(&rdev->dev);
573662306a36Sopenharmony_cirinse:
573762306a36Sopenharmony_ci	if (dangling_cfg_gpiod)
573862306a36Sopenharmony_ci		gpiod_put(cfg->ena_gpiod);
573962306a36Sopenharmony_ci	return ERR_PTR(ret);
574062306a36Sopenharmony_ci}
574162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_register);
574262306a36Sopenharmony_ci
574362306a36Sopenharmony_ci/**
574462306a36Sopenharmony_ci * regulator_unregister - unregister regulator
574562306a36Sopenharmony_ci * @rdev: regulator to unregister
574662306a36Sopenharmony_ci *
574762306a36Sopenharmony_ci * Called by regulator drivers to unregister a regulator.
574862306a36Sopenharmony_ci */
574962306a36Sopenharmony_civoid regulator_unregister(struct regulator_dev *rdev)
575062306a36Sopenharmony_ci{
575162306a36Sopenharmony_ci	if (rdev == NULL)
575262306a36Sopenharmony_ci		return;
575362306a36Sopenharmony_ci
575462306a36Sopenharmony_ci	if (rdev->supply) {
575562306a36Sopenharmony_ci		while (rdev->use_count--)
575662306a36Sopenharmony_ci			regulator_disable(rdev->supply);
575762306a36Sopenharmony_ci		regulator_put(rdev->supply);
575862306a36Sopenharmony_ci	}
575962306a36Sopenharmony_ci
576062306a36Sopenharmony_ci	flush_work(&rdev->disable_work.work);
576162306a36Sopenharmony_ci
576262306a36Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
576362306a36Sopenharmony_ci
576462306a36Sopenharmony_ci	WARN_ON(rdev->open_count);
576562306a36Sopenharmony_ci	regulator_remove_coupling(rdev);
576662306a36Sopenharmony_ci	unset_regulator_supplies(rdev);
576762306a36Sopenharmony_ci	list_del(&rdev->list);
576862306a36Sopenharmony_ci	regulator_ena_gpio_free(rdev);
576962306a36Sopenharmony_ci	device_unregister(&rdev->dev);
577062306a36Sopenharmony_ci
577162306a36Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
577262306a36Sopenharmony_ci}
577362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_unregister);
577462306a36Sopenharmony_ci
577562306a36Sopenharmony_ci#ifdef CONFIG_SUSPEND
577662306a36Sopenharmony_ci/**
577762306a36Sopenharmony_ci * regulator_suspend - prepare regulators for system wide suspend
577862306a36Sopenharmony_ci * @dev: ``&struct device`` pointer that is passed to _regulator_suspend()
577962306a36Sopenharmony_ci *
578062306a36Sopenharmony_ci * Configure each regulator with it's suspend operating parameters for state.
578162306a36Sopenharmony_ci */
578262306a36Sopenharmony_cistatic int regulator_suspend(struct device *dev)
578362306a36Sopenharmony_ci{
578462306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
578562306a36Sopenharmony_ci	suspend_state_t state = pm_suspend_target_state;
578662306a36Sopenharmony_ci	int ret;
578762306a36Sopenharmony_ci	const struct regulator_state *rstate;
578862306a36Sopenharmony_ci
578962306a36Sopenharmony_ci	rstate = regulator_get_suspend_state_check(rdev, state);
579062306a36Sopenharmony_ci	if (!rstate)
579162306a36Sopenharmony_ci		return 0;
579262306a36Sopenharmony_ci
579362306a36Sopenharmony_ci	regulator_lock(rdev);
579462306a36Sopenharmony_ci	ret = __suspend_set_state(rdev, rstate);
579562306a36Sopenharmony_ci	regulator_unlock(rdev);
579662306a36Sopenharmony_ci
579762306a36Sopenharmony_ci	return ret;
579862306a36Sopenharmony_ci}
579962306a36Sopenharmony_ci
580062306a36Sopenharmony_cistatic int regulator_resume(struct device *dev)
580162306a36Sopenharmony_ci{
580262306a36Sopenharmony_ci	suspend_state_t state = pm_suspend_target_state;
580362306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
580462306a36Sopenharmony_ci	struct regulator_state *rstate;
580562306a36Sopenharmony_ci	int ret = 0;
580662306a36Sopenharmony_ci
580762306a36Sopenharmony_ci	rstate = regulator_get_suspend_state(rdev, state);
580862306a36Sopenharmony_ci	if (rstate == NULL)
580962306a36Sopenharmony_ci		return 0;
581062306a36Sopenharmony_ci
581162306a36Sopenharmony_ci	/* Avoid grabbing the lock if we don't need to */
581262306a36Sopenharmony_ci	if (!rdev->desc->ops->resume)
581362306a36Sopenharmony_ci		return 0;
581462306a36Sopenharmony_ci
581562306a36Sopenharmony_ci	regulator_lock(rdev);
581662306a36Sopenharmony_ci
581762306a36Sopenharmony_ci	if (rstate->enabled == ENABLE_IN_SUSPEND ||
581862306a36Sopenharmony_ci	    rstate->enabled == DISABLE_IN_SUSPEND)
581962306a36Sopenharmony_ci		ret = rdev->desc->ops->resume(rdev);
582062306a36Sopenharmony_ci
582162306a36Sopenharmony_ci	regulator_unlock(rdev);
582262306a36Sopenharmony_ci
582362306a36Sopenharmony_ci	return ret;
582462306a36Sopenharmony_ci}
582562306a36Sopenharmony_ci#else /* !CONFIG_SUSPEND */
582662306a36Sopenharmony_ci
582762306a36Sopenharmony_ci#define regulator_suspend	NULL
582862306a36Sopenharmony_ci#define regulator_resume	NULL
582962306a36Sopenharmony_ci
583062306a36Sopenharmony_ci#endif /* !CONFIG_SUSPEND */
583162306a36Sopenharmony_ci
583262306a36Sopenharmony_ci#ifdef CONFIG_PM
583362306a36Sopenharmony_cistatic const struct dev_pm_ops __maybe_unused regulator_pm_ops = {
583462306a36Sopenharmony_ci	.suspend	= regulator_suspend,
583562306a36Sopenharmony_ci	.resume		= regulator_resume,
583662306a36Sopenharmony_ci};
583762306a36Sopenharmony_ci#endif
583862306a36Sopenharmony_ci
583962306a36Sopenharmony_cistruct class regulator_class = {
584062306a36Sopenharmony_ci	.name = "regulator",
584162306a36Sopenharmony_ci	.dev_release = regulator_dev_release,
584262306a36Sopenharmony_ci	.dev_groups = regulator_dev_groups,
584362306a36Sopenharmony_ci#ifdef CONFIG_PM
584462306a36Sopenharmony_ci	.pm = &regulator_pm_ops,
584562306a36Sopenharmony_ci#endif
584662306a36Sopenharmony_ci};
584762306a36Sopenharmony_ci/**
584862306a36Sopenharmony_ci * regulator_has_full_constraints - the system has fully specified constraints
584962306a36Sopenharmony_ci *
585062306a36Sopenharmony_ci * Calling this function will cause the regulator API to disable all
585162306a36Sopenharmony_ci * regulators which have a zero use count and don't have an always_on
585262306a36Sopenharmony_ci * constraint in a late_initcall.
585362306a36Sopenharmony_ci *
585462306a36Sopenharmony_ci * The intention is that this will become the default behaviour in a
585562306a36Sopenharmony_ci * future kernel release so users are encouraged to use this facility
585662306a36Sopenharmony_ci * now.
585762306a36Sopenharmony_ci */
585862306a36Sopenharmony_civoid regulator_has_full_constraints(void)
585962306a36Sopenharmony_ci{
586062306a36Sopenharmony_ci	has_full_constraints = 1;
586162306a36Sopenharmony_ci}
586262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_has_full_constraints);
586362306a36Sopenharmony_ci
586462306a36Sopenharmony_ci/**
586562306a36Sopenharmony_ci * rdev_get_drvdata - get rdev regulator driver data
586662306a36Sopenharmony_ci * @rdev: regulator
586762306a36Sopenharmony_ci *
586862306a36Sopenharmony_ci * Get rdev regulator driver private data. This call can be used in the
586962306a36Sopenharmony_ci * regulator driver context.
587062306a36Sopenharmony_ci */
587162306a36Sopenharmony_civoid *rdev_get_drvdata(struct regulator_dev *rdev)
587262306a36Sopenharmony_ci{
587362306a36Sopenharmony_ci	return rdev->reg_data;
587462306a36Sopenharmony_ci}
587562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rdev_get_drvdata);
587662306a36Sopenharmony_ci
587762306a36Sopenharmony_ci/**
587862306a36Sopenharmony_ci * regulator_get_drvdata - get regulator driver data
587962306a36Sopenharmony_ci * @regulator: regulator
588062306a36Sopenharmony_ci *
588162306a36Sopenharmony_ci * Get regulator driver private data. This call can be used in the consumer
588262306a36Sopenharmony_ci * driver context when non API regulator specific functions need to be called.
588362306a36Sopenharmony_ci */
588462306a36Sopenharmony_civoid *regulator_get_drvdata(struct regulator *regulator)
588562306a36Sopenharmony_ci{
588662306a36Sopenharmony_ci	return regulator->rdev->reg_data;
588762306a36Sopenharmony_ci}
588862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_drvdata);
588962306a36Sopenharmony_ci
589062306a36Sopenharmony_ci/**
589162306a36Sopenharmony_ci * regulator_set_drvdata - set regulator driver data
589262306a36Sopenharmony_ci * @regulator: regulator
589362306a36Sopenharmony_ci * @data: data
589462306a36Sopenharmony_ci */
589562306a36Sopenharmony_civoid regulator_set_drvdata(struct regulator *regulator, void *data)
589662306a36Sopenharmony_ci{
589762306a36Sopenharmony_ci	regulator->rdev->reg_data = data;
589862306a36Sopenharmony_ci}
589962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_drvdata);
590062306a36Sopenharmony_ci
590162306a36Sopenharmony_ci/**
590262306a36Sopenharmony_ci * rdev_get_id - get regulator ID
590362306a36Sopenharmony_ci * @rdev: regulator
590462306a36Sopenharmony_ci */
590562306a36Sopenharmony_ciint rdev_get_id(struct regulator_dev *rdev)
590662306a36Sopenharmony_ci{
590762306a36Sopenharmony_ci	return rdev->desc->id;
590862306a36Sopenharmony_ci}
590962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rdev_get_id);
591062306a36Sopenharmony_ci
591162306a36Sopenharmony_cistruct device *rdev_get_dev(struct regulator_dev *rdev)
591262306a36Sopenharmony_ci{
591362306a36Sopenharmony_ci	return &rdev->dev;
591462306a36Sopenharmony_ci}
591562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rdev_get_dev);
591662306a36Sopenharmony_ci
591762306a36Sopenharmony_cistruct regmap *rdev_get_regmap(struct regulator_dev *rdev)
591862306a36Sopenharmony_ci{
591962306a36Sopenharmony_ci	return rdev->regmap;
592062306a36Sopenharmony_ci}
592162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rdev_get_regmap);
592262306a36Sopenharmony_ci
592362306a36Sopenharmony_civoid *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
592462306a36Sopenharmony_ci{
592562306a36Sopenharmony_ci	return reg_init_data->driver_data;
592662306a36Sopenharmony_ci}
592762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
592862306a36Sopenharmony_ci
592962306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
593062306a36Sopenharmony_cistatic int supply_map_show(struct seq_file *sf, void *data)
593162306a36Sopenharmony_ci{
593262306a36Sopenharmony_ci	struct regulator_map *map;
593362306a36Sopenharmony_ci
593462306a36Sopenharmony_ci	list_for_each_entry(map, &regulator_map_list, list) {
593562306a36Sopenharmony_ci		seq_printf(sf, "%s -> %s.%s\n",
593662306a36Sopenharmony_ci				rdev_get_name(map->regulator), map->dev_name,
593762306a36Sopenharmony_ci				map->supply);
593862306a36Sopenharmony_ci	}
593962306a36Sopenharmony_ci
594062306a36Sopenharmony_ci	return 0;
594162306a36Sopenharmony_ci}
594262306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(supply_map);
594362306a36Sopenharmony_ci
594462306a36Sopenharmony_cistruct summary_data {
594562306a36Sopenharmony_ci	struct seq_file *s;
594662306a36Sopenharmony_ci	struct regulator_dev *parent;
594762306a36Sopenharmony_ci	int level;
594862306a36Sopenharmony_ci};
594962306a36Sopenharmony_ci
595062306a36Sopenharmony_cistatic void regulator_summary_show_subtree(struct seq_file *s,
595162306a36Sopenharmony_ci					   struct regulator_dev *rdev,
595262306a36Sopenharmony_ci					   int level);
595362306a36Sopenharmony_ci
595462306a36Sopenharmony_cistatic int regulator_summary_show_children(struct device *dev, void *data)
595562306a36Sopenharmony_ci{
595662306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
595762306a36Sopenharmony_ci	struct summary_data *summary_data = data;
595862306a36Sopenharmony_ci
595962306a36Sopenharmony_ci	if (rdev->supply && rdev->supply->rdev == summary_data->parent)
596062306a36Sopenharmony_ci		regulator_summary_show_subtree(summary_data->s, rdev,
596162306a36Sopenharmony_ci					       summary_data->level + 1);
596262306a36Sopenharmony_ci
596362306a36Sopenharmony_ci	return 0;
596462306a36Sopenharmony_ci}
596562306a36Sopenharmony_ci
596662306a36Sopenharmony_cistatic void regulator_summary_show_subtree(struct seq_file *s,
596762306a36Sopenharmony_ci					   struct regulator_dev *rdev,
596862306a36Sopenharmony_ci					   int level)
596962306a36Sopenharmony_ci{
597062306a36Sopenharmony_ci	struct regulation_constraints *c;
597162306a36Sopenharmony_ci	struct regulator *consumer;
597262306a36Sopenharmony_ci	struct summary_data summary_data;
597362306a36Sopenharmony_ci	unsigned int opmode;
597462306a36Sopenharmony_ci
597562306a36Sopenharmony_ci	if (!rdev)
597662306a36Sopenharmony_ci		return;
597762306a36Sopenharmony_ci
597862306a36Sopenharmony_ci	opmode = _regulator_get_mode_unlocked(rdev);
597962306a36Sopenharmony_ci	seq_printf(s, "%*s%-*s %3d %4d %6d %7s ",
598062306a36Sopenharmony_ci		   level * 3 + 1, "",
598162306a36Sopenharmony_ci		   30 - level * 3, rdev_get_name(rdev),
598262306a36Sopenharmony_ci		   rdev->use_count, rdev->open_count, rdev->bypass_count,
598362306a36Sopenharmony_ci		   regulator_opmode_to_str(opmode));
598462306a36Sopenharmony_ci
598562306a36Sopenharmony_ci	seq_printf(s, "%5dmV ", regulator_get_voltage_rdev(rdev) / 1000);
598662306a36Sopenharmony_ci	seq_printf(s, "%5dmA ",
598762306a36Sopenharmony_ci		   _regulator_get_current_limit_unlocked(rdev) / 1000);
598862306a36Sopenharmony_ci
598962306a36Sopenharmony_ci	c = rdev->constraints;
599062306a36Sopenharmony_ci	if (c) {
599162306a36Sopenharmony_ci		switch (rdev->desc->type) {
599262306a36Sopenharmony_ci		case REGULATOR_VOLTAGE:
599362306a36Sopenharmony_ci			seq_printf(s, "%5dmV %5dmV ",
599462306a36Sopenharmony_ci				   c->min_uV / 1000, c->max_uV / 1000);
599562306a36Sopenharmony_ci			break;
599662306a36Sopenharmony_ci		case REGULATOR_CURRENT:
599762306a36Sopenharmony_ci			seq_printf(s, "%5dmA %5dmA ",
599862306a36Sopenharmony_ci				   c->min_uA / 1000, c->max_uA / 1000);
599962306a36Sopenharmony_ci			break;
600062306a36Sopenharmony_ci		}
600162306a36Sopenharmony_ci	}
600262306a36Sopenharmony_ci
600362306a36Sopenharmony_ci	seq_puts(s, "\n");
600462306a36Sopenharmony_ci
600562306a36Sopenharmony_ci	list_for_each_entry(consumer, &rdev->consumer_list, list) {
600662306a36Sopenharmony_ci		if (consumer->dev && consumer->dev->class == &regulator_class)
600762306a36Sopenharmony_ci			continue;
600862306a36Sopenharmony_ci
600962306a36Sopenharmony_ci		seq_printf(s, "%*s%-*s ",
601062306a36Sopenharmony_ci			   (level + 1) * 3 + 1, "",
601162306a36Sopenharmony_ci			   30 - (level + 1) * 3,
601262306a36Sopenharmony_ci			   consumer->supply_name ? consumer->supply_name :
601362306a36Sopenharmony_ci			   consumer->dev ? dev_name(consumer->dev) : "deviceless");
601462306a36Sopenharmony_ci
601562306a36Sopenharmony_ci		switch (rdev->desc->type) {
601662306a36Sopenharmony_ci		case REGULATOR_VOLTAGE:
601762306a36Sopenharmony_ci			seq_printf(s, "%3d %33dmA%c%5dmV %5dmV",
601862306a36Sopenharmony_ci				   consumer->enable_count,
601962306a36Sopenharmony_ci				   consumer->uA_load / 1000,
602062306a36Sopenharmony_ci				   consumer->uA_load && !consumer->enable_count ?
602162306a36Sopenharmony_ci				   '*' : ' ',
602262306a36Sopenharmony_ci				   consumer->voltage[PM_SUSPEND_ON].min_uV / 1000,
602362306a36Sopenharmony_ci				   consumer->voltage[PM_SUSPEND_ON].max_uV / 1000);
602462306a36Sopenharmony_ci			break;
602562306a36Sopenharmony_ci		case REGULATOR_CURRENT:
602662306a36Sopenharmony_ci			break;
602762306a36Sopenharmony_ci		}
602862306a36Sopenharmony_ci
602962306a36Sopenharmony_ci		seq_puts(s, "\n");
603062306a36Sopenharmony_ci	}
603162306a36Sopenharmony_ci
603262306a36Sopenharmony_ci	summary_data.s = s;
603362306a36Sopenharmony_ci	summary_data.level = level;
603462306a36Sopenharmony_ci	summary_data.parent = rdev;
603562306a36Sopenharmony_ci
603662306a36Sopenharmony_ci	class_for_each_device(&regulator_class, NULL, &summary_data,
603762306a36Sopenharmony_ci			      regulator_summary_show_children);
603862306a36Sopenharmony_ci}
603962306a36Sopenharmony_ci
604062306a36Sopenharmony_cistruct summary_lock_data {
604162306a36Sopenharmony_ci	struct ww_acquire_ctx *ww_ctx;
604262306a36Sopenharmony_ci	struct regulator_dev **new_contended_rdev;
604362306a36Sopenharmony_ci	struct regulator_dev **old_contended_rdev;
604462306a36Sopenharmony_ci};
604562306a36Sopenharmony_ci
604662306a36Sopenharmony_cistatic int regulator_summary_lock_one(struct device *dev, void *data)
604762306a36Sopenharmony_ci{
604862306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
604962306a36Sopenharmony_ci	struct summary_lock_data *lock_data = data;
605062306a36Sopenharmony_ci	int ret = 0;
605162306a36Sopenharmony_ci
605262306a36Sopenharmony_ci	if (rdev != *lock_data->old_contended_rdev) {
605362306a36Sopenharmony_ci		ret = regulator_lock_nested(rdev, lock_data->ww_ctx);
605462306a36Sopenharmony_ci
605562306a36Sopenharmony_ci		if (ret == -EDEADLK)
605662306a36Sopenharmony_ci			*lock_data->new_contended_rdev = rdev;
605762306a36Sopenharmony_ci		else
605862306a36Sopenharmony_ci			WARN_ON_ONCE(ret);
605962306a36Sopenharmony_ci	} else {
606062306a36Sopenharmony_ci		*lock_data->old_contended_rdev = NULL;
606162306a36Sopenharmony_ci	}
606262306a36Sopenharmony_ci
606362306a36Sopenharmony_ci	return ret;
606462306a36Sopenharmony_ci}
606562306a36Sopenharmony_ci
606662306a36Sopenharmony_cistatic int regulator_summary_unlock_one(struct device *dev, void *data)
606762306a36Sopenharmony_ci{
606862306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
606962306a36Sopenharmony_ci	struct summary_lock_data *lock_data = data;
607062306a36Sopenharmony_ci
607162306a36Sopenharmony_ci	if (lock_data) {
607262306a36Sopenharmony_ci		if (rdev == *lock_data->new_contended_rdev)
607362306a36Sopenharmony_ci			return -EDEADLK;
607462306a36Sopenharmony_ci	}
607562306a36Sopenharmony_ci
607662306a36Sopenharmony_ci	regulator_unlock(rdev);
607762306a36Sopenharmony_ci
607862306a36Sopenharmony_ci	return 0;
607962306a36Sopenharmony_ci}
608062306a36Sopenharmony_ci
608162306a36Sopenharmony_cistatic int regulator_summary_lock_all(struct ww_acquire_ctx *ww_ctx,
608262306a36Sopenharmony_ci				      struct regulator_dev **new_contended_rdev,
608362306a36Sopenharmony_ci				      struct regulator_dev **old_contended_rdev)
608462306a36Sopenharmony_ci{
608562306a36Sopenharmony_ci	struct summary_lock_data lock_data;
608662306a36Sopenharmony_ci	int ret;
608762306a36Sopenharmony_ci
608862306a36Sopenharmony_ci	lock_data.ww_ctx = ww_ctx;
608962306a36Sopenharmony_ci	lock_data.new_contended_rdev = new_contended_rdev;
609062306a36Sopenharmony_ci	lock_data.old_contended_rdev = old_contended_rdev;
609162306a36Sopenharmony_ci
609262306a36Sopenharmony_ci	ret = class_for_each_device(&regulator_class, NULL, &lock_data,
609362306a36Sopenharmony_ci				    regulator_summary_lock_one);
609462306a36Sopenharmony_ci	if (ret)
609562306a36Sopenharmony_ci		class_for_each_device(&regulator_class, NULL, &lock_data,
609662306a36Sopenharmony_ci				      regulator_summary_unlock_one);
609762306a36Sopenharmony_ci
609862306a36Sopenharmony_ci	return ret;
609962306a36Sopenharmony_ci}
610062306a36Sopenharmony_ci
610162306a36Sopenharmony_cistatic void regulator_summary_lock(struct ww_acquire_ctx *ww_ctx)
610262306a36Sopenharmony_ci{
610362306a36Sopenharmony_ci	struct regulator_dev *new_contended_rdev = NULL;
610462306a36Sopenharmony_ci	struct regulator_dev *old_contended_rdev = NULL;
610562306a36Sopenharmony_ci	int err;
610662306a36Sopenharmony_ci
610762306a36Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
610862306a36Sopenharmony_ci
610962306a36Sopenharmony_ci	ww_acquire_init(ww_ctx, &regulator_ww_class);
611062306a36Sopenharmony_ci
611162306a36Sopenharmony_ci	do {
611262306a36Sopenharmony_ci		if (new_contended_rdev) {
611362306a36Sopenharmony_ci			ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx);
611462306a36Sopenharmony_ci			old_contended_rdev = new_contended_rdev;
611562306a36Sopenharmony_ci			old_contended_rdev->ref_cnt++;
611662306a36Sopenharmony_ci			old_contended_rdev->mutex_owner = current;
611762306a36Sopenharmony_ci		}
611862306a36Sopenharmony_ci
611962306a36Sopenharmony_ci		err = regulator_summary_lock_all(ww_ctx,
612062306a36Sopenharmony_ci						 &new_contended_rdev,
612162306a36Sopenharmony_ci						 &old_contended_rdev);
612262306a36Sopenharmony_ci
612362306a36Sopenharmony_ci		if (old_contended_rdev)
612462306a36Sopenharmony_ci			regulator_unlock(old_contended_rdev);
612562306a36Sopenharmony_ci
612662306a36Sopenharmony_ci	} while (err == -EDEADLK);
612762306a36Sopenharmony_ci
612862306a36Sopenharmony_ci	ww_acquire_done(ww_ctx);
612962306a36Sopenharmony_ci}
613062306a36Sopenharmony_ci
613162306a36Sopenharmony_cistatic void regulator_summary_unlock(struct ww_acquire_ctx *ww_ctx)
613262306a36Sopenharmony_ci{
613362306a36Sopenharmony_ci	class_for_each_device(&regulator_class, NULL, NULL,
613462306a36Sopenharmony_ci			      regulator_summary_unlock_one);
613562306a36Sopenharmony_ci	ww_acquire_fini(ww_ctx);
613662306a36Sopenharmony_ci
613762306a36Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
613862306a36Sopenharmony_ci}
613962306a36Sopenharmony_ci
614062306a36Sopenharmony_cistatic int regulator_summary_show_roots(struct device *dev, void *data)
614162306a36Sopenharmony_ci{
614262306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
614362306a36Sopenharmony_ci	struct seq_file *s = data;
614462306a36Sopenharmony_ci
614562306a36Sopenharmony_ci	if (!rdev->supply)
614662306a36Sopenharmony_ci		regulator_summary_show_subtree(s, rdev, 0);
614762306a36Sopenharmony_ci
614862306a36Sopenharmony_ci	return 0;
614962306a36Sopenharmony_ci}
615062306a36Sopenharmony_ci
615162306a36Sopenharmony_cistatic int regulator_summary_show(struct seq_file *s, void *data)
615262306a36Sopenharmony_ci{
615362306a36Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
615462306a36Sopenharmony_ci
615562306a36Sopenharmony_ci	seq_puts(s, " regulator                      use open bypass  opmode voltage current     min     max\n");
615662306a36Sopenharmony_ci	seq_puts(s, "---------------------------------------------------------------------------------------\n");
615762306a36Sopenharmony_ci
615862306a36Sopenharmony_ci	regulator_summary_lock(&ww_ctx);
615962306a36Sopenharmony_ci
616062306a36Sopenharmony_ci	class_for_each_device(&regulator_class, NULL, s,
616162306a36Sopenharmony_ci			      regulator_summary_show_roots);
616262306a36Sopenharmony_ci
616362306a36Sopenharmony_ci	regulator_summary_unlock(&ww_ctx);
616462306a36Sopenharmony_ci
616562306a36Sopenharmony_ci	return 0;
616662306a36Sopenharmony_ci}
616762306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(regulator_summary);
616862306a36Sopenharmony_ci#endif /* CONFIG_DEBUG_FS */
616962306a36Sopenharmony_ci
617062306a36Sopenharmony_cistatic int __init regulator_init(void)
617162306a36Sopenharmony_ci{
617262306a36Sopenharmony_ci	int ret;
617362306a36Sopenharmony_ci
617462306a36Sopenharmony_ci	ret = class_register(&regulator_class);
617562306a36Sopenharmony_ci
617662306a36Sopenharmony_ci	debugfs_root = debugfs_create_dir("regulator", NULL);
617762306a36Sopenharmony_ci	if (IS_ERR(debugfs_root))
617862306a36Sopenharmony_ci		pr_debug("regulator: Failed to create debugfs directory\n");
617962306a36Sopenharmony_ci
618062306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
618162306a36Sopenharmony_ci	debugfs_create_file("supply_map", 0444, debugfs_root, NULL,
618262306a36Sopenharmony_ci			    &supply_map_fops);
618362306a36Sopenharmony_ci
618462306a36Sopenharmony_ci	debugfs_create_file("regulator_summary", 0444, debugfs_root,
618562306a36Sopenharmony_ci			    NULL, &regulator_summary_fops);
618662306a36Sopenharmony_ci#endif
618762306a36Sopenharmony_ci	regulator_dummy_init();
618862306a36Sopenharmony_ci
618962306a36Sopenharmony_ci	regulator_coupler_register(&generic_regulator_coupler);
619062306a36Sopenharmony_ci
619162306a36Sopenharmony_ci	return ret;
619262306a36Sopenharmony_ci}
619362306a36Sopenharmony_ci
619462306a36Sopenharmony_ci/* init early to allow our consumers to complete system booting */
619562306a36Sopenharmony_cicore_initcall(regulator_init);
619662306a36Sopenharmony_ci
619762306a36Sopenharmony_cistatic int regulator_late_cleanup(struct device *dev, void *data)
619862306a36Sopenharmony_ci{
619962306a36Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
620062306a36Sopenharmony_ci	struct regulation_constraints *c = rdev->constraints;
620162306a36Sopenharmony_ci	int ret;
620262306a36Sopenharmony_ci
620362306a36Sopenharmony_ci	if (c && c->always_on)
620462306a36Sopenharmony_ci		return 0;
620562306a36Sopenharmony_ci
620662306a36Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS))
620762306a36Sopenharmony_ci		return 0;
620862306a36Sopenharmony_ci
620962306a36Sopenharmony_ci	regulator_lock(rdev);
621062306a36Sopenharmony_ci
621162306a36Sopenharmony_ci	if (rdev->use_count)
621262306a36Sopenharmony_ci		goto unlock;
621362306a36Sopenharmony_ci
621462306a36Sopenharmony_ci	/* If reading the status failed, assume that it's off. */
621562306a36Sopenharmony_ci	if (_regulator_is_enabled(rdev) <= 0)
621662306a36Sopenharmony_ci		goto unlock;
621762306a36Sopenharmony_ci
621862306a36Sopenharmony_ci	if (have_full_constraints()) {
621962306a36Sopenharmony_ci		/* We log since this may kill the system if it goes
622062306a36Sopenharmony_ci		 * wrong.
622162306a36Sopenharmony_ci		 */
622262306a36Sopenharmony_ci		rdev_info(rdev, "disabling\n");
622362306a36Sopenharmony_ci		ret = _regulator_do_disable(rdev);
622462306a36Sopenharmony_ci		if (ret != 0)
622562306a36Sopenharmony_ci			rdev_err(rdev, "couldn't disable: %pe\n", ERR_PTR(ret));
622662306a36Sopenharmony_ci	} else {
622762306a36Sopenharmony_ci		/* The intention is that in future we will
622862306a36Sopenharmony_ci		 * assume that full constraints are provided
622962306a36Sopenharmony_ci		 * so warn even if we aren't going to do
623062306a36Sopenharmony_ci		 * anything here.
623162306a36Sopenharmony_ci		 */
623262306a36Sopenharmony_ci		rdev_warn(rdev, "incomplete constraints, leaving on\n");
623362306a36Sopenharmony_ci	}
623462306a36Sopenharmony_ci
623562306a36Sopenharmony_ciunlock:
623662306a36Sopenharmony_ci	regulator_unlock(rdev);
623762306a36Sopenharmony_ci
623862306a36Sopenharmony_ci	return 0;
623962306a36Sopenharmony_ci}
624062306a36Sopenharmony_ci
624162306a36Sopenharmony_cistatic void regulator_init_complete_work_function(struct work_struct *work)
624262306a36Sopenharmony_ci{
624362306a36Sopenharmony_ci	/*
624462306a36Sopenharmony_ci	 * Regulators may had failed to resolve their input supplies
624562306a36Sopenharmony_ci	 * when were registered, either because the input supply was
624662306a36Sopenharmony_ci	 * not registered yet or because its parent device was not
624762306a36Sopenharmony_ci	 * bound yet. So attempt to resolve the input supplies for
624862306a36Sopenharmony_ci	 * pending regulators before trying to disable unused ones.
624962306a36Sopenharmony_ci	 */
625062306a36Sopenharmony_ci	class_for_each_device(&regulator_class, NULL, NULL,
625162306a36Sopenharmony_ci			      regulator_register_resolve_supply);
625262306a36Sopenharmony_ci
625362306a36Sopenharmony_ci	/* If we have a full configuration then disable any regulators
625462306a36Sopenharmony_ci	 * we have permission to change the status for and which are
625562306a36Sopenharmony_ci	 * not in use or always_on.  This is effectively the default
625662306a36Sopenharmony_ci	 * for DT and ACPI as they have full constraints.
625762306a36Sopenharmony_ci	 */
625862306a36Sopenharmony_ci	class_for_each_device(&regulator_class, NULL, NULL,
625962306a36Sopenharmony_ci			      regulator_late_cleanup);
626062306a36Sopenharmony_ci}
626162306a36Sopenharmony_ci
626262306a36Sopenharmony_cistatic DECLARE_DELAYED_WORK(regulator_init_complete_work,
626362306a36Sopenharmony_ci			    regulator_init_complete_work_function);
626462306a36Sopenharmony_ci
626562306a36Sopenharmony_cistatic int __init regulator_init_complete(void)
626662306a36Sopenharmony_ci{
626762306a36Sopenharmony_ci	/*
626862306a36Sopenharmony_ci	 * Since DT doesn't provide an idiomatic mechanism for
626962306a36Sopenharmony_ci	 * enabling full constraints and since it's much more natural
627062306a36Sopenharmony_ci	 * with DT to provide them just assume that a DT enabled
627162306a36Sopenharmony_ci	 * system has full constraints.
627262306a36Sopenharmony_ci	 */
627362306a36Sopenharmony_ci	if (of_have_populated_dt())
627462306a36Sopenharmony_ci		has_full_constraints = true;
627562306a36Sopenharmony_ci
627662306a36Sopenharmony_ci	/*
627762306a36Sopenharmony_ci	 * We punt completion for an arbitrary amount of time since
627862306a36Sopenharmony_ci	 * systems like distros will load many drivers from userspace
627962306a36Sopenharmony_ci	 * so consumers might not always be ready yet, this is
628062306a36Sopenharmony_ci	 * particularly an issue with laptops where this might bounce
628162306a36Sopenharmony_ci	 * the display off then on.  Ideally we'd get a notification
628262306a36Sopenharmony_ci	 * from userspace when this happens but we don't so just wait
628362306a36Sopenharmony_ci	 * a bit and hope we waited long enough.  It'd be better if
628462306a36Sopenharmony_ci	 * we'd only do this on systems that need it, and a kernel
628562306a36Sopenharmony_ci	 * command line option might be useful.
628662306a36Sopenharmony_ci	 */
628762306a36Sopenharmony_ci	schedule_delayed_work(&regulator_init_complete_work,
628862306a36Sopenharmony_ci			      msecs_to_jiffies(30000));
628962306a36Sopenharmony_ci
629062306a36Sopenharmony_ci	return 0;
629162306a36Sopenharmony_ci}
629262306a36Sopenharmony_cilate_initcall_sync(regulator_init_complete);
6293