18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci//
38c2ecf20Sopenharmony_ci// core.c  --  Voltage/Current Regulator framework.
48c2ecf20Sopenharmony_ci//
58c2ecf20Sopenharmony_ci// Copyright 2007, 2008 Wolfson Microelectronics PLC.
68c2ecf20Sopenharmony_ci// Copyright 2008 SlimLogic Ltd.
78c2ecf20Sopenharmony_ci//
88c2ecf20Sopenharmony_ci// Author: Liam Girdwood <lrg@slimlogic.co.uk>
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/kernel.h>
118c2ecf20Sopenharmony_ci#include <linux/init.h>
128c2ecf20Sopenharmony_ci#include <linux/debugfs.h>
138c2ecf20Sopenharmony_ci#include <linux/device.h>
148c2ecf20Sopenharmony_ci#include <linux/slab.h>
158c2ecf20Sopenharmony_ci#include <linux/async.h>
168c2ecf20Sopenharmony_ci#include <linux/err.h>
178c2ecf20Sopenharmony_ci#include <linux/mutex.h>
188c2ecf20Sopenharmony_ci#include <linux/suspend.h>
198c2ecf20Sopenharmony_ci#include <linux/delay.h>
208c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h>
218c2ecf20Sopenharmony_ci#include <linux/of.h>
228c2ecf20Sopenharmony_ci#include <linux/regmap.h>
238c2ecf20Sopenharmony_ci#include <linux/regulator/of_regulator.h>
248c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h>
258c2ecf20Sopenharmony_ci#include <linux/regulator/coupler.h>
268c2ecf20Sopenharmony_ci#include <linux/regulator/driver.h>
278c2ecf20Sopenharmony_ci#include <linux/regulator/machine.h>
288c2ecf20Sopenharmony_ci#include <linux/module.h>
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#define CREATE_TRACE_POINTS
318c2ecf20Sopenharmony_ci#include <trace/events/regulator.h>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#include "dummy.h"
348c2ecf20Sopenharmony_ci#include "internal.h"
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#define rdev_crit(rdev, fmt, ...)					\
378c2ecf20Sopenharmony_ci	pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
388c2ecf20Sopenharmony_ci#define rdev_err(rdev, fmt, ...)					\
398c2ecf20Sopenharmony_ci	pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
408c2ecf20Sopenharmony_ci#define rdev_warn(rdev, fmt, ...)					\
418c2ecf20Sopenharmony_ci	pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
428c2ecf20Sopenharmony_ci#define rdev_info(rdev, fmt, ...)					\
438c2ecf20Sopenharmony_ci	pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
448c2ecf20Sopenharmony_ci#define rdev_dbg(rdev, fmt, ...)					\
458c2ecf20Sopenharmony_ci	pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic DEFINE_WW_CLASS(regulator_ww_class);
488c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(regulator_nesting_mutex);
498c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(regulator_list_mutex);
508c2ecf20Sopenharmony_cistatic LIST_HEAD(regulator_map_list);
518c2ecf20Sopenharmony_cistatic LIST_HEAD(regulator_ena_gpio_list);
528c2ecf20Sopenharmony_cistatic LIST_HEAD(regulator_supply_alias_list);
538c2ecf20Sopenharmony_cistatic LIST_HEAD(regulator_coupler_list);
548c2ecf20Sopenharmony_cistatic bool has_full_constraints;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic struct dentry *debugfs_root;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci/*
598c2ecf20Sopenharmony_ci * struct regulator_map
608c2ecf20Sopenharmony_ci *
618c2ecf20Sopenharmony_ci * Used to provide symbolic supply names to devices.
628c2ecf20Sopenharmony_ci */
638c2ecf20Sopenharmony_cistruct regulator_map {
648c2ecf20Sopenharmony_ci	struct list_head list;
658c2ecf20Sopenharmony_ci	const char *dev_name;   /* The dev_name() for the consumer */
668c2ecf20Sopenharmony_ci	const char *supply;
678c2ecf20Sopenharmony_ci	struct regulator_dev *regulator;
688c2ecf20Sopenharmony_ci};
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci/*
718c2ecf20Sopenharmony_ci * struct regulator_enable_gpio
728c2ecf20Sopenharmony_ci *
738c2ecf20Sopenharmony_ci * Management for shared enable GPIO pin
748c2ecf20Sopenharmony_ci */
758c2ecf20Sopenharmony_cistruct regulator_enable_gpio {
768c2ecf20Sopenharmony_ci	struct list_head list;
778c2ecf20Sopenharmony_ci	struct gpio_desc *gpiod;
788c2ecf20Sopenharmony_ci	u32 enable_count;	/* a number of enabled shared GPIO */
798c2ecf20Sopenharmony_ci	u32 request_count;	/* a number of requested shared GPIO */
808c2ecf20Sopenharmony_ci};
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci/*
838c2ecf20Sopenharmony_ci * struct regulator_supply_alias
848c2ecf20Sopenharmony_ci *
858c2ecf20Sopenharmony_ci * Used to map lookups for a supply onto an alternative device.
868c2ecf20Sopenharmony_ci */
878c2ecf20Sopenharmony_cistruct regulator_supply_alias {
888c2ecf20Sopenharmony_ci	struct list_head list;
898c2ecf20Sopenharmony_ci	struct device *src_dev;
908c2ecf20Sopenharmony_ci	const char *src_supply;
918c2ecf20Sopenharmony_ci	struct device *alias_dev;
928c2ecf20Sopenharmony_ci	const char *alias_supply;
938c2ecf20Sopenharmony_ci};
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic int _regulator_is_enabled(struct regulator_dev *rdev);
968c2ecf20Sopenharmony_cistatic int _regulator_disable(struct regulator *regulator);
978c2ecf20Sopenharmony_cistatic int _regulator_get_current_limit(struct regulator_dev *rdev);
988c2ecf20Sopenharmony_cistatic unsigned int _regulator_get_mode(struct regulator_dev *rdev);
998c2ecf20Sopenharmony_cistatic int _notifier_call_chain(struct regulator_dev *rdev,
1008c2ecf20Sopenharmony_ci				  unsigned long event, void *data);
1018c2ecf20Sopenharmony_cistatic int _regulator_do_set_voltage(struct regulator_dev *rdev,
1028c2ecf20Sopenharmony_ci				     int min_uV, int max_uV);
1038c2ecf20Sopenharmony_cistatic int regulator_balance_voltage(struct regulator_dev *rdev,
1048c2ecf20Sopenharmony_ci				     suspend_state_t state);
1058c2ecf20Sopenharmony_cistatic struct regulator *create_regulator(struct regulator_dev *rdev,
1068c2ecf20Sopenharmony_ci					  struct device *dev,
1078c2ecf20Sopenharmony_ci					  const char *supply_name);
1088c2ecf20Sopenharmony_cistatic void destroy_regulator(struct regulator *regulator);
1098c2ecf20Sopenharmony_cistatic void _regulator_put(struct regulator *regulator);
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ciconst char *rdev_get_name(struct regulator_dev *rdev)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	if (rdev->constraints && rdev->constraints->name)
1148c2ecf20Sopenharmony_ci		return rdev->constraints->name;
1158c2ecf20Sopenharmony_ci	else if (rdev->desc->name)
1168c2ecf20Sopenharmony_ci		return rdev->desc->name;
1178c2ecf20Sopenharmony_ci	else
1188c2ecf20Sopenharmony_ci		return "";
1198c2ecf20Sopenharmony_ci}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistatic bool have_full_constraints(void)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	return has_full_constraints || of_have_populated_dt();
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cistatic bool regulator_ops_is_valid(struct regulator_dev *rdev, int ops)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	if (!rdev->constraints) {
1298c2ecf20Sopenharmony_ci		rdev_err(rdev, "no constraints\n");
1308c2ecf20Sopenharmony_ci		return false;
1318c2ecf20Sopenharmony_ci	}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	if (rdev->constraints->valid_ops_mask & ops)
1348c2ecf20Sopenharmony_ci		return true;
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	return false;
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci/**
1408c2ecf20Sopenharmony_ci * regulator_lock_nested - lock a single regulator
1418c2ecf20Sopenharmony_ci * @rdev:		regulator source
1428c2ecf20Sopenharmony_ci * @ww_ctx:		w/w mutex acquire context
1438c2ecf20Sopenharmony_ci *
1448c2ecf20Sopenharmony_ci * This function can be called many times by one task on
1458c2ecf20Sopenharmony_ci * a single regulator and its mutex will be locked only
1468c2ecf20Sopenharmony_ci * once. If a task, which is calling this function is other
1478c2ecf20Sopenharmony_ci * than the one, which initially locked the mutex, it will
1488c2ecf20Sopenharmony_ci * wait on mutex.
1498c2ecf20Sopenharmony_ci */
1508c2ecf20Sopenharmony_cistatic inline int regulator_lock_nested(struct regulator_dev *rdev,
1518c2ecf20Sopenharmony_ci					struct ww_acquire_ctx *ww_ctx)
1528c2ecf20Sopenharmony_ci{
1538c2ecf20Sopenharmony_ci	bool lock = false;
1548c2ecf20Sopenharmony_ci	int ret = 0;
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	mutex_lock(&regulator_nesting_mutex);
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) {
1598c2ecf20Sopenharmony_ci		if (rdev->mutex_owner == current)
1608c2ecf20Sopenharmony_ci			rdev->ref_cnt++;
1618c2ecf20Sopenharmony_ci		else
1628c2ecf20Sopenharmony_ci			lock = true;
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci		if (lock) {
1658c2ecf20Sopenharmony_ci			mutex_unlock(&regulator_nesting_mutex);
1668c2ecf20Sopenharmony_ci			ret = ww_mutex_lock(&rdev->mutex, ww_ctx);
1678c2ecf20Sopenharmony_ci			mutex_lock(&regulator_nesting_mutex);
1688c2ecf20Sopenharmony_ci		}
1698c2ecf20Sopenharmony_ci	} else {
1708c2ecf20Sopenharmony_ci		lock = true;
1718c2ecf20Sopenharmony_ci	}
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	if (lock && ret != -EDEADLK) {
1748c2ecf20Sopenharmony_ci		rdev->ref_cnt++;
1758c2ecf20Sopenharmony_ci		rdev->mutex_owner = current;
1768c2ecf20Sopenharmony_ci	}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	mutex_unlock(&regulator_nesting_mutex);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	return ret;
1818c2ecf20Sopenharmony_ci}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci/**
1848c2ecf20Sopenharmony_ci * regulator_lock - lock a single regulator
1858c2ecf20Sopenharmony_ci * @rdev:		regulator source
1868c2ecf20Sopenharmony_ci *
1878c2ecf20Sopenharmony_ci * This function can be called many times by one task on
1888c2ecf20Sopenharmony_ci * a single regulator and its mutex will be locked only
1898c2ecf20Sopenharmony_ci * once. If a task, which is calling this function is other
1908c2ecf20Sopenharmony_ci * than the one, which initially locked the mutex, it will
1918c2ecf20Sopenharmony_ci * wait on mutex.
1928c2ecf20Sopenharmony_ci */
1938c2ecf20Sopenharmony_cistatic void regulator_lock(struct regulator_dev *rdev)
1948c2ecf20Sopenharmony_ci{
1958c2ecf20Sopenharmony_ci	regulator_lock_nested(rdev, NULL);
1968c2ecf20Sopenharmony_ci}
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci/**
1998c2ecf20Sopenharmony_ci * regulator_unlock - unlock a single regulator
2008c2ecf20Sopenharmony_ci * @rdev:		regulator_source
2018c2ecf20Sopenharmony_ci *
2028c2ecf20Sopenharmony_ci * This function unlocks the mutex when the
2038c2ecf20Sopenharmony_ci * reference counter reaches 0.
2048c2ecf20Sopenharmony_ci */
2058c2ecf20Sopenharmony_cistatic void regulator_unlock(struct regulator_dev *rdev)
2068c2ecf20Sopenharmony_ci{
2078c2ecf20Sopenharmony_ci	mutex_lock(&regulator_nesting_mutex);
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	if (--rdev->ref_cnt == 0) {
2108c2ecf20Sopenharmony_ci		rdev->mutex_owner = NULL;
2118c2ecf20Sopenharmony_ci		ww_mutex_unlock(&rdev->mutex);
2128c2ecf20Sopenharmony_ci	}
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	WARN_ON_ONCE(rdev->ref_cnt < 0);
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	mutex_unlock(&regulator_nesting_mutex);
2178c2ecf20Sopenharmony_ci}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci/**
2208c2ecf20Sopenharmony_ci * regulator_lock_two - lock two regulators
2218c2ecf20Sopenharmony_ci * @rdev1:		first regulator
2228c2ecf20Sopenharmony_ci * @rdev2:		second regulator
2238c2ecf20Sopenharmony_ci * @ww_ctx:		w/w mutex acquire context
2248c2ecf20Sopenharmony_ci *
2258c2ecf20Sopenharmony_ci * Locks both rdevs using the regulator_ww_class.
2268c2ecf20Sopenharmony_ci */
2278c2ecf20Sopenharmony_cistatic void regulator_lock_two(struct regulator_dev *rdev1,
2288c2ecf20Sopenharmony_ci			       struct regulator_dev *rdev2,
2298c2ecf20Sopenharmony_ci			       struct ww_acquire_ctx *ww_ctx)
2308c2ecf20Sopenharmony_ci{
2318c2ecf20Sopenharmony_ci	struct regulator_dev *tmp;
2328c2ecf20Sopenharmony_ci	int ret;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	ww_acquire_init(ww_ctx, &regulator_ww_class);
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	/* Try to just grab both of them */
2378c2ecf20Sopenharmony_ci	ret = regulator_lock_nested(rdev1, ww_ctx);
2388c2ecf20Sopenharmony_ci	WARN_ON(ret);
2398c2ecf20Sopenharmony_ci	ret = regulator_lock_nested(rdev2, ww_ctx);
2408c2ecf20Sopenharmony_ci	if (ret != -EDEADLOCK) {
2418c2ecf20Sopenharmony_ci		WARN_ON(ret);
2428c2ecf20Sopenharmony_ci		goto exit;
2438c2ecf20Sopenharmony_ci	}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	while (true) {
2468c2ecf20Sopenharmony_ci		/*
2478c2ecf20Sopenharmony_ci		 * Start of loop: rdev1 was locked and rdev2 was contended.
2488c2ecf20Sopenharmony_ci		 * Need to unlock rdev1, slowly lock rdev2, then try rdev1
2498c2ecf20Sopenharmony_ci		 * again.
2508c2ecf20Sopenharmony_ci		 */
2518c2ecf20Sopenharmony_ci		regulator_unlock(rdev1);
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci		ww_mutex_lock_slow(&rdev2->mutex, ww_ctx);
2548c2ecf20Sopenharmony_ci		rdev2->ref_cnt++;
2558c2ecf20Sopenharmony_ci		rdev2->mutex_owner = current;
2568c2ecf20Sopenharmony_ci		ret = regulator_lock_nested(rdev1, ww_ctx);
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci		if (ret == -EDEADLOCK) {
2598c2ecf20Sopenharmony_ci			/* More contention; swap which needs to be slow */
2608c2ecf20Sopenharmony_ci			tmp = rdev1;
2618c2ecf20Sopenharmony_ci			rdev1 = rdev2;
2628c2ecf20Sopenharmony_ci			rdev2 = tmp;
2638c2ecf20Sopenharmony_ci		} else {
2648c2ecf20Sopenharmony_ci			WARN_ON(ret);
2658c2ecf20Sopenharmony_ci			break;
2668c2ecf20Sopenharmony_ci		}
2678c2ecf20Sopenharmony_ci	}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ciexit:
2708c2ecf20Sopenharmony_ci	ww_acquire_done(ww_ctx);
2718c2ecf20Sopenharmony_ci}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci/**
2748c2ecf20Sopenharmony_ci * regulator_unlock_two - unlock two regulators
2758c2ecf20Sopenharmony_ci * @rdev1:		first regulator
2768c2ecf20Sopenharmony_ci * @rdev2:		second regulator
2778c2ecf20Sopenharmony_ci * @ww_ctx:		w/w mutex acquire context
2788c2ecf20Sopenharmony_ci *
2798c2ecf20Sopenharmony_ci * The inverse of regulator_lock_two().
2808c2ecf20Sopenharmony_ci */
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_cistatic void regulator_unlock_two(struct regulator_dev *rdev1,
2838c2ecf20Sopenharmony_ci				 struct regulator_dev *rdev2,
2848c2ecf20Sopenharmony_ci				 struct ww_acquire_ctx *ww_ctx)
2858c2ecf20Sopenharmony_ci{
2868c2ecf20Sopenharmony_ci	regulator_unlock(rdev2);
2878c2ecf20Sopenharmony_ci	regulator_unlock(rdev1);
2888c2ecf20Sopenharmony_ci	ww_acquire_fini(ww_ctx);
2898c2ecf20Sopenharmony_ci}
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_cistatic bool regulator_supply_is_couple(struct regulator_dev *rdev)
2928c2ecf20Sopenharmony_ci{
2938c2ecf20Sopenharmony_ci	struct regulator_dev *c_rdev;
2948c2ecf20Sopenharmony_ci	int i;
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	for (i = 1; i < rdev->coupling_desc.n_coupled; i++) {
2978c2ecf20Sopenharmony_ci		c_rdev = rdev->coupling_desc.coupled_rdevs[i];
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci		if (rdev->supply->rdev == c_rdev)
3008c2ecf20Sopenharmony_ci			return true;
3018c2ecf20Sopenharmony_ci	}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	return false;
3048c2ecf20Sopenharmony_ci}
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_cistatic void regulator_unlock_recursive(struct regulator_dev *rdev,
3078c2ecf20Sopenharmony_ci				       unsigned int n_coupled)
3088c2ecf20Sopenharmony_ci{
3098c2ecf20Sopenharmony_ci	struct regulator_dev *c_rdev, *supply_rdev;
3108c2ecf20Sopenharmony_ci	int i, supply_n_coupled;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	for (i = n_coupled; i > 0; i--) {
3138c2ecf20Sopenharmony_ci		c_rdev = rdev->coupling_desc.coupled_rdevs[i - 1];
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci		if (!c_rdev)
3168c2ecf20Sopenharmony_ci			continue;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci		if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) {
3198c2ecf20Sopenharmony_ci			supply_rdev = c_rdev->supply->rdev;
3208c2ecf20Sopenharmony_ci			supply_n_coupled = supply_rdev->coupling_desc.n_coupled;
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci			regulator_unlock_recursive(supply_rdev,
3238c2ecf20Sopenharmony_ci						   supply_n_coupled);
3248c2ecf20Sopenharmony_ci		}
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci		regulator_unlock(c_rdev);
3278c2ecf20Sopenharmony_ci	}
3288c2ecf20Sopenharmony_ci}
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_cistatic int regulator_lock_recursive(struct regulator_dev *rdev,
3318c2ecf20Sopenharmony_ci				    struct regulator_dev **new_contended_rdev,
3328c2ecf20Sopenharmony_ci				    struct regulator_dev **old_contended_rdev,
3338c2ecf20Sopenharmony_ci				    struct ww_acquire_ctx *ww_ctx)
3348c2ecf20Sopenharmony_ci{
3358c2ecf20Sopenharmony_ci	struct regulator_dev *c_rdev;
3368c2ecf20Sopenharmony_ci	int i, err;
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	for (i = 0; i < rdev->coupling_desc.n_coupled; i++) {
3398c2ecf20Sopenharmony_ci		c_rdev = rdev->coupling_desc.coupled_rdevs[i];
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci		if (!c_rdev)
3428c2ecf20Sopenharmony_ci			continue;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci		if (c_rdev != *old_contended_rdev) {
3458c2ecf20Sopenharmony_ci			err = regulator_lock_nested(c_rdev, ww_ctx);
3468c2ecf20Sopenharmony_ci			if (err) {
3478c2ecf20Sopenharmony_ci				if (err == -EDEADLK) {
3488c2ecf20Sopenharmony_ci					*new_contended_rdev = c_rdev;
3498c2ecf20Sopenharmony_ci					goto err_unlock;
3508c2ecf20Sopenharmony_ci				}
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci				/* shouldn't happen */
3538c2ecf20Sopenharmony_ci				WARN_ON_ONCE(err != -EALREADY);
3548c2ecf20Sopenharmony_ci			}
3558c2ecf20Sopenharmony_ci		} else {
3568c2ecf20Sopenharmony_ci			*old_contended_rdev = NULL;
3578c2ecf20Sopenharmony_ci		}
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci		if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) {
3608c2ecf20Sopenharmony_ci			err = regulator_lock_recursive(c_rdev->supply->rdev,
3618c2ecf20Sopenharmony_ci						       new_contended_rdev,
3628c2ecf20Sopenharmony_ci						       old_contended_rdev,
3638c2ecf20Sopenharmony_ci						       ww_ctx);
3648c2ecf20Sopenharmony_ci			if (err) {
3658c2ecf20Sopenharmony_ci				regulator_unlock(c_rdev);
3668c2ecf20Sopenharmony_ci				goto err_unlock;
3678c2ecf20Sopenharmony_ci			}
3688c2ecf20Sopenharmony_ci		}
3698c2ecf20Sopenharmony_ci	}
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	return 0;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_cierr_unlock:
3748c2ecf20Sopenharmony_ci	regulator_unlock_recursive(rdev, i);
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	return err;
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci/**
3808c2ecf20Sopenharmony_ci * regulator_unlock_dependent - unlock regulator's suppliers and coupled
3818c2ecf20Sopenharmony_ci *				regulators
3828c2ecf20Sopenharmony_ci * @rdev:			regulator source
3838c2ecf20Sopenharmony_ci * @ww_ctx:			w/w mutex acquire context
3848c2ecf20Sopenharmony_ci *
3858c2ecf20Sopenharmony_ci * Unlock all regulators related with rdev by coupling or supplying.
3868c2ecf20Sopenharmony_ci */
3878c2ecf20Sopenharmony_cistatic void regulator_unlock_dependent(struct regulator_dev *rdev,
3888c2ecf20Sopenharmony_ci				       struct ww_acquire_ctx *ww_ctx)
3898c2ecf20Sopenharmony_ci{
3908c2ecf20Sopenharmony_ci	regulator_unlock_recursive(rdev, rdev->coupling_desc.n_coupled);
3918c2ecf20Sopenharmony_ci	ww_acquire_fini(ww_ctx);
3928c2ecf20Sopenharmony_ci}
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci/**
3958c2ecf20Sopenharmony_ci * regulator_lock_dependent - lock regulator's suppliers and coupled regulators
3968c2ecf20Sopenharmony_ci * @rdev:			regulator source
3978c2ecf20Sopenharmony_ci * @ww_ctx:			w/w mutex acquire context
3988c2ecf20Sopenharmony_ci *
3998c2ecf20Sopenharmony_ci * This function as a wrapper on regulator_lock_recursive(), which locks
4008c2ecf20Sopenharmony_ci * all regulators related with rdev by coupling or supplying.
4018c2ecf20Sopenharmony_ci */
4028c2ecf20Sopenharmony_cistatic void regulator_lock_dependent(struct regulator_dev *rdev,
4038c2ecf20Sopenharmony_ci				     struct ww_acquire_ctx *ww_ctx)
4048c2ecf20Sopenharmony_ci{
4058c2ecf20Sopenharmony_ci	struct regulator_dev *new_contended_rdev = NULL;
4068c2ecf20Sopenharmony_ci	struct regulator_dev *old_contended_rdev = NULL;
4078c2ecf20Sopenharmony_ci	int err;
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	ww_acquire_init(ww_ctx, &regulator_ww_class);
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	do {
4148c2ecf20Sopenharmony_ci		if (new_contended_rdev) {
4158c2ecf20Sopenharmony_ci			ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx);
4168c2ecf20Sopenharmony_ci			old_contended_rdev = new_contended_rdev;
4178c2ecf20Sopenharmony_ci			old_contended_rdev->ref_cnt++;
4188c2ecf20Sopenharmony_ci			old_contended_rdev->mutex_owner = current;
4198c2ecf20Sopenharmony_ci		}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci		err = regulator_lock_recursive(rdev,
4228c2ecf20Sopenharmony_ci					       &new_contended_rdev,
4238c2ecf20Sopenharmony_ci					       &old_contended_rdev,
4248c2ecf20Sopenharmony_ci					       ww_ctx);
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci		if (old_contended_rdev)
4278c2ecf20Sopenharmony_ci			regulator_unlock(old_contended_rdev);
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	} while (err == -EDEADLK);
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	ww_acquire_done(ww_ctx);
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
4348c2ecf20Sopenharmony_ci}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci/**
4378c2ecf20Sopenharmony_ci * of_get_child_regulator - get a child regulator device node
4388c2ecf20Sopenharmony_ci * based on supply name
4398c2ecf20Sopenharmony_ci * @parent: Parent device node
4408c2ecf20Sopenharmony_ci * @prop_name: Combination regulator supply name and "-supply"
4418c2ecf20Sopenharmony_ci *
4428c2ecf20Sopenharmony_ci * Traverse all child nodes.
4438c2ecf20Sopenharmony_ci * Extract the child regulator device node corresponding to the supply name.
4448c2ecf20Sopenharmony_ci * returns the device node corresponding to the regulator if found, else
4458c2ecf20Sopenharmony_ci * returns NULL.
4468c2ecf20Sopenharmony_ci */
4478c2ecf20Sopenharmony_cistatic struct device_node *of_get_child_regulator(struct device_node *parent,
4488c2ecf20Sopenharmony_ci						  const char *prop_name)
4498c2ecf20Sopenharmony_ci{
4508c2ecf20Sopenharmony_ci	struct device_node *regnode = NULL;
4518c2ecf20Sopenharmony_ci	struct device_node *child = NULL;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	for_each_child_of_node(parent, child) {
4548c2ecf20Sopenharmony_ci		regnode = of_parse_phandle(child, prop_name, 0);
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci		if (!regnode) {
4578c2ecf20Sopenharmony_ci			regnode = of_get_child_regulator(child, prop_name);
4588c2ecf20Sopenharmony_ci			if (regnode)
4598c2ecf20Sopenharmony_ci				goto err_node_put;
4608c2ecf20Sopenharmony_ci		} else {
4618c2ecf20Sopenharmony_ci			goto err_node_put;
4628c2ecf20Sopenharmony_ci		}
4638c2ecf20Sopenharmony_ci	}
4648c2ecf20Sopenharmony_ci	return NULL;
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_cierr_node_put:
4678c2ecf20Sopenharmony_ci	of_node_put(child);
4688c2ecf20Sopenharmony_ci	return regnode;
4698c2ecf20Sopenharmony_ci}
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci/**
4728c2ecf20Sopenharmony_ci * of_get_regulator - get a regulator device node based on supply name
4738c2ecf20Sopenharmony_ci * @dev: Device pointer for the consumer (of regulator) device
4748c2ecf20Sopenharmony_ci * @supply: regulator supply name
4758c2ecf20Sopenharmony_ci *
4768c2ecf20Sopenharmony_ci * Extract the regulator device node corresponding to the supply name.
4778c2ecf20Sopenharmony_ci * returns the device node corresponding to the regulator if found, else
4788c2ecf20Sopenharmony_ci * returns NULL.
4798c2ecf20Sopenharmony_ci */
4808c2ecf20Sopenharmony_cistatic struct device_node *of_get_regulator(struct device *dev, const char *supply)
4818c2ecf20Sopenharmony_ci{
4828c2ecf20Sopenharmony_ci	struct device_node *regnode = NULL;
4838c2ecf20Sopenharmony_ci	char prop_name[64]; /* 64 is max size of property name */
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	dev_dbg(dev, "Looking up %s-supply from device tree\n", supply);
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	snprintf(prop_name, 64, "%s-supply", supply);
4888c2ecf20Sopenharmony_ci	regnode = of_parse_phandle(dev->of_node, prop_name, 0);
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	if (!regnode) {
4918c2ecf20Sopenharmony_ci		regnode = of_get_child_regulator(dev->of_node, prop_name);
4928c2ecf20Sopenharmony_ci		if (regnode)
4938c2ecf20Sopenharmony_ci			return regnode;
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci		dev_dbg(dev, "Looking up %s property in node %pOF failed\n",
4968c2ecf20Sopenharmony_ci				prop_name, dev->of_node);
4978c2ecf20Sopenharmony_ci		return NULL;
4988c2ecf20Sopenharmony_ci	}
4998c2ecf20Sopenharmony_ci	return regnode;
5008c2ecf20Sopenharmony_ci}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci/* Platform voltage constraint check */
5038c2ecf20Sopenharmony_ciint regulator_check_voltage(struct regulator_dev *rdev,
5048c2ecf20Sopenharmony_ci			    int *min_uV, int *max_uV)
5058c2ecf20Sopenharmony_ci{
5068c2ecf20Sopenharmony_ci	BUG_ON(*min_uV > *max_uV);
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
5098c2ecf20Sopenharmony_ci		rdev_err(rdev, "voltage operation not allowed\n");
5108c2ecf20Sopenharmony_ci		return -EPERM;
5118c2ecf20Sopenharmony_ci	}
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	if (*max_uV > rdev->constraints->max_uV)
5148c2ecf20Sopenharmony_ci		*max_uV = rdev->constraints->max_uV;
5158c2ecf20Sopenharmony_ci	if (*min_uV < rdev->constraints->min_uV)
5168c2ecf20Sopenharmony_ci		*min_uV = rdev->constraints->min_uV;
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci	if (*min_uV > *max_uV) {
5198c2ecf20Sopenharmony_ci		rdev_err(rdev, "unsupportable voltage range: %d-%duV\n",
5208c2ecf20Sopenharmony_ci			 *min_uV, *max_uV);
5218c2ecf20Sopenharmony_ci		return -EINVAL;
5228c2ecf20Sopenharmony_ci	}
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	return 0;
5258c2ecf20Sopenharmony_ci}
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci/* return 0 if the state is valid */
5288c2ecf20Sopenharmony_cistatic int regulator_check_states(suspend_state_t state)
5298c2ecf20Sopenharmony_ci{
5308c2ecf20Sopenharmony_ci	return (state > PM_SUSPEND_MAX || state == PM_SUSPEND_TO_IDLE);
5318c2ecf20Sopenharmony_ci}
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci/* Make sure we select a voltage that suits the needs of all
5348c2ecf20Sopenharmony_ci * regulator consumers
5358c2ecf20Sopenharmony_ci */
5368c2ecf20Sopenharmony_ciint regulator_check_consumers(struct regulator_dev *rdev,
5378c2ecf20Sopenharmony_ci			      int *min_uV, int *max_uV,
5388c2ecf20Sopenharmony_ci			      suspend_state_t state)
5398c2ecf20Sopenharmony_ci{
5408c2ecf20Sopenharmony_ci	struct regulator *regulator;
5418c2ecf20Sopenharmony_ci	struct regulator_voltage *voltage;
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	list_for_each_entry(regulator, &rdev->consumer_list, list) {
5448c2ecf20Sopenharmony_ci		voltage = &regulator->voltage[state];
5458c2ecf20Sopenharmony_ci		/*
5468c2ecf20Sopenharmony_ci		 * Assume consumers that didn't say anything are OK
5478c2ecf20Sopenharmony_ci		 * with anything in the constraint range.
5488c2ecf20Sopenharmony_ci		 */
5498c2ecf20Sopenharmony_ci		if (!voltage->min_uV && !voltage->max_uV)
5508c2ecf20Sopenharmony_ci			continue;
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci		if (*max_uV > voltage->max_uV)
5538c2ecf20Sopenharmony_ci			*max_uV = voltage->max_uV;
5548c2ecf20Sopenharmony_ci		if (*min_uV < voltage->min_uV)
5558c2ecf20Sopenharmony_ci			*min_uV = voltage->min_uV;
5568c2ecf20Sopenharmony_ci	}
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	if (*min_uV > *max_uV) {
5598c2ecf20Sopenharmony_ci		rdev_err(rdev, "Restricting voltage, %u-%uuV\n",
5608c2ecf20Sopenharmony_ci			*min_uV, *max_uV);
5618c2ecf20Sopenharmony_ci		return -EINVAL;
5628c2ecf20Sopenharmony_ci	}
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	return 0;
5658c2ecf20Sopenharmony_ci}
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci/* current constraint check */
5688c2ecf20Sopenharmony_cistatic int regulator_check_current_limit(struct regulator_dev *rdev,
5698c2ecf20Sopenharmony_ci					int *min_uA, int *max_uA)
5708c2ecf20Sopenharmony_ci{
5718c2ecf20Sopenharmony_ci	BUG_ON(*min_uA > *max_uA);
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_CURRENT)) {
5748c2ecf20Sopenharmony_ci		rdev_err(rdev, "current operation not allowed\n");
5758c2ecf20Sopenharmony_ci		return -EPERM;
5768c2ecf20Sopenharmony_ci	}
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	if (*max_uA > rdev->constraints->max_uA)
5798c2ecf20Sopenharmony_ci		*max_uA = rdev->constraints->max_uA;
5808c2ecf20Sopenharmony_ci	if (*min_uA < rdev->constraints->min_uA)
5818c2ecf20Sopenharmony_ci		*min_uA = rdev->constraints->min_uA;
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	if (*min_uA > *max_uA) {
5848c2ecf20Sopenharmony_ci		rdev_err(rdev, "unsupportable current range: %d-%duA\n",
5858c2ecf20Sopenharmony_ci			 *min_uA, *max_uA);
5868c2ecf20Sopenharmony_ci		return -EINVAL;
5878c2ecf20Sopenharmony_ci	}
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	return 0;
5908c2ecf20Sopenharmony_ci}
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci/* operating mode constraint check */
5938c2ecf20Sopenharmony_cistatic int regulator_mode_constrain(struct regulator_dev *rdev,
5948c2ecf20Sopenharmony_ci				    unsigned int *mode)
5958c2ecf20Sopenharmony_ci{
5968c2ecf20Sopenharmony_ci	switch (*mode) {
5978c2ecf20Sopenharmony_ci	case REGULATOR_MODE_FAST:
5988c2ecf20Sopenharmony_ci	case REGULATOR_MODE_NORMAL:
5998c2ecf20Sopenharmony_ci	case REGULATOR_MODE_IDLE:
6008c2ecf20Sopenharmony_ci	case REGULATOR_MODE_STANDBY:
6018c2ecf20Sopenharmony_ci		break;
6028c2ecf20Sopenharmony_ci	default:
6038c2ecf20Sopenharmony_ci		rdev_err(rdev, "invalid mode %x specified\n", *mode);
6048c2ecf20Sopenharmony_ci		return -EINVAL;
6058c2ecf20Sopenharmony_ci	}
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_MODE)) {
6088c2ecf20Sopenharmony_ci		rdev_err(rdev, "mode operation not allowed\n");
6098c2ecf20Sopenharmony_ci		return -EPERM;
6108c2ecf20Sopenharmony_ci	}
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	/* The modes are bitmasks, the most power hungry modes having
6138c2ecf20Sopenharmony_ci	 * the lowest values. If the requested mode isn't supported
6148c2ecf20Sopenharmony_ci	 * try higher modes. */
6158c2ecf20Sopenharmony_ci	while (*mode) {
6168c2ecf20Sopenharmony_ci		if (rdev->constraints->valid_modes_mask & *mode)
6178c2ecf20Sopenharmony_ci			return 0;
6188c2ecf20Sopenharmony_ci		*mode /= 2;
6198c2ecf20Sopenharmony_ci	}
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	return -EINVAL;
6228c2ecf20Sopenharmony_ci}
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_cistatic inline struct regulator_state *
6258c2ecf20Sopenharmony_ciregulator_get_suspend_state(struct regulator_dev *rdev, suspend_state_t state)
6268c2ecf20Sopenharmony_ci{
6278c2ecf20Sopenharmony_ci	if (rdev->constraints == NULL)
6288c2ecf20Sopenharmony_ci		return NULL;
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	switch (state) {
6318c2ecf20Sopenharmony_ci	case PM_SUSPEND_STANDBY:
6328c2ecf20Sopenharmony_ci		return &rdev->constraints->state_standby;
6338c2ecf20Sopenharmony_ci	case PM_SUSPEND_MEM:
6348c2ecf20Sopenharmony_ci		return &rdev->constraints->state_mem;
6358c2ecf20Sopenharmony_ci	case PM_SUSPEND_MAX:
6368c2ecf20Sopenharmony_ci		return &rdev->constraints->state_disk;
6378c2ecf20Sopenharmony_ci	default:
6388c2ecf20Sopenharmony_ci		return NULL;
6398c2ecf20Sopenharmony_ci	}
6408c2ecf20Sopenharmony_ci}
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_cistatic const struct regulator_state *
6438c2ecf20Sopenharmony_ciregulator_get_suspend_state_check(struct regulator_dev *rdev, suspend_state_t state)
6448c2ecf20Sopenharmony_ci{
6458c2ecf20Sopenharmony_ci	const struct regulator_state *rstate;
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	rstate = regulator_get_suspend_state(rdev, state);
6488c2ecf20Sopenharmony_ci	if (rstate == NULL)
6498c2ecf20Sopenharmony_ci		return NULL;
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	/* If we have no suspend mode configuration don't set anything;
6528c2ecf20Sopenharmony_ci	 * only warn if the driver implements set_suspend_voltage or
6538c2ecf20Sopenharmony_ci	 * set_suspend_mode callback.
6548c2ecf20Sopenharmony_ci	 */
6558c2ecf20Sopenharmony_ci	if (rstate->enabled != ENABLE_IN_SUSPEND &&
6568c2ecf20Sopenharmony_ci	    rstate->enabled != DISABLE_IN_SUSPEND) {
6578c2ecf20Sopenharmony_ci		if (rdev->desc->ops->set_suspend_voltage ||
6588c2ecf20Sopenharmony_ci		    rdev->desc->ops->set_suspend_mode)
6598c2ecf20Sopenharmony_ci			rdev_warn(rdev, "No configuration\n");
6608c2ecf20Sopenharmony_ci		return NULL;
6618c2ecf20Sopenharmony_ci	}
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	return rstate;
6648c2ecf20Sopenharmony_ci}
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_cistatic ssize_t regulator_uV_show(struct device *dev,
6678c2ecf20Sopenharmony_ci				struct device_attribute *attr, char *buf)
6688c2ecf20Sopenharmony_ci{
6698c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
6708c2ecf20Sopenharmony_ci	int uV;
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	regulator_lock(rdev);
6738c2ecf20Sopenharmony_ci	uV = regulator_get_voltage_rdev(rdev);
6748c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_ci	if (uV < 0)
6778c2ecf20Sopenharmony_ci		return uV;
6788c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", uV);
6798c2ecf20Sopenharmony_ci}
6808c2ecf20Sopenharmony_cistatic DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL);
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_cistatic ssize_t regulator_uA_show(struct device *dev,
6838c2ecf20Sopenharmony_ci				struct device_attribute *attr, char *buf)
6848c2ecf20Sopenharmony_ci{
6858c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev));
6888c2ecf20Sopenharmony_ci}
6898c2ecf20Sopenharmony_cistatic DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL);
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_cistatic ssize_t name_show(struct device *dev, struct device_attribute *attr,
6928c2ecf20Sopenharmony_ci			 char *buf)
6938c2ecf20Sopenharmony_ci{
6948c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", rdev_get_name(rdev));
6978c2ecf20Sopenharmony_ci}
6988c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(name);
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_cistatic const char *regulator_opmode_to_str(int mode)
7018c2ecf20Sopenharmony_ci{
7028c2ecf20Sopenharmony_ci	switch (mode) {
7038c2ecf20Sopenharmony_ci	case REGULATOR_MODE_FAST:
7048c2ecf20Sopenharmony_ci		return "fast";
7058c2ecf20Sopenharmony_ci	case REGULATOR_MODE_NORMAL:
7068c2ecf20Sopenharmony_ci		return "normal";
7078c2ecf20Sopenharmony_ci	case REGULATOR_MODE_IDLE:
7088c2ecf20Sopenharmony_ci		return "idle";
7098c2ecf20Sopenharmony_ci	case REGULATOR_MODE_STANDBY:
7108c2ecf20Sopenharmony_ci		return "standby";
7118c2ecf20Sopenharmony_ci	}
7128c2ecf20Sopenharmony_ci	return "unknown";
7138c2ecf20Sopenharmony_ci}
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_cistatic ssize_t regulator_print_opmode(char *buf, int mode)
7168c2ecf20Sopenharmony_ci{
7178c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", regulator_opmode_to_str(mode));
7188c2ecf20Sopenharmony_ci}
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_cistatic ssize_t regulator_opmode_show(struct device *dev,
7218c2ecf20Sopenharmony_ci				    struct device_attribute *attr, char *buf)
7228c2ecf20Sopenharmony_ci{
7238c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	return regulator_print_opmode(buf, _regulator_get_mode(rdev));
7268c2ecf20Sopenharmony_ci}
7278c2ecf20Sopenharmony_cistatic DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL);
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_cistatic ssize_t regulator_print_state(char *buf, int state)
7308c2ecf20Sopenharmony_ci{
7318c2ecf20Sopenharmony_ci	if (state > 0)
7328c2ecf20Sopenharmony_ci		return sprintf(buf, "enabled\n");
7338c2ecf20Sopenharmony_ci	else if (state == 0)
7348c2ecf20Sopenharmony_ci		return sprintf(buf, "disabled\n");
7358c2ecf20Sopenharmony_ci	else
7368c2ecf20Sopenharmony_ci		return sprintf(buf, "unknown\n");
7378c2ecf20Sopenharmony_ci}
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_cistatic ssize_t regulator_state_show(struct device *dev,
7408c2ecf20Sopenharmony_ci				   struct device_attribute *attr, char *buf)
7418c2ecf20Sopenharmony_ci{
7428c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
7438c2ecf20Sopenharmony_ci	ssize_t ret;
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	regulator_lock(rdev);
7468c2ecf20Sopenharmony_ci	ret = regulator_print_state(buf, _regulator_is_enabled(rdev));
7478c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci	return ret;
7508c2ecf20Sopenharmony_ci}
7518c2ecf20Sopenharmony_cistatic DEVICE_ATTR(state, 0444, regulator_state_show, NULL);
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_cistatic ssize_t regulator_status_show(struct device *dev,
7548c2ecf20Sopenharmony_ci				   struct device_attribute *attr, char *buf)
7558c2ecf20Sopenharmony_ci{
7568c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
7578c2ecf20Sopenharmony_ci	int status;
7588c2ecf20Sopenharmony_ci	char *label;
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci	status = rdev->desc->ops->get_status(rdev);
7618c2ecf20Sopenharmony_ci	if (status < 0)
7628c2ecf20Sopenharmony_ci		return status;
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	switch (status) {
7658c2ecf20Sopenharmony_ci	case REGULATOR_STATUS_OFF:
7668c2ecf20Sopenharmony_ci		label = "off";
7678c2ecf20Sopenharmony_ci		break;
7688c2ecf20Sopenharmony_ci	case REGULATOR_STATUS_ON:
7698c2ecf20Sopenharmony_ci		label = "on";
7708c2ecf20Sopenharmony_ci		break;
7718c2ecf20Sopenharmony_ci	case REGULATOR_STATUS_ERROR:
7728c2ecf20Sopenharmony_ci		label = "error";
7738c2ecf20Sopenharmony_ci		break;
7748c2ecf20Sopenharmony_ci	case REGULATOR_STATUS_FAST:
7758c2ecf20Sopenharmony_ci		label = "fast";
7768c2ecf20Sopenharmony_ci		break;
7778c2ecf20Sopenharmony_ci	case REGULATOR_STATUS_NORMAL:
7788c2ecf20Sopenharmony_ci		label = "normal";
7798c2ecf20Sopenharmony_ci		break;
7808c2ecf20Sopenharmony_ci	case REGULATOR_STATUS_IDLE:
7818c2ecf20Sopenharmony_ci		label = "idle";
7828c2ecf20Sopenharmony_ci		break;
7838c2ecf20Sopenharmony_ci	case REGULATOR_STATUS_STANDBY:
7848c2ecf20Sopenharmony_ci		label = "standby";
7858c2ecf20Sopenharmony_ci		break;
7868c2ecf20Sopenharmony_ci	case REGULATOR_STATUS_BYPASS:
7878c2ecf20Sopenharmony_ci		label = "bypass";
7888c2ecf20Sopenharmony_ci		break;
7898c2ecf20Sopenharmony_ci	case REGULATOR_STATUS_UNDEFINED:
7908c2ecf20Sopenharmony_ci		label = "undefined";
7918c2ecf20Sopenharmony_ci		break;
7928c2ecf20Sopenharmony_ci	default:
7938c2ecf20Sopenharmony_ci		return -ERANGE;
7948c2ecf20Sopenharmony_ci	}
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", label);
7978c2ecf20Sopenharmony_ci}
7988c2ecf20Sopenharmony_cistatic DEVICE_ATTR(status, 0444, regulator_status_show, NULL);
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_cistatic ssize_t regulator_min_uA_show(struct device *dev,
8018c2ecf20Sopenharmony_ci				    struct device_attribute *attr, char *buf)
8028c2ecf20Sopenharmony_ci{
8038c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci	if (!rdev->constraints)
8068c2ecf20Sopenharmony_ci		return sprintf(buf, "constraint not defined\n");
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", rdev->constraints->min_uA);
8098c2ecf20Sopenharmony_ci}
8108c2ecf20Sopenharmony_cistatic DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL);
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_cistatic ssize_t regulator_max_uA_show(struct device *dev,
8138c2ecf20Sopenharmony_ci				    struct device_attribute *attr, char *buf)
8148c2ecf20Sopenharmony_ci{
8158c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	if (!rdev->constraints)
8188c2ecf20Sopenharmony_ci		return sprintf(buf, "constraint not defined\n");
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", rdev->constraints->max_uA);
8218c2ecf20Sopenharmony_ci}
8228c2ecf20Sopenharmony_cistatic DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL);
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_cistatic ssize_t regulator_min_uV_show(struct device *dev,
8258c2ecf20Sopenharmony_ci				    struct device_attribute *attr, char *buf)
8268c2ecf20Sopenharmony_ci{
8278c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	if (!rdev->constraints)
8308c2ecf20Sopenharmony_ci		return sprintf(buf, "constraint not defined\n");
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", rdev->constraints->min_uV);
8338c2ecf20Sopenharmony_ci}
8348c2ecf20Sopenharmony_cistatic DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL);
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_cistatic ssize_t regulator_max_uV_show(struct device *dev,
8378c2ecf20Sopenharmony_ci				    struct device_attribute *attr, char *buf)
8388c2ecf20Sopenharmony_ci{
8398c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	if (!rdev->constraints)
8428c2ecf20Sopenharmony_ci		return sprintf(buf, "constraint not defined\n");
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", rdev->constraints->max_uV);
8458c2ecf20Sopenharmony_ci}
8468c2ecf20Sopenharmony_cistatic DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL);
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_cistatic ssize_t regulator_total_uA_show(struct device *dev,
8498c2ecf20Sopenharmony_ci				      struct device_attribute *attr, char *buf)
8508c2ecf20Sopenharmony_ci{
8518c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
8528c2ecf20Sopenharmony_ci	struct regulator *regulator;
8538c2ecf20Sopenharmony_ci	int uA = 0;
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	regulator_lock(rdev);
8568c2ecf20Sopenharmony_ci	list_for_each_entry(regulator, &rdev->consumer_list, list) {
8578c2ecf20Sopenharmony_ci		if (regulator->enable_count)
8588c2ecf20Sopenharmony_ci			uA += regulator->uA_load;
8598c2ecf20Sopenharmony_ci	}
8608c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
8618c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", uA);
8628c2ecf20Sopenharmony_ci}
8638c2ecf20Sopenharmony_cistatic DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL);
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_cistatic ssize_t num_users_show(struct device *dev, struct device_attribute *attr,
8668c2ecf20Sopenharmony_ci			      char *buf)
8678c2ecf20Sopenharmony_ci{
8688c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
8698c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", rdev->use_count);
8708c2ecf20Sopenharmony_ci}
8718c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(num_users);
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_cistatic ssize_t type_show(struct device *dev, struct device_attribute *attr,
8748c2ecf20Sopenharmony_ci			 char *buf)
8758c2ecf20Sopenharmony_ci{
8768c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	switch (rdev->desc->type) {
8798c2ecf20Sopenharmony_ci	case REGULATOR_VOLTAGE:
8808c2ecf20Sopenharmony_ci		return sprintf(buf, "voltage\n");
8818c2ecf20Sopenharmony_ci	case REGULATOR_CURRENT:
8828c2ecf20Sopenharmony_ci		return sprintf(buf, "current\n");
8838c2ecf20Sopenharmony_ci	}
8848c2ecf20Sopenharmony_ci	return sprintf(buf, "unknown\n");
8858c2ecf20Sopenharmony_ci}
8868c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(type);
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_cistatic ssize_t regulator_suspend_mem_uV_show(struct device *dev,
8898c2ecf20Sopenharmony_ci				struct device_attribute *attr, char *buf)
8908c2ecf20Sopenharmony_ci{
8918c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV);
8948c2ecf20Sopenharmony_ci}
8958c2ecf20Sopenharmony_cistatic DEVICE_ATTR(suspend_mem_microvolts, 0444,
8968c2ecf20Sopenharmony_ci		regulator_suspend_mem_uV_show, NULL);
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_cistatic ssize_t regulator_suspend_disk_uV_show(struct device *dev,
8998c2ecf20Sopenharmony_ci				struct device_attribute *attr, char *buf)
9008c2ecf20Sopenharmony_ci{
9018c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV);
9048c2ecf20Sopenharmony_ci}
9058c2ecf20Sopenharmony_cistatic DEVICE_ATTR(suspend_disk_microvolts, 0444,
9068c2ecf20Sopenharmony_ci		regulator_suspend_disk_uV_show, NULL);
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_cistatic ssize_t regulator_suspend_standby_uV_show(struct device *dev,
9098c2ecf20Sopenharmony_ci				struct device_attribute *attr, char *buf)
9108c2ecf20Sopenharmony_ci{
9118c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV);
9148c2ecf20Sopenharmony_ci}
9158c2ecf20Sopenharmony_cistatic DEVICE_ATTR(suspend_standby_microvolts, 0444,
9168c2ecf20Sopenharmony_ci		regulator_suspend_standby_uV_show, NULL);
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_cistatic ssize_t regulator_suspend_mem_mode_show(struct device *dev,
9198c2ecf20Sopenharmony_ci				struct device_attribute *attr, char *buf)
9208c2ecf20Sopenharmony_ci{
9218c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci	return regulator_print_opmode(buf,
9248c2ecf20Sopenharmony_ci		rdev->constraints->state_mem.mode);
9258c2ecf20Sopenharmony_ci}
9268c2ecf20Sopenharmony_cistatic DEVICE_ATTR(suspend_mem_mode, 0444,
9278c2ecf20Sopenharmony_ci		regulator_suspend_mem_mode_show, NULL);
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_cistatic ssize_t regulator_suspend_disk_mode_show(struct device *dev,
9308c2ecf20Sopenharmony_ci				struct device_attribute *attr, char *buf)
9318c2ecf20Sopenharmony_ci{
9328c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci	return regulator_print_opmode(buf,
9358c2ecf20Sopenharmony_ci		rdev->constraints->state_disk.mode);
9368c2ecf20Sopenharmony_ci}
9378c2ecf20Sopenharmony_cistatic DEVICE_ATTR(suspend_disk_mode, 0444,
9388c2ecf20Sopenharmony_ci		regulator_suspend_disk_mode_show, NULL);
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_cistatic ssize_t regulator_suspend_standby_mode_show(struct device *dev,
9418c2ecf20Sopenharmony_ci				struct device_attribute *attr, char *buf)
9428c2ecf20Sopenharmony_ci{
9438c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	return regulator_print_opmode(buf,
9468c2ecf20Sopenharmony_ci		rdev->constraints->state_standby.mode);
9478c2ecf20Sopenharmony_ci}
9488c2ecf20Sopenharmony_cistatic DEVICE_ATTR(suspend_standby_mode, 0444,
9498c2ecf20Sopenharmony_ci		regulator_suspend_standby_mode_show, NULL);
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_cistatic ssize_t regulator_suspend_mem_state_show(struct device *dev,
9528c2ecf20Sopenharmony_ci				   struct device_attribute *attr, char *buf)
9538c2ecf20Sopenharmony_ci{
9548c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	return regulator_print_state(buf,
9578c2ecf20Sopenharmony_ci			rdev->constraints->state_mem.enabled);
9588c2ecf20Sopenharmony_ci}
9598c2ecf20Sopenharmony_cistatic DEVICE_ATTR(suspend_mem_state, 0444,
9608c2ecf20Sopenharmony_ci		regulator_suspend_mem_state_show, NULL);
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_cistatic ssize_t regulator_suspend_disk_state_show(struct device *dev,
9638c2ecf20Sopenharmony_ci				   struct device_attribute *attr, char *buf)
9648c2ecf20Sopenharmony_ci{
9658c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci	return regulator_print_state(buf,
9688c2ecf20Sopenharmony_ci			rdev->constraints->state_disk.enabled);
9698c2ecf20Sopenharmony_ci}
9708c2ecf20Sopenharmony_cistatic DEVICE_ATTR(suspend_disk_state, 0444,
9718c2ecf20Sopenharmony_ci		regulator_suspend_disk_state_show, NULL);
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_cistatic ssize_t regulator_suspend_standby_state_show(struct device *dev,
9748c2ecf20Sopenharmony_ci				   struct device_attribute *attr, char *buf)
9758c2ecf20Sopenharmony_ci{
9768c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci	return regulator_print_state(buf,
9798c2ecf20Sopenharmony_ci			rdev->constraints->state_standby.enabled);
9808c2ecf20Sopenharmony_ci}
9818c2ecf20Sopenharmony_cistatic DEVICE_ATTR(suspend_standby_state, 0444,
9828c2ecf20Sopenharmony_ci		regulator_suspend_standby_state_show, NULL);
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_cistatic ssize_t regulator_bypass_show(struct device *dev,
9858c2ecf20Sopenharmony_ci				     struct device_attribute *attr, char *buf)
9868c2ecf20Sopenharmony_ci{
9878c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
9888c2ecf20Sopenharmony_ci	const char *report;
9898c2ecf20Sopenharmony_ci	bool bypass;
9908c2ecf20Sopenharmony_ci	int ret;
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	ret = rdev->desc->ops->get_bypass(rdev, &bypass);
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	if (ret != 0)
9958c2ecf20Sopenharmony_ci		report = "unknown";
9968c2ecf20Sopenharmony_ci	else if (bypass)
9978c2ecf20Sopenharmony_ci		report = "enabled";
9988c2ecf20Sopenharmony_ci	else
9998c2ecf20Sopenharmony_ci		report = "disabled";
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci	return sprintf(buf, "%s\n", report);
10028c2ecf20Sopenharmony_ci}
10038c2ecf20Sopenharmony_cistatic DEVICE_ATTR(bypass, 0444,
10048c2ecf20Sopenharmony_ci		   regulator_bypass_show, NULL);
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ci/* Calculate the new optimum regulator operating mode based on the new total
10078c2ecf20Sopenharmony_ci * consumer load. All locks held by caller */
10088c2ecf20Sopenharmony_cistatic int drms_uA_update(struct regulator_dev *rdev)
10098c2ecf20Sopenharmony_ci{
10108c2ecf20Sopenharmony_ci	struct regulator *sibling;
10118c2ecf20Sopenharmony_ci	int current_uA = 0, output_uV, input_uV, err;
10128c2ecf20Sopenharmony_ci	unsigned int mode;
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	/*
10158c2ecf20Sopenharmony_ci	 * first check to see if we can set modes at all, otherwise just
10168c2ecf20Sopenharmony_ci	 * tell the consumer everything is OK.
10178c2ecf20Sopenharmony_ci	 */
10188c2ecf20Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) {
10198c2ecf20Sopenharmony_ci		rdev_dbg(rdev, "DRMS operation not allowed\n");
10208c2ecf20Sopenharmony_ci		return 0;
10218c2ecf20Sopenharmony_ci	}
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ci	if (!rdev->desc->ops->get_optimum_mode &&
10248c2ecf20Sopenharmony_ci	    !rdev->desc->ops->set_load)
10258c2ecf20Sopenharmony_ci		return 0;
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	if (!rdev->desc->ops->set_mode &&
10288c2ecf20Sopenharmony_ci	    !rdev->desc->ops->set_load)
10298c2ecf20Sopenharmony_ci		return -EINVAL;
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci	/* calc total requested load */
10328c2ecf20Sopenharmony_ci	list_for_each_entry(sibling, &rdev->consumer_list, list) {
10338c2ecf20Sopenharmony_ci		if (sibling->enable_count)
10348c2ecf20Sopenharmony_ci			current_uA += sibling->uA_load;
10358c2ecf20Sopenharmony_ci	}
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_ci	current_uA += rdev->constraints->system_load;
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_ci	if (rdev->desc->ops->set_load) {
10408c2ecf20Sopenharmony_ci		/* set the optimum mode for our new total regulator load */
10418c2ecf20Sopenharmony_ci		err = rdev->desc->ops->set_load(rdev, current_uA);
10428c2ecf20Sopenharmony_ci		if (err < 0)
10438c2ecf20Sopenharmony_ci			rdev_err(rdev, "failed to set load %d: %pe\n",
10448c2ecf20Sopenharmony_ci				 current_uA, ERR_PTR(err));
10458c2ecf20Sopenharmony_ci	} else {
10468c2ecf20Sopenharmony_ci		/* get output voltage */
10478c2ecf20Sopenharmony_ci		output_uV = regulator_get_voltage_rdev(rdev);
10488c2ecf20Sopenharmony_ci		if (output_uV <= 0) {
10498c2ecf20Sopenharmony_ci			rdev_err(rdev, "invalid output voltage found\n");
10508c2ecf20Sopenharmony_ci			return -EINVAL;
10518c2ecf20Sopenharmony_ci		}
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci		/* get input voltage */
10548c2ecf20Sopenharmony_ci		input_uV = 0;
10558c2ecf20Sopenharmony_ci		if (rdev->supply)
10568c2ecf20Sopenharmony_ci			input_uV = regulator_get_voltage_rdev(rdev->supply->rdev);
10578c2ecf20Sopenharmony_ci		if (input_uV <= 0)
10588c2ecf20Sopenharmony_ci			input_uV = rdev->constraints->input_uV;
10598c2ecf20Sopenharmony_ci		if (input_uV <= 0) {
10608c2ecf20Sopenharmony_ci			rdev_err(rdev, "invalid input voltage found\n");
10618c2ecf20Sopenharmony_ci			return -EINVAL;
10628c2ecf20Sopenharmony_ci		}
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci		/* now get the optimum mode for our new total regulator load */
10658c2ecf20Sopenharmony_ci		mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV,
10668c2ecf20Sopenharmony_ci							 output_uV, current_uA);
10678c2ecf20Sopenharmony_ci
10688c2ecf20Sopenharmony_ci		/* check the new mode is allowed */
10698c2ecf20Sopenharmony_ci		err = regulator_mode_constrain(rdev, &mode);
10708c2ecf20Sopenharmony_ci		if (err < 0) {
10718c2ecf20Sopenharmony_ci			rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV: %pe\n",
10728c2ecf20Sopenharmony_ci				 current_uA, input_uV, output_uV, ERR_PTR(err));
10738c2ecf20Sopenharmony_ci			return err;
10748c2ecf20Sopenharmony_ci		}
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci		err = rdev->desc->ops->set_mode(rdev, mode);
10778c2ecf20Sopenharmony_ci		if (err < 0)
10788c2ecf20Sopenharmony_ci			rdev_err(rdev, "failed to set optimum mode %x: %pe\n",
10798c2ecf20Sopenharmony_ci				 mode, ERR_PTR(err));
10808c2ecf20Sopenharmony_ci	}
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci	return err;
10838c2ecf20Sopenharmony_ci}
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_cistatic int __suspend_set_state(struct regulator_dev *rdev,
10868c2ecf20Sopenharmony_ci			       const struct regulator_state *rstate)
10878c2ecf20Sopenharmony_ci{
10888c2ecf20Sopenharmony_ci	int ret = 0;
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_ci	if (rstate->enabled == ENABLE_IN_SUSPEND &&
10918c2ecf20Sopenharmony_ci		rdev->desc->ops->set_suspend_enable)
10928c2ecf20Sopenharmony_ci		ret = rdev->desc->ops->set_suspend_enable(rdev);
10938c2ecf20Sopenharmony_ci	else if (rstate->enabled == DISABLE_IN_SUSPEND &&
10948c2ecf20Sopenharmony_ci		rdev->desc->ops->set_suspend_disable)
10958c2ecf20Sopenharmony_ci		ret = rdev->desc->ops->set_suspend_disable(rdev);
10968c2ecf20Sopenharmony_ci	else /* OK if set_suspend_enable or set_suspend_disable is NULL */
10978c2ecf20Sopenharmony_ci		ret = 0;
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_ci	if (ret < 0) {
11008c2ecf20Sopenharmony_ci		rdev_err(rdev, "failed to enabled/disable: %pe\n", ERR_PTR(ret));
11018c2ecf20Sopenharmony_ci		return ret;
11028c2ecf20Sopenharmony_ci	}
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci	if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) {
11058c2ecf20Sopenharmony_ci		ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV);
11068c2ecf20Sopenharmony_ci		if (ret < 0) {
11078c2ecf20Sopenharmony_ci			rdev_err(rdev, "failed to set voltage: %pe\n", ERR_PTR(ret));
11088c2ecf20Sopenharmony_ci			return ret;
11098c2ecf20Sopenharmony_ci		}
11108c2ecf20Sopenharmony_ci	}
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_ci	if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) {
11138c2ecf20Sopenharmony_ci		ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode);
11148c2ecf20Sopenharmony_ci		if (ret < 0) {
11158c2ecf20Sopenharmony_ci			rdev_err(rdev, "failed to set mode: %pe\n", ERR_PTR(ret));
11168c2ecf20Sopenharmony_ci			return ret;
11178c2ecf20Sopenharmony_ci		}
11188c2ecf20Sopenharmony_ci	}
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci	return ret;
11218c2ecf20Sopenharmony_ci}
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_cistatic int suspend_set_initial_state(struct regulator_dev *rdev)
11248c2ecf20Sopenharmony_ci{
11258c2ecf20Sopenharmony_ci	const struct regulator_state *rstate;
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci	rstate = regulator_get_suspend_state_check(rdev,
11288c2ecf20Sopenharmony_ci			rdev->constraints->initial_state);
11298c2ecf20Sopenharmony_ci	if (!rstate)
11308c2ecf20Sopenharmony_ci		return 0;
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_ci	return __suspend_set_state(rdev, rstate);
11338c2ecf20Sopenharmony_ci}
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ci#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
11368c2ecf20Sopenharmony_cistatic void print_constraints_debug(struct regulator_dev *rdev)
11378c2ecf20Sopenharmony_ci{
11388c2ecf20Sopenharmony_ci	struct regulation_constraints *constraints = rdev->constraints;
11398c2ecf20Sopenharmony_ci	char buf[160] = "";
11408c2ecf20Sopenharmony_ci	size_t len = sizeof(buf) - 1;
11418c2ecf20Sopenharmony_ci	int count = 0;
11428c2ecf20Sopenharmony_ci	int ret;
11438c2ecf20Sopenharmony_ci
11448c2ecf20Sopenharmony_ci	if (constraints->min_uV && constraints->max_uV) {
11458c2ecf20Sopenharmony_ci		if (constraints->min_uV == constraints->max_uV)
11468c2ecf20Sopenharmony_ci			count += scnprintf(buf + count, len - count, "%d mV ",
11478c2ecf20Sopenharmony_ci					   constraints->min_uV / 1000);
11488c2ecf20Sopenharmony_ci		else
11498c2ecf20Sopenharmony_ci			count += scnprintf(buf + count, len - count,
11508c2ecf20Sopenharmony_ci					   "%d <--> %d mV ",
11518c2ecf20Sopenharmony_ci					   constraints->min_uV / 1000,
11528c2ecf20Sopenharmony_ci					   constraints->max_uV / 1000);
11538c2ecf20Sopenharmony_ci	}
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci	if (!constraints->min_uV ||
11568c2ecf20Sopenharmony_ci	    constraints->min_uV != constraints->max_uV) {
11578c2ecf20Sopenharmony_ci		ret = regulator_get_voltage_rdev(rdev);
11588c2ecf20Sopenharmony_ci		if (ret > 0)
11598c2ecf20Sopenharmony_ci			count += scnprintf(buf + count, len - count,
11608c2ecf20Sopenharmony_ci					   "at %d mV ", ret / 1000);
11618c2ecf20Sopenharmony_ci	}
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci	if (constraints->uV_offset)
11648c2ecf20Sopenharmony_ci		count += scnprintf(buf + count, len - count, "%dmV offset ",
11658c2ecf20Sopenharmony_ci				   constraints->uV_offset / 1000);
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_ci	if (constraints->min_uA && constraints->max_uA) {
11688c2ecf20Sopenharmony_ci		if (constraints->min_uA == constraints->max_uA)
11698c2ecf20Sopenharmony_ci			count += scnprintf(buf + count, len - count, "%d mA ",
11708c2ecf20Sopenharmony_ci					   constraints->min_uA / 1000);
11718c2ecf20Sopenharmony_ci		else
11728c2ecf20Sopenharmony_ci			count += scnprintf(buf + count, len - count,
11738c2ecf20Sopenharmony_ci					   "%d <--> %d mA ",
11748c2ecf20Sopenharmony_ci					   constraints->min_uA / 1000,
11758c2ecf20Sopenharmony_ci					   constraints->max_uA / 1000);
11768c2ecf20Sopenharmony_ci	}
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci	if (!constraints->min_uA ||
11798c2ecf20Sopenharmony_ci	    constraints->min_uA != constraints->max_uA) {
11808c2ecf20Sopenharmony_ci		ret = _regulator_get_current_limit(rdev);
11818c2ecf20Sopenharmony_ci		if (ret > 0)
11828c2ecf20Sopenharmony_ci			count += scnprintf(buf + count, len - count,
11838c2ecf20Sopenharmony_ci					   "at %d mA ", ret / 1000);
11848c2ecf20Sopenharmony_ci	}
11858c2ecf20Sopenharmony_ci
11868c2ecf20Sopenharmony_ci	if (constraints->valid_modes_mask & REGULATOR_MODE_FAST)
11878c2ecf20Sopenharmony_ci		count += scnprintf(buf + count, len - count, "fast ");
11888c2ecf20Sopenharmony_ci	if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL)
11898c2ecf20Sopenharmony_ci		count += scnprintf(buf + count, len - count, "normal ");
11908c2ecf20Sopenharmony_ci	if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE)
11918c2ecf20Sopenharmony_ci		count += scnprintf(buf + count, len - count, "idle ");
11928c2ecf20Sopenharmony_ci	if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY)
11938c2ecf20Sopenharmony_ci		count += scnprintf(buf + count, len - count, "standby ");
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_ci	if (!count)
11968c2ecf20Sopenharmony_ci		count = scnprintf(buf, len, "no parameters");
11978c2ecf20Sopenharmony_ci	else
11988c2ecf20Sopenharmony_ci		--count;
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci	count += scnprintf(buf + count, len - count, ", %s",
12018c2ecf20Sopenharmony_ci		_regulator_is_enabled(rdev) ? "enabled" : "disabled");
12028c2ecf20Sopenharmony_ci
12038c2ecf20Sopenharmony_ci	rdev_dbg(rdev, "%s\n", buf);
12048c2ecf20Sopenharmony_ci}
12058c2ecf20Sopenharmony_ci#else /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */
12068c2ecf20Sopenharmony_cistatic inline void print_constraints_debug(struct regulator_dev *rdev) {}
12078c2ecf20Sopenharmony_ci#endif /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_cistatic void print_constraints(struct regulator_dev *rdev)
12108c2ecf20Sopenharmony_ci{
12118c2ecf20Sopenharmony_ci	struct regulation_constraints *constraints = rdev->constraints;
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	print_constraints_debug(rdev);
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_ci	if ((constraints->min_uV != constraints->max_uV) &&
12168c2ecf20Sopenharmony_ci	    !regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE))
12178c2ecf20Sopenharmony_ci		rdev_warn(rdev,
12188c2ecf20Sopenharmony_ci			  "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n");
12198c2ecf20Sopenharmony_ci}
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_cistatic int machine_constraints_voltage(struct regulator_dev *rdev,
12228c2ecf20Sopenharmony_ci	struct regulation_constraints *constraints)
12238c2ecf20Sopenharmony_ci{
12248c2ecf20Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
12258c2ecf20Sopenharmony_ci	int ret;
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci	/* do we need to apply the constraint voltage */
12288c2ecf20Sopenharmony_ci	if (rdev->constraints->apply_uV &&
12298c2ecf20Sopenharmony_ci	    rdev->constraints->min_uV && rdev->constraints->max_uV) {
12308c2ecf20Sopenharmony_ci		int target_min, target_max;
12318c2ecf20Sopenharmony_ci		int current_uV = regulator_get_voltage_rdev(rdev);
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ci		if (current_uV == -ENOTRECOVERABLE) {
12348c2ecf20Sopenharmony_ci			/* This regulator can't be read and must be initialized */
12358c2ecf20Sopenharmony_ci			rdev_info(rdev, "Setting %d-%duV\n",
12368c2ecf20Sopenharmony_ci				  rdev->constraints->min_uV,
12378c2ecf20Sopenharmony_ci				  rdev->constraints->max_uV);
12388c2ecf20Sopenharmony_ci			_regulator_do_set_voltage(rdev,
12398c2ecf20Sopenharmony_ci						  rdev->constraints->min_uV,
12408c2ecf20Sopenharmony_ci						  rdev->constraints->max_uV);
12418c2ecf20Sopenharmony_ci			current_uV = regulator_get_voltage_rdev(rdev);
12428c2ecf20Sopenharmony_ci		}
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci		if (current_uV < 0) {
12458c2ecf20Sopenharmony_ci			rdev_err(rdev,
12468c2ecf20Sopenharmony_ci				 "failed to get the current voltage: %pe\n",
12478c2ecf20Sopenharmony_ci				 ERR_PTR(current_uV));
12488c2ecf20Sopenharmony_ci			return current_uV;
12498c2ecf20Sopenharmony_ci		}
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci		/*
12528c2ecf20Sopenharmony_ci		 * If we're below the minimum voltage move up to the
12538c2ecf20Sopenharmony_ci		 * minimum voltage, if we're above the maximum voltage
12548c2ecf20Sopenharmony_ci		 * then move down to the maximum.
12558c2ecf20Sopenharmony_ci		 */
12568c2ecf20Sopenharmony_ci		target_min = current_uV;
12578c2ecf20Sopenharmony_ci		target_max = current_uV;
12588c2ecf20Sopenharmony_ci
12598c2ecf20Sopenharmony_ci		if (current_uV < rdev->constraints->min_uV) {
12608c2ecf20Sopenharmony_ci			target_min = rdev->constraints->min_uV;
12618c2ecf20Sopenharmony_ci			target_max = rdev->constraints->min_uV;
12628c2ecf20Sopenharmony_ci		}
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_ci		if (current_uV > rdev->constraints->max_uV) {
12658c2ecf20Sopenharmony_ci			target_min = rdev->constraints->max_uV;
12668c2ecf20Sopenharmony_ci			target_max = rdev->constraints->max_uV;
12678c2ecf20Sopenharmony_ci		}
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci		if (target_min != current_uV || target_max != current_uV) {
12708c2ecf20Sopenharmony_ci			rdev_info(rdev, "Bringing %duV into %d-%duV\n",
12718c2ecf20Sopenharmony_ci				  current_uV, target_min, target_max);
12728c2ecf20Sopenharmony_ci			ret = _regulator_do_set_voltage(
12738c2ecf20Sopenharmony_ci				rdev, target_min, target_max);
12748c2ecf20Sopenharmony_ci			if (ret < 0) {
12758c2ecf20Sopenharmony_ci				rdev_err(rdev,
12768c2ecf20Sopenharmony_ci					"failed to apply %d-%duV constraint: %pe\n",
12778c2ecf20Sopenharmony_ci					target_min, target_max, ERR_PTR(ret));
12788c2ecf20Sopenharmony_ci				return ret;
12798c2ecf20Sopenharmony_ci			}
12808c2ecf20Sopenharmony_ci		}
12818c2ecf20Sopenharmony_ci	}
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci	/* constrain machine-level voltage specs to fit
12848c2ecf20Sopenharmony_ci	 * the actual range supported by this regulator.
12858c2ecf20Sopenharmony_ci	 */
12868c2ecf20Sopenharmony_ci	if (ops->list_voltage && rdev->desc->n_voltages) {
12878c2ecf20Sopenharmony_ci		int	count = rdev->desc->n_voltages;
12888c2ecf20Sopenharmony_ci		int	i;
12898c2ecf20Sopenharmony_ci		int	min_uV = INT_MAX;
12908c2ecf20Sopenharmony_ci		int	max_uV = INT_MIN;
12918c2ecf20Sopenharmony_ci		int	cmin = constraints->min_uV;
12928c2ecf20Sopenharmony_ci		int	cmax = constraints->max_uV;
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci		/* it's safe to autoconfigure fixed-voltage supplies
12958c2ecf20Sopenharmony_ci		   and the constraints are used by list_voltage. */
12968c2ecf20Sopenharmony_ci		if (count == 1 && !cmin) {
12978c2ecf20Sopenharmony_ci			cmin = 1;
12988c2ecf20Sopenharmony_ci			cmax = INT_MAX;
12998c2ecf20Sopenharmony_ci			constraints->min_uV = cmin;
13008c2ecf20Sopenharmony_ci			constraints->max_uV = cmax;
13018c2ecf20Sopenharmony_ci		}
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ci		/* voltage constraints are optional */
13048c2ecf20Sopenharmony_ci		if ((cmin == 0) && (cmax == 0))
13058c2ecf20Sopenharmony_ci			return 0;
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci		/* else require explicit machine-level constraints */
13088c2ecf20Sopenharmony_ci		if (cmin <= 0 || cmax <= 0 || cmax < cmin) {
13098c2ecf20Sopenharmony_ci			rdev_err(rdev, "invalid voltage constraints\n");
13108c2ecf20Sopenharmony_ci			return -EINVAL;
13118c2ecf20Sopenharmony_ci		}
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci		/* no need to loop voltages if range is continuous */
13148c2ecf20Sopenharmony_ci		if (rdev->desc->continuous_voltage_range)
13158c2ecf20Sopenharmony_ci			return 0;
13168c2ecf20Sopenharmony_ci
13178c2ecf20Sopenharmony_ci		/* initial: [cmin..cmax] valid, [min_uV..max_uV] not */
13188c2ecf20Sopenharmony_ci		for (i = 0; i < count; i++) {
13198c2ecf20Sopenharmony_ci			int	value;
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_ci			value = ops->list_voltage(rdev, i);
13228c2ecf20Sopenharmony_ci			if (value <= 0)
13238c2ecf20Sopenharmony_ci				continue;
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_ci			/* maybe adjust [min_uV..max_uV] */
13268c2ecf20Sopenharmony_ci			if (value >= cmin && value < min_uV)
13278c2ecf20Sopenharmony_ci				min_uV = value;
13288c2ecf20Sopenharmony_ci			if (value <= cmax && value > max_uV)
13298c2ecf20Sopenharmony_ci				max_uV = value;
13308c2ecf20Sopenharmony_ci		}
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_ci		/* final: [min_uV..max_uV] valid iff constraints valid */
13338c2ecf20Sopenharmony_ci		if (max_uV < min_uV) {
13348c2ecf20Sopenharmony_ci			rdev_err(rdev,
13358c2ecf20Sopenharmony_ci				 "unsupportable voltage constraints %u-%uuV\n",
13368c2ecf20Sopenharmony_ci				 min_uV, max_uV);
13378c2ecf20Sopenharmony_ci			return -EINVAL;
13388c2ecf20Sopenharmony_ci		}
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci		/* use regulator's subset of machine constraints */
13418c2ecf20Sopenharmony_ci		if (constraints->min_uV < min_uV) {
13428c2ecf20Sopenharmony_ci			rdev_dbg(rdev, "override min_uV, %d -> %d\n",
13438c2ecf20Sopenharmony_ci				 constraints->min_uV, min_uV);
13448c2ecf20Sopenharmony_ci			constraints->min_uV = min_uV;
13458c2ecf20Sopenharmony_ci		}
13468c2ecf20Sopenharmony_ci		if (constraints->max_uV > max_uV) {
13478c2ecf20Sopenharmony_ci			rdev_dbg(rdev, "override max_uV, %d -> %d\n",
13488c2ecf20Sopenharmony_ci				 constraints->max_uV, max_uV);
13498c2ecf20Sopenharmony_ci			constraints->max_uV = max_uV;
13508c2ecf20Sopenharmony_ci		}
13518c2ecf20Sopenharmony_ci	}
13528c2ecf20Sopenharmony_ci
13538c2ecf20Sopenharmony_ci	return 0;
13548c2ecf20Sopenharmony_ci}
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_cistatic int machine_constraints_current(struct regulator_dev *rdev,
13578c2ecf20Sopenharmony_ci	struct regulation_constraints *constraints)
13588c2ecf20Sopenharmony_ci{
13598c2ecf20Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
13608c2ecf20Sopenharmony_ci	int ret;
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_ci	if (!constraints->min_uA && !constraints->max_uA)
13638c2ecf20Sopenharmony_ci		return 0;
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_ci	if (constraints->min_uA > constraints->max_uA) {
13668c2ecf20Sopenharmony_ci		rdev_err(rdev, "Invalid current constraints\n");
13678c2ecf20Sopenharmony_ci		return -EINVAL;
13688c2ecf20Sopenharmony_ci	}
13698c2ecf20Sopenharmony_ci
13708c2ecf20Sopenharmony_ci	if (!ops->set_current_limit || !ops->get_current_limit) {
13718c2ecf20Sopenharmony_ci		rdev_warn(rdev, "Operation of current configuration missing\n");
13728c2ecf20Sopenharmony_ci		return 0;
13738c2ecf20Sopenharmony_ci	}
13748c2ecf20Sopenharmony_ci
13758c2ecf20Sopenharmony_ci	/* Set regulator current in constraints range */
13768c2ecf20Sopenharmony_ci	ret = ops->set_current_limit(rdev, constraints->min_uA,
13778c2ecf20Sopenharmony_ci			constraints->max_uA);
13788c2ecf20Sopenharmony_ci	if (ret < 0) {
13798c2ecf20Sopenharmony_ci		rdev_err(rdev, "Failed to set current constraint, %d\n", ret);
13808c2ecf20Sopenharmony_ci		return ret;
13818c2ecf20Sopenharmony_ci	}
13828c2ecf20Sopenharmony_ci
13838c2ecf20Sopenharmony_ci	return 0;
13848c2ecf20Sopenharmony_ci}
13858c2ecf20Sopenharmony_ci
13868c2ecf20Sopenharmony_cistatic int _regulator_do_enable(struct regulator_dev *rdev);
13878c2ecf20Sopenharmony_ci
13888c2ecf20Sopenharmony_ci/**
13898c2ecf20Sopenharmony_ci * set_machine_constraints - sets regulator constraints
13908c2ecf20Sopenharmony_ci * @rdev: regulator source
13918c2ecf20Sopenharmony_ci *
13928c2ecf20Sopenharmony_ci * Allows platform initialisation code to define and constrain
13938c2ecf20Sopenharmony_ci * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
13948c2ecf20Sopenharmony_ci * Constraints *must* be set by platform code in order for some
13958c2ecf20Sopenharmony_ci * regulator operations to proceed i.e. set_voltage, set_current_limit,
13968c2ecf20Sopenharmony_ci * set_mode.
13978c2ecf20Sopenharmony_ci */
13988c2ecf20Sopenharmony_cistatic int set_machine_constraints(struct regulator_dev *rdev)
13998c2ecf20Sopenharmony_ci{
14008c2ecf20Sopenharmony_ci	int ret = 0;
14018c2ecf20Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
14028c2ecf20Sopenharmony_ci
14038c2ecf20Sopenharmony_ci	ret = machine_constraints_voltage(rdev, rdev->constraints);
14048c2ecf20Sopenharmony_ci	if (ret != 0)
14058c2ecf20Sopenharmony_ci		return ret;
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci	ret = machine_constraints_current(rdev, rdev->constraints);
14088c2ecf20Sopenharmony_ci	if (ret != 0)
14098c2ecf20Sopenharmony_ci		return ret;
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_ci	if (rdev->constraints->ilim_uA && ops->set_input_current_limit) {
14128c2ecf20Sopenharmony_ci		ret = ops->set_input_current_limit(rdev,
14138c2ecf20Sopenharmony_ci						   rdev->constraints->ilim_uA);
14148c2ecf20Sopenharmony_ci		if (ret < 0) {
14158c2ecf20Sopenharmony_ci			rdev_err(rdev, "failed to set input limit: %pe\n", ERR_PTR(ret));
14168c2ecf20Sopenharmony_ci			return ret;
14178c2ecf20Sopenharmony_ci		}
14188c2ecf20Sopenharmony_ci	}
14198c2ecf20Sopenharmony_ci
14208c2ecf20Sopenharmony_ci	/* do we need to setup our suspend state */
14218c2ecf20Sopenharmony_ci	if (rdev->constraints->initial_state) {
14228c2ecf20Sopenharmony_ci		ret = suspend_set_initial_state(rdev);
14238c2ecf20Sopenharmony_ci		if (ret < 0) {
14248c2ecf20Sopenharmony_ci			rdev_err(rdev, "failed to set suspend state: %pe\n", ERR_PTR(ret));
14258c2ecf20Sopenharmony_ci			return ret;
14268c2ecf20Sopenharmony_ci		}
14278c2ecf20Sopenharmony_ci	}
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_ci	if (rdev->constraints->initial_mode) {
14308c2ecf20Sopenharmony_ci		if (!ops->set_mode) {
14318c2ecf20Sopenharmony_ci			rdev_err(rdev, "no set_mode operation\n");
14328c2ecf20Sopenharmony_ci			return -EINVAL;
14338c2ecf20Sopenharmony_ci		}
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_ci		ret = ops->set_mode(rdev, rdev->constraints->initial_mode);
14368c2ecf20Sopenharmony_ci		if (ret < 0) {
14378c2ecf20Sopenharmony_ci			rdev_err(rdev, "failed to set initial mode: %pe\n", ERR_PTR(ret));
14388c2ecf20Sopenharmony_ci			return ret;
14398c2ecf20Sopenharmony_ci		}
14408c2ecf20Sopenharmony_ci	} else if (rdev->constraints->system_load) {
14418c2ecf20Sopenharmony_ci		/*
14428c2ecf20Sopenharmony_ci		 * We'll only apply the initial system load if an
14438c2ecf20Sopenharmony_ci		 * initial mode wasn't specified.
14448c2ecf20Sopenharmony_ci		 */
14458c2ecf20Sopenharmony_ci		drms_uA_update(rdev);
14468c2ecf20Sopenharmony_ci	}
14478c2ecf20Sopenharmony_ci
14488c2ecf20Sopenharmony_ci	if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable)
14498c2ecf20Sopenharmony_ci		&& ops->set_ramp_delay) {
14508c2ecf20Sopenharmony_ci		ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay);
14518c2ecf20Sopenharmony_ci		if (ret < 0) {
14528c2ecf20Sopenharmony_ci			rdev_err(rdev, "failed to set ramp_delay: %pe\n", ERR_PTR(ret));
14538c2ecf20Sopenharmony_ci			return ret;
14548c2ecf20Sopenharmony_ci		}
14558c2ecf20Sopenharmony_ci	}
14568c2ecf20Sopenharmony_ci
14578c2ecf20Sopenharmony_ci	if (rdev->constraints->pull_down && ops->set_pull_down) {
14588c2ecf20Sopenharmony_ci		ret = ops->set_pull_down(rdev);
14598c2ecf20Sopenharmony_ci		if (ret < 0) {
14608c2ecf20Sopenharmony_ci			rdev_err(rdev, "failed to set pull down: %pe\n", ERR_PTR(ret));
14618c2ecf20Sopenharmony_ci			return ret;
14628c2ecf20Sopenharmony_ci		}
14638c2ecf20Sopenharmony_ci	}
14648c2ecf20Sopenharmony_ci
14658c2ecf20Sopenharmony_ci	if (rdev->constraints->soft_start && ops->set_soft_start) {
14668c2ecf20Sopenharmony_ci		ret = ops->set_soft_start(rdev);
14678c2ecf20Sopenharmony_ci		if (ret < 0) {
14688c2ecf20Sopenharmony_ci			rdev_err(rdev, "failed to set soft start: %pe\n", ERR_PTR(ret));
14698c2ecf20Sopenharmony_ci			return ret;
14708c2ecf20Sopenharmony_ci		}
14718c2ecf20Sopenharmony_ci	}
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_ci	if (rdev->constraints->over_current_protection
14748c2ecf20Sopenharmony_ci		&& ops->set_over_current_protection) {
14758c2ecf20Sopenharmony_ci		ret = ops->set_over_current_protection(rdev);
14768c2ecf20Sopenharmony_ci		if (ret < 0) {
14778c2ecf20Sopenharmony_ci			rdev_err(rdev, "failed to set over current protection: %pe\n",
14788c2ecf20Sopenharmony_ci				 ERR_PTR(ret));
14798c2ecf20Sopenharmony_ci			return ret;
14808c2ecf20Sopenharmony_ci		}
14818c2ecf20Sopenharmony_ci	}
14828c2ecf20Sopenharmony_ci
14838c2ecf20Sopenharmony_ci	if (rdev->constraints->active_discharge && ops->set_active_discharge) {
14848c2ecf20Sopenharmony_ci		bool ad_state = (rdev->constraints->active_discharge ==
14858c2ecf20Sopenharmony_ci			      REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false;
14868c2ecf20Sopenharmony_ci
14878c2ecf20Sopenharmony_ci		ret = ops->set_active_discharge(rdev, ad_state);
14888c2ecf20Sopenharmony_ci		if (ret < 0) {
14898c2ecf20Sopenharmony_ci			rdev_err(rdev, "failed to set active discharge: %pe\n", ERR_PTR(ret));
14908c2ecf20Sopenharmony_ci			return ret;
14918c2ecf20Sopenharmony_ci		}
14928c2ecf20Sopenharmony_ci	}
14938c2ecf20Sopenharmony_ci
14948c2ecf20Sopenharmony_ci	/* If the constraints say the regulator should be on at this point
14958c2ecf20Sopenharmony_ci	 * and we have control then make sure it is enabled.
14968c2ecf20Sopenharmony_ci	 */
14978c2ecf20Sopenharmony_ci	if (rdev->constraints->always_on || rdev->constraints->boot_on) {
14988c2ecf20Sopenharmony_ci		/* If we want to enable this regulator, make sure that we know
14998c2ecf20Sopenharmony_ci		 * the supplying regulator.
15008c2ecf20Sopenharmony_ci		 */
15018c2ecf20Sopenharmony_ci		if (rdev->supply_name && !rdev->supply)
15028c2ecf20Sopenharmony_ci			return -EPROBE_DEFER;
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci		/* If supplying regulator has already been enabled,
15058c2ecf20Sopenharmony_ci		 * it's not intended to have use_count increment
15068c2ecf20Sopenharmony_ci		 * when rdev is only boot-on.
15078c2ecf20Sopenharmony_ci		 */
15088c2ecf20Sopenharmony_ci		if (rdev->supply &&
15098c2ecf20Sopenharmony_ci		    (rdev->constraints->always_on ||
15108c2ecf20Sopenharmony_ci		     !regulator_is_enabled(rdev->supply))) {
15118c2ecf20Sopenharmony_ci			ret = regulator_enable(rdev->supply);
15128c2ecf20Sopenharmony_ci			if (ret < 0) {
15138c2ecf20Sopenharmony_ci				_regulator_put(rdev->supply);
15148c2ecf20Sopenharmony_ci				rdev->supply = NULL;
15158c2ecf20Sopenharmony_ci				return ret;
15168c2ecf20Sopenharmony_ci			}
15178c2ecf20Sopenharmony_ci		}
15188c2ecf20Sopenharmony_ci
15198c2ecf20Sopenharmony_ci		ret = _regulator_do_enable(rdev);
15208c2ecf20Sopenharmony_ci		if (ret < 0 && ret != -EINVAL) {
15218c2ecf20Sopenharmony_ci			rdev_err(rdev, "failed to enable: %pe\n", ERR_PTR(ret));
15228c2ecf20Sopenharmony_ci			return ret;
15238c2ecf20Sopenharmony_ci		}
15248c2ecf20Sopenharmony_ci
15258c2ecf20Sopenharmony_ci		if (rdev->constraints->always_on)
15268c2ecf20Sopenharmony_ci			rdev->use_count++;
15278c2ecf20Sopenharmony_ci	} else if (rdev->desc->off_on_delay) {
15288c2ecf20Sopenharmony_ci		rdev->last_off_jiffy = jiffies;
15298c2ecf20Sopenharmony_ci	}
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_ci	print_constraints(rdev);
15328c2ecf20Sopenharmony_ci	return 0;
15338c2ecf20Sopenharmony_ci}
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_ci/**
15368c2ecf20Sopenharmony_ci * set_supply - set regulator supply regulator
15378c2ecf20Sopenharmony_ci * @rdev: regulator (locked)
15388c2ecf20Sopenharmony_ci * @supply_rdev: supply regulator (locked))
15398c2ecf20Sopenharmony_ci *
15408c2ecf20Sopenharmony_ci * Called by platform initialisation code to set the supply regulator for this
15418c2ecf20Sopenharmony_ci * regulator. This ensures that a regulators supply will also be enabled by the
15428c2ecf20Sopenharmony_ci * core if it's child is enabled.
15438c2ecf20Sopenharmony_ci */
15448c2ecf20Sopenharmony_cistatic int set_supply(struct regulator_dev *rdev,
15458c2ecf20Sopenharmony_ci		      struct regulator_dev *supply_rdev)
15468c2ecf20Sopenharmony_ci{
15478c2ecf20Sopenharmony_ci	int err;
15488c2ecf20Sopenharmony_ci
15498c2ecf20Sopenharmony_ci	rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev));
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_ci	if (!try_module_get(supply_rdev->owner))
15528c2ecf20Sopenharmony_ci		return -ENODEV;
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_ci	rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY");
15558c2ecf20Sopenharmony_ci	if (rdev->supply == NULL) {
15568c2ecf20Sopenharmony_ci		module_put(supply_rdev->owner);
15578c2ecf20Sopenharmony_ci		err = -ENOMEM;
15588c2ecf20Sopenharmony_ci		return err;
15598c2ecf20Sopenharmony_ci	}
15608c2ecf20Sopenharmony_ci	supply_rdev->open_count++;
15618c2ecf20Sopenharmony_ci
15628c2ecf20Sopenharmony_ci	return 0;
15638c2ecf20Sopenharmony_ci}
15648c2ecf20Sopenharmony_ci
15658c2ecf20Sopenharmony_ci/**
15668c2ecf20Sopenharmony_ci * set_consumer_device_supply - Bind a regulator to a symbolic supply
15678c2ecf20Sopenharmony_ci * @rdev:         regulator source
15688c2ecf20Sopenharmony_ci * @consumer_dev_name: dev_name() string for device supply applies to
15698c2ecf20Sopenharmony_ci * @supply:       symbolic name for supply
15708c2ecf20Sopenharmony_ci *
15718c2ecf20Sopenharmony_ci * Allows platform initialisation code to map physical regulator
15728c2ecf20Sopenharmony_ci * sources to symbolic names for supplies for use by devices.  Devices
15738c2ecf20Sopenharmony_ci * should use these symbolic names to request regulators, avoiding the
15748c2ecf20Sopenharmony_ci * need to provide board-specific regulator names as platform data.
15758c2ecf20Sopenharmony_ci */
15768c2ecf20Sopenharmony_cistatic int set_consumer_device_supply(struct regulator_dev *rdev,
15778c2ecf20Sopenharmony_ci				      const char *consumer_dev_name,
15788c2ecf20Sopenharmony_ci				      const char *supply)
15798c2ecf20Sopenharmony_ci{
15808c2ecf20Sopenharmony_ci	struct regulator_map *node, *new_node;
15818c2ecf20Sopenharmony_ci	int has_dev;
15828c2ecf20Sopenharmony_ci
15838c2ecf20Sopenharmony_ci	if (supply == NULL)
15848c2ecf20Sopenharmony_ci		return -EINVAL;
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci	if (consumer_dev_name != NULL)
15878c2ecf20Sopenharmony_ci		has_dev = 1;
15888c2ecf20Sopenharmony_ci	else
15898c2ecf20Sopenharmony_ci		has_dev = 0;
15908c2ecf20Sopenharmony_ci
15918c2ecf20Sopenharmony_ci	new_node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL);
15928c2ecf20Sopenharmony_ci	if (new_node == NULL)
15938c2ecf20Sopenharmony_ci		return -ENOMEM;
15948c2ecf20Sopenharmony_ci
15958c2ecf20Sopenharmony_ci	new_node->regulator = rdev;
15968c2ecf20Sopenharmony_ci	new_node->supply = supply;
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_ci	if (has_dev) {
15998c2ecf20Sopenharmony_ci		new_node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL);
16008c2ecf20Sopenharmony_ci		if (new_node->dev_name == NULL) {
16018c2ecf20Sopenharmony_ci			kfree(new_node);
16028c2ecf20Sopenharmony_ci			return -ENOMEM;
16038c2ecf20Sopenharmony_ci		}
16048c2ecf20Sopenharmony_ci	}
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
16078c2ecf20Sopenharmony_ci	list_for_each_entry(node, &regulator_map_list, list) {
16088c2ecf20Sopenharmony_ci		if (node->dev_name && consumer_dev_name) {
16098c2ecf20Sopenharmony_ci			if (strcmp(node->dev_name, consumer_dev_name) != 0)
16108c2ecf20Sopenharmony_ci				continue;
16118c2ecf20Sopenharmony_ci		} else if (node->dev_name || consumer_dev_name) {
16128c2ecf20Sopenharmony_ci			continue;
16138c2ecf20Sopenharmony_ci		}
16148c2ecf20Sopenharmony_ci
16158c2ecf20Sopenharmony_ci		if (strcmp(node->supply, supply) != 0)
16168c2ecf20Sopenharmony_ci			continue;
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_ci		pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n",
16198c2ecf20Sopenharmony_ci			 consumer_dev_name,
16208c2ecf20Sopenharmony_ci			 dev_name(&node->regulator->dev),
16218c2ecf20Sopenharmony_ci			 node->regulator->desc->name,
16228c2ecf20Sopenharmony_ci			 supply,
16238c2ecf20Sopenharmony_ci			 dev_name(&rdev->dev), rdev_get_name(rdev));
16248c2ecf20Sopenharmony_ci		goto fail;
16258c2ecf20Sopenharmony_ci	}
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci	list_add(&new_node->list, &regulator_map_list);
16288c2ecf20Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	return 0;
16318c2ecf20Sopenharmony_ci
16328c2ecf20Sopenharmony_cifail:
16338c2ecf20Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
16348c2ecf20Sopenharmony_ci	kfree(new_node->dev_name);
16358c2ecf20Sopenharmony_ci	kfree(new_node);
16368c2ecf20Sopenharmony_ci	return -EBUSY;
16378c2ecf20Sopenharmony_ci}
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_cistatic void unset_regulator_supplies(struct regulator_dev *rdev)
16408c2ecf20Sopenharmony_ci{
16418c2ecf20Sopenharmony_ci	struct regulator_map *node, *n;
16428c2ecf20Sopenharmony_ci
16438c2ecf20Sopenharmony_ci	list_for_each_entry_safe(node, n, &regulator_map_list, list) {
16448c2ecf20Sopenharmony_ci		if (rdev == node->regulator) {
16458c2ecf20Sopenharmony_ci			list_del(&node->list);
16468c2ecf20Sopenharmony_ci			kfree(node->dev_name);
16478c2ecf20Sopenharmony_ci			kfree(node);
16488c2ecf20Sopenharmony_ci		}
16498c2ecf20Sopenharmony_ci	}
16508c2ecf20Sopenharmony_ci}
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
16538c2ecf20Sopenharmony_cistatic ssize_t constraint_flags_read_file(struct file *file,
16548c2ecf20Sopenharmony_ci					  char __user *user_buf,
16558c2ecf20Sopenharmony_ci					  size_t count, loff_t *ppos)
16568c2ecf20Sopenharmony_ci{
16578c2ecf20Sopenharmony_ci	const struct regulator *regulator = file->private_data;
16588c2ecf20Sopenharmony_ci	const struct regulation_constraints *c = regulator->rdev->constraints;
16598c2ecf20Sopenharmony_ci	char *buf;
16608c2ecf20Sopenharmony_ci	ssize_t ret;
16618c2ecf20Sopenharmony_ci
16628c2ecf20Sopenharmony_ci	if (!c)
16638c2ecf20Sopenharmony_ci		return 0;
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_ci	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
16668c2ecf20Sopenharmony_ci	if (!buf)
16678c2ecf20Sopenharmony_ci		return -ENOMEM;
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_ci	ret = snprintf(buf, PAGE_SIZE,
16708c2ecf20Sopenharmony_ci			"always_on: %u\n"
16718c2ecf20Sopenharmony_ci			"boot_on: %u\n"
16728c2ecf20Sopenharmony_ci			"apply_uV: %u\n"
16738c2ecf20Sopenharmony_ci			"ramp_disable: %u\n"
16748c2ecf20Sopenharmony_ci			"soft_start: %u\n"
16758c2ecf20Sopenharmony_ci			"pull_down: %u\n"
16768c2ecf20Sopenharmony_ci			"over_current_protection: %u\n",
16778c2ecf20Sopenharmony_ci			c->always_on,
16788c2ecf20Sopenharmony_ci			c->boot_on,
16798c2ecf20Sopenharmony_ci			c->apply_uV,
16808c2ecf20Sopenharmony_ci			c->ramp_disable,
16818c2ecf20Sopenharmony_ci			c->soft_start,
16828c2ecf20Sopenharmony_ci			c->pull_down,
16838c2ecf20Sopenharmony_ci			c->over_current_protection);
16848c2ecf20Sopenharmony_ci
16858c2ecf20Sopenharmony_ci	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
16868c2ecf20Sopenharmony_ci	kfree(buf);
16878c2ecf20Sopenharmony_ci
16888c2ecf20Sopenharmony_ci	return ret;
16898c2ecf20Sopenharmony_ci}
16908c2ecf20Sopenharmony_ci
16918c2ecf20Sopenharmony_ci#endif
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_cistatic const struct file_operations constraint_flags_fops = {
16948c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
16958c2ecf20Sopenharmony_ci	.open = simple_open,
16968c2ecf20Sopenharmony_ci	.read = constraint_flags_read_file,
16978c2ecf20Sopenharmony_ci	.llseek = default_llseek,
16988c2ecf20Sopenharmony_ci#endif
16998c2ecf20Sopenharmony_ci};
17008c2ecf20Sopenharmony_ci
17018c2ecf20Sopenharmony_ci#define REG_STR_SIZE	64
17028c2ecf20Sopenharmony_ci
17038c2ecf20Sopenharmony_cistatic struct regulator *create_regulator(struct regulator_dev *rdev,
17048c2ecf20Sopenharmony_ci					  struct device *dev,
17058c2ecf20Sopenharmony_ci					  const char *supply_name)
17068c2ecf20Sopenharmony_ci{
17078c2ecf20Sopenharmony_ci	struct regulator *regulator;
17088c2ecf20Sopenharmony_ci	int err = 0;
17098c2ecf20Sopenharmony_ci
17108c2ecf20Sopenharmony_ci	lockdep_assert_held_once(&rdev->mutex.base);
17118c2ecf20Sopenharmony_ci
17128c2ecf20Sopenharmony_ci	if (dev) {
17138c2ecf20Sopenharmony_ci		char buf[REG_STR_SIZE];
17148c2ecf20Sopenharmony_ci		int size;
17158c2ecf20Sopenharmony_ci
17168c2ecf20Sopenharmony_ci		size = snprintf(buf, REG_STR_SIZE, "%s-%s",
17178c2ecf20Sopenharmony_ci				dev->kobj.name, supply_name);
17188c2ecf20Sopenharmony_ci		if (size >= REG_STR_SIZE)
17198c2ecf20Sopenharmony_ci			return NULL;
17208c2ecf20Sopenharmony_ci
17218c2ecf20Sopenharmony_ci		supply_name = kstrdup(buf, GFP_KERNEL);
17228c2ecf20Sopenharmony_ci		if (supply_name == NULL)
17238c2ecf20Sopenharmony_ci			return NULL;
17248c2ecf20Sopenharmony_ci	} else {
17258c2ecf20Sopenharmony_ci		supply_name = kstrdup_const(supply_name, GFP_KERNEL);
17268c2ecf20Sopenharmony_ci		if (supply_name == NULL)
17278c2ecf20Sopenharmony_ci			return NULL;
17288c2ecf20Sopenharmony_ci	}
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci	regulator = kzalloc(sizeof(*regulator), GFP_KERNEL);
17318c2ecf20Sopenharmony_ci	if (regulator == NULL) {
17328c2ecf20Sopenharmony_ci		kfree_const(supply_name);
17338c2ecf20Sopenharmony_ci		return NULL;
17348c2ecf20Sopenharmony_ci	}
17358c2ecf20Sopenharmony_ci
17368c2ecf20Sopenharmony_ci	regulator->rdev = rdev;
17378c2ecf20Sopenharmony_ci	regulator->supply_name = supply_name;
17388c2ecf20Sopenharmony_ci
17398c2ecf20Sopenharmony_ci	list_add(&regulator->list, &rdev->consumer_list);
17408c2ecf20Sopenharmony_ci
17418c2ecf20Sopenharmony_ci	if (dev) {
17428c2ecf20Sopenharmony_ci		regulator->dev = dev;
17438c2ecf20Sopenharmony_ci
17448c2ecf20Sopenharmony_ci		/* Add a link to the device sysfs entry */
17458c2ecf20Sopenharmony_ci		err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj,
17468c2ecf20Sopenharmony_ci					       supply_name);
17478c2ecf20Sopenharmony_ci		if (err) {
17488c2ecf20Sopenharmony_ci			rdev_dbg(rdev, "could not add device link %s: %pe\n",
17498c2ecf20Sopenharmony_ci				  dev->kobj.name, ERR_PTR(err));
17508c2ecf20Sopenharmony_ci			/* non-fatal */
17518c2ecf20Sopenharmony_ci		}
17528c2ecf20Sopenharmony_ci	}
17538c2ecf20Sopenharmony_ci
17548c2ecf20Sopenharmony_ci	if (err != -EEXIST)
17558c2ecf20Sopenharmony_ci		regulator->debugfs = debugfs_create_dir(supply_name, rdev->debugfs);
17568c2ecf20Sopenharmony_ci	if (IS_ERR(regulator->debugfs))
17578c2ecf20Sopenharmony_ci		rdev_dbg(rdev, "Failed to create debugfs directory\n");
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci	debugfs_create_u32("uA_load", 0444, regulator->debugfs,
17608c2ecf20Sopenharmony_ci			   &regulator->uA_load);
17618c2ecf20Sopenharmony_ci	debugfs_create_u32("min_uV", 0444, regulator->debugfs,
17628c2ecf20Sopenharmony_ci			   &regulator->voltage[PM_SUSPEND_ON].min_uV);
17638c2ecf20Sopenharmony_ci	debugfs_create_u32("max_uV", 0444, regulator->debugfs,
17648c2ecf20Sopenharmony_ci			   &regulator->voltage[PM_SUSPEND_ON].max_uV);
17658c2ecf20Sopenharmony_ci	debugfs_create_file("constraint_flags", 0444, regulator->debugfs,
17668c2ecf20Sopenharmony_ci			    regulator, &constraint_flags_fops);
17678c2ecf20Sopenharmony_ci
17688c2ecf20Sopenharmony_ci	/*
17698c2ecf20Sopenharmony_ci	 * Check now if the regulator is an always on regulator - if
17708c2ecf20Sopenharmony_ci	 * it is then we don't need to do nearly so much work for
17718c2ecf20Sopenharmony_ci	 * enable/disable calls.
17728c2ecf20Sopenharmony_ci	 */
17738c2ecf20Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS) &&
17748c2ecf20Sopenharmony_ci	    _regulator_is_enabled(rdev))
17758c2ecf20Sopenharmony_ci		regulator->always_on = true;
17768c2ecf20Sopenharmony_ci
17778c2ecf20Sopenharmony_ci	return regulator;
17788c2ecf20Sopenharmony_ci}
17798c2ecf20Sopenharmony_ci
17808c2ecf20Sopenharmony_cistatic int _regulator_get_enable_time(struct regulator_dev *rdev)
17818c2ecf20Sopenharmony_ci{
17828c2ecf20Sopenharmony_ci	if (rdev->constraints && rdev->constraints->enable_time)
17838c2ecf20Sopenharmony_ci		return rdev->constraints->enable_time;
17848c2ecf20Sopenharmony_ci	if (rdev->desc->ops->enable_time)
17858c2ecf20Sopenharmony_ci		return rdev->desc->ops->enable_time(rdev);
17868c2ecf20Sopenharmony_ci	return rdev->desc->enable_time;
17878c2ecf20Sopenharmony_ci}
17888c2ecf20Sopenharmony_ci
17898c2ecf20Sopenharmony_cistatic struct regulator_supply_alias *regulator_find_supply_alias(
17908c2ecf20Sopenharmony_ci		struct device *dev, const char *supply)
17918c2ecf20Sopenharmony_ci{
17928c2ecf20Sopenharmony_ci	struct regulator_supply_alias *map;
17938c2ecf20Sopenharmony_ci
17948c2ecf20Sopenharmony_ci	list_for_each_entry(map, &regulator_supply_alias_list, list)
17958c2ecf20Sopenharmony_ci		if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0)
17968c2ecf20Sopenharmony_ci			return map;
17978c2ecf20Sopenharmony_ci
17988c2ecf20Sopenharmony_ci	return NULL;
17998c2ecf20Sopenharmony_ci}
18008c2ecf20Sopenharmony_ci
18018c2ecf20Sopenharmony_cistatic void regulator_supply_alias(struct device **dev, const char **supply)
18028c2ecf20Sopenharmony_ci{
18038c2ecf20Sopenharmony_ci	struct regulator_supply_alias *map;
18048c2ecf20Sopenharmony_ci
18058c2ecf20Sopenharmony_ci	map = regulator_find_supply_alias(*dev, *supply);
18068c2ecf20Sopenharmony_ci	if (map) {
18078c2ecf20Sopenharmony_ci		dev_dbg(*dev, "Mapping supply %s to %s,%s\n",
18088c2ecf20Sopenharmony_ci				*supply, map->alias_supply,
18098c2ecf20Sopenharmony_ci				dev_name(map->alias_dev));
18108c2ecf20Sopenharmony_ci		*dev = map->alias_dev;
18118c2ecf20Sopenharmony_ci		*supply = map->alias_supply;
18128c2ecf20Sopenharmony_ci	}
18138c2ecf20Sopenharmony_ci}
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_cistatic int regulator_match(struct device *dev, const void *data)
18168c2ecf20Sopenharmony_ci{
18178c2ecf20Sopenharmony_ci	struct regulator_dev *r = dev_to_rdev(dev);
18188c2ecf20Sopenharmony_ci
18198c2ecf20Sopenharmony_ci	return strcmp(rdev_get_name(r), data) == 0;
18208c2ecf20Sopenharmony_ci}
18218c2ecf20Sopenharmony_ci
18228c2ecf20Sopenharmony_cistatic struct regulator_dev *regulator_lookup_by_name(const char *name)
18238c2ecf20Sopenharmony_ci{
18248c2ecf20Sopenharmony_ci	struct device *dev;
18258c2ecf20Sopenharmony_ci
18268c2ecf20Sopenharmony_ci	dev = class_find_device(&regulator_class, NULL, name, regulator_match);
18278c2ecf20Sopenharmony_ci
18288c2ecf20Sopenharmony_ci	return dev ? dev_to_rdev(dev) : NULL;
18298c2ecf20Sopenharmony_ci}
18308c2ecf20Sopenharmony_ci
18318c2ecf20Sopenharmony_ci/**
18328c2ecf20Sopenharmony_ci * regulator_dev_lookup - lookup a regulator device.
18338c2ecf20Sopenharmony_ci * @dev: device for regulator "consumer".
18348c2ecf20Sopenharmony_ci * @supply: Supply name or regulator ID.
18358c2ecf20Sopenharmony_ci *
18368c2ecf20Sopenharmony_ci * If successful, returns a struct regulator_dev that corresponds to the name
18378c2ecf20Sopenharmony_ci * @supply and with the embedded struct device refcount incremented by one.
18388c2ecf20Sopenharmony_ci * The refcount must be dropped by calling put_device().
18398c2ecf20Sopenharmony_ci * On failure one of the following ERR-PTR-encoded values is returned:
18408c2ecf20Sopenharmony_ci * -ENODEV if lookup fails permanently, -EPROBE_DEFER if lookup could succeed
18418c2ecf20Sopenharmony_ci * in the future.
18428c2ecf20Sopenharmony_ci */
18438c2ecf20Sopenharmony_cistatic struct regulator_dev *regulator_dev_lookup(struct device *dev,
18448c2ecf20Sopenharmony_ci						  const char *supply)
18458c2ecf20Sopenharmony_ci{
18468c2ecf20Sopenharmony_ci	struct regulator_dev *r = NULL;
18478c2ecf20Sopenharmony_ci	struct device_node *node;
18488c2ecf20Sopenharmony_ci	struct regulator_map *map;
18498c2ecf20Sopenharmony_ci	const char *devname = NULL;
18508c2ecf20Sopenharmony_ci
18518c2ecf20Sopenharmony_ci	regulator_supply_alias(&dev, &supply);
18528c2ecf20Sopenharmony_ci
18538c2ecf20Sopenharmony_ci	/* first do a dt based lookup */
18548c2ecf20Sopenharmony_ci	if (dev && dev->of_node) {
18558c2ecf20Sopenharmony_ci		node = of_get_regulator(dev, supply);
18568c2ecf20Sopenharmony_ci		if (node) {
18578c2ecf20Sopenharmony_ci			r = of_find_regulator_by_node(node);
18588c2ecf20Sopenharmony_ci			of_node_put(node);
18598c2ecf20Sopenharmony_ci			if (r)
18608c2ecf20Sopenharmony_ci				return r;
18618c2ecf20Sopenharmony_ci
18628c2ecf20Sopenharmony_ci			/*
18638c2ecf20Sopenharmony_ci			 * We have a node, but there is no device.
18648c2ecf20Sopenharmony_ci			 * assume it has not registered yet.
18658c2ecf20Sopenharmony_ci			 */
18668c2ecf20Sopenharmony_ci			return ERR_PTR(-EPROBE_DEFER);
18678c2ecf20Sopenharmony_ci		}
18688c2ecf20Sopenharmony_ci	}
18698c2ecf20Sopenharmony_ci
18708c2ecf20Sopenharmony_ci	/* if not found, try doing it non-dt way */
18718c2ecf20Sopenharmony_ci	if (dev)
18728c2ecf20Sopenharmony_ci		devname = dev_name(dev);
18738c2ecf20Sopenharmony_ci
18748c2ecf20Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
18758c2ecf20Sopenharmony_ci	list_for_each_entry(map, &regulator_map_list, list) {
18768c2ecf20Sopenharmony_ci		/* If the mapping has a device set up it must match */
18778c2ecf20Sopenharmony_ci		if (map->dev_name &&
18788c2ecf20Sopenharmony_ci		    (!devname || strcmp(map->dev_name, devname)))
18798c2ecf20Sopenharmony_ci			continue;
18808c2ecf20Sopenharmony_ci
18818c2ecf20Sopenharmony_ci		if (strcmp(map->supply, supply) == 0 &&
18828c2ecf20Sopenharmony_ci		    get_device(&map->regulator->dev)) {
18838c2ecf20Sopenharmony_ci			r = map->regulator;
18848c2ecf20Sopenharmony_ci			break;
18858c2ecf20Sopenharmony_ci		}
18868c2ecf20Sopenharmony_ci	}
18878c2ecf20Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
18888c2ecf20Sopenharmony_ci
18898c2ecf20Sopenharmony_ci	if (r)
18908c2ecf20Sopenharmony_ci		return r;
18918c2ecf20Sopenharmony_ci
18928c2ecf20Sopenharmony_ci	r = regulator_lookup_by_name(supply);
18938c2ecf20Sopenharmony_ci	if (r)
18948c2ecf20Sopenharmony_ci		return r;
18958c2ecf20Sopenharmony_ci
18968c2ecf20Sopenharmony_ci	return ERR_PTR(-ENODEV);
18978c2ecf20Sopenharmony_ci}
18988c2ecf20Sopenharmony_ci
18998c2ecf20Sopenharmony_cistatic int regulator_resolve_supply(struct regulator_dev *rdev)
19008c2ecf20Sopenharmony_ci{
19018c2ecf20Sopenharmony_ci	struct regulator_dev *r;
19028c2ecf20Sopenharmony_ci	struct device *dev = rdev->dev.parent;
19038c2ecf20Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
19048c2ecf20Sopenharmony_ci	int ret = 0;
19058c2ecf20Sopenharmony_ci
19068c2ecf20Sopenharmony_ci	/* No supply to resolve? */
19078c2ecf20Sopenharmony_ci	if (!rdev->supply_name)
19088c2ecf20Sopenharmony_ci		return 0;
19098c2ecf20Sopenharmony_ci
19108c2ecf20Sopenharmony_ci	/* Supply already resolved? (fast-path without locking contention) */
19118c2ecf20Sopenharmony_ci	if (rdev->supply)
19128c2ecf20Sopenharmony_ci		return 0;
19138c2ecf20Sopenharmony_ci
19148c2ecf20Sopenharmony_ci	r = regulator_dev_lookup(dev, rdev->supply_name);
19158c2ecf20Sopenharmony_ci	if (IS_ERR(r)) {
19168c2ecf20Sopenharmony_ci		ret = PTR_ERR(r);
19178c2ecf20Sopenharmony_ci
19188c2ecf20Sopenharmony_ci		/* Did the lookup explicitly defer for us? */
19198c2ecf20Sopenharmony_ci		if (ret == -EPROBE_DEFER)
19208c2ecf20Sopenharmony_ci			goto out;
19218c2ecf20Sopenharmony_ci
19228c2ecf20Sopenharmony_ci		if (have_full_constraints()) {
19238c2ecf20Sopenharmony_ci			r = dummy_regulator_rdev;
19248c2ecf20Sopenharmony_ci			get_device(&r->dev);
19258c2ecf20Sopenharmony_ci		} else {
19268c2ecf20Sopenharmony_ci			dev_err(dev, "Failed to resolve %s-supply for %s\n",
19278c2ecf20Sopenharmony_ci				rdev->supply_name, rdev->desc->name);
19288c2ecf20Sopenharmony_ci			ret = -EPROBE_DEFER;
19298c2ecf20Sopenharmony_ci			goto out;
19308c2ecf20Sopenharmony_ci		}
19318c2ecf20Sopenharmony_ci	}
19328c2ecf20Sopenharmony_ci
19338c2ecf20Sopenharmony_ci	if (r == rdev) {
19348c2ecf20Sopenharmony_ci		dev_err(dev, "Supply for %s (%s) resolved to itself\n",
19358c2ecf20Sopenharmony_ci			rdev->desc->name, rdev->supply_name);
19368c2ecf20Sopenharmony_ci		if (!have_full_constraints()) {
19378c2ecf20Sopenharmony_ci			ret = -EINVAL;
19388c2ecf20Sopenharmony_ci			goto out;
19398c2ecf20Sopenharmony_ci		}
19408c2ecf20Sopenharmony_ci		r = dummy_regulator_rdev;
19418c2ecf20Sopenharmony_ci		get_device(&r->dev);
19428c2ecf20Sopenharmony_ci	}
19438c2ecf20Sopenharmony_ci
19448c2ecf20Sopenharmony_ci	/*
19458c2ecf20Sopenharmony_ci	 * If the supply's parent device is not the same as the
19468c2ecf20Sopenharmony_ci	 * regulator's parent device, then ensure the parent device
19478c2ecf20Sopenharmony_ci	 * is bound before we resolve the supply, in case the parent
19488c2ecf20Sopenharmony_ci	 * device get probe deferred and unregisters the supply.
19498c2ecf20Sopenharmony_ci	 */
19508c2ecf20Sopenharmony_ci	if (r->dev.parent && r->dev.parent != rdev->dev.parent) {
19518c2ecf20Sopenharmony_ci		if (!device_is_bound(r->dev.parent)) {
19528c2ecf20Sopenharmony_ci			put_device(&r->dev);
19538c2ecf20Sopenharmony_ci			ret = -EPROBE_DEFER;
19548c2ecf20Sopenharmony_ci			goto out;
19558c2ecf20Sopenharmony_ci		}
19568c2ecf20Sopenharmony_ci	}
19578c2ecf20Sopenharmony_ci
19588c2ecf20Sopenharmony_ci	/* Recursively resolve the supply of the supply */
19598c2ecf20Sopenharmony_ci	ret = regulator_resolve_supply(r);
19608c2ecf20Sopenharmony_ci	if (ret < 0) {
19618c2ecf20Sopenharmony_ci		put_device(&r->dev);
19628c2ecf20Sopenharmony_ci		goto out;
19638c2ecf20Sopenharmony_ci	}
19648c2ecf20Sopenharmony_ci
19658c2ecf20Sopenharmony_ci	/*
19668c2ecf20Sopenharmony_ci	 * Recheck rdev->supply with rdev->mutex lock held to avoid a race
19678c2ecf20Sopenharmony_ci	 * between rdev->supply null check and setting rdev->supply in
19688c2ecf20Sopenharmony_ci	 * set_supply() from concurrent tasks.
19698c2ecf20Sopenharmony_ci	 */
19708c2ecf20Sopenharmony_ci	regulator_lock_two(rdev, r, &ww_ctx);
19718c2ecf20Sopenharmony_ci
19728c2ecf20Sopenharmony_ci	/* Supply just resolved by a concurrent task? */
19738c2ecf20Sopenharmony_ci	if (rdev->supply) {
19748c2ecf20Sopenharmony_ci		regulator_unlock_two(rdev, r, &ww_ctx);
19758c2ecf20Sopenharmony_ci		put_device(&r->dev);
19768c2ecf20Sopenharmony_ci		goto out;
19778c2ecf20Sopenharmony_ci	}
19788c2ecf20Sopenharmony_ci
19798c2ecf20Sopenharmony_ci	ret = set_supply(rdev, r);
19808c2ecf20Sopenharmony_ci	if (ret < 0) {
19818c2ecf20Sopenharmony_ci		regulator_unlock_two(rdev, r, &ww_ctx);
19828c2ecf20Sopenharmony_ci		put_device(&r->dev);
19838c2ecf20Sopenharmony_ci		goto out;
19848c2ecf20Sopenharmony_ci	}
19858c2ecf20Sopenharmony_ci
19868c2ecf20Sopenharmony_ci	regulator_unlock_two(rdev, r, &ww_ctx);
19878c2ecf20Sopenharmony_ci
19888c2ecf20Sopenharmony_ci	/*
19898c2ecf20Sopenharmony_ci	 * In set_machine_constraints() we may have turned this regulator on
19908c2ecf20Sopenharmony_ci	 * but we couldn't propagate to the supply if it hadn't been resolved
19918c2ecf20Sopenharmony_ci	 * yet.  Do it now.
19928c2ecf20Sopenharmony_ci	 */
19938c2ecf20Sopenharmony_ci	if (rdev->use_count) {
19948c2ecf20Sopenharmony_ci		ret = regulator_enable(rdev->supply);
19958c2ecf20Sopenharmony_ci		if (ret < 0) {
19968c2ecf20Sopenharmony_ci			_regulator_put(rdev->supply);
19978c2ecf20Sopenharmony_ci			rdev->supply = NULL;
19988c2ecf20Sopenharmony_ci			goto out;
19998c2ecf20Sopenharmony_ci		}
20008c2ecf20Sopenharmony_ci	}
20018c2ecf20Sopenharmony_ci
20028c2ecf20Sopenharmony_ciout:
20038c2ecf20Sopenharmony_ci	return ret;
20048c2ecf20Sopenharmony_ci}
20058c2ecf20Sopenharmony_ci
20068c2ecf20Sopenharmony_ci/* Internal regulator request function */
20078c2ecf20Sopenharmony_cistruct regulator *_regulator_get(struct device *dev, const char *id,
20088c2ecf20Sopenharmony_ci				 enum regulator_get_type get_type)
20098c2ecf20Sopenharmony_ci{
20108c2ecf20Sopenharmony_ci	struct regulator_dev *rdev;
20118c2ecf20Sopenharmony_ci	struct regulator *regulator;
20128c2ecf20Sopenharmony_ci	struct device_link *link;
20138c2ecf20Sopenharmony_ci	int ret;
20148c2ecf20Sopenharmony_ci
20158c2ecf20Sopenharmony_ci	if (get_type >= MAX_GET_TYPE) {
20168c2ecf20Sopenharmony_ci		dev_err(dev, "invalid type %d in %s\n", get_type, __func__);
20178c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
20188c2ecf20Sopenharmony_ci	}
20198c2ecf20Sopenharmony_ci
20208c2ecf20Sopenharmony_ci	if (id == NULL) {
20218c2ecf20Sopenharmony_ci		pr_err("get() with no identifier\n");
20228c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
20238c2ecf20Sopenharmony_ci	}
20248c2ecf20Sopenharmony_ci
20258c2ecf20Sopenharmony_ci	rdev = regulator_dev_lookup(dev, id);
20268c2ecf20Sopenharmony_ci	if (IS_ERR(rdev)) {
20278c2ecf20Sopenharmony_ci		ret = PTR_ERR(rdev);
20288c2ecf20Sopenharmony_ci
20298c2ecf20Sopenharmony_ci		/*
20308c2ecf20Sopenharmony_ci		 * If regulator_dev_lookup() fails with error other
20318c2ecf20Sopenharmony_ci		 * than -ENODEV our job here is done, we simply return it.
20328c2ecf20Sopenharmony_ci		 */
20338c2ecf20Sopenharmony_ci		if (ret != -ENODEV)
20348c2ecf20Sopenharmony_ci			return ERR_PTR(ret);
20358c2ecf20Sopenharmony_ci
20368c2ecf20Sopenharmony_ci		if (!have_full_constraints()) {
20378c2ecf20Sopenharmony_ci			dev_warn(dev,
20388c2ecf20Sopenharmony_ci				 "incomplete constraints, dummy supplies not allowed\n");
20398c2ecf20Sopenharmony_ci			return ERR_PTR(-ENODEV);
20408c2ecf20Sopenharmony_ci		}
20418c2ecf20Sopenharmony_ci
20428c2ecf20Sopenharmony_ci		switch (get_type) {
20438c2ecf20Sopenharmony_ci		case NORMAL_GET:
20448c2ecf20Sopenharmony_ci			/*
20458c2ecf20Sopenharmony_ci			 * Assume that a regulator is physically present and
20468c2ecf20Sopenharmony_ci			 * enabled, even if it isn't hooked up, and just
20478c2ecf20Sopenharmony_ci			 * provide a dummy.
20488c2ecf20Sopenharmony_ci			 */
20498c2ecf20Sopenharmony_ci			dev_warn(dev, "supply %s not found, using dummy regulator\n", id);
20508c2ecf20Sopenharmony_ci			rdev = dummy_regulator_rdev;
20518c2ecf20Sopenharmony_ci			get_device(&rdev->dev);
20528c2ecf20Sopenharmony_ci			break;
20538c2ecf20Sopenharmony_ci
20548c2ecf20Sopenharmony_ci		case EXCLUSIVE_GET:
20558c2ecf20Sopenharmony_ci			dev_warn(dev,
20568c2ecf20Sopenharmony_ci				 "dummy supplies not allowed for exclusive requests\n");
20578c2ecf20Sopenharmony_ci			fallthrough;
20588c2ecf20Sopenharmony_ci
20598c2ecf20Sopenharmony_ci		default:
20608c2ecf20Sopenharmony_ci			return ERR_PTR(-ENODEV);
20618c2ecf20Sopenharmony_ci		}
20628c2ecf20Sopenharmony_ci	}
20638c2ecf20Sopenharmony_ci
20648c2ecf20Sopenharmony_ci	if (rdev->exclusive) {
20658c2ecf20Sopenharmony_ci		regulator = ERR_PTR(-EPERM);
20668c2ecf20Sopenharmony_ci		put_device(&rdev->dev);
20678c2ecf20Sopenharmony_ci		return regulator;
20688c2ecf20Sopenharmony_ci	}
20698c2ecf20Sopenharmony_ci
20708c2ecf20Sopenharmony_ci	if (get_type == EXCLUSIVE_GET && rdev->open_count) {
20718c2ecf20Sopenharmony_ci		regulator = ERR_PTR(-EBUSY);
20728c2ecf20Sopenharmony_ci		put_device(&rdev->dev);
20738c2ecf20Sopenharmony_ci		return regulator;
20748c2ecf20Sopenharmony_ci	}
20758c2ecf20Sopenharmony_ci
20768c2ecf20Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
20778c2ecf20Sopenharmony_ci	ret = (rdev->coupling_desc.n_resolved != rdev->coupling_desc.n_coupled);
20788c2ecf20Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
20798c2ecf20Sopenharmony_ci
20808c2ecf20Sopenharmony_ci	if (ret != 0) {
20818c2ecf20Sopenharmony_ci		regulator = ERR_PTR(-EPROBE_DEFER);
20828c2ecf20Sopenharmony_ci		put_device(&rdev->dev);
20838c2ecf20Sopenharmony_ci		return regulator;
20848c2ecf20Sopenharmony_ci	}
20858c2ecf20Sopenharmony_ci
20868c2ecf20Sopenharmony_ci	ret = regulator_resolve_supply(rdev);
20878c2ecf20Sopenharmony_ci	if (ret < 0) {
20888c2ecf20Sopenharmony_ci		regulator = ERR_PTR(ret);
20898c2ecf20Sopenharmony_ci		put_device(&rdev->dev);
20908c2ecf20Sopenharmony_ci		return regulator;
20918c2ecf20Sopenharmony_ci	}
20928c2ecf20Sopenharmony_ci
20938c2ecf20Sopenharmony_ci	if (!try_module_get(rdev->owner)) {
20948c2ecf20Sopenharmony_ci		regulator = ERR_PTR(-EPROBE_DEFER);
20958c2ecf20Sopenharmony_ci		put_device(&rdev->dev);
20968c2ecf20Sopenharmony_ci		return regulator;
20978c2ecf20Sopenharmony_ci	}
20988c2ecf20Sopenharmony_ci
20998c2ecf20Sopenharmony_ci	regulator_lock(rdev);
21008c2ecf20Sopenharmony_ci	regulator = create_regulator(rdev, dev, id);
21018c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
21028c2ecf20Sopenharmony_ci	if (regulator == NULL) {
21038c2ecf20Sopenharmony_ci		regulator = ERR_PTR(-ENOMEM);
21048c2ecf20Sopenharmony_ci		module_put(rdev->owner);
21058c2ecf20Sopenharmony_ci		put_device(&rdev->dev);
21068c2ecf20Sopenharmony_ci		return regulator;
21078c2ecf20Sopenharmony_ci	}
21088c2ecf20Sopenharmony_ci
21098c2ecf20Sopenharmony_ci	rdev->open_count++;
21108c2ecf20Sopenharmony_ci	if (get_type == EXCLUSIVE_GET) {
21118c2ecf20Sopenharmony_ci		rdev->exclusive = 1;
21128c2ecf20Sopenharmony_ci
21138c2ecf20Sopenharmony_ci		ret = _regulator_is_enabled(rdev);
21148c2ecf20Sopenharmony_ci		if (ret > 0) {
21158c2ecf20Sopenharmony_ci			rdev->use_count = 1;
21168c2ecf20Sopenharmony_ci			regulator->enable_count = 1;
21178c2ecf20Sopenharmony_ci		} else {
21188c2ecf20Sopenharmony_ci			rdev->use_count = 0;
21198c2ecf20Sopenharmony_ci			regulator->enable_count = 0;
21208c2ecf20Sopenharmony_ci		}
21218c2ecf20Sopenharmony_ci	}
21228c2ecf20Sopenharmony_ci
21238c2ecf20Sopenharmony_ci	link = device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS);
21248c2ecf20Sopenharmony_ci	if (!IS_ERR_OR_NULL(link))
21258c2ecf20Sopenharmony_ci		regulator->device_link = true;
21268c2ecf20Sopenharmony_ci
21278c2ecf20Sopenharmony_ci	return regulator;
21288c2ecf20Sopenharmony_ci}
21298c2ecf20Sopenharmony_ci
21308c2ecf20Sopenharmony_ci/**
21318c2ecf20Sopenharmony_ci * regulator_get - lookup and obtain a reference to a regulator.
21328c2ecf20Sopenharmony_ci * @dev: device for regulator "consumer"
21338c2ecf20Sopenharmony_ci * @id: Supply name or regulator ID.
21348c2ecf20Sopenharmony_ci *
21358c2ecf20Sopenharmony_ci * Returns a struct regulator corresponding to the regulator producer,
21368c2ecf20Sopenharmony_ci * or IS_ERR() condition containing errno.
21378c2ecf20Sopenharmony_ci *
21388c2ecf20Sopenharmony_ci * Use of supply names configured via regulator_set_device_supply() is
21398c2ecf20Sopenharmony_ci * strongly encouraged.  It is recommended that the supply name used
21408c2ecf20Sopenharmony_ci * should match the name used for the supply and/or the relevant
21418c2ecf20Sopenharmony_ci * device pins in the datasheet.
21428c2ecf20Sopenharmony_ci */
21438c2ecf20Sopenharmony_cistruct regulator *regulator_get(struct device *dev, const char *id)
21448c2ecf20Sopenharmony_ci{
21458c2ecf20Sopenharmony_ci	return _regulator_get(dev, id, NORMAL_GET);
21468c2ecf20Sopenharmony_ci}
21478c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get);
21488c2ecf20Sopenharmony_ci
21498c2ecf20Sopenharmony_ci/**
21508c2ecf20Sopenharmony_ci * regulator_get_exclusive - obtain exclusive access to a regulator.
21518c2ecf20Sopenharmony_ci * @dev: device for regulator "consumer"
21528c2ecf20Sopenharmony_ci * @id: Supply name or regulator ID.
21538c2ecf20Sopenharmony_ci *
21548c2ecf20Sopenharmony_ci * Returns a struct regulator corresponding to the regulator producer,
21558c2ecf20Sopenharmony_ci * or IS_ERR() condition containing errno.  Other consumers will be
21568c2ecf20Sopenharmony_ci * unable to obtain this regulator while this reference is held and the
21578c2ecf20Sopenharmony_ci * use count for the regulator will be initialised to reflect the current
21588c2ecf20Sopenharmony_ci * state of the regulator.
21598c2ecf20Sopenharmony_ci *
21608c2ecf20Sopenharmony_ci * This is intended for use by consumers which cannot tolerate shared
21618c2ecf20Sopenharmony_ci * use of the regulator such as those which need to force the
21628c2ecf20Sopenharmony_ci * regulator off for correct operation of the hardware they are
21638c2ecf20Sopenharmony_ci * controlling.
21648c2ecf20Sopenharmony_ci *
21658c2ecf20Sopenharmony_ci * Use of supply names configured via regulator_set_device_supply() is
21668c2ecf20Sopenharmony_ci * strongly encouraged.  It is recommended that the supply name used
21678c2ecf20Sopenharmony_ci * should match the name used for the supply and/or the relevant
21688c2ecf20Sopenharmony_ci * device pins in the datasheet.
21698c2ecf20Sopenharmony_ci */
21708c2ecf20Sopenharmony_cistruct regulator *regulator_get_exclusive(struct device *dev, const char *id)
21718c2ecf20Sopenharmony_ci{
21728c2ecf20Sopenharmony_ci	return _regulator_get(dev, id, EXCLUSIVE_GET);
21738c2ecf20Sopenharmony_ci}
21748c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_exclusive);
21758c2ecf20Sopenharmony_ci
21768c2ecf20Sopenharmony_ci/**
21778c2ecf20Sopenharmony_ci * regulator_get_optional - obtain optional access to a regulator.
21788c2ecf20Sopenharmony_ci * @dev: device for regulator "consumer"
21798c2ecf20Sopenharmony_ci * @id: Supply name or regulator ID.
21808c2ecf20Sopenharmony_ci *
21818c2ecf20Sopenharmony_ci * Returns a struct regulator corresponding to the regulator producer,
21828c2ecf20Sopenharmony_ci * or IS_ERR() condition containing errno.
21838c2ecf20Sopenharmony_ci *
21848c2ecf20Sopenharmony_ci * This is intended for use by consumers for devices which can have
21858c2ecf20Sopenharmony_ci * some supplies unconnected in normal use, such as some MMC devices.
21868c2ecf20Sopenharmony_ci * It can allow the regulator core to provide stub supplies for other
21878c2ecf20Sopenharmony_ci * supplies requested using normal regulator_get() calls without
21888c2ecf20Sopenharmony_ci * disrupting the operation of drivers that can handle absent
21898c2ecf20Sopenharmony_ci * supplies.
21908c2ecf20Sopenharmony_ci *
21918c2ecf20Sopenharmony_ci * Use of supply names configured via regulator_set_device_supply() is
21928c2ecf20Sopenharmony_ci * strongly encouraged.  It is recommended that the supply name used
21938c2ecf20Sopenharmony_ci * should match the name used for the supply and/or the relevant
21948c2ecf20Sopenharmony_ci * device pins in the datasheet.
21958c2ecf20Sopenharmony_ci */
21968c2ecf20Sopenharmony_cistruct regulator *regulator_get_optional(struct device *dev, const char *id)
21978c2ecf20Sopenharmony_ci{
21988c2ecf20Sopenharmony_ci	return _regulator_get(dev, id, OPTIONAL_GET);
21998c2ecf20Sopenharmony_ci}
22008c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_optional);
22018c2ecf20Sopenharmony_ci
22028c2ecf20Sopenharmony_cistatic void destroy_regulator(struct regulator *regulator)
22038c2ecf20Sopenharmony_ci{
22048c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
22058c2ecf20Sopenharmony_ci
22068c2ecf20Sopenharmony_ci	debugfs_remove_recursive(regulator->debugfs);
22078c2ecf20Sopenharmony_ci
22088c2ecf20Sopenharmony_ci	if (regulator->dev) {
22098c2ecf20Sopenharmony_ci		if (regulator->device_link)
22108c2ecf20Sopenharmony_ci			device_link_remove(regulator->dev, &rdev->dev);
22118c2ecf20Sopenharmony_ci
22128c2ecf20Sopenharmony_ci		/* remove any sysfs entries */
22138c2ecf20Sopenharmony_ci		sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
22148c2ecf20Sopenharmony_ci	}
22158c2ecf20Sopenharmony_ci
22168c2ecf20Sopenharmony_ci	regulator_lock(rdev);
22178c2ecf20Sopenharmony_ci	list_del(&regulator->list);
22188c2ecf20Sopenharmony_ci
22198c2ecf20Sopenharmony_ci	rdev->open_count--;
22208c2ecf20Sopenharmony_ci	rdev->exclusive = 0;
22218c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
22228c2ecf20Sopenharmony_ci
22238c2ecf20Sopenharmony_ci	kfree_const(regulator->supply_name);
22248c2ecf20Sopenharmony_ci	kfree(regulator);
22258c2ecf20Sopenharmony_ci}
22268c2ecf20Sopenharmony_ci
22278c2ecf20Sopenharmony_ci/* regulator_list_mutex lock held by regulator_put() */
22288c2ecf20Sopenharmony_cistatic void _regulator_put(struct regulator *regulator)
22298c2ecf20Sopenharmony_ci{
22308c2ecf20Sopenharmony_ci	struct regulator_dev *rdev;
22318c2ecf20Sopenharmony_ci
22328c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(regulator))
22338c2ecf20Sopenharmony_ci		return;
22348c2ecf20Sopenharmony_ci
22358c2ecf20Sopenharmony_ci	lockdep_assert_held_once(&regulator_list_mutex);
22368c2ecf20Sopenharmony_ci
22378c2ecf20Sopenharmony_ci	/* Docs say you must disable before calling regulator_put() */
22388c2ecf20Sopenharmony_ci	WARN_ON(regulator->enable_count);
22398c2ecf20Sopenharmony_ci
22408c2ecf20Sopenharmony_ci	rdev = regulator->rdev;
22418c2ecf20Sopenharmony_ci
22428c2ecf20Sopenharmony_ci	destroy_regulator(regulator);
22438c2ecf20Sopenharmony_ci
22448c2ecf20Sopenharmony_ci	module_put(rdev->owner);
22458c2ecf20Sopenharmony_ci	put_device(&rdev->dev);
22468c2ecf20Sopenharmony_ci}
22478c2ecf20Sopenharmony_ci
22488c2ecf20Sopenharmony_ci/**
22498c2ecf20Sopenharmony_ci * regulator_put - "free" the regulator source
22508c2ecf20Sopenharmony_ci * @regulator: regulator source
22518c2ecf20Sopenharmony_ci *
22528c2ecf20Sopenharmony_ci * Note: drivers must ensure that all regulator_enable calls made on this
22538c2ecf20Sopenharmony_ci * regulator source are balanced by regulator_disable calls prior to calling
22548c2ecf20Sopenharmony_ci * this function.
22558c2ecf20Sopenharmony_ci */
22568c2ecf20Sopenharmony_civoid regulator_put(struct regulator *regulator)
22578c2ecf20Sopenharmony_ci{
22588c2ecf20Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
22598c2ecf20Sopenharmony_ci	_regulator_put(regulator);
22608c2ecf20Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
22618c2ecf20Sopenharmony_ci}
22628c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_put);
22638c2ecf20Sopenharmony_ci
22648c2ecf20Sopenharmony_ci/**
22658c2ecf20Sopenharmony_ci * regulator_register_supply_alias - Provide device alias for supply lookup
22668c2ecf20Sopenharmony_ci *
22678c2ecf20Sopenharmony_ci * @dev: device that will be given as the regulator "consumer"
22688c2ecf20Sopenharmony_ci * @id: Supply name or regulator ID
22698c2ecf20Sopenharmony_ci * @alias_dev: device that should be used to lookup the supply
22708c2ecf20Sopenharmony_ci * @alias_id: Supply name or regulator ID that should be used to lookup the
22718c2ecf20Sopenharmony_ci * supply
22728c2ecf20Sopenharmony_ci *
22738c2ecf20Sopenharmony_ci * All lookups for id on dev will instead be conducted for alias_id on
22748c2ecf20Sopenharmony_ci * alias_dev.
22758c2ecf20Sopenharmony_ci */
22768c2ecf20Sopenharmony_ciint regulator_register_supply_alias(struct device *dev, const char *id,
22778c2ecf20Sopenharmony_ci				    struct device *alias_dev,
22788c2ecf20Sopenharmony_ci				    const char *alias_id)
22798c2ecf20Sopenharmony_ci{
22808c2ecf20Sopenharmony_ci	struct regulator_supply_alias *map;
22818c2ecf20Sopenharmony_ci
22828c2ecf20Sopenharmony_ci	map = regulator_find_supply_alias(dev, id);
22838c2ecf20Sopenharmony_ci	if (map)
22848c2ecf20Sopenharmony_ci		return -EEXIST;
22858c2ecf20Sopenharmony_ci
22868c2ecf20Sopenharmony_ci	map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL);
22878c2ecf20Sopenharmony_ci	if (!map)
22888c2ecf20Sopenharmony_ci		return -ENOMEM;
22898c2ecf20Sopenharmony_ci
22908c2ecf20Sopenharmony_ci	map->src_dev = dev;
22918c2ecf20Sopenharmony_ci	map->src_supply = id;
22928c2ecf20Sopenharmony_ci	map->alias_dev = alias_dev;
22938c2ecf20Sopenharmony_ci	map->alias_supply = alias_id;
22948c2ecf20Sopenharmony_ci
22958c2ecf20Sopenharmony_ci	list_add(&map->list, &regulator_supply_alias_list);
22968c2ecf20Sopenharmony_ci
22978c2ecf20Sopenharmony_ci	pr_info("Adding alias for supply %s,%s -> %s,%s\n",
22988c2ecf20Sopenharmony_ci		id, dev_name(dev), alias_id, dev_name(alias_dev));
22998c2ecf20Sopenharmony_ci
23008c2ecf20Sopenharmony_ci	return 0;
23018c2ecf20Sopenharmony_ci}
23028c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_register_supply_alias);
23038c2ecf20Sopenharmony_ci
23048c2ecf20Sopenharmony_ci/**
23058c2ecf20Sopenharmony_ci * regulator_unregister_supply_alias - Remove device alias
23068c2ecf20Sopenharmony_ci *
23078c2ecf20Sopenharmony_ci * @dev: device that will be given as the regulator "consumer"
23088c2ecf20Sopenharmony_ci * @id: Supply name or regulator ID
23098c2ecf20Sopenharmony_ci *
23108c2ecf20Sopenharmony_ci * Remove a lookup alias if one exists for id on dev.
23118c2ecf20Sopenharmony_ci */
23128c2ecf20Sopenharmony_civoid regulator_unregister_supply_alias(struct device *dev, const char *id)
23138c2ecf20Sopenharmony_ci{
23148c2ecf20Sopenharmony_ci	struct regulator_supply_alias *map;
23158c2ecf20Sopenharmony_ci
23168c2ecf20Sopenharmony_ci	map = regulator_find_supply_alias(dev, id);
23178c2ecf20Sopenharmony_ci	if (map) {
23188c2ecf20Sopenharmony_ci		list_del(&map->list);
23198c2ecf20Sopenharmony_ci		kfree(map);
23208c2ecf20Sopenharmony_ci	}
23218c2ecf20Sopenharmony_ci}
23228c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_unregister_supply_alias);
23238c2ecf20Sopenharmony_ci
23248c2ecf20Sopenharmony_ci/**
23258c2ecf20Sopenharmony_ci * regulator_bulk_register_supply_alias - register multiple aliases
23268c2ecf20Sopenharmony_ci *
23278c2ecf20Sopenharmony_ci * @dev: device that will be given as the regulator "consumer"
23288c2ecf20Sopenharmony_ci * @id: List of supply names or regulator IDs
23298c2ecf20Sopenharmony_ci * @alias_dev: device that should be used to lookup the supply
23308c2ecf20Sopenharmony_ci * @alias_id: List of supply names or regulator IDs that should be used to
23318c2ecf20Sopenharmony_ci * lookup the supply
23328c2ecf20Sopenharmony_ci * @num_id: Number of aliases to register
23338c2ecf20Sopenharmony_ci *
23348c2ecf20Sopenharmony_ci * @return 0 on success, an errno on failure.
23358c2ecf20Sopenharmony_ci *
23368c2ecf20Sopenharmony_ci * This helper function allows drivers to register several supply
23378c2ecf20Sopenharmony_ci * aliases in one operation.  If any of the aliases cannot be
23388c2ecf20Sopenharmony_ci * registered any aliases that were registered will be removed
23398c2ecf20Sopenharmony_ci * before returning to the caller.
23408c2ecf20Sopenharmony_ci */
23418c2ecf20Sopenharmony_ciint regulator_bulk_register_supply_alias(struct device *dev,
23428c2ecf20Sopenharmony_ci					 const char *const *id,
23438c2ecf20Sopenharmony_ci					 struct device *alias_dev,
23448c2ecf20Sopenharmony_ci					 const char *const *alias_id,
23458c2ecf20Sopenharmony_ci					 int num_id)
23468c2ecf20Sopenharmony_ci{
23478c2ecf20Sopenharmony_ci	int i;
23488c2ecf20Sopenharmony_ci	int ret;
23498c2ecf20Sopenharmony_ci
23508c2ecf20Sopenharmony_ci	for (i = 0; i < num_id; ++i) {
23518c2ecf20Sopenharmony_ci		ret = regulator_register_supply_alias(dev, id[i], alias_dev,
23528c2ecf20Sopenharmony_ci						      alias_id[i]);
23538c2ecf20Sopenharmony_ci		if (ret < 0)
23548c2ecf20Sopenharmony_ci			goto err;
23558c2ecf20Sopenharmony_ci	}
23568c2ecf20Sopenharmony_ci
23578c2ecf20Sopenharmony_ci	return 0;
23588c2ecf20Sopenharmony_ci
23598c2ecf20Sopenharmony_cierr:
23608c2ecf20Sopenharmony_ci	dev_err(dev,
23618c2ecf20Sopenharmony_ci		"Failed to create supply alias %s,%s -> %s,%s\n",
23628c2ecf20Sopenharmony_ci		id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
23638c2ecf20Sopenharmony_ci
23648c2ecf20Sopenharmony_ci	while (--i >= 0)
23658c2ecf20Sopenharmony_ci		regulator_unregister_supply_alias(dev, id[i]);
23668c2ecf20Sopenharmony_ci
23678c2ecf20Sopenharmony_ci	return ret;
23688c2ecf20Sopenharmony_ci}
23698c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias);
23708c2ecf20Sopenharmony_ci
23718c2ecf20Sopenharmony_ci/**
23728c2ecf20Sopenharmony_ci * regulator_bulk_unregister_supply_alias - unregister multiple aliases
23738c2ecf20Sopenharmony_ci *
23748c2ecf20Sopenharmony_ci * @dev: device that will be given as the regulator "consumer"
23758c2ecf20Sopenharmony_ci * @id: List of supply names or regulator IDs
23768c2ecf20Sopenharmony_ci * @num_id: Number of aliases to unregister
23778c2ecf20Sopenharmony_ci *
23788c2ecf20Sopenharmony_ci * This helper function allows drivers to unregister several supply
23798c2ecf20Sopenharmony_ci * aliases in one operation.
23808c2ecf20Sopenharmony_ci */
23818c2ecf20Sopenharmony_civoid regulator_bulk_unregister_supply_alias(struct device *dev,
23828c2ecf20Sopenharmony_ci					    const char *const *id,
23838c2ecf20Sopenharmony_ci					    int num_id)
23848c2ecf20Sopenharmony_ci{
23858c2ecf20Sopenharmony_ci	int i;
23868c2ecf20Sopenharmony_ci
23878c2ecf20Sopenharmony_ci	for (i = 0; i < num_id; ++i)
23888c2ecf20Sopenharmony_ci		regulator_unregister_supply_alias(dev, id[i]);
23898c2ecf20Sopenharmony_ci}
23908c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias);
23918c2ecf20Sopenharmony_ci
23928c2ecf20Sopenharmony_ci
23938c2ecf20Sopenharmony_ci/* Manage enable GPIO list. Same GPIO pin can be shared among regulators */
23948c2ecf20Sopenharmony_cistatic int regulator_ena_gpio_request(struct regulator_dev *rdev,
23958c2ecf20Sopenharmony_ci				const struct regulator_config *config)
23968c2ecf20Sopenharmony_ci{
23978c2ecf20Sopenharmony_ci	struct regulator_enable_gpio *pin, *new_pin;
23988c2ecf20Sopenharmony_ci	struct gpio_desc *gpiod;
23998c2ecf20Sopenharmony_ci
24008c2ecf20Sopenharmony_ci	gpiod = config->ena_gpiod;
24018c2ecf20Sopenharmony_ci	new_pin = kzalloc(sizeof(*new_pin), GFP_KERNEL);
24028c2ecf20Sopenharmony_ci
24038c2ecf20Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
24048c2ecf20Sopenharmony_ci
24058c2ecf20Sopenharmony_ci	list_for_each_entry(pin, &regulator_ena_gpio_list, list) {
24068c2ecf20Sopenharmony_ci		if (pin->gpiod == gpiod) {
24078c2ecf20Sopenharmony_ci			rdev_dbg(rdev, "GPIO is already used\n");
24088c2ecf20Sopenharmony_ci			goto update_ena_gpio_to_rdev;
24098c2ecf20Sopenharmony_ci		}
24108c2ecf20Sopenharmony_ci	}
24118c2ecf20Sopenharmony_ci
24128c2ecf20Sopenharmony_ci	if (new_pin == NULL) {
24138c2ecf20Sopenharmony_ci		mutex_unlock(&regulator_list_mutex);
24148c2ecf20Sopenharmony_ci		return -ENOMEM;
24158c2ecf20Sopenharmony_ci	}
24168c2ecf20Sopenharmony_ci
24178c2ecf20Sopenharmony_ci	pin = new_pin;
24188c2ecf20Sopenharmony_ci	new_pin = NULL;
24198c2ecf20Sopenharmony_ci
24208c2ecf20Sopenharmony_ci	pin->gpiod = gpiod;
24218c2ecf20Sopenharmony_ci	list_add(&pin->list, &regulator_ena_gpio_list);
24228c2ecf20Sopenharmony_ci
24238c2ecf20Sopenharmony_ciupdate_ena_gpio_to_rdev:
24248c2ecf20Sopenharmony_ci	pin->request_count++;
24258c2ecf20Sopenharmony_ci	rdev->ena_pin = pin;
24268c2ecf20Sopenharmony_ci
24278c2ecf20Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
24288c2ecf20Sopenharmony_ci	kfree(new_pin);
24298c2ecf20Sopenharmony_ci
24308c2ecf20Sopenharmony_ci	return 0;
24318c2ecf20Sopenharmony_ci}
24328c2ecf20Sopenharmony_ci
24338c2ecf20Sopenharmony_cistatic void regulator_ena_gpio_free(struct regulator_dev *rdev)
24348c2ecf20Sopenharmony_ci{
24358c2ecf20Sopenharmony_ci	struct regulator_enable_gpio *pin, *n;
24368c2ecf20Sopenharmony_ci
24378c2ecf20Sopenharmony_ci	if (!rdev->ena_pin)
24388c2ecf20Sopenharmony_ci		return;
24398c2ecf20Sopenharmony_ci
24408c2ecf20Sopenharmony_ci	/* Free the GPIO only in case of no use */
24418c2ecf20Sopenharmony_ci	list_for_each_entry_safe(pin, n, &regulator_ena_gpio_list, list) {
24428c2ecf20Sopenharmony_ci		if (pin != rdev->ena_pin)
24438c2ecf20Sopenharmony_ci			continue;
24448c2ecf20Sopenharmony_ci
24458c2ecf20Sopenharmony_ci		if (--pin->request_count)
24468c2ecf20Sopenharmony_ci			break;
24478c2ecf20Sopenharmony_ci
24488c2ecf20Sopenharmony_ci		gpiod_put(pin->gpiod);
24498c2ecf20Sopenharmony_ci		list_del(&pin->list);
24508c2ecf20Sopenharmony_ci		kfree(pin);
24518c2ecf20Sopenharmony_ci		break;
24528c2ecf20Sopenharmony_ci	}
24538c2ecf20Sopenharmony_ci
24548c2ecf20Sopenharmony_ci	rdev->ena_pin = NULL;
24558c2ecf20Sopenharmony_ci}
24568c2ecf20Sopenharmony_ci
24578c2ecf20Sopenharmony_ci/**
24588c2ecf20Sopenharmony_ci * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control
24598c2ecf20Sopenharmony_ci * @rdev: regulator_dev structure
24608c2ecf20Sopenharmony_ci * @enable: enable GPIO at initial use?
24618c2ecf20Sopenharmony_ci *
24628c2ecf20Sopenharmony_ci * GPIO is enabled in case of initial use. (enable_count is 0)
24638c2ecf20Sopenharmony_ci * GPIO is disabled when it is not shared any more. (enable_count <= 1)
24648c2ecf20Sopenharmony_ci */
24658c2ecf20Sopenharmony_cistatic int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable)
24668c2ecf20Sopenharmony_ci{
24678c2ecf20Sopenharmony_ci	struct regulator_enable_gpio *pin = rdev->ena_pin;
24688c2ecf20Sopenharmony_ci
24698c2ecf20Sopenharmony_ci	if (!pin)
24708c2ecf20Sopenharmony_ci		return -EINVAL;
24718c2ecf20Sopenharmony_ci
24728c2ecf20Sopenharmony_ci	if (enable) {
24738c2ecf20Sopenharmony_ci		/* Enable GPIO at initial use */
24748c2ecf20Sopenharmony_ci		if (pin->enable_count == 0)
24758c2ecf20Sopenharmony_ci			gpiod_set_value_cansleep(pin->gpiod, 1);
24768c2ecf20Sopenharmony_ci
24778c2ecf20Sopenharmony_ci		pin->enable_count++;
24788c2ecf20Sopenharmony_ci	} else {
24798c2ecf20Sopenharmony_ci		if (pin->enable_count > 1) {
24808c2ecf20Sopenharmony_ci			pin->enable_count--;
24818c2ecf20Sopenharmony_ci			return 0;
24828c2ecf20Sopenharmony_ci		}
24838c2ecf20Sopenharmony_ci
24848c2ecf20Sopenharmony_ci		/* Disable GPIO if not used */
24858c2ecf20Sopenharmony_ci		if (pin->enable_count <= 1) {
24868c2ecf20Sopenharmony_ci			gpiod_set_value_cansleep(pin->gpiod, 0);
24878c2ecf20Sopenharmony_ci			pin->enable_count = 0;
24888c2ecf20Sopenharmony_ci		}
24898c2ecf20Sopenharmony_ci	}
24908c2ecf20Sopenharmony_ci
24918c2ecf20Sopenharmony_ci	return 0;
24928c2ecf20Sopenharmony_ci}
24938c2ecf20Sopenharmony_ci
24948c2ecf20Sopenharmony_ci/**
24958c2ecf20Sopenharmony_ci * _regulator_enable_delay - a delay helper function
24968c2ecf20Sopenharmony_ci * @delay: time to delay in microseconds
24978c2ecf20Sopenharmony_ci *
24988c2ecf20Sopenharmony_ci * Delay for the requested amount of time as per the guidelines in:
24998c2ecf20Sopenharmony_ci *
25008c2ecf20Sopenharmony_ci *     Documentation/timers/timers-howto.rst
25018c2ecf20Sopenharmony_ci *
25028c2ecf20Sopenharmony_ci * The assumption here is that regulators will never be enabled in
25038c2ecf20Sopenharmony_ci * atomic context and therefore sleeping functions can be used.
25048c2ecf20Sopenharmony_ci */
25058c2ecf20Sopenharmony_cistatic void _regulator_enable_delay(unsigned int delay)
25068c2ecf20Sopenharmony_ci{
25078c2ecf20Sopenharmony_ci	unsigned int ms = delay / 1000;
25088c2ecf20Sopenharmony_ci	unsigned int us = delay % 1000;
25098c2ecf20Sopenharmony_ci
25108c2ecf20Sopenharmony_ci	if (ms > 0) {
25118c2ecf20Sopenharmony_ci		/*
25128c2ecf20Sopenharmony_ci		 * For small enough values, handle super-millisecond
25138c2ecf20Sopenharmony_ci		 * delays in the usleep_range() call below.
25148c2ecf20Sopenharmony_ci		 */
25158c2ecf20Sopenharmony_ci		if (ms < 20)
25168c2ecf20Sopenharmony_ci			us += ms * 1000;
25178c2ecf20Sopenharmony_ci		else
25188c2ecf20Sopenharmony_ci			msleep(ms);
25198c2ecf20Sopenharmony_ci	}
25208c2ecf20Sopenharmony_ci
25218c2ecf20Sopenharmony_ci	/*
25228c2ecf20Sopenharmony_ci	 * Give the scheduler some room to coalesce with any other
25238c2ecf20Sopenharmony_ci	 * wakeup sources. For delays shorter than 10 us, don't even
25248c2ecf20Sopenharmony_ci	 * bother setting up high-resolution timers and just busy-
25258c2ecf20Sopenharmony_ci	 * loop.
25268c2ecf20Sopenharmony_ci	 */
25278c2ecf20Sopenharmony_ci	if (us >= 10)
25288c2ecf20Sopenharmony_ci		usleep_range(us, us + 100);
25298c2ecf20Sopenharmony_ci	else
25308c2ecf20Sopenharmony_ci		udelay(us);
25318c2ecf20Sopenharmony_ci}
25328c2ecf20Sopenharmony_ci
25338c2ecf20Sopenharmony_ci/**
25348c2ecf20Sopenharmony_ci * _regulator_check_status_enabled
25358c2ecf20Sopenharmony_ci *
25368c2ecf20Sopenharmony_ci * A helper function to check if the regulator status can be interpreted
25378c2ecf20Sopenharmony_ci * as 'regulator is enabled'.
25388c2ecf20Sopenharmony_ci * @rdev: the regulator device to check
25398c2ecf20Sopenharmony_ci *
25408c2ecf20Sopenharmony_ci * Return:
25418c2ecf20Sopenharmony_ci * * 1			- if status shows regulator is in enabled state
25428c2ecf20Sopenharmony_ci * * 0			- if not enabled state
25438c2ecf20Sopenharmony_ci * * Error Value	- as received from ops->get_status()
25448c2ecf20Sopenharmony_ci */
25458c2ecf20Sopenharmony_cistatic inline int _regulator_check_status_enabled(struct regulator_dev *rdev)
25468c2ecf20Sopenharmony_ci{
25478c2ecf20Sopenharmony_ci	int ret = rdev->desc->ops->get_status(rdev);
25488c2ecf20Sopenharmony_ci
25498c2ecf20Sopenharmony_ci	if (ret < 0) {
25508c2ecf20Sopenharmony_ci		rdev_info(rdev, "get_status returned error: %d\n", ret);
25518c2ecf20Sopenharmony_ci		return ret;
25528c2ecf20Sopenharmony_ci	}
25538c2ecf20Sopenharmony_ci
25548c2ecf20Sopenharmony_ci	switch (ret) {
25558c2ecf20Sopenharmony_ci	case REGULATOR_STATUS_OFF:
25568c2ecf20Sopenharmony_ci	case REGULATOR_STATUS_ERROR:
25578c2ecf20Sopenharmony_ci	case REGULATOR_STATUS_UNDEFINED:
25588c2ecf20Sopenharmony_ci		return 0;
25598c2ecf20Sopenharmony_ci	default:
25608c2ecf20Sopenharmony_ci		return 1;
25618c2ecf20Sopenharmony_ci	}
25628c2ecf20Sopenharmony_ci}
25638c2ecf20Sopenharmony_ci
25648c2ecf20Sopenharmony_cistatic int _regulator_do_enable(struct regulator_dev *rdev)
25658c2ecf20Sopenharmony_ci{
25668c2ecf20Sopenharmony_ci	int ret, delay;
25678c2ecf20Sopenharmony_ci
25688c2ecf20Sopenharmony_ci	/* Query before enabling in case configuration dependent.  */
25698c2ecf20Sopenharmony_ci	ret = _regulator_get_enable_time(rdev);
25708c2ecf20Sopenharmony_ci	if (ret >= 0) {
25718c2ecf20Sopenharmony_ci		delay = ret;
25728c2ecf20Sopenharmony_ci	} else {
25738c2ecf20Sopenharmony_ci		rdev_warn(rdev, "enable_time() failed: %pe\n", ERR_PTR(ret));
25748c2ecf20Sopenharmony_ci		delay = 0;
25758c2ecf20Sopenharmony_ci	}
25768c2ecf20Sopenharmony_ci
25778c2ecf20Sopenharmony_ci	trace_regulator_enable(rdev_get_name(rdev));
25788c2ecf20Sopenharmony_ci
25798c2ecf20Sopenharmony_ci	if (rdev->desc->off_on_delay) {
25808c2ecf20Sopenharmony_ci		/* if needed, keep a distance of off_on_delay from last time
25818c2ecf20Sopenharmony_ci		 * this regulator was disabled.
25828c2ecf20Sopenharmony_ci		 */
25838c2ecf20Sopenharmony_ci		unsigned long start_jiffy = jiffies;
25848c2ecf20Sopenharmony_ci		unsigned long intended, max_delay, remaining;
25858c2ecf20Sopenharmony_ci
25868c2ecf20Sopenharmony_ci		max_delay = usecs_to_jiffies(rdev->desc->off_on_delay);
25878c2ecf20Sopenharmony_ci		intended = rdev->last_off_jiffy + max_delay;
25888c2ecf20Sopenharmony_ci
25898c2ecf20Sopenharmony_ci		if (time_before(start_jiffy, intended)) {
25908c2ecf20Sopenharmony_ci			/* calc remaining jiffies to deal with one-time
25918c2ecf20Sopenharmony_ci			 * timer wrapping.
25928c2ecf20Sopenharmony_ci			 * in case of multiple timer wrapping, either it can be
25938c2ecf20Sopenharmony_ci			 * detected by out-of-range remaining, or it cannot be
25948c2ecf20Sopenharmony_ci			 * detected and we get a penalty of
25958c2ecf20Sopenharmony_ci			 * _regulator_enable_delay().
25968c2ecf20Sopenharmony_ci			 */
25978c2ecf20Sopenharmony_ci			remaining = intended - start_jiffy;
25988c2ecf20Sopenharmony_ci			if (remaining <= max_delay)
25998c2ecf20Sopenharmony_ci				_regulator_enable_delay(
26008c2ecf20Sopenharmony_ci						jiffies_to_usecs(remaining));
26018c2ecf20Sopenharmony_ci		}
26028c2ecf20Sopenharmony_ci	}
26038c2ecf20Sopenharmony_ci
26048c2ecf20Sopenharmony_ci	if (rdev->ena_pin) {
26058c2ecf20Sopenharmony_ci		if (!rdev->ena_gpio_state) {
26068c2ecf20Sopenharmony_ci			ret = regulator_ena_gpio_ctrl(rdev, true);
26078c2ecf20Sopenharmony_ci			if (ret < 0)
26088c2ecf20Sopenharmony_ci				return ret;
26098c2ecf20Sopenharmony_ci			rdev->ena_gpio_state = 1;
26108c2ecf20Sopenharmony_ci		}
26118c2ecf20Sopenharmony_ci	} else if (rdev->desc->ops->enable) {
26128c2ecf20Sopenharmony_ci		ret = rdev->desc->ops->enable(rdev);
26138c2ecf20Sopenharmony_ci		if (ret < 0)
26148c2ecf20Sopenharmony_ci			return ret;
26158c2ecf20Sopenharmony_ci	} else {
26168c2ecf20Sopenharmony_ci		return -EINVAL;
26178c2ecf20Sopenharmony_ci	}
26188c2ecf20Sopenharmony_ci
26198c2ecf20Sopenharmony_ci	/* Allow the regulator to ramp; it would be useful to extend
26208c2ecf20Sopenharmony_ci	 * this for bulk operations so that the regulators can ramp
26218c2ecf20Sopenharmony_ci	 * together.  */
26228c2ecf20Sopenharmony_ci	trace_regulator_enable_delay(rdev_get_name(rdev));
26238c2ecf20Sopenharmony_ci
26248c2ecf20Sopenharmony_ci	/* If poll_enabled_time is set, poll upto the delay calculated
26258c2ecf20Sopenharmony_ci	 * above, delaying poll_enabled_time uS to check if the regulator
26268c2ecf20Sopenharmony_ci	 * actually got enabled.
26278c2ecf20Sopenharmony_ci	 * If the regulator isn't enabled after enable_delay has
26288c2ecf20Sopenharmony_ci	 * expired, return -ETIMEDOUT.
26298c2ecf20Sopenharmony_ci	 */
26308c2ecf20Sopenharmony_ci	if (rdev->desc->poll_enabled_time) {
26318c2ecf20Sopenharmony_ci		int time_remaining = delay;
26328c2ecf20Sopenharmony_ci
26338c2ecf20Sopenharmony_ci		while (time_remaining > 0) {
26348c2ecf20Sopenharmony_ci			_regulator_enable_delay(rdev->desc->poll_enabled_time);
26358c2ecf20Sopenharmony_ci
26368c2ecf20Sopenharmony_ci			if (rdev->desc->ops->get_status) {
26378c2ecf20Sopenharmony_ci				ret = _regulator_check_status_enabled(rdev);
26388c2ecf20Sopenharmony_ci				if (ret < 0)
26398c2ecf20Sopenharmony_ci					return ret;
26408c2ecf20Sopenharmony_ci				else if (ret)
26418c2ecf20Sopenharmony_ci					break;
26428c2ecf20Sopenharmony_ci			} else if (rdev->desc->ops->is_enabled(rdev))
26438c2ecf20Sopenharmony_ci				break;
26448c2ecf20Sopenharmony_ci
26458c2ecf20Sopenharmony_ci			time_remaining -= rdev->desc->poll_enabled_time;
26468c2ecf20Sopenharmony_ci		}
26478c2ecf20Sopenharmony_ci
26488c2ecf20Sopenharmony_ci		if (time_remaining <= 0) {
26498c2ecf20Sopenharmony_ci			rdev_err(rdev, "Enabled check timed out\n");
26508c2ecf20Sopenharmony_ci			return -ETIMEDOUT;
26518c2ecf20Sopenharmony_ci		}
26528c2ecf20Sopenharmony_ci	} else {
26538c2ecf20Sopenharmony_ci		_regulator_enable_delay(delay);
26548c2ecf20Sopenharmony_ci	}
26558c2ecf20Sopenharmony_ci
26568c2ecf20Sopenharmony_ci	trace_regulator_enable_complete(rdev_get_name(rdev));
26578c2ecf20Sopenharmony_ci
26588c2ecf20Sopenharmony_ci	return 0;
26598c2ecf20Sopenharmony_ci}
26608c2ecf20Sopenharmony_ci
26618c2ecf20Sopenharmony_ci/**
26628c2ecf20Sopenharmony_ci * _regulator_handle_consumer_enable - handle that a consumer enabled
26638c2ecf20Sopenharmony_ci * @regulator: regulator source
26648c2ecf20Sopenharmony_ci *
26658c2ecf20Sopenharmony_ci * Some things on a regulator consumer (like the contribution towards total
26668c2ecf20Sopenharmony_ci * load on the regulator) only have an effect when the consumer wants the
26678c2ecf20Sopenharmony_ci * regulator enabled.  Explained in example with two consumers of the same
26688c2ecf20Sopenharmony_ci * regulator:
26698c2ecf20Sopenharmony_ci *   consumer A: set_load(100);       => total load = 0
26708c2ecf20Sopenharmony_ci *   consumer A: regulator_enable();  => total load = 100
26718c2ecf20Sopenharmony_ci *   consumer B: set_load(1000);      => total load = 100
26728c2ecf20Sopenharmony_ci *   consumer B: regulator_enable();  => total load = 1100
26738c2ecf20Sopenharmony_ci *   consumer A: regulator_disable(); => total_load = 1000
26748c2ecf20Sopenharmony_ci *
26758c2ecf20Sopenharmony_ci * This function (together with _regulator_handle_consumer_disable) is
26768c2ecf20Sopenharmony_ci * responsible for keeping track of the refcount for a given regulator consumer
26778c2ecf20Sopenharmony_ci * and applying / unapplying these things.
26788c2ecf20Sopenharmony_ci *
26798c2ecf20Sopenharmony_ci * Returns 0 upon no error; -error upon error.
26808c2ecf20Sopenharmony_ci */
26818c2ecf20Sopenharmony_cistatic int _regulator_handle_consumer_enable(struct regulator *regulator)
26828c2ecf20Sopenharmony_ci{
26838c2ecf20Sopenharmony_ci	int ret;
26848c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
26858c2ecf20Sopenharmony_ci
26868c2ecf20Sopenharmony_ci	lockdep_assert_held_once(&rdev->mutex.base);
26878c2ecf20Sopenharmony_ci
26888c2ecf20Sopenharmony_ci	regulator->enable_count++;
26898c2ecf20Sopenharmony_ci	if (regulator->uA_load && regulator->enable_count == 1) {
26908c2ecf20Sopenharmony_ci		ret = drms_uA_update(rdev);
26918c2ecf20Sopenharmony_ci		if (ret)
26928c2ecf20Sopenharmony_ci			regulator->enable_count--;
26938c2ecf20Sopenharmony_ci		return ret;
26948c2ecf20Sopenharmony_ci	}
26958c2ecf20Sopenharmony_ci
26968c2ecf20Sopenharmony_ci	return 0;
26978c2ecf20Sopenharmony_ci}
26988c2ecf20Sopenharmony_ci
26998c2ecf20Sopenharmony_ci/**
27008c2ecf20Sopenharmony_ci * _regulator_handle_consumer_disable - handle that a consumer disabled
27018c2ecf20Sopenharmony_ci * @regulator: regulator source
27028c2ecf20Sopenharmony_ci *
27038c2ecf20Sopenharmony_ci * The opposite of _regulator_handle_consumer_enable().
27048c2ecf20Sopenharmony_ci *
27058c2ecf20Sopenharmony_ci * Returns 0 upon no error; -error upon error.
27068c2ecf20Sopenharmony_ci */
27078c2ecf20Sopenharmony_cistatic int _regulator_handle_consumer_disable(struct regulator *regulator)
27088c2ecf20Sopenharmony_ci{
27098c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
27108c2ecf20Sopenharmony_ci
27118c2ecf20Sopenharmony_ci	lockdep_assert_held_once(&rdev->mutex.base);
27128c2ecf20Sopenharmony_ci
27138c2ecf20Sopenharmony_ci	if (!regulator->enable_count) {
27148c2ecf20Sopenharmony_ci		rdev_err(rdev, "Underflow of regulator enable count\n");
27158c2ecf20Sopenharmony_ci		return -EINVAL;
27168c2ecf20Sopenharmony_ci	}
27178c2ecf20Sopenharmony_ci
27188c2ecf20Sopenharmony_ci	regulator->enable_count--;
27198c2ecf20Sopenharmony_ci	if (regulator->uA_load && regulator->enable_count == 0)
27208c2ecf20Sopenharmony_ci		return drms_uA_update(rdev);
27218c2ecf20Sopenharmony_ci
27228c2ecf20Sopenharmony_ci	return 0;
27238c2ecf20Sopenharmony_ci}
27248c2ecf20Sopenharmony_ci
27258c2ecf20Sopenharmony_ci/* locks held by regulator_enable() */
27268c2ecf20Sopenharmony_cistatic int _regulator_enable(struct regulator *regulator)
27278c2ecf20Sopenharmony_ci{
27288c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
27298c2ecf20Sopenharmony_ci	int ret;
27308c2ecf20Sopenharmony_ci
27318c2ecf20Sopenharmony_ci	lockdep_assert_held_once(&rdev->mutex.base);
27328c2ecf20Sopenharmony_ci
27338c2ecf20Sopenharmony_ci	if (rdev->use_count == 0 && rdev->supply) {
27348c2ecf20Sopenharmony_ci		ret = _regulator_enable(rdev->supply);
27358c2ecf20Sopenharmony_ci		if (ret < 0)
27368c2ecf20Sopenharmony_ci			return ret;
27378c2ecf20Sopenharmony_ci	}
27388c2ecf20Sopenharmony_ci
27398c2ecf20Sopenharmony_ci	/* balance only if there are regulators coupled */
27408c2ecf20Sopenharmony_ci	if (rdev->coupling_desc.n_coupled > 1) {
27418c2ecf20Sopenharmony_ci		ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
27428c2ecf20Sopenharmony_ci		if (ret < 0)
27438c2ecf20Sopenharmony_ci			goto err_disable_supply;
27448c2ecf20Sopenharmony_ci	}
27458c2ecf20Sopenharmony_ci
27468c2ecf20Sopenharmony_ci	ret = _regulator_handle_consumer_enable(regulator);
27478c2ecf20Sopenharmony_ci	if (ret < 0)
27488c2ecf20Sopenharmony_ci		goto err_disable_supply;
27498c2ecf20Sopenharmony_ci
27508c2ecf20Sopenharmony_ci	if (rdev->use_count == 0) {
27518c2ecf20Sopenharmony_ci		/* The regulator may on if it's not switchable or left on */
27528c2ecf20Sopenharmony_ci		ret = _regulator_is_enabled(rdev);
27538c2ecf20Sopenharmony_ci		if (ret == -EINVAL || ret == 0) {
27548c2ecf20Sopenharmony_ci			if (!regulator_ops_is_valid(rdev,
27558c2ecf20Sopenharmony_ci					REGULATOR_CHANGE_STATUS)) {
27568c2ecf20Sopenharmony_ci				ret = -EPERM;
27578c2ecf20Sopenharmony_ci				goto err_consumer_disable;
27588c2ecf20Sopenharmony_ci			}
27598c2ecf20Sopenharmony_ci
27608c2ecf20Sopenharmony_ci			ret = _regulator_do_enable(rdev);
27618c2ecf20Sopenharmony_ci			if (ret < 0)
27628c2ecf20Sopenharmony_ci				goto err_consumer_disable;
27638c2ecf20Sopenharmony_ci
27648c2ecf20Sopenharmony_ci			_notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE,
27658c2ecf20Sopenharmony_ci					     NULL);
27668c2ecf20Sopenharmony_ci		} else if (ret < 0) {
27678c2ecf20Sopenharmony_ci			rdev_err(rdev, "is_enabled() failed: %pe\n", ERR_PTR(ret));
27688c2ecf20Sopenharmony_ci			goto err_consumer_disable;
27698c2ecf20Sopenharmony_ci		}
27708c2ecf20Sopenharmony_ci		/* Fallthrough on positive return values - already enabled */
27718c2ecf20Sopenharmony_ci	}
27728c2ecf20Sopenharmony_ci
27738c2ecf20Sopenharmony_ci	if (regulator->enable_count == 1)
27748c2ecf20Sopenharmony_ci		rdev->use_count++;
27758c2ecf20Sopenharmony_ci
27768c2ecf20Sopenharmony_ci	return 0;
27778c2ecf20Sopenharmony_ci
27788c2ecf20Sopenharmony_cierr_consumer_disable:
27798c2ecf20Sopenharmony_ci	_regulator_handle_consumer_disable(regulator);
27808c2ecf20Sopenharmony_ci
27818c2ecf20Sopenharmony_cierr_disable_supply:
27828c2ecf20Sopenharmony_ci	if (rdev->use_count == 0 && rdev->supply)
27838c2ecf20Sopenharmony_ci		_regulator_disable(rdev->supply);
27848c2ecf20Sopenharmony_ci
27858c2ecf20Sopenharmony_ci	return ret;
27868c2ecf20Sopenharmony_ci}
27878c2ecf20Sopenharmony_ci
27888c2ecf20Sopenharmony_ci/**
27898c2ecf20Sopenharmony_ci * regulator_enable - enable regulator output
27908c2ecf20Sopenharmony_ci * @regulator: regulator source
27918c2ecf20Sopenharmony_ci *
27928c2ecf20Sopenharmony_ci * Request that the regulator be enabled with the regulator output at
27938c2ecf20Sopenharmony_ci * the predefined voltage or current value.  Calls to regulator_enable()
27948c2ecf20Sopenharmony_ci * must be balanced with calls to regulator_disable().
27958c2ecf20Sopenharmony_ci *
27968c2ecf20Sopenharmony_ci * NOTE: the output value can be set by other drivers, boot loader or may be
27978c2ecf20Sopenharmony_ci * hardwired in the regulator.
27988c2ecf20Sopenharmony_ci */
27998c2ecf20Sopenharmony_ciint regulator_enable(struct regulator *regulator)
28008c2ecf20Sopenharmony_ci{
28018c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
28028c2ecf20Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
28038c2ecf20Sopenharmony_ci	int ret;
28048c2ecf20Sopenharmony_ci
28058c2ecf20Sopenharmony_ci	regulator_lock_dependent(rdev, &ww_ctx);
28068c2ecf20Sopenharmony_ci	ret = _regulator_enable(regulator);
28078c2ecf20Sopenharmony_ci	regulator_unlock_dependent(rdev, &ww_ctx);
28088c2ecf20Sopenharmony_ci
28098c2ecf20Sopenharmony_ci	return ret;
28108c2ecf20Sopenharmony_ci}
28118c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_enable);
28128c2ecf20Sopenharmony_ci
28138c2ecf20Sopenharmony_cistatic int _regulator_do_disable(struct regulator_dev *rdev)
28148c2ecf20Sopenharmony_ci{
28158c2ecf20Sopenharmony_ci	int ret;
28168c2ecf20Sopenharmony_ci
28178c2ecf20Sopenharmony_ci	trace_regulator_disable(rdev_get_name(rdev));
28188c2ecf20Sopenharmony_ci
28198c2ecf20Sopenharmony_ci	if (rdev->ena_pin) {
28208c2ecf20Sopenharmony_ci		if (rdev->ena_gpio_state) {
28218c2ecf20Sopenharmony_ci			ret = regulator_ena_gpio_ctrl(rdev, false);
28228c2ecf20Sopenharmony_ci			if (ret < 0)
28238c2ecf20Sopenharmony_ci				return ret;
28248c2ecf20Sopenharmony_ci			rdev->ena_gpio_state = 0;
28258c2ecf20Sopenharmony_ci		}
28268c2ecf20Sopenharmony_ci
28278c2ecf20Sopenharmony_ci	} else if (rdev->desc->ops->disable) {
28288c2ecf20Sopenharmony_ci		ret = rdev->desc->ops->disable(rdev);
28298c2ecf20Sopenharmony_ci		if (ret != 0)
28308c2ecf20Sopenharmony_ci			return ret;
28318c2ecf20Sopenharmony_ci	}
28328c2ecf20Sopenharmony_ci
28338c2ecf20Sopenharmony_ci	/* cares about last_off_jiffy only if off_on_delay is required by
28348c2ecf20Sopenharmony_ci	 * device.
28358c2ecf20Sopenharmony_ci	 */
28368c2ecf20Sopenharmony_ci	if (rdev->desc->off_on_delay)
28378c2ecf20Sopenharmony_ci		rdev->last_off_jiffy = jiffies;
28388c2ecf20Sopenharmony_ci
28398c2ecf20Sopenharmony_ci	trace_regulator_disable_complete(rdev_get_name(rdev));
28408c2ecf20Sopenharmony_ci
28418c2ecf20Sopenharmony_ci	return 0;
28428c2ecf20Sopenharmony_ci}
28438c2ecf20Sopenharmony_ci
28448c2ecf20Sopenharmony_ci/* locks held by regulator_disable() */
28458c2ecf20Sopenharmony_cistatic int _regulator_disable(struct regulator *regulator)
28468c2ecf20Sopenharmony_ci{
28478c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
28488c2ecf20Sopenharmony_ci	int ret = 0;
28498c2ecf20Sopenharmony_ci
28508c2ecf20Sopenharmony_ci	lockdep_assert_held_once(&rdev->mutex.base);
28518c2ecf20Sopenharmony_ci
28528c2ecf20Sopenharmony_ci	if (WARN(regulator->enable_count == 0,
28538c2ecf20Sopenharmony_ci		 "unbalanced disables for %s\n", rdev_get_name(rdev)))
28548c2ecf20Sopenharmony_ci		return -EIO;
28558c2ecf20Sopenharmony_ci
28568c2ecf20Sopenharmony_ci	if (regulator->enable_count == 1) {
28578c2ecf20Sopenharmony_ci	/* disabling last enable_count from this regulator */
28588c2ecf20Sopenharmony_ci		/* are we the last user and permitted to disable ? */
28598c2ecf20Sopenharmony_ci		if (rdev->use_count == 1 &&
28608c2ecf20Sopenharmony_ci		    (rdev->constraints && !rdev->constraints->always_on)) {
28618c2ecf20Sopenharmony_ci
28628c2ecf20Sopenharmony_ci			/* we are last user */
28638c2ecf20Sopenharmony_ci			if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) {
28648c2ecf20Sopenharmony_ci				ret = _notifier_call_chain(rdev,
28658c2ecf20Sopenharmony_ci							   REGULATOR_EVENT_PRE_DISABLE,
28668c2ecf20Sopenharmony_ci							   NULL);
28678c2ecf20Sopenharmony_ci				if (ret & NOTIFY_STOP_MASK)
28688c2ecf20Sopenharmony_ci					return -EINVAL;
28698c2ecf20Sopenharmony_ci
28708c2ecf20Sopenharmony_ci				ret = _regulator_do_disable(rdev);
28718c2ecf20Sopenharmony_ci				if (ret < 0) {
28728c2ecf20Sopenharmony_ci					rdev_err(rdev, "failed to disable: %pe\n", ERR_PTR(ret));
28738c2ecf20Sopenharmony_ci					_notifier_call_chain(rdev,
28748c2ecf20Sopenharmony_ci							REGULATOR_EVENT_ABORT_DISABLE,
28758c2ecf20Sopenharmony_ci							NULL);
28768c2ecf20Sopenharmony_ci					return ret;
28778c2ecf20Sopenharmony_ci				}
28788c2ecf20Sopenharmony_ci				_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
28798c2ecf20Sopenharmony_ci						NULL);
28808c2ecf20Sopenharmony_ci			}
28818c2ecf20Sopenharmony_ci
28828c2ecf20Sopenharmony_ci			rdev->use_count = 0;
28838c2ecf20Sopenharmony_ci		} else if (rdev->use_count > 1) {
28848c2ecf20Sopenharmony_ci			rdev->use_count--;
28858c2ecf20Sopenharmony_ci		}
28868c2ecf20Sopenharmony_ci	}
28878c2ecf20Sopenharmony_ci
28888c2ecf20Sopenharmony_ci	if (ret == 0)
28898c2ecf20Sopenharmony_ci		ret = _regulator_handle_consumer_disable(regulator);
28908c2ecf20Sopenharmony_ci
28918c2ecf20Sopenharmony_ci	if (ret == 0 && rdev->coupling_desc.n_coupled > 1)
28928c2ecf20Sopenharmony_ci		ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);
28938c2ecf20Sopenharmony_ci
28948c2ecf20Sopenharmony_ci	if (ret == 0 && rdev->use_count == 0 && rdev->supply)
28958c2ecf20Sopenharmony_ci		ret = _regulator_disable(rdev->supply);
28968c2ecf20Sopenharmony_ci
28978c2ecf20Sopenharmony_ci	return ret;
28988c2ecf20Sopenharmony_ci}
28998c2ecf20Sopenharmony_ci
29008c2ecf20Sopenharmony_ci/**
29018c2ecf20Sopenharmony_ci * regulator_disable - disable regulator output
29028c2ecf20Sopenharmony_ci * @regulator: regulator source
29038c2ecf20Sopenharmony_ci *
29048c2ecf20Sopenharmony_ci * Disable the regulator output voltage or current.  Calls to
29058c2ecf20Sopenharmony_ci * regulator_enable() must be balanced with calls to
29068c2ecf20Sopenharmony_ci * regulator_disable().
29078c2ecf20Sopenharmony_ci *
29088c2ecf20Sopenharmony_ci * NOTE: this will only disable the regulator output if no other consumer
29098c2ecf20Sopenharmony_ci * devices have it enabled, the regulator device supports disabling and
29108c2ecf20Sopenharmony_ci * machine constraints permit this operation.
29118c2ecf20Sopenharmony_ci */
29128c2ecf20Sopenharmony_ciint regulator_disable(struct regulator *regulator)
29138c2ecf20Sopenharmony_ci{
29148c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
29158c2ecf20Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
29168c2ecf20Sopenharmony_ci	int ret;
29178c2ecf20Sopenharmony_ci
29188c2ecf20Sopenharmony_ci	regulator_lock_dependent(rdev, &ww_ctx);
29198c2ecf20Sopenharmony_ci	ret = _regulator_disable(regulator);
29208c2ecf20Sopenharmony_ci	regulator_unlock_dependent(rdev, &ww_ctx);
29218c2ecf20Sopenharmony_ci
29228c2ecf20Sopenharmony_ci	return ret;
29238c2ecf20Sopenharmony_ci}
29248c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_disable);
29258c2ecf20Sopenharmony_ci
29268c2ecf20Sopenharmony_ci/* locks held by regulator_force_disable() */
29278c2ecf20Sopenharmony_cistatic int _regulator_force_disable(struct regulator_dev *rdev)
29288c2ecf20Sopenharmony_ci{
29298c2ecf20Sopenharmony_ci	int ret = 0;
29308c2ecf20Sopenharmony_ci
29318c2ecf20Sopenharmony_ci	lockdep_assert_held_once(&rdev->mutex.base);
29328c2ecf20Sopenharmony_ci
29338c2ecf20Sopenharmony_ci	ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
29348c2ecf20Sopenharmony_ci			REGULATOR_EVENT_PRE_DISABLE, NULL);
29358c2ecf20Sopenharmony_ci	if (ret & NOTIFY_STOP_MASK)
29368c2ecf20Sopenharmony_ci		return -EINVAL;
29378c2ecf20Sopenharmony_ci
29388c2ecf20Sopenharmony_ci	ret = _regulator_do_disable(rdev);
29398c2ecf20Sopenharmony_ci	if (ret < 0) {
29408c2ecf20Sopenharmony_ci		rdev_err(rdev, "failed to force disable: %pe\n", ERR_PTR(ret));
29418c2ecf20Sopenharmony_ci		_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
29428c2ecf20Sopenharmony_ci				REGULATOR_EVENT_ABORT_DISABLE, NULL);
29438c2ecf20Sopenharmony_ci		return ret;
29448c2ecf20Sopenharmony_ci	}
29458c2ecf20Sopenharmony_ci
29468c2ecf20Sopenharmony_ci	_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
29478c2ecf20Sopenharmony_ci			REGULATOR_EVENT_DISABLE, NULL);
29488c2ecf20Sopenharmony_ci
29498c2ecf20Sopenharmony_ci	return 0;
29508c2ecf20Sopenharmony_ci}
29518c2ecf20Sopenharmony_ci
29528c2ecf20Sopenharmony_ci/**
29538c2ecf20Sopenharmony_ci * regulator_force_disable - force disable regulator output
29548c2ecf20Sopenharmony_ci * @regulator: regulator source
29558c2ecf20Sopenharmony_ci *
29568c2ecf20Sopenharmony_ci * Forcibly disable the regulator output voltage or current.
29578c2ecf20Sopenharmony_ci * NOTE: this *will* disable the regulator output even if other consumer
29588c2ecf20Sopenharmony_ci * devices have it enabled. This should be used for situations when device
29598c2ecf20Sopenharmony_ci * damage will likely occur if the regulator is not disabled (e.g. over temp).
29608c2ecf20Sopenharmony_ci */
29618c2ecf20Sopenharmony_ciint regulator_force_disable(struct regulator *regulator)
29628c2ecf20Sopenharmony_ci{
29638c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
29648c2ecf20Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
29658c2ecf20Sopenharmony_ci	int ret;
29668c2ecf20Sopenharmony_ci
29678c2ecf20Sopenharmony_ci	regulator_lock_dependent(rdev, &ww_ctx);
29688c2ecf20Sopenharmony_ci
29698c2ecf20Sopenharmony_ci	ret = _regulator_force_disable(regulator->rdev);
29708c2ecf20Sopenharmony_ci
29718c2ecf20Sopenharmony_ci	if (rdev->coupling_desc.n_coupled > 1)
29728c2ecf20Sopenharmony_ci		regulator_balance_voltage(rdev, PM_SUSPEND_ON);
29738c2ecf20Sopenharmony_ci
29748c2ecf20Sopenharmony_ci	if (regulator->uA_load) {
29758c2ecf20Sopenharmony_ci		regulator->uA_load = 0;
29768c2ecf20Sopenharmony_ci		ret = drms_uA_update(rdev);
29778c2ecf20Sopenharmony_ci	}
29788c2ecf20Sopenharmony_ci
29798c2ecf20Sopenharmony_ci	if (rdev->use_count != 0 && rdev->supply)
29808c2ecf20Sopenharmony_ci		_regulator_disable(rdev->supply);
29818c2ecf20Sopenharmony_ci
29828c2ecf20Sopenharmony_ci	regulator_unlock_dependent(rdev, &ww_ctx);
29838c2ecf20Sopenharmony_ci
29848c2ecf20Sopenharmony_ci	return ret;
29858c2ecf20Sopenharmony_ci}
29868c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_force_disable);
29878c2ecf20Sopenharmony_ci
29888c2ecf20Sopenharmony_cistatic void regulator_disable_work(struct work_struct *work)
29898c2ecf20Sopenharmony_ci{
29908c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = container_of(work, struct regulator_dev,
29918c2ecf20Sopenharmony_ci						  disable_work.work);
29928c2ecf20Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
29938c2ecf20Sopenharmony_ci	int count, i, ret;
29948c2ecf20Sopenharmony_ci	struct regulator *regulator;
29958c2ecf20Sopenharmony_ci	int total_count = 0;
29968c2ecf20Sopenharmony_ci
29978c2ecf20Sopenharmony_ci	regulator_lock_dependent(rdev, &ww_ctx);
29988c2ecf20Sopenharmony_ci
29998c2ecf20Sopenharmony_ci	/*
30008c2ecf20Sopenharmony_ci	 * Workqueue functions queue the new work instance while the previous
30018c2ecf20Sopenharmony_ci	 * work instance is being processed. Cancel the queued work instance
30028c2ecf20Sopenharmony_ci	 * as the work instance under processing does the job of the queued
30038c2ecf20Sopenharmony_ci	 * work instance.
30048c2ecf20Sopenharmony_ci	 */
30058c2ecf20Sopenharmony_ci	cancel_delayed_work(&rdev->disable_work);
30068c2ecf20Sopenharmony_ci
30078c2ecf20Sopenharmony_ci	list_for_each_entry(regulator, &rdev->consumer_list, list) {
30088c2ecf20Sopenharmony_ci		count = regulator->deferred_disables;
30098c2ecf20Sopenharmony_ci
30108c2ecf20Sopenharmony_ci		if (!count)
30118c2ecf20Sopenharmony_ci			continue;
30128c2ecf20Sopenharmony_ci
30138c2ecf20Sopenharmony_ci		total_count += count;
30148c2ecf20Sopenharmony_ci		regulator->deferred_disables = 0;
30158c2ecf20Sopenharmony_ci
30168c2ecf20Sopenharmony_ci		for (i = 0; i < count; i++) {
30178c2ecf20Sopenharmony_ci			ret = _regulator_disable(regulator);
30188c2ecf20Sopenharmony_ci			if (ret != 0)
30198c2ecf20Sopenharmony_ci				rdev_err(rdev, "Deferred disable failed: %pe\n",
30208c2ecf20Sopenharmony_ci					 ERR_PTR(ret));
30218c2ecf20Sopenharmony_ci		}
30228c2ecf20Sopenharmony_ci	}
30238c2ecf20Sopenharmony_ci	WARN_ON(!total_count);
30248c2ecf20Sopenharmony_ci
30258c2ecf20Sopenharmony_ci	if (rdev->coupling_desc.n_coupled > 1)
30268c2ecf20Sopenharmony_ci		regulator_balance_voltage(rdev, PM_SUSPEND_ON);
30278c2ecf20Sopenharmony_ci
30288c2ecf20Sopenharmony_ci	regulator_unlock_dependent(rdev, &ww_ctx);
30298c2ecf20Sopenharmony_ci}
30308c2ecf20Sopenharmony_ci
30318c2ecf20Sopenharmony_ci/**
30328c2ecf20Sopenharmony_ci * regulator_disable_deferred - disable regulator output with delay
30338c2ecf20Sopenharmony_ci * @regulator: regulator source
30348c2ecf20Sopenharmony_ci * @ms: milliseconds until the regulator is disabled
30358c2ecf20Sopenharmony_ci *
30368c2ecf20Sopenharmony_ci * Execute regulator_disable() on the regulator after a delay.  This
30378c2ecf20Sopenharmony_ci * is intended for use with devices that require some time to quiesce.
30388c2ecf20Sopenharmony_ci *
30398c2ecf20Sopenharmony_ci * NOTE: this will only disable the regulator output if no other consumer
30408c2ecf20Sopenharmony_ci * devices have it enabled, the regulator device supports disabling and
30418c2ecf20Sopenharmony_ci * machine constraints permit this operation.
30428c2ecf20Sopenharmony_ci */
30438c2ecf20Sopenharmony_ciint regulator_disable_deferred(struct regulator *regulator, int ms)
30448c2ecf20Sopenharmony_ci{
30458c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
30468c2ecf20Sopenharmony_ci
30478c2ecf20Sopenharmony_ci	if (!ms)
30488c2ecf20Sopenharmony_ci		return regulator_disable(regulator);
30498c2ecf20Sopenharmony_ci
30508c2ecf20Sopenharmony_ci	regulator_lock(rdev);
30518c2ecf20Sopenharmony_ci	regulator->deferred_disables++;
30528c2ecf20Sopenharmony_ci	mod_delayed_work(system_power_efficient_wq, &rdev->disable_work,
30538c2ecf20Sopenharmony_ci			 msecs_to_jiffies(ms));
30548c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
30558c2ecf20Sopenharmony_ci
30568c2ecf20Sopenharmony_ci	return 0;
30578c2ecf20Sopenharmony_ci}
30588c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_disable_deferred);
30598c2ecf20Sopenharmony_ci
30608c2ecf20Sopenharmony_cistatic int _regulator_is_enabled(struct regulator_dev *rdev)
30618c2ecf20Sopenharmony_ci{
30628c2ecf20Sopenharmony_ci	/* A GPIO control always takes precedence */
30638c2ecf20Sopenharmony_ci	if (rdev->ena_pin)
30648c2ecf20Sopenharmony_ci		return rdev->ena_gpio_state;
30658c2ecf20Sopenharmony_ci
30668c2ecf20Sopenharmony_ci	/* If we don't know then assume that the regulator is always on */
30678c2ecf20Sopenharmony_ci	if (!rdev->desc->ops->is_enabled)
30688c2ecf20Sopenharmony_ci		return 1;
30698c2ecf20Sopenharmony_ci
30708c2ecf20Sopenharmony_ci	return rdev->desc->ops->is_enabled(rdev);
30718c2ecf20Sopenharmony_ci}
30728c2ecf20Sopenharmony_ci
30738c2ecf20Sopenharmony_cistatic int _regulator_list_voltage(struct regulator_dev *rdev,
30748c2ecf20Sopenharmony_ci				   unsigned selector, int lock)
30758c2ecf20Sopenharmony_ci{
30768c2ecf20Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
30778c2ecf20Sopenharmony_ci	int ret;
30788c2ecf20Sopenharmony_ci
30798c2ecf20Sopenharmony_ci	if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector)
30808c2ecf20Sopenharmony_ci		return rdev->desc->fixed_uV;
30818c2ecf20Sopenharmony_ci
30828c2ecf20Sopenharmony_ci	if (ops->list_voltage) {
30838c2ecf20Sopenharmony_ci		if (selector >= rdev->desc->n_voltages)
30848c2ecf20Sopenharmony_ci			return -EINVAL;
30858c2ecf20Sopenharmony_ci		if (lock)
30868c2ecf20Sopenharmony_ci			regulator_lock(rdev);
30878c2ecf20Sopenharmony_ci		ret = ops->list_voltage(rdev, selector);
30888c2ecf20Sopenharmony_ci		if (lock)
30898c2ecf20Sopenharmony_ci			regulator_unlock(rdev);
30908c2ecf20Sopenharmony_ci	} else if (rdev->is_switch && rdev->supply) {
30918c2ecf20Sopenharmony_ci		ret = _regulator_list_voltage(rdev->supply->rdev,
30928c2ecf20Sopenharmony_ci					      selector, lock);
30938c2ecf20Sopenharmony_ci	} else {
30948c2ecf20Sopenharmony_ci		return -EINVAL;
30958c2ecf20Sopenharmony_ci	}
30968c2ecf20Sopenharmony_ci
30978c2ecf20Sopenharmony_ci	if (ret > 0) {
30988c2ecf20Sopenharmony_ci		if (ret < rdev->constraints->min_uV)
30998c2ecf20Sopenharmony_ci			ret = 0;
31008c2ecf20Sopenharmony_ci		else if (ret > rdev->constraints->max_uV)
31018c2ecf20Sopenharmony_ci			ret = 0;
31028c2ecf20Sopenharmony_ci	}
31038c2ecf20Sopenharmony_ci
31048c2ecf20Sopenharmony_ci	return ret;
31058c2ecf20Sopenharmony_ci}
31068c2ecf20Sopenharmony_ci
31078c2ecf20Sopenharmony_ci/**
31088c2ecf20Sopenharmony_ci * regulator_is_enabled - is the regulator output enabled
31098c2ecf20Sopenharmony_ci * @regulator: regulator source
31108c2ecf20Sopenharmony_ci *
31118c2ecf20Sopenharmony_ci * Returns positive if the regulator driver backing the source/client
31128c2ecf20Sopenharmony_ci * has requested that the device be enabled, zero if it hasn't, else a
31138c2ecf20Sopenharmony_ci * negative errno code.
31148c2ecf20Sopenharmony_ci *
31158c2ecf20Sopenharmony_ci * Note that the device backing this regulator handle can have multiple
31168c2ecf20Sopenharmony_ci * users, so it might be enabled even if regulator_enable() was never
31178c2ecf20Sopenharmony_ci * called for this particular source.
31188c2ecf20Sopenharmony_ci */
31198c2ecf20Sopenharmony_ciint regulator_is_enabled(struct regulator *regulator)
31208c2ecf20Sopenharmony_ci{
31218c2ecf20Sopenharmony_ci	int ret;
31228c2ecf20Sopenharmony_ci
31238c2ecf20Sopenharmony_ci	if (regulator->always_on)
31248c2ecf20Sopenharmony_ci		return 1;
31258c2ecf20Sopenharmony_ci
31268c2ecf20Sopenharmony_ci	regulator_lock(regulator->rdev);
31278c2ecf20Sopenharmony_ci	ret = _regulator_is_enabled(regulator->rdev);
31288c2ecf20Sopenharmony_ci	regulator_unlock(regulator->rdev);
31298c2ecf20Sopenharmony_ci
31308c2ecf20Sopenharmony_ci	return ret;
31318c2ecf20Sopenharmony_ci}
31328c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_is_enabled);
31338c2ecf20Sopenharmony_ci
31348c2ecf20Sopenharmony_ci/**
31358c2ecf20Sopenharmony_ci * regulator_count_voltages - count regulator_list_voltage() selectors
31368c2ecf20Sopenharmony_ci * @regulator: regulator source
31378c2ecf20Sopenharmony_ci *
31388c2ecf20Sopenharmony_ci * Returns number of selectors, or negative errno.  Selectors are
31398c2ecf20Sopenharmony_ci * numbered starting at zero, and typically correspond to bitfields
31408c2ecf20Sopenharmony_ci * in hardware registers.
31418c2ecf20Sopenharmony_ci */
31428c2ecf20Sopenharmony_ciint regulator_count_voltages(struct regulator *regulator)
31438c2ecf20Sopenharmony_ci{
31448c2ecf20Sopenharmony_ci	struct regulator_dev	*rdev = regulator->rdev;
31458c2ecf20Sopenharmony_ci
31468c2ecf20Sopenharmony_ci	if (rdev->desc->n_voltages)
31478c2ecf20Sopenharmony_ci		return rdev->desc->n_voltages;
31488c2ecf20Sopenharmony_ci
31498c2ecf20Sopenharmony_ci	if (!rdev->is_switch || !rdev->supply)
31508c2ecf20Sopenharmony_ci		return -EINVAL;
31518c2ecf20Sopenharmony_ci
31528c2ecf20Sopenharmony_ci	return regulator_count_voltages(rdev->supply);
31538c2ecf20Sopenharmony_ci}
31548c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_count_voltages);
31558c2ecf20Sopenharmony_ci
31568c2ecf20Sopenharmony_ci/**
31578c2ecf20Sopenharmony_ci * regulator_list_voltage - enumerate supported voltages
31588c2ecf20Sopenharmony_ci * @regulator: regulator source
31598c2ecf20Sopenharmony_ci * @selector: identify voltage to list
31608c2ecf20Sopenharmony_ci * Context: can sleep
31618c2ecf20Sopenharmony_ci *
31628c2ecf20Sopenharmony_ci * Returns a voltage that can be passed to @regulator_set_voltage(),
31638c2ecf20Sopenharmony_ci * zero if this selector code can't be used on this system, or a
31648c2ecf20Sopenharmony_ci * negative errno.
31658c2ecf20Sopenharmony_ci */
31668c2ecf20Sopenharmony_ciint regulator_list_voltage(struct regulator *regulator, unsigned selector)
31678c2ecf20Sopenharmony_ci{
31688c2ecf20Sopenharmony_ci	return _regulator_list_voltage(regulator->rdev, selector, 1);
31698c2ecf20Sopenharmony_ci}
31708c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_list_voltage);
31718c2ecf20Sopenharmony_ci
31728c2ecf20Sopenharmony_ci/**
31738c2ecf20Sopenharmony_ci * regulator_get_regmap - get the regulator's register map
31748c2ecf20Sopenharmony_ci * @regulator: regulator source
31758c2ecf20Sopenharmony_ci *
31768c2ecf20Sopenharmony_ci * Returns the register map for the given regulator, or an ERR_PTR value
31778c2ecf20Sopenharmony_ci * if the regulator doesn't use regmap.
31788c2ecf20Sopenharmony_ci */
31798c2ecf20Sopenharmony_cistruct regmap *regulator_get_regmap(struct regulator *regulator)
31808c2ecf20Sopenharmony_ci{
31818c2ecf20Sopenharmony_ci	struct regmap *map = regulator->rdev->regmap;
31828c2ecf20Sopenharmony_ci
31838c2ecf20Sopenharmony_ci	return map ? map : ERR_PTR(-EOPNOTSUPP);
31848c2ecf20Sopenharmony_ci}
31858c2ecf20Sopenharmony_ci
31868c2ecf20Sopenharmony_ci/**
31878c2ecf20Sopenharmony_ci * regulator_get_hardware_vsel_register - get the HW voltage selector register
31888c2ecf20Sopenharmony_ci * @regulator: regulator source
31898c2ecf20Sopenharmony_ci * @vsel_reg: voltage selector register, output parameter
31908c2ecf20Sopenharmony_ci * @vsel_mask: mask for voltage selector bitfield, output parameter
31918c2ecf20Sopenharmony_ci *
31928c2ecf20Sopenharmony_ci * Returns the hardware register offset and bitmask used for setting the
31938c2ecf20Sopenharmony_ci * regulator voltage. This might be useful when configuring voltage-scaling
31948c2ecf20Sopenharmony_ci * hardware or firmware that can make I2C requests behind the kernel's back,
31958c2ecf20Sopenharmony_ci * for example.
31968c2ecf20Sopenharmony_ci *
31978c2ecf20Sopenharmony_ci * On success, the output parameters @vsel_reg and @vsel_mask are filled in
31988c2ecf20Sopenharmony_ci * and 0 is returned, otherwise a negative errno is returned.
31998c2ecf20Sopenharmony_ci */
32008c2ecf20Sopenharmony_ciint regulator_get_hardware_vsel_register(struct regulator *regulator,
32018c2ecf20Sopenharmony_ci					 unsigned *vsel_reg,
32028c2ecf20Sopenharmony_ci					 unsigned *vsel_mask)
32038c2ecf20Sopenharmony_ci{
32048c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
32058c2ecf20Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
32068c2ecf20Sopenharmony_ci
32078c2ecf20Sopenharmony_ci	if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap)
32088c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
32098c2ecf20Sopenharmony_ci
32108c2ecf20Sopenharmony_ci	*vsel_reg = rdev->desc->vsel_reg;
32118c2ecf20Sopenharmony_ci	*vsel_mask = rdev->desc->vsel_mask;
32128c2ecf20Sopenharmony_ci
32138c2ecf20Sopenharmony_ci	return 0;
32148c2ecf20Sopenharmony_ci}
32158c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register);
32168c2ecf20Sopenharmony_ci
32178c2ecf20Sopenharmony_ci/**
32188c2ecf20Sopenharmony_ci * regulator_list_hardware_vsel - get the HW-specific register value for a selector
32198c2ecf20Sopenharmony_ci * @regulator: regulator source
32208c2ecf20Sopenharmony_ci * @selector: identify voltage to list
32218c2ecf20Sopenharmony_ci *
32228c2ecf20Sopenharmony_ci * Converts the selector to a hardware-specific voltage selector that can be
32238c2ecf20Sopenharmony_ci * directly written to the regulator registers. The address of the voltage
32248c2ecf20Sopenharmony_ci * register can be determined by calling @regulator_get_hardware_vsel_register.
32258c2ecf20Sopenharmony_ci *
32268c2ecf20Sopenharmony_ci * On error a negative errno is returned.
32278c2ecf20Sopenharmony_ci */
32288c2ecf20Sopenharmony_ciint regulator_list_hardware_vsel(struct regulator *regulator,
32298c2ecf20Sopenharmony_ci				 unsigned selector)
32308c2ecf20Sopenharmony_ci{
32318c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
32328c2ecf20Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
32338c2ecf20Sopenharmony_ci
32348c2ecf20Sopenharmony_ci	if (selector >= rdev->desc->n_voltages)
32358c2ecf20Sopenharmony_ci		return -EINVAL;
32368c2ecf20Sopenharmony_ci	if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap)
32378c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
32388c2ecf20Sopenharmony_ci
32398c2ecf20Sopenharmony_ci	return selector;
32408c2ecf20Sopenharmony_ci}
32418c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_list_hardware_vsel);
32428c2ecf20Sopenharmony_ci
32438c2ecf20Sopenharmony_ci/**
32448c2ecf20Sopenharmony_ci * regulator_get_linear_step - return the voltage step size between VSEL values
32458c2ecf20Sopenharmony_ci * @regulator: regulator source
32468c2ecf20Sopenharmony_ci *
32478c2ecf20Sopenharmony_ci * Returns the voltage step size between VSEL values for linear
32488c2ecf20Sopenharmony_ci * regulators, or return 0 if the regulator isn't a linear regulator.
32498c2ecf20Sopenharmony_ci */
32508c2ecf20Sopenharmony_ciunsigned int regulator_get_linear_step(struct regulator *regulator)
32518c2ecf20Sopenharmony_ci{
32528c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
32538c2ecf20Sopenharmony_ci
32548c2ecf20Sopenharmony_ci	return rdev->desc->uV_step;
32558c2ecf20Sopenharmony_ci}
32568c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_linear_step);
32578c2ecf20Sopenharmony_ci
32588c2ecf20Sopenharmony_ci/**
32598c2ecf20Sopenharmony_ci * regulator_is_supported_voltage - check if a voltage range can be supported
32608c2ecf20Sopenharmony_ci *
32618c2ecf20Sopenharmony_ci * @regulator: Regulator to check.
32628c2ecf20Sopenharmony_ci * @min_uV: Minimum required voltage in uV.
32638c2ecf20Sopenharmony_ci * @max_uV: Maximum required voltage in uV.
32648c2ecf20Sopenharmony_ci *
32658c2ecf20Sopenharmony_ci * Returns a boolean.
32668c2ecf20Sopenharmony_ci */
32678c2ecf20Sopenharmony_ciint regulator_is_supported_voltage(struct regulator *regulator,
32688c2ecf20Sopenharmony_ci				   int min_uV, int max_uV)
32698c2ecf20Sopenharmony_ci{
32708c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
32718c2ecf20Sopenharmony_ci	int i, voltages, ret;
32728c2ecf20Sopenharmony_ci
32738c2ecf20Sopenharmony_ci	/* If we can't change voltage check the current voltage */
32748c2ecf20Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
32758c2ecf20Sopenharmony_ci		ret = regulator_get_voltage(regulator);
32768c2ecf20Sopenharmony_ci		if (ret >= 0)
32778c2ecf20Sopenharmony_ci			return min_uV <= ret && ret <= max_uV;
32788c2ecf20Sopenharmony_ci		else
32798c2ecf20Sopenharmony_ci			return ret;
32808c2ecf20Sopenharmony_ci	}
32818c2ecf20Sopenharmony_ci
32828c2ecf20Sopenharmony_ci	/* Any voltage within constrains range is fine? */
32838c2ecf20Sopenharmony_ci	if (rdev->desc->continuous_voltage_range)
32848c2ecf20Sopenharmony_ci		return min_uV >= rdev->constraints->min_uV &&
32858c2ecf20Sopenharmony_ci				max_uV <= rdev->constraints->max_uV;
32868c2ecf20Sopenharmony_ci
32878c2ecf20Sopenharmony_ci	ret = regulator_count_voltages(regulator);
32888c2ecf20Sopenharmony_ci	if (ret < 0)
32898c2ecf20Sopenharmony_ci		return 0;
32908c2ecf20Sopenharmony_ci	voltages = ret;
32918c2ecf20Sopenharmony_ci
32928c2ecf20Sopenharmony_ci	for (i = 0; i < voltages; i++) {
32938c2ecf20Sopenharmony_ci		ret = regulator_list_voltage(regulator, i);
32948c2ecf20Sopenharmony_ci
32958c2ecf20Sopenharmony_ci		if (ret >= min_uV && ret <= max_uV)
32968c2ecf20Sopenharmony_ci			return 1;
32978c2ecf20Sopenharmony_ci	}
32988c2ecf20Sopenharmony_ci
32998c2ecf20Sopenharmony_ci	return 0;
33008c2ecf20Sopenharmony_ci}
33018c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_is_supported_voltage);
33028c2ecf20Sopenharmony_ci
33038c2ecf20Sopenharmony_cistatic int regulator_map_voltage(struct regulator_dev *rdev, int min_uV,
33048c2ecf20Sopenharmony_ci				 int max_uV)
33058c2ecf20Sopenharmony_ci{
33068c2ecf20Sopenharmony_ci	const struct regulator_desc *desc = rdev->desc;
33078c2ecf20Sopenharmony_ci
33088c2ecf20Sopenharmony_ci	if (desc->ops->map_voltage)
33098c2ecf20Sopenharmony_ci		return desc->ops->map_voltage(rdev, min_uV, max_uV);
33108c2ecf20Sopenharmony_ci
33118c2ecf20Sopenharmony_ci	if (desc->ops->list_voltage == regulator_list_voltage_linear)
33128c2ecf20Sopenharmony_ci		return regulator_map_voltage_linear(rdev, min_uV, max_uV);
33138c2ecf20Sopenharmony_ci
33148c2ecf20Sopenharmony_ci	if (desc->ops->list_voltage == regulator_list_voltage_linear_range)
33158c2ecf20Sopenharmony_ci		return regulator_map_voltage_linear_range(rdev, min_uV, max_uV);
33168c2ecf20Sopenharmony_ci
33178c2ecf20Sopenharmony_ci	if (desc->ops->list_voltage ==
33188c2ecf20Sopenharmony_ci		regulator_list_voltage_pickable_linear_range)
33198c2ecf20Sopenharmony_ci		return regulator_map_voltage_pickable_linear_range(rdev,
33208c2ecf20Sopenharmony_ci							min_uV, max_uV);
33218c2ecf20Sopenharmony_ci
33228c2ecf20Sopenharmony_ci	return regulator_map_voltage_iterate(rdev, min_uV, max_uV);
33238c2ecf20Sopenharmony_ci}
33248c2ecf20Sopenharmony_ci
33258c2ecf20Sopenharmony_cistatic int _regulator_call_set_voltage(struct regulator_dev *rdev,
33268c2ecf20Sopenharmony_ci				       int min_uV, int max_uV,
33278c2ecf20Sopenharmony_ci				       unsigned *selector)
33288c2ecf20Sopenharmony_ci{
33298c2ecf20Sopenharmony_ci	struct pre_voltage_change_data data;
33308c2ecf20Sopenharmony_ci	int ret;
33318c2ecf20Sopenharmony_ci
33328c2ecf20Sopenharmony_ci	data.old_uV = regulator_get_voltage_rdev(rdev);
33338c2ecf20Sopenharmony_ci	data.min_uV = min_uV;
33348c2ecf20Sopenharmony_ci	data.max_uV = max_uV;
33358c2ecf20Sopenharmony_ci	ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE,
33368c2ecf20Sopenharmony_ci				   &data);
33378c2ecf20Sopenharmony_ci	if (ret & NOTIFY_STOP_MASK)
33388c2ecf20Sopenharmony_ci		return -EINVAL;
33398c2ecf20Sopenharmony_ci
33408c2ecf20Sopenharmony_ci	ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector);
33418c2ecf20Sopenharmony_ci	if (ret >= 0)
33428c2ecf20Sopenharmony_ci		return ret;
33438c2ecf20Sopenharmony_ci
33448c2ecf20Sopenharmony_ci	_notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE,
33458c2ecf20Sopenharmony_ci			     (void *)data.old_uV);
33468c2ecf20Sopenharmony_ci
33478c2ecf20Sopenharmony_ci	return ret;
33488c2ecf20Sopenharmony_ci}
33498c2ecf20Sopenharmony_ci
33508c2ecf20Sopenharmony_cistatic int _regulator_call_set_voltage_sel(struct regulator_dev *rdev,
33518c2ecf20Sopenharmony_ci					   int uV, unsigned selector)
33528c2ecf20Sopenharmony_ci{
33538c2ecf20Sopenharmony_ci	struct pre_voltage_change_data data;
33548c2ecf20Sopenharmony_ci	int ret;
33558c2ecf20Sopenharmony_ci
33568c2ecf20Sopenharmony_ci	data.old_uV = regulator_get_voltage_rdev(rdev);
33578c2ecf20Sopenharmony_ci	data.min_uV = uV;
33588c2ecf20Sopenharmony_ci	data.max_uV = uV;
33598c2ecf20Sopenharmony_ci	ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE,
33608c2ecf20Sopenharmony_ci				   &data);
33618c2ecf20Sopenharmony_ci	if (ret & NOTIFY_STOP_MASK)
33628c2ecf20Sopenharmony_ci		return -EINVAL;
33638c2ecf20Sopenharmony_ci
33648c2ecf20Sopenharmony_ci	ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
33658c2ecf20Sopenharmony_ci	if (ret >= 0)
33668c2ecf20Sopenharmony_ci		return ret;
33678c2ecf20Sopenharmony_ci
33688c2ecf20Sopenharmony_ci	_notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE,
33698c2ecf20Sopenharmony_ci			     (void *)data.old_uV);
33708c2ecf20Sopenharmony_ci
33718c2ecf20Sopenharmony_ci	return ret;
33728c2ecf20Sopenharmony_ci}
33738c2ecf20Sopenharmony_ci
33748c2ecf20Sopenharmony_cistatic int _regulator_set_voltage_sel_step(struct regulator_dev *rdev,
33758c2ecf20Sopenharmony_ci					   int uV, int new_selector)
33768c2ecf20Sopenharmony_ci{
33778c2ecf20Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
33788c2ecf20Sopenharmony_ci	int diff, old_sel, curr_sel, ret;
33798c2ecf20Sopenharmony_ci
33808c2ecf20Sopenharmony_ci	/* Stepping is only needed if the regulator is enabled. */
33818c2ecf20Sopenharmony_ci	if (!_regulator_is_enabled(rdev))
33828c2ecf20Sopenharmony_ci		goto final_set;
33838c2ecf20Sopenharmony_ci
33848c2ecf20Sopenharmony_ci	if (!ops->get_voltage_sel)
33858c2ecf20Sopenharmony_ci		return -EINVAL;
33868c2ecf20Sopenharmony_ci
33878c2ecf20Sopenharmony_ci	old_sel = ops->get_voltage_sel(rdev);
33888c2ecf20Sopenharmony_ci	if (old_sel < 0)
33898c2ecf20Sopenharmony_ci		return old_sel;
33908c2ecf20Sopenharmony_ci
33918c2ecf20Sopenharmony_ci	diff = new_selector - old_sel;
33928c2ecf20Sopenharmony_ci	if (diff == 0)
33938c2ecf20Sopenharmony_ci		return 0; /* No change needed. */
33948c2ecf20Sopenharmony_ci
33958c2ecf20Sopenharmony_ci	if (diff > 0) {
33968c2ecf20Sopenharmony_ci		/* Stepping up. */
33978c2ecf20Sopenharmony_ci		for (curr_sel = old_sel + rdev->desc->vsel_step;
33988c2ecf20Sopenharmony_ci		     curr_sel < new_selector;
33998c2ecf20Sopenharmony_ci		     curr_sel += rdev->desc->vsel_step) {
34008c2ecf20Sopenharmony_ci			/*
34018c2ecf20Sopenharmony_ci			 * Call the callback directly instead of using
34028c2ecf20Sopenharmony_ci			 * _regulator_call_set_voltage_sel() as we don't
34038c2ecf20Sopenharmony_ci			 * want to notify anyone yet. Same in the branch
34048c2ecf20Sopenharmony_ci			 * below.
34058c2ecf20Sopenharmony_ci			 */
34068c2ecf20Sopenharmony_ci			ret = ops->set_voltage_sel(rdev, curr_sel);
34078c2ecf20Sopenharmony_ci			if (ret)
34088c2ecf20Sopenharmony_ci				goto try_revert;
34098c2ecf20Sopenharmony_ci		}
34108c2ecf20Sopenharmony_ci	} else {
34118c2ecf20Sopenharmony_ci		/* Stepping down. */
34128c2ecf20Sopenharmony_ci		for (curr_sel = old_sel - rdev->desc->vsel_step;
34138c2ecf20Sopenharmony_ci		     curr_sel > new_selector;
34148c2ecf20Sopenharmony_ci		     curr_sel -= rdev->desc->vsel_step) {
34158c2ecf20Sopenharmony_ci			ret = ops->set_voltage_sel(rdev, curr_sel);
34168c2ecf20Sopenharmony_ci			if (ret)
34178c2ecf20Sopenharmony_ci				goto try_revert;
34188c2ecf20Sopenharmony_ci		}
34198c2ecf20Sopenharmony_ci	}
34208c2ecf20Sopenharmony_ci
34218c2ecf20Sopenharmony_cifinal_set:
34228c2ecf20Sopenharmony_ci	/* The final selector will trigger the notifiers. */
34238c2ecf20Sopenharmony_ci	return _regulator_call_set_voltage_sel(rdev, uV, new_selector);
34248c2ecf20Sopenharmony_ci
34258c2ecf20Sopenharmony_citry_revert:
34268c2ecf20Sopenharmony_ci	/*
34278c2ecf20Sopenharmony_ci	 * At least try to return to the previous voltage if setting a new
34288c2ecf20Sopenharmony_ci	 * one failed.
34298c2ecf20Sopenharmony_ci	 */
34308c2ecf20Sopenharmony_ci	(void)ops->set_voltage_sel(rdev, old_sel);
34318c2ecf20Sopenharmony_ci	return ret;
34328c2ecf20Sopenharmony_ci}
34338c2ecf20Sopenharmony_ci
34348c2ecf20Sopenharmony_cistatic int _regulator_set_voltage_time(struct regulator_dev *rdev,
34358c2ecf20Sopenharmony_ci				       int old_uV, int new_uV)
34368c2ecf20Sopenharmony_ci{
34378c2ecf20Sopenharmony_ci	unsigned int ramp_delay = 0;
34388c2ecf20Sopenharmony_ci
34398c2ecf20Sopenharmony_ci	if (rdev->constraints->ramp_delay)
34408c2ecf20Sopenharmony_ci		ramp_delay = rdev->constraints->ramp_delay;
34418c2ecf20Sopenharmony_ci	else if (rdev->desc->ramp_delay)
34428c2ecf20Sopenharmony_ci		ramp_delay = rdev->desc->ramp_delay;
34438c2ecf20Sopenharmony_ci	else if (rdev->constraints->settling_time)
34448c2ecf20Sopenharmony_ci		return rdev->constraints->settling_time;
34458c2ecf20Sopenharmony_ci	else if (rdev->constraints->settling_time_up &&
34468c2ecf20Sopenharmony_ci		 (new_uV > old_uV))
34478c2ecf20Sopenharmony_ci		return rdev->constraints->settling_time_up;
34488c2ecf20Sopenharmony_ci	else if (rdev->constraints->settling_time_down &&
34498c2ecf20Sopenharmony_ci		 (new_uV < old_uV))
34508c2ecf20Sopenharmony_ci		return rdev->constraints->settling_time_down;
34518c2ecf20Sopenharmony_ci
34528c2ecf20Sopenharmony_ci	if (ramp_delay == 0) {
34538c2ecf20Sopenharmony_ci		rdev_dbg(rdev, "ramp_delay not set\n");
34548c2ecf20Sopenharmony_ci		return 0;
34558c2ecf20Sopenharmony_ci	}
34568c2ecf20Sopenharmony_ci
34578c2ecf20Sopenharmony_ci	return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay);
34588c2ecf20Sopenharmony_ci}
34598c2ecf20Sopenharmony_ci
34608c2ecf20Sopenharmony_cistatic int _regulator_do_set_voltage(struct regulator_dev *rdev,
34618c2ecf20Sopenharmony_ci				     int min_uV, int max_uV)
34628c2ecf20Sopenharmony_ci{
34638c2ecf20Sopenharmony_ci	int ret;
34648c2ecf20Sopenharmony_ci	int delay = 0;
34658c2ecf20Sopenharmony_ci	int best_val = 0;
34668c2ecf20Sopenharmony_ci	unsigned int selector;
34678c2ecf20Sopenharmony_ci	int old_selector = -1;
34688c2ecf20Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
34698c2ecf20Sopenharmony_ci	int old_uV = regulator_get_voltage_rdev(rdev);
34708c2ecf20Sopenharmony_ci
34718c2ecf20Sopenharmony_ci	trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
34728c2ecf20Sopenharmony_ci
34738c2ecf20Sopenharmony_ci	min_uV += rdev->constraints->uV_offset;
34748c2ecf20Sopenharmony_ci	max_uV += rdev->constraints->uV_offset;
34758c2ecf20Sopenharmony_ci
34768c2ecf20Sopenharmony_ci	/*
34778c2ecf20Sopenharmony_ci	 * If we can't obtain the old selector there is not enough
34788c2ecf20Sopenharmony_ci	 * info to call set_voltage_time_sel().
34798c2ecf20Sopenharmony_ci	 */
34808c2ecf20Sopenharmony_ci	if (_regulator_is_enabled(rdev) &&
34818c2ecf20Sopenharmony_ci	    ops->set_voltage_time_sel && ops->get_voltage_sel) {
34828c2ecf20Sopenharmony_ci		old_selector = ops->get_voltage_sel(rdev);
34838c2ecf20Sopenharmony_ci		if (old_selector < 0)
34848c2ecf20Sopenharmony_ci			return old_selector;
34858c2ecf20Sopenharmony_ci	}
34868c2ecf20Sopenharmony_ci
34878c2ecf20Sopenharmony_ci	if (ops->set_voltage) {
34888c2ecf20Sopenharmony_ci		ret = _regulator_call_set_voltage(rdev, min_uV, max_uV,
34898c2ecf20Sopenharmony_ci						  &selector);
34908c2ecf20Sopenharmony_ci
34918c2ecf20Sopenharmony_ci		if (ret >= 0) {
34928c2ecf20Sopenharmony_ci			if (ops->list_voltage)
34938c2ecf20Sopenharmony_ci				best_val = ops->list_voltage(rdev,
34948c2ecf20Sopenharmony_ci							     selector);
34958c2ecf20Sopenharmony_ci			else
34968c2ecf20Sopenharmony_ci				best_val = regulator_get_voltage_rdev(rdev);
34978c2ecf20Sopenharmony_ci		}
34988c2ecf20Sopenharmony_ci
34998c2ecf20Sopenharmony_ci	} else if (ops->set_voltage_sel) {
35008c2ecf20Sopenharmony_ci		ret = regulator_map_voltage(rdev, min_uV, max_uV);
35018c2ecf20Sopenharmony_ci		if (ret >= 0) {
35028c2ecf20Sopenharmony_ci			best_val = ops->list_voltage(rdev, ret);
35038c2ecf20Sopenharmony_ci			if (min_uV <= best_val && max_uV >= best_val) {
35048c2ecf20Sopenharmony_ci				selector = ret;
35058c2ecf20Sopenharmony_ci				if (old_selector == selector)
35068c2ecf20Sopenharmony_ci					ret = 0;
35078c2ecf20Sopenharmony_ci				else if (rdev->desc->vsel_step)
35088c2ecf20Sopenharmony_ci					ret = _regulator_set_voltage_sel_step(
35098c2ecf20Sopenharmony_ci						rdev, best_val, selector);
35108c2ecf20Sopenharmony_ci				else
35118c2ecf20Sopenharmony_ci					ret = _regulator_call_set_voltage_sel(
35128c2ecf20Sopenharmony_ci						rdev, best_val, selector);
35138c2ecf20Sopenharmony_ci			} else {
35148c2ecf20Sopenharmony_ci				ret = -EINVAL;
35158c2ecf20Sopenharmony_ci			}
35168c2ecf20Sopenharmony_ci		}
35178c2ecf20Sopenharmony_ci	} else {
35188c2ecf20Sopenharmony_ci		ret = -EINVAL;
35198c2ecf20Sopenharmony_ci	}
35208c2ecf20Sopenharmony_ci
35218c2ecf20Sopenharmony_ci	if (ret)
35228c2ecf20Sopenharmony_ci		goto out;
35238c2ecf20Sopenharmony_ci
35248c2ecf20Sopenharmony_ci	if (ops->set_voltage_time_sel) {
35258c2ecf20Sopenharmony_ci		/*
35268c2ecf20Sopenharmony_ci		 * Call set_voltage_time_sel if successfully obtained
35278c2ecf20Sopenharmony_ci		 * old_selector
35288c2ecf20Sopenharmony_ci		 */
35298c2ecf20Sopenharmony_ci		if (old_selector >= 0 && old_selector != selector)
35308c2ecf20Sopenharmony_ci			delay = ops->set_voltage_time_sel(rdev, old_selector,
35318c2ecf20Sopenharmony_ci							  selector);
35328c2ecf20Sopenharmony_ci	} else {
35338c2ecf20Sopenharmony_ci		if (old_uV != best_val) {
35348c2ecf20Sopenharmony_ci			if (ops->set_voltage_time)
35358c2ecf20Sopenharmony_ci				delay = ops->set_voltage_time(rdev, old_uV,
35368c2ecf20Sopenharmony_ci							      best_val);
35378c2ecf20Sopenharmony_ci			else
35388c2ecf20Sopenharmony_ci				delay = _regulator_set_voltage_time(rdev,
35398c2ecf20Sopenharmony_ci								    old_uV,
35408c2ecf20Sopenharmony_ci								    best_val);
35418c2ecf20Sopenharmony_ci		}
35428c2ecf20Sopenharmony_ci	}
35438c2ecf20Sopenharmony_ci
35448c2ecf20Sopenharmony_ci	if (delay < 0) {
35458c2ecf20Sopenharmony_ci		rdev_warn(rdev, "failed to get delay: %pe\n", ERR_PTR(delay));
35468c2ecf20Sopenharmony_ci		delay = 0;
35478c2ecf20Sopenharmony_ci	}
35488c2ecf20Sopenharmony_ci
35498c2ecf20Sopenharmony_ci	/* Insert any necessary delays */
35508c2ecf20Sopenharmony_ci	if (delay >= 1000) {
35518c2ecf20Sopenharmony_ci		mdelay(delay / 1000);
35528c2ecf20Sopenharmony_ci		udelay(delay % 1000);
35538c2ecf20Sopenharmony_ci	} else if (delay) {
35548c2ecf20Sopenharmony_ci		udelay(delay);
35558c2ecf20Sopenharmony_ci	}
35568c2ecf20Sopenharmony_ci
35578c2ecf20Sopenharmony_ci	if (best_val >= 0) {
35588c2ecf20Sopenharmony_ci		unsigned long data = best_val;
35598c2ecf20Sopenharmony_ci
35608c2ecf20Sopenharmony_ci		_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
35618c2ecf20Sopenharmony_ci				     (void *)data);
35628c2ecf20Sopenharmony_ci	}
35638c2ecf20Sopenharmony_ci
35648c2ecf20Sopenharmony_ciout:
35658c2ecf20Sopenharmony_ci	trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
35668c2ecf20Sopenharmony_ci
35678c2ecf20Sopenharmony_ci	return ret;
35688c2ecf20Sopenharmony_ci}
35698c2ecf20Sopenharmony_ci
35708c2ecf20Sopenharmony_cistatic int _regulator_do_set_suspend_voltage(struct regulator_dev *rdev,
35718c2ecf20Sopenharmony_ci				  int min_uV, int max_uV, suspend_state_t state)
35728c2ecf20Sopenharmony_ci{
35738c2ecf20Sopenharmony_ci	struct regulator_state *rstate;
35748c2ecf20Sopenharmony_ci	int uV, sel;
35758c2ecf20Sopenharmony_ci
35768c2ecf20Sopenharmony_ci	rstate = regulator_get_suspend_state(rdev, state);
35778c2ecf20Sopenharmony_ci	if (rstate == NULL)
35788c2ecf20Sopenharmony_ci		return -EINVAL;
35798c2ecf20Sopenharmony_ci
35808c2ecf20Sopenharmony_ci	if (min_uV < rstate->min_uV)
35818c2ecf20Sopenharmony_ci		min_uV = rstate->min_uV;
35828c2ecf20Sopenharmony_ci	if (max_uV > rstate->max_uV)
35838c2ecf20Sopenharmony_ci		max_uV = rstate->max_uV;
35848c2ecf20Sopenharmony_ci
35858c2ecf20Sopenharmony_ci	sel = regulator_map_voltage(rdev, min_uV, max_uV);
35868c2ecf20Sopenharmony_ci	if (sel < 0)
35878c2ecf20Sopenharmony_ci		return sel;
35888c2ecf20Sopenharmony_ci
35898c2ecf20Sopenharmony_ci	uV = rdev->desc->ops->list_voltage(rdev, sel);
35908c2ecf20Sopenharmony_ci	if (uV >= min_uV && uV <= max_uV)
35918c2ecf20Sopenharmony_ci		rstate->uV = uV;
35928c2ecf20Sopenharmony_ci
35938c2ecf20Sopenharmony_ci	return 0;
35948c2ecf20Sopenharmony_ci}
35958c2ecf20Sopenharmony_ci
35968c2ecf20Sopenharmony_cistatic int regulator_set_voltage_unlocked(struct regulator *regulator,
35978c2ecf20Sopenharmony_ci					  int min_uV, int max_uV,
35988c2ecf20Sopenharmony_ci					  suspend_state_t state)
35998c2ecf20Sopenharmony_ci{
36008c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
36018c2ecf20Sopenharmony_ci	struct regulator_voltage *voltage = &regulator->voltage[state];
36028c2ecf20Sopenharmony_ci	int ret = 0;
36038c2ecf20Sopenharmony_ci	int old_min_uV, old_max_uV;
36048c2ecf20Sopenharmony_ci	int current_uV;
36058c2ecf20Sopenharmony_ci
36068c2ecf20Sopenharmony_ci	/* If we're setting the same range as last time the change
36078c2ecf20Sopenharmony_ci	 * should be a noop (some cpufreq implementations use the same
36088c2ecf20Sopenharmony_ci	 * voltage for multiple frequencies, for example).
36098c2ecf20Sopenharmony_ci	 */
36108c2ecf20Sopenharmony_ci	if (voltage->min_uV == min_uV && voltage->max_uV == max_uV)
36118c2ecf20Sopenharmony_ci		goto out;
36128c2ecf20Sopenharmony_ci
36138c2ecf20Sopenharmony_ci	/* If we're trying to set a range that overlaps the current voltage,
36148c2ecf20Sopenharmony_ci	 * return successfully even though the regulator does not support
36158c2ecf20Sopenharmony_ci	 * changing the voltage.
36168c2ecf20Sopenharmony_ci	 */
36178c2ecf20Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
36188c2ecf20Sopenharmony_ci		current_uV = regulator_get_voltage_rdev(rdev);
36198c2ecf20Sopenharmony_ci		if (min_uV <= current_uV && current_uV <= max_uV) {
36208c2ecf20Sopenharmony_ci			voltage->min_uV = min_uV;
36218c2ecf20Sopenharmony_ci			voltage->max_uV = max_uV;
36228c2ecf20Sopenharmony_ci			goto out;
36238c2ecf20Sopenharmony_ci		}
36248c2ecf20Sopenharmony_ci	}
36258c2ecf20Sopenharmony_ci
36268c2ecf20Sopenharmony_ci	/* sanity check */
36278c2ecf20Sopenharmony_ci	if (!rdev->desc->ops->set_voltage &&
36288c2ecf20Sopenharmony_ci	    !rdev->desc->ops->set_voltage_sel) {
36298c2ecf20Sopenharmony_ci		ret = -EINVAL;
36308c2ecf20Sopenharmony_ci		goto out;
36318c2ecf20Sopenharmony_ci	}
36328c2ecf20Sopenharmony_ci
36338c2ecf20Sopenharmony_ci	/* constraints check */
36348c2ecf20Sopenharmony_ci	ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
36358c2ecf20Sopenharmony_ci	if (ret < 0)
36368c2ecf20Sopenharmony_ci		goto out;
36378c2ecf20Sopenharmony_ci
36388c2ecf20Sopenharmony_ci	/* restore original values in case of error */
36398c2ecf20Sopenharmony_ci	old_min_uV = voltage->min_uV;
36408c2ecf20Sopenharmony_ci	old_max_uV = voltage->max_uV;
36418c2ecf20Sopenharmony_ci	voltage->min_uV = min_uV;
36428c2ecf20Sopenharmony_ci	voltage->max_uV = max_uV;
36438c2ecf20Sopenharmony_ci
36448c2ecf20Sopenharmony_ci	/* for not coupled regulators this will just set the voltage */
36458c2ecf20Sopenharmony_ci	ret = regulator_balance_voltage(rdev, state);
36468c2ecf20Sopenharmony_ci	if (ret < 0) {
36478c2ecf20Sopenharmony_ci		voltage->min_uV = old_min_uV;
36488c2ecf20Sopenharmony_ci		voltage->max_uV = old_max_uV;
36498c2ecf20Sopenharmony_ci	}
36508c2ecf20Sopenharmony_ci
36518c2ecf20Sopenharmony_ciout:
36528c2ecf20Sopenharmony_ci	return ret;
36538c2ecf20Sopenharmony_ci}
36548c2ecf20Sopenharmony_ci
36558c2ecf20Sopenharmony_ciint regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV,
36568c2ecf20Sopenharmony_ci			       int max_uV, suspend_state_t state)
36578c2ecf20Sopenharmony_ci{
36588c2ecf20Sopenharmony_ci	int best_supply_uV = 0;
36598c2ecf20Sopenharmony_ci	int supply_change_uV = 0;
36608c2ecf20Sopenharmony_ci	int ret;
36618c2ecf20Sopenharmony_ci
36628c2ecf20Sopenharmony_ci	if (rdev->supply &&
36638c2ecf20Sopenharmony_ci	    regulator_ops_is_valid(rdev->supply->rdev,
36648c2ecf20Sopenharmony_ci				   REGULATOR_CHANGE_VOLTAGE) &&
36658c2ecf20Sopenharmony_ci	    (rdev->desc->min_dropout_uV || !(rdev->desc->ops->get_voltage ||
36668c2ecf20Sopenharmony_ci					   rdev->desc->ops->get_voltage_sel))) {
36678c2ecf20Sopenharmony_ci		int current_supply_uV;
36688c2ecf20Sopenharmony_ci		int selector;
36698c2ecf20Sopenharmony_ci
36708c2ecf20Sopenharmony_ci		selector = regulator_map_voltage(rdev, min_uV, max_uV);
36718c2ecf20Sopenharmony_ci		if (selector < 0) {
36728c2ecf20Sopenharmony_ci			ret = selector;
36738c2ecf20Sopenharmony_ci			goto out;
36748c2ecf20Sopenharmony_ci		}
36758c2ecf20Sopenharmony_ci
36768c2ecf20Sopenharmony_ci		best_supply_uV = _regulator_list_voltage(rdev, selector, 0);
36778c2ecf20Sopenharmony_ci		if (best_supply_uV < 0) {
36788c2ecf20Sopenharmony_ci			ret = best_supply_uV;
36798c2ecf20Sopenharmony_ci			goto out;
36808c2ecf20Sopenharmony_ci		}
36818c2ecf20Sopenharmony_ci
36828c2ecf20Sopenharmony_ci		best_supply_uV += rdev->desc->min_dropout_uV;
36838c2ecf20Sopenharmony_ci
36848c2ecf20Sopenharmony_ci		current_supply_uV = regulator_get_voltage_rdev(rdev->supply->rdev);
36858c2ecf20Sopenharmony_ci		if (current_supply_uV < 0) {
36868c2ecf20Sopenharmony_ci			ret = current_supply_uV;
36878c2ecf20Sopenharmony_ci			goto out;
36888c2ecf20Sopenharmony_ci		}
36898c2ecf20Sopenharmony_ci
36908c2ecf20Sopenharmony_ci		supply_change_uV = best_supply_uV - current_supply_uV;
36918c2ecf20Sopenharmony_ci	}
36928c2ecf20Sopenharmony_ci
36938c2ecf20Sopenharmony_ci	if (supply_change_uV > 0) {
36948c2ecf20Sopenharmony_ci		ret = regulator_set_voltage_unlocked(rdev->supply,
36958c2ecf20Sopenharmony_ci				best_supply_uV, INT_MAX, state);
36968c2ecf20Sopenharmony_ci		if (ret) {
36978c2ecf20Sopenharmony_ci			dev_err(&rdev->dev, "Failed to increase supply voltage: %pe\n",
36988c2ecf20Sopenharmony_ci				ERR_PTR(ret));
36998c2ecf20Sopenharmony_ci			goto out;
37008c2ecf20Sopenharmony_ci		}
37018c2ecf20Sopenharmony_ci	}
37028c2ecf20Sopenharmony_ci
37038c2ecf20Sopenharmony_ci	if (state == PM_SUSPEND_ON)
37048c2ecf20Sopenharmony_ci		ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
37058c2ecf20Sopenharmony_ci	else
37068c2ecf20Sopenharmony_ci		ret = _regulator_do_set_suspend_voltage(rdev, min_uV,
37078c2ecf20Sopenharmony_ci							max_uV, state);
37088c2ecf20Sopenharmony_ci	if (ret < 0)
37098c2ecf20Sopenharmony_ci		goto out;
37108c2ecf20Sopenharmony_ci
37118c2ecf20Sopenharmony_ci	if (supply_change_uV < 0) {
37128c2ecf20Sopenharmony_ci		ret = regulator_set_voltage_unlocked(rdev->supply,
37138c2ecf20Sopenharmony_ci				best_supply_uV, INT_MAX, state);
37148c2ecf20Sopenharmony_ci		if (ret)
37158c2ecf20Sopenharmony_ci			dev_warn(&rdev->dev, "Failed to decrease supply voltage: %pe\n",
37168c2ecf20Sopenharmony_ci				 ERR_PTR(ret));
37178c2ecf20Sopenharmony_ci		/* No need to fail here */
37188c2ecf20Sopenharmony_ci		ret = 0;
37198c2ecf20Sopenharmony_ci	}
37208c2ecf20Sopenharmony_ci
37218c2ecf20Sopenharmony_ciout:
37228c2ecf20Sopenharmony_ci	return ret;
37238c2ecf20Sopenharmony_ci}
37248c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_voltage_rdev);
37258c2ecf20Sopenharmony_ci
37268c2ecf20Sopenharmony_cistatic int regulator_limit_voltage_step(struct regulator_dev *rdev,
37278c2ecf20Sopenharmony_ci					int *current_uV, int *min_uV)
37288c2ecf20Sopenharmony_ci{
37298c2ecf20Sopenharmony_ci	struct regulation_constraints *constraints = rdev->constraints;
37308c2ecf20Sopenharmony_ci
37318c2ecf20Sopenharmony_ci	/* Limit voltage change only if necessary */
37328c2ecf20Sopenharmony_ci	if (!constraints->max_uV_step || !_regulator_is_enabled(rdev))
37338c2ecf20Sopenharmony_ci		return 1;
37348c2ecf20Sopenharmony_ci
37358c2ecf20Sopenharmony_ci	if (*current_uV < 0) {
37368c2ecf20Sopenharmony_ci		*current_uV = regulator_get_voltage_rdev(rdev);
37378c2ecf20Sopenharmony_ci
37388c2ecf20Sopenharmony_ci		if (*current_uV < 0)
37398c2ecf20Sopenharmony_ci			return *current_uV;
37408c2ecf20Sopenharmony_ci	}
37418c2ecf20Sopenharmony_ci
37428c2ecf20Sopenharmony_ci	if (abs(*current_uV - *min_uV) <= constraints->max_uV_step)
37438c2ecf20Sopenharmony_ci		return 1;
37448c2ecf20Sopenharmony_ci
37458c2ecf20Sopenharmony_ci	/* Clamp target voltage within the given step */
37468c2ecf20Sopenharmony_ci	if (*current_uV < *min_uV)
37478c2ecf20Sopenharmony_ci		*min_uV = min(*current_uV + constraints->max_uV_step,
37488c2ecf20Sopenharmony_ci			      *min_uV);
37498c2ecf20Sopenharmony_ci	else
37508c2ecf20Sopenharmony_ci		*min_uV = max(*current_uV - constraints->max_uV_step,
37518c2ecf20Sopenharmony_ci			      *min_uV);
37528c2ecf20Sopenharmony_ci
37538c2ecf20Sopenharmony_ci	return 0;
37548c2ecf20Sopenharmony_ci}
37558c2ecf20Sopenharmony_ci
37568c2ecf20Sopenharmony_cistatic int regulator_get_optimal_voltage(struct regulator_dev *rdev,
37578c2ecf20Sopenharmony_ci					 int *current_uV,
37588c2ecf20Sopenharmony_ci					 int *min_uV, int *max_uV,
37598c2ecf20Sopenharmony_ci					 suspend_state_t state,
37608c2ecf20Sopenharmony_ci					 int n_coupled)
37618c2ecf20Sopenharmony_ci{
37628c2ecf20Sopenharmony_ci	struct coupling_desc *c_desc = &rdev->coupling_desc;
37638c2ecf20Sopenharmony_ci	struct regulator_dev **c_rdevs = c_desc->coupled_rdevs;
37648c2ecf20Sopenharmony_ci	struct regulation_constraints *constraints = rdev->constraints;
37658c2ecf20Sopenharmony_ci	int desired_min_uV = 0, desired_max_uV = INT_MAX;
37668c2ecf20Sopenharmony_ci	int max_current_uV = 0, min_current_uV = INT_MAX;
37678c2ecf20Sopenharmony_ci	int highest_min_uV = 0, target_uV, possible_uV;
37688c2ecf20Sopenharmony_ci	int i, ret, max_spread;
37698c2ecf20Sopenharmony_ci	bool done;
37708c2ecf20Sopenharmony_ci
37718c2ecf20Sopenharmony_ci	*current_uV = -1;
37728c2ecf20Sopenharmony_ci
37738c2ecf20Sopenharmony_ci	/*
37748c2ecf20Sopenharmony_ci	 * If there are no coupled regulators, simply set the voltage
37758c2ecf20Sopenharmony_ci	 * demanded by consumers.
37768c2ecf20Sopenharmony_ci	 */
37778c2ecf20Sopenharmony_ci	if (n_coupled == 1) {
37788c2ecf20Sopenharmony_ci		/*
37798c2ecf20Sopenharmony_ci		 * If consumers don't provide any demands, set voltage
37808c2ecf20Sopenharmony_ci		 * to min_uV
37818c2ecf20Sopenharmony_ci		 */
37828c2ecf20Sopenharmony_ci		desired_min_uV = constraints->min_uV;
37838c2ecf20Sopenharmony_ci		desired_max_uV = constraints->max_uV;
37848c2ecf20Sopenharmony_ci
37858c2ecf20Sopenharmony_ci		ret = regulator_check_consumers(rdev,
37868c2ecf20Sopenharmony_ci						&desired_min_uV,
37878c2ecf20Sopenharmony_ci						&desired_max_uV, state);
37888c2ecf20Sopenharmony_ci		if (ret < 0)
37898c2ecf20Sopenharmony_ci			return ret;
37908c2ecf20Sopenharmony_ci
37918c2ecf20Sopenharmony_ci		possible_uV = desired_min_uV;
37928c2ecf20Sopenharmony_ci		done = true;
37938c2ecf20Sopenharmony_ci
37948c2ecf20Sopenharmony_ci		goto finish;
37958c2ecf20Sopenharmony_ci	}
37968c2ecf20Sopenharmony_ci
37978c2ecf20Sopenharmony_ci	/* Find highest min desired voltage */
37988c2ecf20Sopenharmony_ci	for (i = 0; i < n_coupled; i++) {
37998c2ecf20Sopenharmony_ci		int tmp_min = 0;
38008c2ecf20Sopenharmony_ci		int tmp_max = INT_MAX;
38018c2ecf20Sopenharmony_ci
38028c2ecf20Sopenharmony_ci		lockdep_assert_held_once(&c_rdevs[i]->mutex.base);
38038c2ecf20Sopenharmony_ci
38048c2ecf20Sopenharmony_ci		ret = regulator_check_consumers(c_rdevs[i],
38058c2ecf20Sopenharmony_ci						&tmp_min,
38068c2ecf20Sopenharmony_ci						&tmp_max, state);
38078c2ecf20Sopenharmony_ci		if (ret < 0)
38088c2ecf20Sopenharmony_ci			return ret;
38098c2ecf20Sopenharmony_ci
38108c2ecf20Sopenharmony_ci		ret = regulator_check_voltage(c_rdevs[i], &tmp_min, &tmp_max);
38118c2ecf20Sopenharmony_ci		if (ret < 0)
38128c2ecf20Sopenharmony_ci			return ret;
38138c2ecf20Sopenharmony_ci
38148c2ecf20Sopenharmony_ci		highest_min_uV = max(highest_min_uV, tmp_min);
38158c2ecf20Sopenharmony_ci
38168c2ecf20Sopenharmony_ci		if (i == 0) {
38178c2ecf20Sopenharmony_ci			desired_min_uV = tmp_min;
38188c2ecf20Sopenharmony_ci			desired_max_uV = tmp_max;
38198c2ecf20Sopenharmony_ci		}
38208c2ecf20Sopenharmony_ci	}
38218c2ecf20Sopenharmony_ci
38228c2ecf20Sopenharmony_ci	max_spread = constraints->max_spread[0];
38238c2ecf20Sopenharmony_ci
38248c2ecf20Sopenharmony_ci	/*
38258c2ecf20Sopenharmony_ci	 * Let target_uV be equal to the desired one if possible.
38268c2ecf20Sopenharmony_ci	 * If not, set it to minimum voltage, allowed by other coupled
38278c2ecf20Sopenharmony_ci	 * regulators.
38288c2ecf20Sopenharmony_ci	 */
38298c2ecf20Sopenharmony_ci	target_uV = max(desired_min_uV, highest_min_uV - max_spread);
38308c2ecf20Sopenharmony_ci
38318c2ecf20Sopenharmony_ci	/*
38328c2ecf20Sopenharmony_ci	 * Find min and max voltages, which currently aren't violating
38338c2ecf20Sopenharmony_ci	 * max_spread.
38348c2ecf20Sopenharmony_ci	 */
38358c2ecf20Sopenharmony_ci	for (i = 1; i < n_coupled; i++) {
38368c2ecf20Sopenharmony_ci		int tmp_act;
38378c2ecf20Sopenharmony_ci
38388c2ecf20Sopenharmony_ci		if (!_regulator_is_enabled(c_rdevs[i]))
38398c2ecf20Sopenharmony_ci			continue;
38408c2ecf20Sopenharmony_ci
38418c2ecf20Sopenharmony_ci		tmp_act = regulator_get_voltage_rdev(c_rdevs[i]);
38428c2ecf20Sopenharmony_ci		if (tmp_act < 0)
38438c2ecf20Sopenharmony_ci			return tmp_act;
38448c2ecf20Sopenharmony_ci
38458c2ecf20Sopenharmony_ci		min_current_uV = min(tmp_act, min_current_uV);
38468c2ecf20Sopenharmony_ci		max_current_uV = max(tmp_act, max_current_uV);
38478c2ecf20Sopenharmony_ci	}
38488c2ecf20Sopenharmony_ci
38498c2ecf20Sopenharmony_ci	/* There aren't any other regulators enabled */
38508c2ecf20Sopenharmony_ci	if (max_current_uV == 0) {
38518c2ecf20Sopenharmony_ci		possible_uV = target_uV;
38528c2ecf20Sopenharmony_ci	} else {
38538c2ecf20Sopenharmony_ci		/*
38548c2ecf20Sopenharmony_ci		 * Correct target voltage, so as it currently isn't
38558c2ecf20Sopenharmony_ci		 * violating max_spread
38568c2ecf20Sopenharmony_ci		 */
38578c2ecf20Sopenharmony_ci		possible_uV = max(target_uV, max_current_uV - max_spread);
38588c2ecf20Sopenharmony_ci		possible_uV = min(possible_uV, min_current_uV + max_spread);
38598c2ecf20Sopenharmony_ci	}
38608c2ecf20Sopenharmony_ci
38618c2ecf20Sopenharmony_ci	if (possible_uV > desired_max_uV)
38628c2ecf20Sopenharmony_ci		return -EINVAL;
38638c2ecf20Sopenharmony_ci
38648c2ecf20Sopenharmony_ci	done = (possible_uV == target_uV);
38658c2ecf20Sopenharmony_ci	desired_min_uV = possible_uV;
38668c2ecf20Sopenharmony_ci
38678c2ecf20Sopenharmony_cifinish:
38688c2ecf20Sopenharmony_ci	/* Apply max_uV_step constraint if necessary */
38698c2ecf20Sopenharmony_ci	if (state == PM_SUSPEND_ON) {
38708c2ecf20Sopenharmony_ci		ret = regulator_limit_voltage_step(rdev, current_uV,
38718c2ecf20Sopenharmony_ci						   &desired_min_uV);
38728c2ecf20Sopenharmony_ci		if (ret < 0)
38738c2ecf20Sopenharmony_ci			return ret;
38748c2ecf20Sopenharmony_ci
38758c2ecf20Sopenharmony_ci		if (ret == 0)
38768c2ecf20Sopenharmony_ci			done = false;
38778c2ecf20Sopenharmony_ci	}
38788c2ecf20Sopenharmony_ci
38798c2ecf20Sopenharmony_ci	/* Set current_uV if wasn't done earlier in the code and if necessary */
38808c2ecf20Sopenharmony_ci	if (n_coupled > 1 && *current_uV == -1) {
38818c2ecf20Sopenharmony_ci
38828c2ecf20Sopenharmony_ci		if (_regulator_is_enabled(rdev)) {
38838c2ecf20Sopenharmony_ci			ret = regulator_get_voltage_rdev(rdev);
38848c2ecf20Sopenharmony_ci			if (ret < 0)
38858c2ecf20Sopenharmony_ci				return ret;
38868c2ecf20Sopenharmony_ci
38878c2ecf20Sopenharmony_ci			*current_uV = ret;
38888c2ecf20Sopenharmony_ci		} else {
38898c2ecf20Sopenharmony_ci			*current_uV = desired_min_uV;
38908c2ecf20Sopenharmony_ci		}
38918c2ecf20Sopenharmony_ci	}
38928c2ecf20Sopenharmony_ci
38938c2ecf20Sopenharmony_ci	*min_uV = desired_min_uV;
38948c2ecf20Sopenharmony_ci	*max_uV = desired_max_uV;
38958c2ecf20Sopenharmony_ci
38968c2ecf20Sopenharmony_ci	return done;
38978c2ecf20Sopenharmony_ci}
38988c2ecf20Sopenharmony_ci
38998c2ecf20Sopenharmony_ciint regulator_do_balance_voltage(struct regulator_dev *rdev,
39008c2ecf20Sopenharmony_ci				 suspend_state_t state, bool skip_coupled)
39018c2ecf20Sopenharmony_ci{
39028c2ecf20Sopenharmony_ci	struct regulator_dev **c_rdevs;
39038c2ecf20Sopenharmony_ci	struct regulator_dev *best_rdev;
39048c2ecf20Sopenharmony_ci	struct coupling_desc *c_desc = &rdev->coupling_desc;
39058c2ecf20Sopenharmony_ci	int i, ret, n_coupled, best_min_uV, best_max_uV, best_c_rdev;
39068c2ecf20Sopenharmony_ci	unsigned int delta, best_delta;
39078c2ecf20Sopenharmony_ci	unsigned long c_rdev_done = 0;
39088c2ecf20Sopenharmony_ci	bool best_c_rdev_done;
39098c2ecf20Sopenharmony_ci
39108c2ecf20Sopenharmony_ci	c_rdevs = c_desc->coupled_rdevs;
39118c2ecf20Sopenharmony_ci	n_coupled = skip_coupled ? 1 : c_desc->n_coupled;
39128c2ecf20Sopenharmony_ci
39138c2ecf20Sopenharmony_ci	/*
39148c2ecf20Sopenharmony_ci	 * Find the best possible voltage change on each loop. Leave the loop
39158c2ecf20Sopenharmony_ci	 * if there isn't any possible change.
39168c2ecf20Sopenharmony_ci	 */
39178c2ecf20Sopenharmony_ci	do {
39188c2ecf20Sopenharmony_ci		best_c_rdev_done = false;
39198c2ecf20Sopenharmony_ci		best_delta = 0;
39208c2ecf20Sopenharmony_ci		best_min_uV = 0;
39218c2ecf20Sopenharmony_ci		best_max_uV = 0;
39228c2ecf20Sopenharmony_ci		best_c_rdev = 0;
39238c2ecf20Sopenharmony_ci		best_rdev = NULL;
39248c2ecf20Sopenharmony_ci
39258c2ecf20Sopenharmony_ci		/*
39268c2ecf20Sopenharmony_ci		 * Find highest difference between optimal voltage
39278c2ecf20Sopenharmony_ci		 * and current voltage.
39288c2ecf20Sopenharmony_ci		 */
39298c2ecf20Sopenharmony_ci		for (i = 0; i < n_coupled; i++) {
39308c2ecf20Sopenharmony_ci			/*
39318c2ecf20Sopenharmony_ci			 * optimal_uV is the best voltage that can be set for
39328c2ecf20Sopenharmony_ci			 * i-th regulator at the moment without violating
39338c2ecf20Sopenharmony_ci			 * max_spread constraint in order to balance
39348c2ecf20Sopenharmony_ci			 * the coupled voltages.
39358c2ecf20Sopenharmony_ci			 */
39368c2ecf20Sopenharmony_ci			int optimal_uV = 0, optimal_max_uV = 0, current_uV = 0;
39378c2ecf20Sopenharmony_ci
39388c2ecf20Sopenharmony_ci			if (test_bit(i, &c_rdev_done))
39398c2ecf20Sopenharmony_ci				continue;
39408c2ecf20Sopenharmony_ci
39418c2ecf20Sopenharmony_ci			ret = regulator_get_optimal_voltage(c_rdevs[i],
39428c2ecf20Sopenharmony_ci							    &current_uV,
39438c2ecf20Sopenharmony_ci							    &optimal_uV,
39448c2ecf20Sopenharmony_ci							    &optimal_max_uV,
39458c2ecf20Sopenharmony_ci							    state, n_coupled);
39468c2ecf20Sopenharmony_ci			if (ret < 0)
39478c2ecf20Sopenharmony_ci				goto out;
39488c2ecf20Sopenharmony_ci
39498c2ecf20Sopenharmony_ci			delta = abs(optimal_uV - current_uV);
39508c2ecf20Sopenharmony_ci
39518c2ecf20Sopenharmony_ci			if (delta && best_delta <= delta) {
39528c2ecf20Sopenharmony_ci				best_c_rdev_done = ret;
39538c2ecf20Sopenharmony_ci				best_delta = delta;
39548c2ecf20Sopenharmony_ci				best_rdev = c_rdevs[i];
39558c2ecf20Sopenharmony_ci				best_min_uV = optimal_uV;
39568c2ecf20Sopenharmony_ci				best_max_uV = optimal_max_uV;
39578c2ecf20Sopenharmony_ci				best_c_rdev = i;
39588c2ecf20Sopenharmony_ci			}
39598c2ecf20Sopenharmony_ci		}
39608c2ecf20Sopenharmony_ci
39618c2ecf20Sopenharmony_ci		/* Nothing to change, return successfully */
39628c2ecf20Sopenharmony_ci		if (!best_rdev) {
39638c2ecf20Sopenharmony_ci			ret = 0;
39648c2ecf20Sopenharmony_ci			goto out;
39658c2ecf20Sopenharmony_ci		}
39668c2ecf20Sopenharmony_ci
39678c2ecf20Sopenharmony_ci		ret = regulator_set_voltage_rdev(best_rdev, best_min_uV,
39688c2ecf20Sopenharmony_ci						 best_max_uV, state);
39698c2ecf20Sopenharmony_ci
39708c2ecf20Sopenharmony_ci		if (ret < 0)
39718c2ecf20Sopenharmony_ci			goto out;
39728c2ecf20Sopenharmony_ci
39738c2ecf20Sopenharmony_ci		if (best_c_rdev_done)
39748c2ecf20Sopenharmony_ci			set_bit(best_c_rdev, &c_rdev_done);
39758c2ecf20Sopenharmony_ci
39768c2ecf20Sopenharmony_ci	} while (n_coupled > 1);
39778c2ecf20Sopenharmony_ci
39788c2ecf20Sopenharmony_ciout:
39798c2ecf20Sopenharmony_ci	return ret;
39808c2ecf20Sopenharmony_ci}
39818c2ecf20Sopenharmony_ci
39828c2ecf20Sopenharmony_cistatic int regulator_balance_voltage(struct regulator_dev *rdev,
39838c2ecf20Sopenharmony_ci				     suspend_state_t state)
39848c2ecf20Sopenharmony_ci{
39858c2ecf20Sopenharmony_ci	struct coupling_desc *c_desc = &rdev->coupling_desc;
39868c2ecf20Sopenharmony_ci	struct regulator_coupler *coupler = c_desc->coupler;
39878c2ecf20Sopenharmony_ci	bool skip_coupled = false;
39888c2ecf20Sopenharmony_ci
39898c2ecf20Sopenharmony_ci	/*
39908c2ecf20Sopenharmony_ci	 * If system is in a state other than PM_SUSPEND_ON, don't check
39918c2ecf20Sopenharmony_ci	 * other coupled regulators.
39928c2ecf20Sopenharmony_ci	 */
39938c2ecf20Sopenharmony_ci	if (state != PM_SUSPEND_ON)
39948c2ecf20Sopenharmony_ci		skip_coupled = true;
39958c2ecf20Sopenharmony_ci
39968c2ecf20Sopenharmony_ci	if (c_desc->n_resolved < c_desc->n_coupled) {
39978c2ecf20Sopenharmony_ci		rdev_err(rdev, "Not all coupled regulators registered\n");
39988c2ecf20Sopenharmony_ci		return -EPERM;
39998c2ecf20Sopenharmony_ci	}
40008c2ecf20Sopenharmony_ci
40018c2ecf20Sopenharmony_ci	/* Invoke custom balancer for customized couplers */
40028c2ecf20Sopenharmony_ci	if (coupler && coupler->balance_voltage)
40038c2ecf20Sopenharmony_ci		return coupler->balance_voltage(coupler, rdev, state);
40048c2ecf20Sopenharmony_ci
40058c2ecf20Sopenharmony_ci	return regulator_do_balance_voltage(rdev, state, skip_coupled);
40068c2ecf20Sopenharmony_ci}
40078c2ecf20Sopenharmony_ci
40088c2ecf20Sopenharmony_ci/**
40098c2ecf20Sopenharmony_ci * regulator_set_voltage - set regulator output voltage
40108c2ecf20Sopenharmony_ci * @regulator: regulator source
40118c2ecf20Sopenharmony_ci * @min_uV: Minimum required voltage in uV
40128c2ecf20Sopenharmony_ci * @max_uV: Maximum acceptable voltage in uV
40138c2ecf20Sopenharmony_ci *
40148c2ecf20Sopenharmony_ci * Sets a voltage regulator to the desired output voltage. This can be set
40158c2ecf20Sopenharmony_ci * during any regulator state. IOW, regulator can be disabled or enabled.
40168c2ecf20Sopenharmony_ci *
40178c2ecf20Sopenharmony_ci * If the regulator is enabled then the voltage will change to the new value
40188c2ecf20Sopenharmony_ci * immediately otherwise if the regulator is disabled the regulator will
40198c2ecf20Sopenharmony_ci * output at the new voltage when enabled.
40208c2ecf20Sopenharmony_ci *
40218c2ecf20Sopenharmony_ci * NOTE: If the regulator is shared between several devices then the lowest
40228c2ecf20Sopenharmony_ci * request voltage that meets the system constraints will be used.
40238c2ecf20Sopenharmony_ci * Regulator system constraints must be set for this regulator before
40248c2ecf20Sopenharmony_ci * calling this function otherwise this call will fail.
40258c2ecf20Sopenharmony_ci */
40268c2ecf20Sopenharmony_ciint regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
40278c2ecf20Sopenharmony_ci{
40288c2ecf20Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
40298c2ecf20Sopenharmony_ci	int ret;
40308c2ecf20Sopenharmony_ci
40318c2ecf20Sopenharmony_ci	regulator_lock_dependent(regulator->rdev, &ww_ctx);
40328c2ecf20Sopenharmony_ci
40338c2ecf20Sopenharmony_ci	ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV,
40348c2ecf20Sopenharmony_ci					     PM_SUSPEND_ON);
40358c2ecf20Sopenharmony_ci
40368c2ecf20Sopenharmony_ci	regulator_unlock_dependent(regulator->rdev, &ww_ctx);
40378c2ecf20Sopenharmony_ci
40388c2ecf20Sopenharmony_ci	return ret;
40398c2ecf20Sopenharmony_ci}
40408c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_voltage);
40418c2ecf20Sopenharmony_ci
40428c2ecf20Sopenharmony_cistatic inline int regulator_suspend_toggle(struct regulator_dev *rdev,
40438c2ecf20Sopenharmony_ci					   suspend_state_t state, bool en)
40448c2ecf20Sopenharmony_ci{
40458c2ecf20Sopenharmony_ci	struct regulator_state *rstate;
40468c2ecf20Sopenharmony_ci
40478c2ecf20Sopenharmony_ci	rstate = regulator_get_suspend_state(rdev, state);
40488c2ecf20Sopenharmony_ci	if (rstate == NULL)
40498c2ecf20Sopenharmony_ci		return -EINVAL;
40508c2ecf20Sopenharmony_ci
40518c2ecf20Sopenharmony_ci	if (!rstate->changeable)
40528c2ecf20Sopenharmony_ci		return -EPERM;
40538c2ecf20Sopenharmony_ci
40548c2ecf20Sopenharmony_ci	rstate->enabled = (en) ? ENABLE_IN_SUSPEND : DISABLE_IN_SUSPEND;
40558c2ecf20Sopenharmony_ci
40568c2ecf20Sopenharmony_ci	return 0;
40578c2ecf20Sopenharmony_ci}
40588c2ecf20Sopenharmony_ci
40598c2ecf20Sopenharmony_ciint regulator_suspend_enable(struct regulator_dev *rdev,
40608c2ecf20Sopenharmony_ci				    suspend_state_t state)
40618c2ecf20Sopenharmony_ci{
40628c2ecf20Sopenharmony_ci	return regulator_suspend_toggle(rdev, state, true);
40638c2ecf20Sopenharmony_ci}
40648c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_suspend_enable);
40658c2ecf20Sopenharmony_ci
40668c2ecf20Sopenharmony_ciint regulator_suspend_disable(struct regulator_dev *rdev,
40678c2ecf20Sopenharmony_ci				     suspend_state_t state)
40688c2ecf20Sopenharmony_ci{
40698c2ecf20Sopenharmony_ci	struct regulator *regulator;
40708c2ecf20Sopenharmony_ci	struct regulator_voltage *voltage;
40718c2ecf20Sopenharmony_ci
40728c2ecf20Sopenharmony_ci	/*
40738c2ecf20Sopenharmony_ci	 * if any consumer wants this regulator device keeping on in
40748c2ecf20Sopenharmony_ci	 * suspend states, don't set it as disabled.
40758c2ecf20Sopenharmony_ci	 */
40768c2ecf20Sopenharmony_ci	list_for_each_entry(regulator, &rdev->consumer_list, list) {
40778c2ecf20Sopenharmony_ci		voltage = &regulator->voltage[state];
40788c2ecf20Sopenharmony_ci		if (voltage->min_uV || voltage->max_uV)
40798c2ecf20Sopenharmony_ci			return 0;
40808c2ecf20Sopenharmony_ci	}
40818c2ecf20Sopenharmony_ci
40828c2ecf20Sopenharmony_ci	return regulator_suspend_toggle(rdev, state, false);
40838c2ecf20Sopenharmony_ci}
40848c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_suspend_disable);
40858c2ecf20Sopenharmony_ci
40868c2ecf20Sopenharmony_cistatic int _regulator_set_suspend_voltage(struct regulator *regulator,
40878c2ecf20Sopenharmony_ci					  int min_uV, int max_uV,
40888c2ecf20Sopenharmony_ci					  suspend_state_t state)
40898c2ecf20Sopenharmony_ci{
40908c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
40918c2ecf20Sopenharmony_ci	struct regulator_state *rstate;
40928c2ecf20Sopenharmony_ci
40938c2ecf20Sopenharmony_ci	rstate = regulator_get_suspend_state(rdev, state);
40948c2ecf20Sopenharmony_ci	if (rstate == NULL)
40958c2ecf20Sopenharmony_ci		return -EINVAL;
40968c2ecf20Sopenharmony_ci
40978c2ecf20Sopenharmony_ci	if (rstate->min_uV == rstate->max_uV) {
40988c2ecf20Sopenharmony_ci		rdev_err(rdev, "The suspend voltage can't be changed!\n");
40998c2ecf20Sopenharmony_ci		return -EPERM;
41008c2ecf20Sopenharmony_ci	}
41018c2ecf20Sopenharmony_ci
41028c2ecf20Sopenharmony_ci	return regulator_set_voltage_unlocked(regulator, min_uV, max_uV, state);
41038c2ecf20Sopenharmony_ci}
41048c2ecf20Sopenharmony_ci
41058c2ecf20Sopenharmony_ciint regulator_set_suspend_voltage(struct regulator *regulator, int min_uV,
41068c2ecf20Sopenharmony_ci				  int max_uV, suspend_state_t state)
41078c2ecf20Sopenharmony_ci{
41088c2ecf20Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
41098c2ecf20Sopenharmony_ci	int ret;
41108c2ecf20Sopenharmony_ci
41118c2ecf20Sopenharmony_ci	/* PM_SUSPEND_ON is handled by regulator_set_voltage() */
41128c2ecf20Sopenharmony_ci	if (regulator_check_states(state) || state == PM_SUSPEND_ON)
41138c2ecf20Sopenharmony_ci		return -EINVAL;
41148c2ecf20Sopenharmony_ci
41158c2ecf20Sopenharmony_ci	regulator_lock_dependent(regulator->rdev, &ww_ctx);
41168c2ecf20Sopenharmony_ci
41178c2ecf20Sopenharmony_ci	ret = _regulator_set_suspend_voltage(regulator, min_uV,
41188c2ecf20Sopenharmony_ci					     max_uV, state);
41198c2ecf20Sopenharmony_ci
41208c2ecf20Sopenharmony_ci	regulator_unlock_dependent(regulator->rdev, &ww_ctx);
41218c2ecf20Sopenharmony_ci
41228c2ecf20Sopenharmony_ci	return ret;
41238c2ecf20Sopenharmony_ci}
41248c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_suspend_voltage);
41258c2ecf20Sopenharmony_ci
41268c2ecf20Sopenharmony_ci/**
41278c2ecf20Sopenharmony_ci * regulator_set_voltage_time - get raise/fall time
41288c2ecf20Sopenharmony_ci * @regulator: regulator source
41298c2ecf20Sopenharmony_ci * @old_uV: starting voltage in microvolts
41308c2ecf20Sopenharmony_ci * @new_uV: target voltage in microvolts
41318c2ecf20Sopenharmony_ci *
41328c2ecf20Sopenharmony_ci * Provided with the starting and ending voltage, this function attempts to
41338c2ecf20Sopenharmony_ci * calculate the time in microseconds required to rise or fall to this new
41348c2ecf20Sopenharmony_ci * voltage.
41358c2ecf20Sopenharmony_ci */
41368c2ecf20Sopenharmony_ciint regulator_set_voltage_time(struct regulator *regulator,
41378c2ecf20Sopenharmony_ci			       int old_uV, int new_uV)
41388c2ecf20Sopenharmony_ci{
41398c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
41408c2ecf20Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
41418c2ecf20Sopenharmony_ci	int old_sel = -1;
41428c2ecf20Sopenharmony_ci	int new_sel = -1;
41438c2ecf20Sopenharmony_ci	int voltage;
41448c2ecf20Sopenharmony_ci	int i;
41458c2ecf20Sopenharmony_ci
41468c2ecf20Sopenharmony_ci	if (ops->set_voltage_time)
41478c2ecf20Sopenharmony_ci		return ops->set_voltage_time(rdev, old_uV, new_uV);
41488c2ecf20Sopenharmony_ci	else if (!ops->set_voltage_time_sel)
41498c2ecf20Sopenharmony_ci		return _regulator_set_voltage_time(rdev, old_uV, new_uV);
41508c2ecf20Sopenharmony_ci
41518c2ecf20Sopenharmony_ci	/* Currently requires operations to do this */
41528c2ecf20Sopenharmony_ci	if (!ops->list_voltage || !rdev->desc->n_voltages)
41538c2ecf20Sopenharmony_ci		return -EINVAL;
41548c2ecf20Sopenharmony_ci
41558c2ecf20Sopenharmony_ci	for (i = 0; i < rdev->desc->n_voltages; i++) {
41568c2ecf20Sopenharmony_ci		/* We only look for exact voltage matches here */
41578c2ecf20Sopenharmony_ci
41588c2ecf20Sopenharmony_ci		if (old_sel >= 0 && new_sel >= 0)
41598c2ecf20Sopenharmony_ci			break;
41608c2ecf20Sopenharmony_ci
41618c2ecf20Sopenharmony_ci		voltage = regulator_list_voltage(regulator, i);
41628c2ecf20Sopenharmony_ci		if (voltage < 0)
41638c2ecf20Sopenharmony_ci			return -EINVAL;
41648c2ecf20Sopenharmony_ci		if (voltage == 0)
41658c2ecf20Sopenharmony_ci			continue;
41668c2ecf20Sopenharmony_ci		if (voltage == old_uV)
41678c2ecf20Sopenharmony_ci			old_sel = i;
41688c2ecf20Sopenharmony_ci		if (voltage == new_uV)
41698c2ecf20Sopenharmony_ci			new_sel = i;
41708c2ecf20Sopenharmony_ci	}
41718c2ecf20Sopenharmony_ci
41728c2ecf20Sopenharmony_ci	if (old_sel < 0 || new_sel < 0)
41738c2ecf20Sopenharmony_ci		return -EINVAL;
41748c2ecf20Sopenharmony_ci
41758c2ecf20Sopenharmony_ci	return ops->set_voltage_time_sel(rdev, old_sel, new_sel);
41768c2ecf20Sopenharmony_ci}
41778c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_voltage_time);
41788c2ecf20Sopenharmony_ci
41798c2ecf20Sopenharmony_ci/**
41808c2ecf20Sopenharmony_ci * regulator_set_voltage_time_sel - get raise/fall time
41818c2ecf20Sopenharmony_ci * @rdev: regulator source device
41828c2ecf20Sopenharmony_ci * @old_selector: selector for starting voltage
41838c2ecf20Sopenharmony_ci * @new_selector: selector for target voltage
41848c2ecf20Sopenharmony_ci *
41858c2ecf20Sopenharmony_ci * Provided with the starting and target voltage selectors, this function
41868c2ecf20Sopenharmony_ci * returns time in microseconds required to rise or fall to this new voltage
41878c2ecf20Sopenharmony_ci *
41888c2ecf20Sopenharmony_ci * Drivers providing ramp_delay in regulation_constraints can use this as their
41898c2ecf20Sopenharmony_ci * set_voltage_time_sel() operation.
41908c2ecf20Sopenharmony_ci */
41918c2ecf20Sopenharmony_ciint regulator_set_voltage_time_sel(struct regulator_dev *rdev,
41928c2ecf20Sopenharmony_ci				   unsigned int old_selector,
41938c2ecf20Sopenharmony_ci				   unsigned int new_selector)
41948c2ecf20Sopenharmony_ci{
41958c2ecf20Sopenharmony_ci	int old_volt, new_volt;
41968c2ecf20Sopenharmony_ci
41978c2ecf20Sopenharmony_ci	/* sanity check */
41988c2ecf20Sopenharmony_ci	if (!rdev->desc->ops->list_voltage)
41998c2ecf20Sopenharmony_ci		return -EINVAL;
42008c2ecf20Sopenharmony_ci
42018c2ecf20Sopenharmony_ci	old_volt = rdev->desc->ops->list_voltage(rdev, old_selector);
42028c2ecf20Sopenharmony_ci	new_volt = rdev->desc->ops->list_voltage(rdev, new_selector);
42038c2ecf20Sopenharmony_ci
42048c2ecf20Sopenharmony_ci	if (rdev->desc->ops->set_voltage_time)
42058c2ecf20Sopenharmony_ci		return rdev->desc->ops->set_voltage_time(rdev, old_volt,
42068c2ecf20Sopenharmony_ci							 new_volt);
42078c2ecf20Sopenharmony_ci	else
42088c2ecf20Sopenharmony_ci		return _regulator_set_voltage_time(rdev, old_volt, new_volt);
42098c2ecf20Sopenharmony_ci}
42108c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel);
42118c2ecf20Sopenharmony_ci
42128c2ecf20Sopenharmony_ci/**
42138c2ecf20Sopenharmony_ci * regulator_sync_voltage - re-apply last regulator output voltage
42148c2ecf20Sopenharmony_ci * @regulator: regulator source
42158c2ecf20Sopenharmony_ci *
42168c2ecf20Sopenharmony_ci * Re-apply the last configured voltage.  This is intended to be used
42178c2ecf20Sopenharmony_ci * where some external control source the consumer is cooperating with
42188c2ecf20Sopenharmony_ci * has caused the configured voltage to change.
42198c2ecf20Sopenharmony_ci */
42208c2ecf20Sopenharmony_ciint regulator_sync_voltage(struct regulator *regulator)
42218c2ecf20Sopenharmony_ci{
42228c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
42238c2ecf20Sopenharmony_ci	struct regulator_voltage *voltage = &regulator->voltage[PM_SUSPEND_ON];
42248c2ecf20Sopenharmony_ci	int ret, min_uV, max_uV;
42258c2ecf20Sopenharmony_ci
42268c2ecf20Sopenharmony_ci	regulator_lock(rdev);
42278c2ecf20Sopenharmony_ci
42288c2ecf20Sopenharmony_ci	if (!rdev->desc->ops->set_voltage &&
42298c2ecf20Sopenharmony_ci	    !rdev->desc->ops->set_voltage_sel) {
42308c2ecf20Sopenharmony_ci		ret = -EINVAL;
42318c2ecf20Sopenharmony_ci		goto out;
42328c2ecf20Sopenharmony_ci	}
42338c2ecf20Sopenharmony_ci
42348c2ecf20Sopenharmony_ci	/* This is only going to work if we've had a voltage configured. */
42358c2ecf20Sopenharmony_ci	if (!voltage->min_uV && !voltage->max_uV) {
42368c2ecf20Sopenharmony_ci		ret = -EINVAL;
42378c2ecf20Sopenharmony_ci		goto out;
42388c2ecf20Sopenharmony_ci	}
42398c2ecf20Sopenharmony_ci
42408c2ecf20Sopenharmony_ci	min_uV = voltage->min_uV;
42418c2ecf20Sopenharmony_ci	max_uV = voltage->max_uV;
42428c2ecf20Sopenharmony_ci
42438c2ecf20Sopenharmony_ci	/* This should be a paranoia check... */
42448c2ecf20Sopenharmony_ci	ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
42458c2ecf20Sopenharmony_ci	if (ret < 0)
42468c2ecf20Sopenharmony_ci		goto out;
42478c2ecf20Sopenharmony_ci
42488c2ecf20Sopenharmony_ci	ret = regulator_check_consumers(rdev, &min_uV, &max_uV, 0);
42498c2ecf20Sopenharmony_ci	if (ret < 0)
42508c2ecf20Sopenharmony_ci		goto out;
42518c2ecf20Sopenharmony_ci
42528c2ecf20Sopenharmony_ci	ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
42538c2ecf20Sopenharmony_ci
42548c2ecf20Sopenharmony_ciout:
42558c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
42568c2ecf20Sopenharmony_ci	return ret;
42578c2ecf20Sopenharmony_ci}
42588c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_sync_voltage);
42598c2ecf20Sopenharmony_ci
42608c2ecf20Sopenharmony_ciint regulator_get_voltage_rdev(struct regulator_dev *rdev)
42618c2ecf20Sopenharmony_ci{
42628c2ecf20Sopenharmony_ci	int sel, ret;
42638c2ecf20Sopenharmony_ci	bool bypassed;
42648c2ecf20Sopenharmony_ci
42658c2ecf20Sopenharmony_ci	if (rdev->desc->ops->get_bypass) {
42668c2ecf20Sopenharmony_ci		ret = rdev->desc->ops->get_bypass(rdev, &bypassed);
42678c2ecf20Sopenharmony_ci		if (ret < 0)
42688c2ecf20Sopenharmony_ci			return ret;
42698c2ecf20Sopenharmony_ci		if (bypassed) {
42708c2ecf20Sopenharmony_ci			/* if bypassed the regulator must have a supply */
42718c2ecf20Sopenharmony_ci			if (!rdev->supply) {
42728c2ecf20Sopenharmony_ci				rdev_err(rdev,
42738c2ecf20Sopenharmony_ci					 "bypassed regulator has no supply!\n");
42748c2ecf20Sopenharmony_ci				return -EPROBE_DEFER;
42758c2ecf20Sopenharmony_ci			}
42768c2ecf20Sopenharmony_ci
42778c2ecf20Sopenharmony_ci			return regulator_get_voltage_rdev(rdev->supply->rdev);
42788c2ecf20Sopenharmony_ci		}
42798c2ecf20Sopenharmony_ci	}
42808c2ecf20Sopenharmony_ci
42818c2ecf20Sopenharmony_ci	if (rdev->desc->ops->get_voltage_sel) {
42828c2ecf20Sopenharmony_ci		sel = rdev->desc->ops->get_voltage_sel(rdev);
42838c2ecf20Sopenharmony_ci		if (sel < 0)
42848c2ecf20Sopenharmony_ci			return sel;
42858c2ecf20Sopenharmony_ci		ret = rdev->desc->ops->list_voltage(rdev, sel);
42868c2ecf20Sopenharmony_ci	} else if (rdev->desc->ops->get_voltage) {
42878c2ecf20Sopenharmony_ci		ret = rdev->desc->ops->get_voltage(rdev);
42888c2ecf20Sopenharmony_ci	} else if (rdev->desc->ops->list_voltage) {
42898c2ecf20Sopenharmony_ci		ret = rdev->desc->ops->list_voltage(rdev, 0);
42908c2ecf20Sopenharmony_ci	} else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) {
42918c2ecf20Sopenharmony_ci		ret = rdev->desc->fixed_uV;
42928c2ecf20Sopenharmony_ci	} else if (rdev->supply) {
42938c2ecf20Sopenharmony_ci		ret = regulator_get_voltage_rdev(rdev->supply->rdev);
42948c2ecf20Sopenharmony_ci	} else if (rdev->supply_name) {
42958c2ecf20Sopenharmony_ci		return -EPROBE_DEFER;
42968c2ecf20Sopenharmony_ci	} else {
42978c2ecf20Sopenharmony_ci		return -EINVAL;
42988c2ecf20Sopenharmony_ci	}
42998c2ecf20Sopenharmony_ci
43008c2ecf20Sopenharmony_ci	if (ret < 0)
43018c2ecf20Sopenharmony_ci		return ret;
43028c2ecf20Sopenharmony_ci	return ret - rdev->constraints->uV_offset;
43038c2ecf20Sopenharmony_ci}
43048c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_voltage_rdev);
43058c2ecf20Sopenharmony_ci
43068c2ecf20Sopenharmony_ci/**
43078c2ecf20Sopenharmony_ci * regulator_get_voltage - get regulator output voltage
43088c2ecf20Sopenharmony_ci * @regulator: regulator source
43098c2ecf20Sopenharmony_ci *
43108c2ecf20Sopenharmony_ci * This returns the current regulator voltage in uV.
43118c2ecf20Sopenharmony_ci *
43128c2ecf20Sopenharmony_ci * NOTE: If the regulator is disabled it will return the voltage value. This
43138c2ecf20Sopenharmony_ci * function should not be used to determine regulator state.
43148c2ecf20Sopenharmony_ci */
43158c2ecf20Sopenharmony_ciint regulator_get_voltage(struct regulator *regulator)
43168c2ecf20Sopenharmony_ci{
43178c2ecf20Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
43188c2ecf20Sopenharmony_ci	int ret;
43198c2ecf20Sopenharmony_ci
43208c2ecf20Sopenharmony_ci	regulator_lock_dependent(regulator->rdev, &ww_ctx);
43218c2ecf20Sopenharmony_ci	ret = regulator_get_voltage_rdev(regulator->rdev);
43228c2ecf20Sopenharmony_ci	regulator_unlock_dependent(regulator->rdev, &ww_ctx);
43238c2ecf20Sopenharmony_ci
43248c2ecf20Sopenharmony_ci	return ret;
43258c2ecf20Sopenharmony_ci}
43268c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_voltage);
43278c2ecf20Sopenharmony_ci
43288c2ecf20Sopenharmony_ci/**
43298c2ecf20Sopenharmony_ci * regulator_set_current_limit - set regulator output current limit
43308c2ecf20Sopenharmony_ci * @regulator: regulator source
43318c2ecf20Sopenharmony_ci * @min_uA: Minimum supported current in uA
43328c2ecf20Sopenharmony_ci * @max_uA: Maximum supported current in uA
43338c2ecf20Sopenharmony_ci *
43348c2ecf20Sopenharmony_ci * Sets current sink to the desired output current. This can be set during
43358c2ecf20Sopenharmony_ci * any regulator state. IOW, regulator can be disabled or enabled.
43368c2ecf20Sopenharmony_ci *
43378c2ecf20Sopenharmony_ci * If the regulator is enabled then the current will change to the new value
43388c2ecf20Sopenharmony_ci * immediately otherwise if the regulator is disabled the regulator will
43398c2ecf20Sopenharmony_ci * output at the new current when enabled.
43408c2ecf20Sopenharmony_ci *
43418c2ecf20Sopenharmony_ci * NOTE: Regulator system constraints must be set for this regulator before
43428c2ecf20Sopenharmony_ci * calling this function otherwise this call will fail.
43438c2ecf20Sopenharmony_ci */
43448c2ecf20Sopenharmony_ciint regulator_set_current_limit(struct regulator *regulator,
43458c2ecf20Sopenharmony_ci			       int min_uA, int max_uA)
43468c2ecf20Sopenharmony_ci{
43478c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
43488c2ecf20Sopenharmony_ci	int ret;
43498c2ecf20Sopenharmony_ci
43508c2ecf20Sopenharmony_ci	regulator_lock(rdev);
43518c2ecf20Sopenharmony_ci
43528c2ecf20Sopenharmony_ci	/* sanity check */
43538c2ecf20Sopenharmony_ci	if (!rdev->desc->ops->set_current_limit) {
43548c2ecf20Sopenharmony_ci		ret = -EINVAL;
43558c2ecf20Sopenharmony_ci		goto out;
43568c2ecf20Sopenharmony_ci	}
43578c2ecf20Sopenharmony_ci
43588c2ecf20Sopenharmony_ci	/* constraints check */
43598c2ecf20Sopenharmony_ci	ret = regulator_check_current_limit(rdev, &min_uA, &max_uA);
43608c2ecf20Sopenharmony_ci	if (ret < 0)
43618c2ecf20Sopenharmony_ci		goto out;
43628c2ecf20Sopenharmony_ci
43638c2ecf20Sopenharmony_ci	ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA);
43648c2ecf20Sopenharmony_ciout:
43658c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
43668c2ecf20Sopenharmony_ci	return ret;
43678c2ecf20Sopenharmony_ci}
43688c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_current_limit);
43698c2ecf20Sopenharmony_ci
43708c2ecf20Sopenharmony_cistatic int _regulator_get_current_limit_unlocked(struct regulator_dev *rdev)
43718c2ecf20Sopenharmony_ci{
43728c2ecf20Sopenharmony_ci	/* sanity check */
43738c2ecf20Sopenharmony_ci	if (!rdev->desc->ops->get_current_limit)
43748c2ecf20Sopenharmony_ci		return -EINVAL;
43758c2ecf20Sopenharmony_ci
43768c2ecf20Sopenharmony_ci	return rdev->desc->ops->get_current_limit(rdev);
43778c2ecf20Sopenharmony_ci}
43788c2ecf20Sopenharmony_ci
43798c2ecf20Sopenharmony_cistatic int _regulator_get_current_limit(struct regulator_dev *rdev)
43808c2ecf20Sopenharmony_ci{
43818c2ecf20Sopenharmony_ci	int ret;
43828c2ecf20Sopenharmony_ci
43838c2ecf20Sopenharmony_ci	regulator_lock(rdev);
43848c2ecf20Sopenharmony_ci	ret = _regulator_get_current_limit_unlocked(rdev);
43858c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
43868c2ecf20Sopenharmony_ci
43878c2ecf20Sopenharmony_ci	return ret;
43888c2ecf20Sopenharmony_ci}
43898c2ecf20Sopenharmony_ci
43908c2ecf20Sopenharmony_ci/**
43918c2ecf20Sopenharmony_ci * regulator_get_current_limit - get regulator output current
43928c2ecf20Sopenharmony_ci * @regulator: regulator source
43938c2ecf20Sopenharmony_ci *
43948c2ecf20Sopenharmony_ci * This returns the current supplied by the specified current sink in uA.
43958c2ecf20Sopenharmony_ci *
43968c2ecf20Sopenharmony_ci * NOTE: If the regulator is disabled it will return the current value. This
43978c2ecf20Sopenharmony_ci * function should not be used to determine regulator state.
43988c2ecf20Sopenharmony_ci */
43998c2ecf20Sopenharmony_ciint regulator_get_current_limit(struct regulator *regulator)
44008c2ecf20Sopenharmony_ci{
44018c2ecf20Sopenharmony_ci	return _regulator_get_current_limit(regulator->rdev);
44028c2ecf20Sopenharmony_ci}
44038c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_current_limit);
44048c2ecf20Sopenharmony_ci
44058c2ecf20Sopenharmony_ci/**
44068c2ecf20Sopenharmony_ci * regulator_set_mode - set regulator operating mode
44078c2ecf20Sopenharmony_ci * @regulator: regulator source
44088c2ecf20Sopenharmony_ci * @mode: operating mode - one of the REGULATOR_MODE constants
44098c2ecf20Sopenharmony_ci *
44108c2ecf20Sopenharmony_ci * Set regulator operating mode to increase regulator efficiency or improve
44118c2ecf20Sopenharmony_ci * regulation performance.
44128c2ecf20Sopenharmony_ci *
44138c2ecf20Sopenharmony_ci * NOTE: Regulator system constraints must be set for this regulator before
44148c2ecf20Sopenharmony_ci * calling this function otherwise this call will fail.
44158c2ecf20Sopenharmony_ci */
44168c2ecf20Sopenharmony_ciint regulator_set_mode(struct regulator *regulator, unsigned int mode)
44178c2ecf20Sopenharmony_ci{
44188c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
44198c2ecf20Sopenharmony_ci	int ret;
44208c2ecf20Sopenharmony_ci	int regulator_curr_mode;
44218c2ecf20Sopenharmony_ci
44228c2ecf20Sopenharmony_ci	regulator_lock(rdev);
44238c2ecf20Sopenharmony_ci
44248c2ecf20Sopenharmony_ci	/* sanity check */
44258c2ecf20Sopenharmony_ci	if (!rdev->desc->ops->set_mode) {
44268c2ecf20Sopenharmony_ci		ret = -EINVAL;
44278c2ecf20Sopenharmony_ci		goto out;
44288c2ecf20Sopenharmony_ci	}
44298c2ecf20Sopenharmony_ci
44308c2ecf20Sopenharmony_ci	/* return if the same mode is requested */
44318c2ecf20Sopenharmony_ci	if (rdev->desc->ops->get_mode) {
44328c2ecf20Sopenharmony_ci		regulator_curr_mode = rdev->desc->ops->get_mode(rdev);
44338c2ecf20Sopenharmony_ci		if (regulator_curr_mode == mode) {
44348c2ecf20Sopenharmony_ci			ret = 0;
44358c2ecf20Sopenharmony_ci			goto out;
44368c2ecf20Sopenharmony_ci		}
44378c2ecf20Sopenharmony_ci	}
44388c2ecf20Sopenharmony_ci
44398c2ecf20Sopenharmony_ci	/* constraints check */
44408c2ecf20Sopenharmony_ci	ret = regulator_mode_constrain(rdev, &mode);
44418c2ecf20Sopenharmony_ci	if (ret < 0)
44428c2ecf20Sopenharmony_ci		goto out;
44438c2ecf20Sopenharmony_ci
44448c2ecf20Sopenharmony_ci	ret = rdev->desc->ops->set_mode(rdev, mode);
44458c2ecf20Sopenharmony_ciout:
44468c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
44478c2ecf20Sopenharmony_ci	return ret;
44488c2ecf20Sopenharmony_ci}
44498c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_mode);
44508c2ecf20Sopenharmony_ci
44518c2ecf20Sopenharmony_cistatic unsigned int _regulator_get_mode_unlocked(struct regulator_dev *rdev)
44528c2ecf20Sopenharmony_ci{
44538c2ecf20Sopenharmony_ci	/* sanity check */
44548c2ecf20Sopenharmony_ci	if (!rdev->desc->ops->get_mode)
44558c2ecf20Sopenharmony_ci		return -EINVAL;
44568c2ecf20Sopenharmony_ci
44578c2ecf20Sopenharmony_ci	return rdev->desc->ops->get_mode(rdev);
44588c2ecf20Sopenharmony_ci}
44598c2ecf20Sopenharmony_ci
44608c2ecf20Sopenharmony_cistatic unsigned int _regulator_get_mode(struct regulator_dev *rdev)
44618c2ecf20Sopenharmony_ci{
44628c2ecf20Sopenharmony_ci	int ret;
44638c2ecf20Sopenharmony_ci
44648c2ecf20Sopenharmony_ci	regulator_lock(rdev);
44658c2ecf20Sopenharmony_ci	ret = _regulator_get_mode_unlocked(rdev);
44668c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
44678c2ecf20Sopenharmony_ci
44688c2ecf20Sopenharmony_ci	return ret;
44698c2ecf20Sopenharmony_ci}
44708c2ecf20Sopenharmony_ci
44718c2ecf20Sopenharmony_ci/**
44728c2ecf20Sopenharmony_ci * regulator_get_mode - get regulator operating mode
44738c2ecf20Sopenharmony_ci * @regulator: regulator source
44748c2ecf20Sopenharmony_ci *
44758c2ecf20Sopenharmony_ci * Get the current regulator operating mode.
44768c2ecf20Sopenharmony_ci */
44778c2ecf20Sopenharmony_ciunsigned int regulator_get_mode(struct regulator *regulator)
44788c2ecf20Sopenharmony_ci{
44798c2ecf20Sopenharmony_ci	return _regulator_get_mode(regulator->rdev);
44808c2ecf20Sopenharmony_ci}
44818c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_mode);
44828c2ecf20Sopenharmony_ci
44838c2ecf20Sopenharmony_cistatic int _regulator_get_error_flags(struct regulator_dev *rdev,
44848c2ecf20Sopenharmony_ci					unsigned int *flags)
44858c2ecf20Sopenharmony_ci{
44868c2ecf20Sopenharmony_ci	int ret;
44878c2ecf20Sopenharmony_ci
44888c2ecf20Sopenharmony_ci	regulator_lock(rdev);
44898c2ecf20Sopenharmony_ci
44908c2ecf20Sopenharmony_ci	/* sanity check */
44918c2ecf20Sopenharmony_ci	if (!rdev->desc->ops->get_error_flags) {
44928c2ecf20Sopenharmony_ci		ret = -EINVAL;
44938c2ecf20Sopenharmony_ci		goto out;
44948c2ecf20Sopenharmony_ci	}
44958c2ecf20Sopenharmony_ci
44968c2ecf20Sopenharmony_ci	ret = rdev->desc->ops->get_error_flags(rdev, flags);
44978c2ecf20Sopenharmony_ciout:
44988c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
44998c2ecf20Sopenharmony_ci	return ret;
45008c2ecf20Sopenharmony_ci}
45018c2ecf20Sopenharmony_ci
45028c2ecf20Sopenharmony_ci/**
45038c2ecf20Sopenharmony_ci * regulator_get_error_flags - get regulator error information
45048c2ecf20Sopenharmony_ci * @regulator: regulator source
45058c2ecf20Sopenharmony_ci * @flags: pointer to store error flags
45068c2ecf20Sopenharmony_ci *
45078c2ecf20Sopenharmony_ci * Get the current regulator error information.
45088c2ecf20Sopenharmony_ci */
45098c2ecf20Sopenharmony_ciint regulator_get_error_flags(struct regulator *regulator,
45108c2ecf20Sopenharmony_ci				unsigned int *flags)
45118c2ecf20Sopenharmony_ci{
45128c2ecf20Sopenharmony_ci	return _regulator_get_error_flags(regulator->rdev, flags);
45138c2ecf20Sopenharmony_ci}
45148c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_error_flags);
45158c2ecf20Sopenharmony_ci
45168c2ecf20Sopenharmony_ci/**
45178c2ecf20Sopenharmony_ci * regulator_set_load - set regulator load
45188c2ecf20Sopenharmony_ci * @regulator: regulator source
45198c2ecf20Sopenharmony_ci * @uA_load: load current
45208c2ecf20Sopenharmony_ci *
45218c2ecf20Sopenharmony_ci * Notifies the regulator core of a new device load. This is then used by
45228c2ecf20Sopenharmony_ci * DRMS (if enabled by constraints) to set the most efficient regulator
45238c2ecf20Sopenharmony_ci * operating mode for the new regulator loading.
45248c2ecf20Sopenharmony_ci *
45258c2ecf20Sopenharmony_ci * Consumer devices notify their supply regulator of the maximum power
45268c2ecf20Sopenharmony_ci * they will require (can be taken from device datasheet in the power
45278c2ecf20Sopenharmony_ci * consumption tables) when they change operational status and hence power
45288c2ecf20Sopenharmony_ci * state. Examples of operational state changes that can affect power
45298c2ecf20Sopenharmony_ci * consumption are :-
45308c2ecf20Sopenharmony_ci *
45318c2ecf20Sopenharmony_ci *    o Device is opened / closed.
45328c2ecf20Sopenharmony_ci *    o Device I/O is about to begin or has just finished.
45338c2ecf20Sopenharmony_ci *    o Device is idling in between work.
45348c2ecf20Sopenharmony_ci *
45358c2ecf20Sopenharmony_ci * This information is also exported via sysfs to userspace.
45368c2ecf20Sopenharmony_ci *
45378c2ecf20Sopenharmony_ci * DRMS will sum the total requested load on the regulator and change
45388c2ecf20Sopenharmony_ci * to the most efficient operating mode if platform constraints allow.
45398c2ecf20Sopenharmony_ci *
45408c2ecf20Sopenharmony_ci * NOTE: when a regulator consumer requests to have a regulator
45418c2ecf20Sopenharmony_ci * disabled then any load that consumer requested no longer counts
45428c2ecf20Sopenharmony_ci * toward the total requested load.  If the regulator is re-enabled
45438c2ecf20Sopenharmony_ci * then the previously requested load will start counting again.
45448c2ecf20Sopenharmony_ci *
45458c2ecf20Sopenharmony_ci * If a regulator is an always-on regulator then an individual consumer's
45468c2ecf20Sopenharmony_ci * load will still be removed if that consumer is fully disabled.
45478c2ecf20Sopenharmony_ci *
45488c2ecf20Sopenharmony_ci * On error a negative errno is returned.
45498c2ecf20Sopenharmony_ci */
45508c2ecf20Sopenharmony_ciint regulator_set_load(struct regulator *regulator, int uA_load)
45518c2ecf20Sopenharmony_ci{
45528c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
45538c2ecf20Sopenharmony_ci	int old_uA_load;
45548c2ecf20Sopenharmony_ci	int ret = 0;
45558c2ecf20Sopenharmony_ci
45568c2ecf20Sopenharmony_ci	regulator_lock(rdev);
45578c2ecf20Sopenharmony_ci	old_uA_load = regulator->uA_load;
45588c2ecf20Sopenharmony_ci	regulator->uA_load = uA_load;
45598c2ecf20Sopenharmony_ci	if (regulator->enable_count && old_uA_load != uA_load) {
45608c2ecf20Sopenharmony_ci		ret = drms_uA_update(rdev);
45618c2ecf20Sopenharmony_ci		if (ret < 0)
45628c2ecf20Sopenharmony_ci			regulator->uA_load = old_uA_load;
45638c2ecf20Sopenharmony_ci	}
45648c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
45658c2ecf20Sopenharmony_ci
45668c2ecf20Sopenharmony_ci	return ret;
45678c2ecf20Sopenharmony_ci}
45688c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_load);
45698c2ecf20Sopenharmony_ci
45708c2ecf20Sopenharmony_ci/**
45718c2ecf20Sopenharmony_ci * regulator_allow_bypass - allow the regulator to go into bypass mode
45728c2ecf20Sopenharmony_ci *
45738c2ecf20Sopenharmony_ci * @regulator: Regulator to configure
45748c2ecf20Sopenharmony_ci * @enable: enable or disable bypass mode
45758c2ecf20Sopenharmony_ci *
45768c2ecf20Sopenharmony_ci * Allow the regulator to go into bypass mode if all other consumers
45778c2ecf20Sopenharmony_ci * for the regulator also enable bypass mode and the machine
45788c2ecf20Sopenharmony_ci * constraints allow this.  Bypass mode means that the regulator is
45798c2ecf20Sopenharmony_ci * simply passing the input directly to the output with no regulation.
45808c2ecf20Sopenharmony_ci */
45818c2ecf20Sopenharmony_ciint regulator_allow_bypass(struct regulator *regulator, bool enable)
45828c2ecf20Sopenharmony_ci{
45838c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = regulator->rdev;
45848c2ecf20Sopenharmony_ci	const char *name = rdev_get_name(rdev);
45858c2ecf20Sopenharmony_ci	int ret = 0;
45868c2ecf20Sopenharmony_ci
45878c2ecf20Sopenharmony_ci	if (!rdev->desc->ops->set_bypass)
45888c2ecf20Sopenharmony_ci		return 0;
45898c2ecf20Sopenharmony_ci
45908c2ecf20Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_BYPASS))
45918c2ecf20Sopenharmony_ci		return 0;
45928c2ecf20Sopenharmony_ci
45938c2ecf20Sopenharmony_ci	regulator_lock(rdev);
45948c2ecf20Sopenharmony_ci
45958c2ecf20Sopenharmony_ci	if (enable && !regulator->bypass) {
45968c2ecf20Sopenharmony_ci		rdev->bypass_count++;
45978c2ecf20Sopenharmony_ci
45988c2ecf20Sopenharmony_ci		if (rdev->bypass_count == rdev->open_count) {
45998c2ecf20Sopenharmony_ci			trace_regulator_bypass_enable(name);
46008c2ecf20Sopenharmony_ci
46018c2ecf20Sopenharmony_ci			ret = rdev->desc->ops->set_bypass(rdev, enable);
46028c2ecf20Sopenharmony_ci			if (ret != 0)
46038c2ecf20Sopenharmony_ci				rdev->bypass_count--;
46048c2ecf20Sopenharmony_ci			else
46058c2ecf20Sopenharmony_ci				trace_regulator_bypass_enable_complete(name);
46068c2ecf20Sopenharmony_ci		}
46078c2ecf20Sopenharmony_ci
46088c2ecf20Sopenharmony_ci	} else if (!enable && regulator->bypass) {
46098c2ecf20Sopenharmony_ci		rdev->bypass_count--;
46108c2ecf20Sopenharmony_ci
46118c2ecf20Sopenharmony_ci		if (rdev->bypass_count != rdev->open_count) {
46128c2ecf20Sopenharmony_ci			trace_regulator_bypass_disable(name);
46138c2ecf20Sopenharmony_ci
46148c2ecf20Sopenharmony_ci			ret = rdev->desc->ops->set_bypass(rdev, enable);
46158c2ecf20Sopenharmony_ci			if (ret != 0)
46168c2ecf20Sopenharmony_ci				rdev->bypass_count++;
46178c2ecf20Sopenharmony_ci			else
46188c2ecf20Sopenharmony_ci				trace_regulator_bypass_disable_complete(name);
46198c2ecf20Sopenharmony_ci		}
46208c2ecf20Sopenharmony_ci	}
46218c2ecf20Sopenharmony_ci
46228c2ecf20Sopenharmony_ci	if (ret == 0)
46238c2ecf20Sopenharmony_ci		regulator->bypass = enable;
46248c2ecf20Sopenharmony_ci
46258c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
46268c2ecf20Sopenharmony_ci
46278c2ecf20Sopenharmony_ci	return ret;
46288c2ecf20Sopenharmony_ci}
46298c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_allow_bypass);
46308c2ecf20Sopenharmony_ci
46318c2ecf20Sopenharmony_ci/**
46328c2ecf20Sopenharmony_ci * regulator_register_notifier - register regulator event notifier
46338c2ecf20Sopenharmony_ci * @regulator: regulator source
46348c2ecf20Sopenharmony_ci * @nb: notifier block
46358c2ecf20Sopenharmony_ci *
46368c2ecf20Sopenharmony_ci * Register notifier block to receive regulator events.
46378c2ecf20Sopenharmony_ci */
46388c2ecf20Sopenharmony_ciint regulator_register_notifier(struct regulator *regulator,
46398c2ecf20Sopenharmony_ci			      struct notifier_block *nb)
46408c2ecf20Sopenharmony_ci{
46418c2ecf20Sopenharmony_ci	return blocking_notifier_chain_register(&regulator->rdev->notifier,
46428c2ecf20Sopenharmony_ci						nb);
46438c2ecf20Sopenharmony_ci}
46448c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_register_notifier);
46458c2ecf20Sopenharmony_ci
46468c2ecf20Sopenharmony_ci/**
46478c2ecf20Sopenharmony_ci * regulator_unregister_notifier - unregister regulator event notifier
46488c2ecf20Sopenharmony_ci * @regulator: regulator source
46498c2ecf20Sopenharmony_ci * @nb: notifier block
46508c2ecf20Sopenharmony_ci *
46518c2ecf20Sopenharmony_ci * Unregister regulator event notifier block.
46528c2ecf20Sopenharmony_ci */
46538c2ecf20Sopenharmony_ciint regulator_unregister_notifier(struct regulator *regulator,
46548c2ecf20Sopenharmony_ci				struct notifier_block *nb)
46558c2ecf20Sopenharmony_ci{
46568c2ecf20Sopenharmony_ci	return blocking_notifier_chain_unregister(&regulator->rdev->notifier,
46578c2ecf20Sopenharmony_ci						  nb);
46588c2ecf20Sopenharmony_ci}
46598c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_unregister_notifier);
46608c2ecf20Sopenharmony_ci
46618c2ecf20Sopenharmony_ci/* notify regulator consumers and downstream regulator consumers.
46628c2ecf20Sopenharmony_ci * Note mutex must be held by caller.
46638c2ecf20Sopenharmony_ci */
46648c2ecf20Sopenharmony_cistatic int _notifier_call_chain(struct regulator_dev *rdev,
46658c2ecf20Sopenharmony_ci				  unsigned long event, void *data)
46668c2ecf20Sopenharmony_ci{
46678c2ecf20Sopenharmony_ci	/* call rdev chain first */
46688c2ecf20Sopenharmony_ci	return blocking_notifier_call_chain(&rdev->notifier, event, data);
46698c2ecf20Sopenharmony_ci}
46708c2ecf20Sopenharmony_ci
46718c2ecf20Sopenharmony_ci/**
46728c2ecf20Sopenharmony_ci * regulator_bulk_get - get multiple regulator consumers
46738c2ecf20Sopenharmony_ci *
46748c2ecf20Sopenharmony_ci * @dev:           Device to supply
46758c2ecf20Sopenharmony_ci * @num_consumers: Number of consumers to register
46768c2ecf20Sopenharmony_ci * @consumers:     Configuration of consumers; clients are stored here.
46778c2ecf20Sopenharmony_ci *
46788c2ecf20Sopenharmony_ci * @return 0 on success, an errno on failure.
46798c2ecf20Sopenharmony_ci *
46808c2ecf20Sopenharmony_ci * This helper function allows drivers to get several regulator
46818c2ecf20Sopenharmony_ci * consumers in one operation.  If any of the regulators cannot be
46828c2ecf20Sopenharmony_ci * acquired then any regulators that were allocated will be freed
46838c2ecf20Sopenharmony_ci * before returning to the caller.
46848c2ecf20Sopenharmony_ci */
46858c2ecf20Sopenharmony_ciint regulator_bulk_get(struct device *dev, int num_consumers,
46868c2ecf20Sopenharmony_ci		       struct regulator_bulk_data *consumers)
46878c2ecf20Sopenharmony_ci{
46888c2ecf20Sopenharmony_ci	int i;
46898c2ecf20Sopenharmony_ci	int ret;
46908c2ecf20Sopenharmony_ci
46918c2ecf20Sopenharmony_ci	for (i = 0; i < num_consumers; i++)
46928c2ecf20Sopenharmony_ci		consumers[i].consumer = NULL;
46938c2ecf20Sopenharmony_ci
46948c2ecf20Sopenharmony_ci	for (i = 0; i < num_consumers; i++) {
46958c2ecf20Sopenharmony_ci		consumers[i].consumer = regulator_get(dev,
46968c2ecf20Sopenharmony_ci						      consumers[i].supply);
46978c2ecf20Sopenharmony_ci		if (IS_ERR(consumers[i].consumer)) {
46988c2ecf20Sopenharmony_ci			ret = PTR_ERR(consumers[i].consumer);
46998c2ecf20Sopenharmony_ci			consumers[i].consumer = NULL;
47008c2ecf20Sopenharmony_ci			goto err;
47018c2ecf20Sopenharmony_ci		}
47028c2ecf20Sopenharmony_ci	}
47038c2ecf20Sopenharmony_ci
47048c2ecf20Sopenharmony_ci	return 0;
47058c2ecf20Sopenharmony_ci
47068c2ecf20Sopenharmony_cierr:
47078c2ecf20Sopenharmony_ci	if (ret != -EPROBE_DEFER)
47088c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to get supply '%s': %pe\n",
47098c2ecf20Sopenharmony_ci			consumers[i].supply, ERR_PTR(ret));
47108c2ecf20Sopenharmony_ci	else
47118c2ecf20Sopenharmony_ci		dev_dbg(dev, "Failed to get supply '%s', deferring\n",
47128c2ecf20Sopenharmony_ci			consumers[i].supply);
47138c2ecf20Sopenharmony_ci
47148c2ecf20Sopenharmony_ci	while (--i >= 0)
47158c2ecf20Sopenharmony_ci		regulator_put(consumers[i].consumer);
47168c2ecf20Sopenharmony_ci
47178c2ecf20Sopenharmony_ci	return ret;
47188c2ecf20Sopenharmony_ci}
47198c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_bulk_get);
47208c2ecf20Sopenharmony_ci
47218c2ecf20Sopenharmony_cistatic void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
47228c2ecf20Sopenharmony_ci{
47238c2ecf20Sopenharmony_ci	struct regulator_bulk_data *bulk = data;
47248c2ecf20Sopenharmony_ci
47258c2ecf20Sopenharmony_ci	bulk->ret = regulator_enable(bulk->consumer);
47268c2ecf20Sopenharmony_ci}
47278c2ecf20Sopenharmony_ci
47288c2ecf20Sopenharmony_ci/**
47298c2ecf20Sopenharmony_ci * regulator_bulk_enable - enable multiple regulator consumers
47308c2ecf20Sopenharmony_ci *
47318c2ecf20Sopenharmony_ci * @num_consumers: Number of consumers
47328c2ecf20Sopenharmony_ci * @consumers:     Consumer data; clients are stored here.
47338c2ecf20Sopenharmony_ci * @return         0 on success, an errno on failure
47348c2ecf20Sopenharmony_ci *
47358c2ecf20Sopenharmony_ci * This convenience API allows consumers to enable multiple regulator
47368c2ecf20Sopenharmony_ci * clients in a single API call.  If any consumers cannot be enabled
47378c2ecf20Sopenharmony_ci * then any others that were enabled will be disabled again prior to
47388c2ecf20Sopenharmony_ci * return.
47398c2ecf20Sopenharmony_ci */
47408c2ecf20Sopenharmony_ciint regulator_bulk_enable(int num_consumers,
47418c2ecf20Sopenharmony_ci			  struct regulator_bulk_data *consumers)
47428c2ecf20Sopenharmony_ci{
47438c2ecf20Sopenharmony_ci	ASYNC_DOMAIN_EXCLUSIVE(async_domain);
47448c2ecf20Sopenharmony_ci	int i;
47458c2ecf20Sopenharmony_ci	int ret = 0;
47468c2ecf20Sopenharmony_ci
47478c2ecf20Sopenharmony_ci	for (i = 0; i < num_consumers; i++) {
47488c2ecf20Sopenharmony_ci		async_schedule_domain(regulator_bulk_enable_async,
47498c2ecf20Sopenharmony_ci				      &consumers[i], &async_domain);
47508c2ecf20Sopenharmony_ci	}
47518c2ecf20Sopenharmony_ci
47528c2ecf20Sopenharmony_ci	async_synchronize_full_domain(&async_domain);
47538c2ecf20Sopenharmony_ci
47548c2ecf20Sopenharmony_ci	/* If any consumer failed we need to unwind any that succeeded */
47558c2ecf20Sopenharmony_ci	for (i = 0; i < num_consumers; i++) {
47568c2ecf20Sopenharmony_ci		if (consumers[i].ret != 0) {
47578c2ecf20Sopenharmony_ci			ret = consumers[i].ret;
47588c2ecf20Sopenharmony_ci			goto err;
47598c2ecf20Sopenharmony_ci		}
47608c2ecf20Sopenharmony_ci	}
47618c2ecf20Sopenharmony_ci
47628c2ecf20Sopenharmony_ci	return 0;
47638c2ecf20Sopenharmony_ci
47648c2ecf20Sopenharmony_cierr:
47658c2ecf20Sopenharmony_ci	for (i = 0; i < num_consumers; i++) {
47668c2ecf20Sopenharmony_ci		if (consumers[i].ret < 0)
47678c2ecf20Sopenharmony_ci			pr_err("Failed to enable %s: %pe\n", consumers[i].supply,
47688c2ecf20Sopenharmony_ci			       ERR_PTR(consumers[i].ret));
47698c2ecf20Sopenharmony_ci		else
47708c2ecf20Sopenharmony_ci			regulator_disable(consumers[i].consumer);
47718c2ecf20Sopenharmony_ci	}
47728c2ecf20Sopenharmony_ci
47738c2ecf20Sopenharmony_ci	return ret;
47748c2ecf20Sopenharmony_ci}
47758c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_bulk_enable);
47768c2ecf20Sopenharmony_ci
47778c2ecf20Sopenharmony_ci/**
47788c2ecf20Sopenharmony_ci * regulator_bulk_disable - disable multiple regulator consumers
47798c2ecf20Sopenharmony_ci *
47808c2ecf20Sopenharmony_ci * @num_consumers: Number of consumers
47818c2ecf20Sopenharmony_ci * @consumers:     Consumer data; clients are stored here.
47828c2ecf20Sopenharmony_ci * @return         0 on success, an errno on failure
47838c2ecf20Sopenharmony_ci *
47848c2ecf20Sopenharmony_ci * This convenience API allows consumers to disable multiple regulator
47858c2ecf20Sopenharmony_ci * clients in a single API call.  If any consumers cannot be disabled
47868c2ecf20Sopenharmony_ci * then any others that were disabled will be enabled again prior to
47878c2ecf20Sopenharmony_ci * return.
47888c2ecf20Sopenharmony_ci */
47898c2ecf20Sopenharmony_ciint regulator_bulk_disable(int num_consumers,
47908c2ecf20Sopenharmony_ci			   struct regulator_bulk_data *consumers)
47918c2ecf20Sopenharmony_ci{
47928c2ecf20Sopenharmony_ci	int i;
47938c2ecf20Sopenharmony_ci	int ret, r;
47948c2ecf20Sopenharmony_ci
47958c2ecf20Sopenharmony_ci	for (i = num_consumers - 1; i >= 0; --i) {
47968c2ecf20Sopenharmony_ci		ret = regulator_disable(consumers[i].consumer);
47978c2ecf20Sopenharmony_ci		if (ret != 0)
47988c2ecf20Sopenharmony_ci			goto err;
47998c2ecf20Sopenharmony_ci	}
48008c2ecf20Sopenharmony_ci
48018c2ecf20Sopenharmony_ci	return 0;
48028c2ecf20Sopenharmony_ci
48038c2ecf20Sopenharmony_cierr:
48048c2ecf20Sopenharmony_ci	pr_err("Failed to disable %s: %pe\n", consumers[i].supply, ERR_PTR(ret));
48058c2ecf20Sopenharmony_ci	for (++i; i < num_consumers; ++i) {
48068c2ecf20Sopenharmony_ci		r = regulator_enable(consumers[i].consumer);
48078c2ecf20Sopenharmony_ci		if (r != 0)
48088c2ecf20Sopenharmony_ci			pr_err("Failed to re-enable %s: %pe\n",
48098c2ecf20Sopenharmony_ci			       consumers[i].supply, ERR_PTR(r));
48108c2ecf20Sopenharmony_ci	}
48118c2ecf20Sopenharmony_ci
48128c2ecf20Sopenharmony_ci	return ret;
48138c2ecf20Sopenharmony_ci}
48148c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_bulk_disable);
48158c2ecf20Sopenharmony_ci
48168c2ecf20Sopenharmony_ci/**
48178c2ecf20Sopenharmony_ci * regulator_bulk_force_disable - force disable multiple regulator consumers
48188c2ecf20Sopenharmony_ci *
48198c2ecf20Sopenharmony_ci * @num_consumers: Number of consumers
48208c2ecf20Sopenharmony_ci * @consumers:     Consumer data; clients are stored here.
48218c2ecf20Sopenharmony_ci * @return         0 on success, an errno on failure
48228c2ecf20Sopenharmony_ci *
48238c2ecf20Sopenharmony_ci * This convenience API allows consumers to forcibly disable multiple regulator
48248c2ecf20Sopenharmony_ci * clients in a single API call.
48258c2ecf20Sopenharmony_ci * NOTE: This should be used for situations when device damage will
48268c2ecf20Sopenharmony_ci * likely occur if the regulators are not disabled (e.g. over temp).
48278c2ecf20Sopenharmony_ci * Although regulator_force_disable function call for some consumers can
48288c2ecf20Sopenharmony_ci * return error numbers, the function is called for all consumers.
48298c2ecf20Sopenharmony_ci */
48308c2ecf20Sopenharmony_ciint regulator_bulk_force_disable(int num_consumers,
48318c2ecf20Sopenharmony_ci			   struct regulator_bulk_data *consumers)
48328c2ecf20Sopenharmony_ci{
48338c2ecf20Sopenharmony_ci	int i;
48348c2ecf20Sopenharmony_ci	int ret = 0;
48358c2ecf20Sopenharmony_ci
48368c2ecf20Sopenharmony_ci	for (i = 0; i < num_consumers; i++) {
48378c2ecf20Sopenharmony_ci		consumers[i].ret =
48388c2ecf20Sopenharmony_ci			    regulator_force_disable(consumers[i].consumer);
48398c2ecf20Sopenharmony_ci
48408c2ecf20Sopenharmony_ci		/* Store first error for reporting */
48418c2ecf20Sopenharmony_ci		if (consumers[i].ret && !ret)
48428c2ecf20Sopenharmony_ci			ret = consumers[i].ret;
48438c2ecf20Sopenharmony_ci	}
48448c2ecf20Sopenharmony_ci
48458c2ecf20Sopenharmony_ci	return ret;
48468c2ecf20Sopenharmony_ci}
48478c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_bulk_force_disable);
48488c2ecf20Sopenharmony_ci
48498c2ecf20Sopenharmony_ci/**
48508c2ecf20Sopenharmony_ci * regulator_bulk_free - free multiple regulator consumers
48518c2ecf20Sopenharmony_ci *
48528c2ecf20Sopenharmony_ci * @num_consumers: Number of consumers
48538c2ecf20Sopenharmony_ci * @consumers:     Consumer data; clients are stored here.
48548c2ecf20Sopenharmony_ci *
48558c2ecf20Sopenharmony_ci * This convenience API allows consumers to free multiple regulator
48568c2ecf20Sopenharmony_ci * clients in a single API call.
48578c2ecf20Sopenharmony_ci */
48588c2ecf20Sopenharmony_civoid regulator_bulk_free(int num_consumers,
48598c2ecf20Sopenharmony_ci			 struct regulator_bulk_data *consumers)
48608c2ecf20Sopenharmony_ci{
48618c2ecf20Sopenharmony_ci	int i;
48628c2ecf20Sopenharmony_ci
48638c2ecf20Sopenharmony_ci	for (i = 0; i < num_consumers; i++) {
48648c2ecf20Sopenharmony_ci		regulator_put(consumers[i].consumer);
48658c2ecf20Sopenharmony_ci		consumers[i].consumer = NULL;
48668c2ecf20Sopenharmony_ci	}
48678c2ecf20Sopenharmony_ci}
48688c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_bulk_free);
48698c2ecf20Sopenharmony_ci
48708c2ecf20Sopenharmony_ci/**
48718c2ecf20Sopenharmony_ci * regulator_notifier_call_chain - call regulator event notifier
48728c2ecf20Sopenharmony_ci * @rdev: regulator source
48738c2ecf20Sopenharmony_ci * @event: notifier block
48748c2ecf20Sopenharmony_ci * @data: callback-specific data.
48758c2ecf20Sopenharmony_ci *
48768c2ecf20Sopenharmony_ci * Called by regulator drivers to notify clients a regulator event has
48778c2ecf20Sopenharmony_ci * occurred.
48788c2ecf20Sopenharmony_ci */
48798c2ecf20Sopenharmony_ciint regulator_notifier_call_chain(struct regulator_dev *rdev,
48808c2ecf20Sopenharmony_ci				  unsigned long event, void *data)
48818c2ecf20Sopenharmony_ci{
48828c2ecf20Sopenharmony_ci	_notifier_call_chain(rdev, event, data);
48838c2ecf20Sopenharmony_ci	return NOTIFY_DONE;
48848c2ecf20Sopenharmony_ci
48858c2ecf20Sopenharmony_ci}
48868c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_notifier_call_chain);
48878c2ecf20Sopenharmony_ci
48888c2ecf20Sopenharmony_ci/**
48898c2ecf20Sopenharmony_ci * regulator_mode_to_status - convert a regulator mode into a status
48908c2ecf20Sopenharmony_ci *
48918c2ecf20Sopenharmony_ci * @mode: Mode to convert
48928c2ecf20Sopenharmony_ci *
48938c2ecf20Sopenharmony_ci * Convert a regulator mode into a status.
48948c2ecf20Sopenharmony_ci */
48958c2ecf20Sopenharmony_ciint regulator_mode_to_status(unsigned int mode)
48968c2ecf20Sopenharmony_ci{
48978c2ecf20Sopenharmony_ci	switch (mode) {
48988c2ecf20Sopenharmony_ci	case REGULATOR_MODE_FAST:
48998c2ecf20Sopenharmony_ci		return REGULATOR_STATUS_FAST;
49008c2ecf20Sopenharmony_ci	case REGULATOR_MODE_NORMAL:
49018c2ecf20Sopenharmony_ci		return REGULATOR_STATUS_NORMAL;
49028c2ecf20Sopenharmony_ci	case REGULATOR_MODE_IDLE:
49038c2ecf20Sopenharmony_ci		return REGULATOR_STATUS_IDLE;
49048c2ecf20Sopenharmony_ci	case REGULATOR_MODE_STANDBY:
49058c2ecf20Sopenharmony_ci		return REGULATOR_STATUS_STANDBY;
49068c2ecf20Sopenharmony_ci	default:
49078c2ecf20Sopenharmony_ci		return REGULATOR_STATUS_UNDEFINED;
49088c2ecf20Sopenharmony_ci	}
49098c2ecf20Sopenharmony_ci}
49108c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_mode_to_status);
49118c2ecf20Sopenharmony_ci
49128c2ecf20Sopenharmony_cistatic struct attribute *regulator_dev_attrs[] = {
49138c2ecf20Sopenharmony_ci	&dev_attr_name.attr,
49148c2ecf20Sopenharmony_ci	&dev_attr_num_users.attr,
49158c2ecf20Sopenharmony_ci	&dev_attr_type.attr,
49168c2ecf20Sopenharmony_ci	&dev_attr_microvolts.attr,
49178c2ecf20Sopenharmony_ci	&dev_attr_microamps.attr,
49188c2ecf20Sopenharmony_ci	&dev_attr_opmode.attr,
49198c2ecf20Sopenharmony_ci	&dev_attr_state.attr,
49208c2ecf20Sopenharmony_ci	&dev_attr_status.attr,
49218c2ecf20Sopenharmony_ci	&dev_attr_bypass.attr,
49228c2ecf20Sopenharmony_ci	&dev_attr_requested_microamps.attr,
49238c2ecf20Sopenharmony_ci	&dev_attr_min_microvolts.attr,
49248c2ecf20Sopenharmony_ci	&dev_attr_max_microvolts.attr,
49258c2ecf20Sopenharmony_ci	&dev_attr_min_microamps.attr,
49268c2ecf20Sopenharmony_ci	&dev_attr_max_microamps.attr,
49278c2ecf20Sopenharmony_ci	&dev_attr_suspend_standby_state.attr,
49288c2ecf20Sopenharmony_ci	&dev_attr_suspend_mem_state.attr,
49298c2ecf20Sopenharmony_ci	&dev_attr_suspend_disk_state.attr,
49308c2ecf20Sopenharmony_ci	&dev_attr_suspend_standby_microvolts.attr,
49318c2ecf20Sopenharmony_ci	&dev_attr_suspend_mem_microvolts.attr,
49328c2ecf20Sopenharmony_ci	&dev_attr_suspend_disk_microvolts.attr,
49338c2ecf20Sopenharmony_ci	&dev_attr_suspend_standby_mode.attr,
49348c2ecf20Sopenharmony_ci	&dev_attr_suspend_mem_mode.attr,
49358c2ecf20Sopenharmony_ci	&dev_attr_suspend_disk_mode.attr,
49368c2ecf20Sopenharmony_ci	NULL
49378c2ecf20Sopenharmony_ci};
49388c2ecf20Sopenharmony_ci
49398c2ecf20Sopenharmony_ci/*
49408c2ecf20Sopenharmony_ci * To avoid cluttering sysfs (and memory) with useless state, only
49418c2ecf20Sopenharmony_ci * create attributes that can be meaningfully displayed.
49428c2ecf20Sopenharmony_ci */
49438c2ecf20Sopenharmony_cistatic umode_t regulator_attr_is_visible(struct kobject *kobj,
49448c2ecf20Sopenharmony_ci					 struct attribute *attr, int idx)
49458c2ecf20Sopenharmony_ci{
49468c2ecf20Sopenharmony_ci	struct device *dev = kobj_to_dev(kobj);
49478c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
49488c2ecf20Sopenharmony_ci	const struct regulator_ops *ops = rdev->desc->ops;
49498c2ecf20Sopenharmony_ci	umode_t mode = attr->mode;
49508c2ecf20Sopenharmony_ci
49518c2ecf20Sopenharmony_ci	/* these three are always present */
49528c2ecf20Sopenharmony_ci	if (attr == &dev_attr_name.attr ||
49538c2ecf20Sopenharmony_ci	    attr == &dev_attr_num_users.attr ||
49548c2ecf20Sopenharmony_ci	    attr == &dev_attr_type.attr)
49558c2ecf20Sopenharmony_ci		return mode;
49568c2ecf20Sopenharmony_ci
49578c2ecf20Sopenharmony_ci	/* some attributes need specific methods to be displayed */
49588c2ecf20Sopenharmony_ci	if (attr == &dev_attr_microvolts.attr) {
49598c2ecf20Sopenharmony_ci		if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) ||
49608c2ecf20Sopenharmony_ci		    (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) ||
49618c2ecf20Sopenharmony_ci		    (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) ||
49628c2ecf20Sopenharmony_ci		    (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1))
49638c2ecf20Sopenharmony_ci			return mode;
49648c2ecf20Sopenharmony_ci		return 0;
49658c2ecf20Sopenharmony_ci	}
49668c2ecf20Sopenharmony_ci
49678c2ecf20Sopenharmony_ci	if (attr == &dev_attr_microamps.attr)
49688c2ecf20Sopenharmony_ci		return ops->get_current_limit ? mode : 0;
49698c2ecf20Sopenharmony_ci
49708c2ecf20Sopenharmony_ci	if (attr == &dev_attr_opmode.attr)
49718c2ecf20Sopenharmony_ci		return ops->get_mode ? mode : 0;
49728c2ecf20Sopenharmony_ci
49738c2ecf20Sopenharmony_ci	if (attr == &dev_attr_state.attr)
49748c2ecf20Sopenharmony_ci		return (rdev->ena_pin || ops->is_enabled) ? mode : 0;
49758c2ecf20Sopenharmony_ci
49768c2ecf20Sopenharmony_ci	if (attr == &dev_attr_status.attr)
49778c2ecf20Sopenharmony_ci		return ops->get_status ? mode : 0;
49788c2ecf20Sopenharmony_ci
49798c2ecf20Sopenharmony_ci	if (attr == &dev_attr_bypass.attr)
49808c2ecf20Sopenharmony_ci		return ops->get_bypass ? mode : 0;
49818c2ecf20Sopenharmony_ci
49828c2ecf20Sopenharmony_ci	/* constraints need specific supporting methods */
49838c2ecf20Sopenharmony_ci	if (attr == &dev_attr_min_microvolts.attr ||
49848c2ecf20Sopenharmony_ci	    attr == &dev_attr_max_microvolts.attr)
49858c2ecf20Sopenharmony_ci		return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0;
49868c2ecf20Sopenharmony_ci
49878c2ecf20Sopenharmony_ci	if (attr == &dev_attr_min_microamps.attr ||
49888c2ecf20Sopenharmony_ci	    attr == &dev_attr_max_microamps.attr)
49898c2ecf20Sopenharmony_ci		return ops->set_current_limit ? mode : 0;
49908c2ecf20Sopenharmony_ci
49918c2ecf20Sopenharmony_ci	if (attr == &dev_attr_suspend_standby_state.attr ||
49928c2ecf20Sopenharmony_ci	    attr == &dev_attr_suspend_mem_state.attr ||
49938c2ecf20Sopenharmony_ci	    attr == &dev_attr_suspend_disk_state.attr)
49948c2ecf20Sopenharmony_ci		return mode;
49958c2ecf20Sopenharmony_ci
49968c2ecf20Sopenharmony_ci	if (attr == &dev_attr_suspend_standby_microvolts.attr ||
49978c2ecf20Sopenharmony_ci	    attr == &dev_attr_suspend_mem_microvolts.attr ||
49988c2ecf20Sopenharmony_ci	    attr == &dev_attr_suspend_disk_microvolts.attr)
49998c2ecf20Sopenharmony_ci		return ops->set_suspend_voltage ? mode : 0;
50008c2ecf20Sopenharmony_ci
50018c2ecf20Sopenharmony_ci	if (attr == &dev_attr_suspend_standby_mode.attr ||
50028c2ecf20Sopenharmony_ci	    attr == &dev_attr_suspend_mem_mode.attr ||
50038c2ecf20Sopenharmony_ci	    attr == &dev_attr_suspend_disk_mode.attr)
50048c2ecf20Sopenharmony_ci		return ops->set_suspend_mode ? mode : 0;
50058c2ecf20Sopenharmony_ci
50068c2ecf20Sopenharmony_ci	return mode;
50078c2ecf20Sopenharmony_ci}
50088c2ecf20Sopenharmony_ci
50098c2ecf20Sopenharmony_cistatic const struct attribute_group regulator_dev_group = {
50108c2ecf20Sopenharmony_ci	.attrs = regulator_dev_attrs,
50118c2ecf20Sopenharmony_ci	.is_visible = regulator_attr_is_visible,
50128c2ecf20Sopenharmony_ci};
50138c2ecf20Sopenharmony_ci
50148c2ecf20Sopenharmony_cistatic const struct attribute_group *regulator_dev_groups[] = {
50158c2ecf20Sopenharmony_ci	&regulator_dev_group,
50168c2ecf20Sopenharmony_ci	NULL
50178c2ecf20Sopenharmony_ci};
50188c2ecf20Sopenharmony_ci
50198c2ecf20Sopenharmony_cistatic void regulator_dev_release(struct device *dev)
50208c2ecf20Sopenharmony_ci{
50218c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_get_drvdata(dev);
50228c2ecf20Sopenharmony_ci
50238c2ecf20Sopenharmony_ci	debugfs_remove_recursive(rdev->debugfs);
50248c2ecf20Sopenharmony_ci	kfree(rdev->constraints);
50258c2ecf20Sopenharmony_ci	of_node_put(rdev->dev.of_node);
50268c2ecf20Sopenharmony_ci	kfree(rdev);
50278c2ecf20Sopenharmony_ci}
50288c2ecf20Sopenharmony_ci
50298c2ecf20Sopenharmony_cistatic void rdev_init_debugfs(struct regulator_dev *rdev)
50308c2ecf20Sopenharmony_ci{
50318c2ecf20Sopenharmony_ci	struct device *parent = rdev->dev.parent;
50328c2ecf20Sopenharmony_ci	const char *rname = rdev_get_name(rdev);
50338c2ecf20Sopenharmony_ci	char name[NAME_MAX];
50348c2ecf20Sopenharmony_ci
50358c2ecf20Sopenharmony_ci	/* Avoid duplicate debugfs directory names */
50368c2ecf20Sopenharmony_ci	if (parent && rname == rdev->desc->name) {
50378c2ecf20Sopenharmony_ci		snprintf(name, sizeof(name), "%s-%s", dev_name(parent),
50388c2ecf20Sopenharmony_ci			 rname);
50398c2ecf20Sopenharmony_ci		rname = name;
50408c2ecf20Sopenharmony_ci	}
50418c2ecf20Sopenharmony_ci
50428c2ecf20Sopenharmony_ci	rdev->debugfs = debugfs_create_dir(rname, debugfs_root);
50438c2ecf20Sopenharmony_ci	if (IS_ERR(rdev->debugfs))
50448c2ecf20Sopenharmony_ci		rdev_dbg(rdev, "Failed to create debugfs directory\n");
50458c2ecf20Sopenharmony_ci
50468c2ecf20Sopenharmony_ci	debugfs_create_u32("use_count", 0444, rdev->debugfs,
50478c2ecf20Sopenharmony_ci			   &rdev->use_count);
50488c2ecf20Sopenharmony_ci	debugfs_create_u32("open_count", 0444, rdev->debugfs,
50498c2ecf20Sopenharmony_ci			   &rdev->open_count);
50508c2ecf20Sopenharmony_ci	debugfs_create_u32("bypass_count", 0444, rdev->debugfs,
50518c2ecf20Sopenharmony_ci			   &rdev->bypass_count);
50528c2ecf20Sopenharmony_ci}
50538c2ecf20Sopenharmony_ci
50548c2ecf20Sopenharmony_cistatic int regulator_register_resolve_supply(struct device *dev, void *data)
50558c2ecf20Sopenharmony_ci{
50568c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
50578c2ecf20Sopenharmony_ci
50588c2ecf20Sopenharmony_ci	if (regulator_resolve_supply(rdev))
50598c2ecf20Sopenharmony_ci		rdev_dbg(rdev, "unable to resolve supply\n");
50608c2ecf20Sopenharmony_ci
50618c2ecf20Sopenharmony_ci	return 0;
50628c2ecf20Sopenharmony_ci}
50638c2ecf20Sopenharmony_ci
50648c2ecf20Sopenharmony_ciint regulator_coupler_register(struct regulator_coupler *coupler)
50658c2ecf20Sopenharmony_ci{
50668c2ecf20Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
50678c2ecf20Sopenharmony_ci	list_add_tail(&coupler->list, &regulator_coupler_list);
50688c2ecf20Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
50698c2ecf20Sopenharmony_ci
50708c2ecf20Sopenharmony_ci	return 0;
50718c2ecf20Sopenharmony_ci}
50728c2ecf20Sopenharmony_ci
50738c2ecf20Sopenharmony_cistatic struct regulator_coupler *
50748c2ecf20Sopenharmony_ciregulator_find_coupler(struct regulator_dev *rdev)
50758c2ecf20Sopenharmony_ci{
50768c2ecf20Sopenharmony_ci	struct regulator_coupler *coupler;
50778c2ecf20Sopenharmony_ci	int err;
50788c2ecf20Sopenharmony_ci
50798c2ecf20Sopenharmony_ci	/*
50808c2ecf20Sopenharmony_ci	 * Note that regulators are appended to the list and the generic
50818c2ecf20Sopenharmony_ci	 * coupler is registered first, hence it will be attached at last
50828c2ecf20Sopenharmony_ci	 * if nobody cared.
50838c2ecf20Sopenharmony_ci	 */
50848c2ecf20Sopenharmony_ci	list_for_each_entry_reverse(coupler, &regulator_coupler_list, list) {
50858c2ecf20Sopenharmony_ci		err = coupler->attach_regulator(coupler, rdev);
50868c2ecf20Sopenharmony_ci		if (!err) {
50878c2ecf20Sopenharmony_ci			if (!coupler->balance_voltage &&
50888c2ecf20Sopenharmony_ci			    rdev->coupling_desc.n_coupled > 2)
50898c2ecf20Sopenharmony_ci				goto err_unsupported;
50908c2ecf20Sopenharmony_ci
50918c2ecf20Sopenharmony_ci			return coupler;
50928c2ecf20Sopenharmony_ci		}
50938c2ecf20Sopenharmony_ci
50948c2ecf20Sopenharmony_ci		if (err < 0)
50958c2ecf20Sopenharmony_ci			return ERR_PTR(err);
50968c2ecf20Sopenharmony_ci
50978c2ecf20Sopenharmony_ci		if (err == 1)
50988c2ecf20Sopenharmony_ci			continue;
50998c2ecf20Sopenharmony_ci
51008c2ecf20Sopenharmony_ci		break;
51018c2ecf20Sopenharmony_ci	}
51028c2ecf20Sopenharmony_ci
51038c2ecf20Sopenharmony_ci	return ERR_PTR(-EINVAL);
51048c2ecf20Sopenharmony_ci
51058c2ecf20Sopenharmony_cierr_unsupported:
51068c2ecf20Sopenharmony_ci	if (coupler->detach_regulator)
51078c2ecf20Sopenharmony_ci		coupler->detach_regulator(coupler, rdev);
51088c2ecf20Sopenharmony_ci
51098c2ecf20Sopenharmony_ci	rdev_err(rdev,
51108c2ecf20Sopenharmony_ci		"Voltage balancing for multiple regulator couples is unimplemented\n");
51118c2ecf20Sopenharmony_ci
51128c2ecf20Sopenharmony_ci	return ERR_PTR(-EPERM);
51138c2ecf20Sopenharmony_ci}
51148c2ecf20Sopenharmony_ci
51158c2ecf20Sopenharmony_cistatic void regulator_resolve_coupling(struct regulator_dev *rdev)
51168c2ecf20Sopenharmony_ci{
51178c2ecf20Sopenharmony_ci	struct regulator_coupler *coupler = rdev->coupling_desc.coupler;
51188c2ecf20Sopenharmony_ci	struct coupling_desc *c_desc = &rdev->coupling_desc;
51198c2ecf20Sopenharmony_ci	int n_coupled = c_desc->n_coupled;
51208c2ecf20Sopenharmony_ci	struct regulator_dev *c_rdev;
51218c2ecf20Sopenharmony_ci	int i;
51228c2ecf20Sopenharmony_ci
51238c2ecf20Sopenharmony_ci	for (i = 1; i < n_coupled; i++) {
51248c2ecf20Sopenharmony_ci		/* already resolved */
51258c2ecf20Sopenharmony_ci		if (c_desc->coupled_rdevs[i])
51268c2ecf20Sopenharmony_ci			continue;
51278c2ecf20Sopenharmony_ci
51288c2ecf20Sopenharmony_ci		c_rdev = of_parse_coupled_regulator(rdev, i - 1);
51298c2ecf20Sopenharmony_ci
51308c2ecf20Sopenharmony_ci		if (!c_rdev)
51318c2ecf20Sopenharmony_ci			continue;
51328c2ecf20Sopenharmony_ci
51338c2ecf20Sopenharmony_ci		if (c_rdev->coupling_desc.coupler != coupler) {
51348c2ecf20Sopenharmony_ci			rdev_err(rdev, "coupler mismatch with %s\n",
51358c2ecf20Sopenharmony_ci				 rdev_get_name(c_rdev));
51368c2ecf20Sopenharmony_ci			return;
51378c2ecf20Sopenharmony_ci		}
51388c2ecf20Sopenharmony_ci
51398c2ecf20Sopenharmony_ci		c_desc->coupled_rdevs[i] = c_rdev;
51408c2ecf20Sopenharmony_ci		c_desc->n_resolved++;
51418c2ecf20Sopenharmony_ci
51428c2ecf20Sopenharmony_ci		regulator_resolve_coupling(c_rdev);
51438c2ecf20Sopenharmony_ci	}
51448c2ecf20Sopenharmony_ci}
51458c2ecf20Sopenharmony_ci
51468c2ecf20Sopenharmony_cistatic void regulator_remove_coupling(struct regulator_dev *rdev)
51478c2ecf20Sopenharmony_ci{
51488c2ecf20Sopenharmony_ci	struct regulator_coupler *coupler = rdev->coupling_desc.coupler;
51498c2ecf20Sopenharmony_ci	struct coupling_desc *__c_desc, *c_desc = &rdev->coupling_desc;
51508c2ecf20Sopenharmony_ci	struct regulator_dev *__c_rdev, *c_rdev;
51518c2ecf20Sopenharmony_ci	unsigned int __n_coupled, n_coupled;
51528c2ecf20Sopenharmony_ci	int i, k;
51538c2ecf20Sopenharmony_ci	int err;
51548c2ecf20Sopenharmony_ci
51558c2ecf20Sopenharmony_ci	n_coupled = c_desc->n_coupled;
51568c2ecf20Sopenharmony_ci
51578c2ecf20Sopenharmony_ci	for (i = 1; i < n_coupled; i++) {
51588c2ecf20Sopenharmony_ci		c_rdev = c_desc->coupled_rdevs[i];
51598c2ecf20Sopenharmony_ci
51608c2ecf20Sopenharmony_ci		if (!c_rdev)
51618c2ecf20Sopenharmony_ci			continue;
51628c2ecf20Sopenharmony_ci
51638c2ecf20Sopenharmony_ci		regulator_lock(c_rdev);
51648c2ecf20Sopenharmony_ci
51658c2ecf20Sopenharmony_ci		__c_desc = &c_rdev->coupling_desc;
51668c2ecf20Sopenharmony_ci		__n_coupled = __c_desc->n_coupled;
51678c2ecf20Sopenharmony_ci
51688c2ecf20Sopenharmony_ci		for (k = 1; k < __n_coupled; k++) {
51698c2ecf20Sopenharmony_ci			__c_rdev = __c_desc->coupled_rdevs[k];
51708c2ecf20Sopenharmony_ci
51718c2ecf20Sopenharmony_ci			if (__c_rdev == rdev) {
51728c2ecf20Sopenharmony_ci				__c_desc->coupled_rdevs[k] = NULL;
51738c2ecf20Sopenharmony_ci				__c_desc->n_resolved--;
51748c2ecf20Sopenharmony_ci				break;
51758c2ecf20Sopenharmony_ci			}
51768c2ecf20Sopenharmony_ci		}
51778c2ecf20Sopenharmony_ci
51788c2ecf20Sopenharmony_ci		regulator_unlock(c_rdev);
51798c2ecf20Sopenharmony_ci
51808c2ecf20Sopenharmony_ci		c_desc->coupled_rdevs[i] = NULL;
51818c2ecf20Sopenharmony_ci		c_desc->n_resolved--;
51828c2ecf20Sopenharmony_ci	}
51838c2ecf20Sopenharmony_ci
51848c2ecf20Sopenharmony_ci	if (coupler && coupler->detach_regulator) {
51858c2ecf20Sopenharmony_ci		err = coupler->detach_regulator(coupler, rdev);
51868c2ecf20Sopenharmony_ci		if (err)
51878c2ecf20Sopenharmony_ci			rdev_err(rdev, "failed to detach from coupler: %pe\n",
51888c2ecf20Sopenharmony_ci				 ERR_PTR(err));
51898c2ecf20Sopenharmony_ci	}
51908c2ecf20Sopenharmony_ci
51918c2ecf20Sopenharmony_ci	kfree(rdev->coupling_desc.coupled_rdevs);
51928c2ecf20Sopenharmony_ci	rdev->coupling_desc.coupled_rdevs = NULL;
51938c2ecf20Sopenharmony_ci}
51948c2ecf20Sopenharmony_ci
51958c2ecf20Sopenharmony_cistatic int regulator_init_coupling(struct regulator_dev *rdev)
51968c2ecf20Sopenharmony_ci{
51978c2ecf20Sopenharmony_ci	struct regulator_dev **coupled;
51988c2ecf20Sopenharmony_ci	int err, n_phandles;
51998c2ecf20Sopenharmony_ci
52008c2ecf20Sopenharmony_ci	if (!IS_ENABLED(CONFIG_OF))
52018c2ecf20Sopenharmony_ci		n_phandles = 0;
52028c2ecf20Sopenharmony_ci	else
52038c2ecf20Sopenharmony_ci		n_phandles = of_get_n_coupled(rdev);
52048c2ecf20Sopenharmony_ci
52058c2ecf20Sopenharmony_ci	coupled = kcalloc(n_phandles + 1, sizeof(*coupled), GFP_KERNEL);
52068c2ecf20Sopenharmony_ci	if (!coupled)
52078c2ecf20Sopenharmony_ci		return -ENOMEM;
52088c2ecf20Sopenharmony_ci
52098c2ecf20Sopenharmony_ci	rdev->coupling_desc.coupled_rdevs = coupled;
52108c2ecf20Sopenharmony_ci
52118c2ecf20Sopenharmony_ci	/*
52128c2ecf20Sopenharmony_ci	 * Every regulator should always have coupling descriptor filled with
52138c2ecf20Sopenharmony_ci	 * at least pointer to itself.
52148c2ecf20Sopenharmony_ci	 */
52158c2ecf20Sopenharmony_ci	rdev->coupling_desc.coupled_rdevs[0] = rdev;
52168c2ecf20Sopenharmony_ci	rdev->coupling_desc.n_coupled = n_phandles + 1;
52178c2ecf20Sopenharmony_ci	rdev->coupling_desc.n_resolved++;
52188c2ecf20Sopenharmony_ci
52198c2ecf20Sopenharmony_ci	/* regulator isn't coupled */
52208c2ecf20Sopenharmony_ci	if (n_phandles == 0)
52218c2ecf20Sopenharmony_ci		return 0;
52228c2ecf20Sopenharmony_ci
52238c2ecf20Sopenharmony_ci	if (!of_check_coupling_data(rdev))
52248c2ecf20Sopenharmony_ci		return -EPERM;
52258c2ecf20Sopenharmony_ci
52268c2ecf20Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
52278c2ecf20Sopenharmony_ci	rdev->coupling_desc.coupler = regulator_find_coupler(rdev);
52288c2ecf20Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
52298c2ecf20Sopenharmony_ci
52308c2ecf20Sopenharmony_ci	if (IS_ERR(rdev->coupling_desc.coupler)) {
52318c2ecf20Sopenharmony_ci		err = PTR_ERR(rdev->coupling_desc.coupler);
52328c2ecf20Sopenharmony_ci		rdev_err(rdev, "failed to get coupler: %pe\n", ERR_PTR(err));
52338c2ecf20Sopenharmony_ci		return err;
52348c2ecf20Sopenharmony_ci	}
52358c2ecf20Sopenharmony_ci
52368c2ecf20Sopenharmony_ci	return 0;
52378c2ecf20Sopenharmony_ci}
52388c2ecf20Sopenharmony_ci
52398c2ecf20Sopenharmony_cistatic int generic_coupler_attach(struct regulator_coupler *coupler,
52408c2ecf20Sopenharmony_ci				  struct regulator_dev *rdev)
52418c2ecf20Sopenharmony_ci{
52428c2ecf20Sopenharmony_ci	if (rdev->coupling_desc.n_coupled > 2) {
52438c2ecf20Sopenharmony_ci		rdev_err(rdev,
52448c2ecf20Sopenharmony_ci			 "Voltage balancing for multiple regulator couples is unimplemented\n");
52458c2ecf20Sopenharmony_ci		return -EPERM;
52468c2ecf20Sopenharmony_ci	}
52478c2ecf20Sopenharmony_ci
52488c2ecf20Sopenharmony_ci	if (!rdev->constraints->always_on) {
52498c2ecf20Sopenharmony_ci		rdev_err(rdev,
52508c2ecf20Sopenharmony_ci			 "Coupling of a non always-on regulator is unimplemented\n");
52518c2ecf20Sopenharmony_ci		return -ENOTSUPP;
52528c2ecf20Sopenharmony_ci	}
52538c2ecf20Sopenharmony_ci
52548c2ecf20Sopenharmony_ci	return 0;
52558c2ecf20Sopenharmony_ci}
52568c2ecf20Sopenharmony_ci
52578c2ecf20Sopenharmony_cistatic struct regulator_coupler generic_regulator_coupler = {
52588c2ecf20Sopenharmony_ci	.attach_regulator = generic_coupler_attach,
52598c2ecf20Sopenharmony_ci};
52608c2ecf20Sopenharmony_ci
52618c2ecf20Sopenharmony_ci/**
52628c2ecf20Sopenharmony_ci * regulator_register - register regulator
52638c2ecf20Sopenharmony_ci * @regulator_desc: regulator to register
52648c2ecf20Sopenharmony_ci * @cfg: runtime configuration for regulator
52658c2ecf20Sopenharmony_ci *
52668c2ecf20Sopenharmony_ci * Called by regulator drivers to register a regulator.
52678c2ecf20Sopenharmony_ci * Returns a valid pointer to struct regulator_dev on success
52688c2ecf20Sopenharmony_ci * or an ERR_PTR() on error.
52698c2ecf20Sopenharmony_ci */
52708c2ecf20Sopenharmony_cistruct regulator_dev *
52718c2ecf20Sopenharmony_ciregulator_register(const struct regulator_desc *regulator_desc,
52728c2ecf20Sopenharmony_ci		   const struct regulator_config *cfg)
52738c2ecf20Sopenharmony_ci{
52748c2ecf20Sopenharmony_ci	const struct regulator_init_data *init_data;
52758c2ecf20Sopenharmony_ci	struct regulator_config *config = NULL;
52768c2ecf20Sopenharmony_ci	static atomic_t regulator_no = ATOMIC_INIT(-1);
52778c2ecf20Sopenharmony_ci	struct regulator_dev *rdev;
52788c2ecf20Sopenharmony_ci	bool dangling_cfg_gpiod = false;
52798c2ecf20Sopenharmony_ci	bool dangling_of_gpiod = false;
52808c2ecf20Sopenharmony_ci	struct device *dev;
52818c2ecf20Sopenharmony_ci	int ret, i;
52828c2ecf20Sopenharmony_ci
52838c2ecf20Sopenharmony_ci	if (cfg == NULL)
52848c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
52858c2ecf20Sopenharmony_ci	if (cfg->ena_gpiod)
52868c2ecf20Sopenharmony_ci		dangling_cfg_gpiod = true;
52878c2ecf20Sopenharmony_ci	if (regulator_desc == NULL) {
52888c2ecf20Sopenharmony_ci		ret = -EINVAL;
52898c2ecf20Sopenharmony_ci		goto rinse;
52908c2ecf20Sopenharmony_ci	}
52918c2ecf20Sopenharmony_ci
52928c2ecf20Sopenharmony_ci	dev = cfg->dev;
52938c2ecf20Sopenharmony_ci	WARN_ON(!dev);
52948c2ecf20Sopenharmony_ci
52958c2ecf20Sopenharmony_ci	if (regulator_desc->name == NULL || regulator_desc->ops == NULL) {
52968c2ecf20Sopenharmony_ci		ret = -EINVAL;
52978c2ecf20Sopenharmony_ci		goto rinse;
52988c2ecf20Sopenharmony_ci	}
52998c2ecf20Sopenharmony_ci
53008c2ecf20Sopenharmony_ci	if (regulator_desc->type != REGULATOR_VOLTAGE &&
53018c2ecf20Sopenharmony_ci	    regulator_desc->type != REGULATOR_CURRENT) {
53028c2ecf20Sopenharmony_ci		ret = -EINVAL;
53038c2ecf20Sopenharmony_ci		goto rinse;
53048c2ecf20Sopenharmony_ci	}
53058c2ecf20Sopenharmony_ci
53068c2ecf20Sopenharmony_ci	/* Only one of each should be implemented */
53078c2ecf20Sopenharmony_ci	WARN_ON(regulator_desc->ops->get_voltage &&
53088c2ecf20Sopenharmony_ci		regulator_desc->ops->get_voltage_sel);
53098c2ecf20Sopenharmony_ci	WARN_ON(regulator_desc->ops->set_voltage &&
53108c2ecf20Sopenharmony_ci		regulator_desc->ops->set_voltage_sel);
53118c2ecf20Sopenharmony_ci
53128c2ecf20Sopenharmony_ci	/* If we're using selectors we must implement list_voltage. */
53138c2ecf20Sopenharmony_ci	if (regulator_desc->ops->get_voltage_sel &&
53148c2ecf20Sopenharmony_ci	    !regulator_desc->ops->list_voltage) {
53158c2ecf20Sopenharmony_ci		ret = -EINVAL;
53168c2ecf20Sopenharmony_ci		goto rinse;
53178c2ecf20Sopenharmony_ci	}
53188c2ecf20Sopenharmony_ci	if (regulator_desc->ops->set_voltage_sel &&
53198c2ecf20Sopenharmony_ci	    !regulator_desc->ops->list_voltage) {
53208c2ecf20Sopenharmony_ci		ret = -EINVAL;
53218c2ecf20Sopenharmony_ci		goto rinse;
53228c2ecf20Sopenharmony_ci	}
53238c2ecf20Sopenharmony_ci
53248c2ecf20Sopenharmony_ci	rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
53258c2ecf20Sopenharmony_ci	if (rdev == NULL) {
53268c2ecf20Sopenharmony_ci		ret = -ENOMEM;
53278c2ecf20Sopenharmony_ci		goto rinse;
53288c2ecf20Sopenharmony_ci	}
53298c2ecf20Sopenharmony_ci	device_initialize(&rdev->dev);
53308c2ecf20Sopenharmony_ci
53318c2ecf20Sopenharmony_ci	/*
53328c2ecf20Sopenharmony_ci	 * Duplicate the config so the driver could override it after
53338c2ecf20Sopenharmony_ci	 * parsing init data.
53348c2ecf20Sopenharmony_ci	 */
53358c2ecf20Sopenharmony_ci	config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL);
53368c2ecf20Sopenharmony_ci	if (config == NULL) {
53378c2ecf20Sopenharmony_ci		ret = -ENOMEM;
53388c2ecf20Sopenharmony_ci		goto clean;
53398c2ecf20Sopenharmony_ci	}
53408c2ecf20Sopenharmony_ci
53418c2ecf20Sopenharmony_ci	init_data = regulator_of_get_init_data(dev, regulator_desc, config,
53428c2ecf20Sopenharmony_ci					       &rdev->dev.of_node);
53438c2ecf20Sopenharmony_ci
53448c2ecf20Sopenharmony_ci	/*
53458c2ecf20Sopenharmony_ci	 * Sometimes not all resources are probed already so we need to take
53468c2ecf20Sopenharmony_ci	 * that into account. This happens most the time if the ena_gpiod comes
53478c2ecf20Sopenharmony_ci	 * from a gpio extender or something else.
53488c2ecf20Sopenharmony_ci	 */
53498c2ecf20Sopenharmony_ci	if (PTR_ERR(init_data) == -EPROBE_DEFER) {
53508c2ecf20Sopenharmony_ci		ret = -EPROBE_DEFER;
53518c2ecf20Sopenharmony_ci		goto clean;
53528c2ecf20Sopenharmony_ci	}
53538c2ecf20Sopenharmony_ci
53548c2ecf20Sopenharmony_ci	/*
53558c2ecf20Sopenharmony_ci	 * We need to keep track of any GPIO descriptor coming from the
53568c2ecf20Sopenharmony_ci	 * device tree until we have handled it over to the core. If the
53578c2ecf20Sopenharmony_ci	 * config that was passed in to this function DOES NOT contain
53588c2ecf20Sopenharmony_ci	 * a descriptor, and the config after this call DOES contain
53598c2ecf20Sopenharmony_ci	 * a descriptor, we definitely got one from parsing the device
53608c2ecf20Sopenharmony_ci	 * tree.
53618c2ecf20Sopenharmony_ci	 */
53628c2ecf20Sopenharmony_ci	if (!cfg->ena_gpiod && config->ena_gpiod)
53638c2ecf20Sopenharmony_ci		dangling_of_gpiod = true;
53648c2ecf20Sopenharmony_ci	if (!init_data) {
53658c2ecf20Sopenharmony_ci		init_data = config->init_data;
53668c2ecf20Sopenharmony_ci		rdev->dev.of_node = of_node_get(config->of_node);
53678c2ecf20Sopenharmony_ci	}
53688c2ecf20Sopenharmony_ci
53698c2ecf20Sopenharmony_ci	ww_mutex_init(&rdev->mutex, &regulator_ww_class);
53708c2ecf20Sopenharmony_ci	rdev->reg_data = config->driver_data;
53718c2ecf20Sopenharmony_ci	rdev->owner = regulator_desc->owner;
53728c2ecf20Sopenharmony_ci	rdev->desc = regulator_desc;
53738c2ecf20Sopenharmony_ci	if (config->regmap)
53748c2ecf20Sopenharmony_ci		rdev->regmap = config->regmap;
53758c2ecf20Sopenharmony_ci	else if (dev_get_regmap(dev, NULL))
53768c2ecf20Sopenharmony_ci		rdev->regmap = dev_get_regmap(dev, NULL);
53778c2ecf20Sopenharmony_ci	else if (dev->parent)
53788c2ecf20Sopenharmony_ci		rdev->regmap = dev_get_regmap(dev->parent, NULL);
53798c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&rdev->consumer_list);
53808c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&rdev->list);
53818c2ecf20Sopenharmony_ci	BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
53828c2ecf20Sopenharmony_ci	INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work);
53838c2ecf20Sopenharmony_ci
53848c2ecf20Sopenharmony_ci	/* preform any regulator specific init */
53858c2ecf20Sopenharmony_ci	if (init_data && init_data->regulator_init) {
53868c2ecf20Sopenharmony_ci		ret = init_data->regulator_init(rdev->reg_data);
53878c2ecf20Sopenharmony_ci		if (ret < 0)
53888c2ecf20Sopenharmony_ci			goto clean;
53898c2ecf20Sopenharmony_ci	}
53908c2ecf20Sopenharmony_ci
53918c2ecf20Sopenharmony_ci	if (config->ena_gpiod) {
53928c2ecf20Sopenharmony_ci		ret = regulator_ena_gpio_request(rdev, config);
53938c2ecf20Sopenharmony_ci		if (ret != 0) {
53948c2ecf20Sopenharmony_ci			rdev_err(rdev, "Failed to request enable GPIO: %pe\n",
53958c2ecf20Sopenharmony_ci				 ERR_PTR(ret));
53968c2ecf20Sopenharmony_ci			goto clean;
53978c2ecf20Sopenharmony_ci		}
53988c2ecf20Sopenharmony_ci		/* The regulator core took over the GPIO descriptor */
53998c2ecf20Sopenharmony_ci		dangling_cfg_gpiod = false;
54008c2ecf20Sopenharmony_ci		dangling_of_gpiod = false;
54018c2ecf20Sopenharmony_ci	}
54028c2ecf20Sopenharmony_ci
54038c2ecf20Sopenharmony_ci	/* register with sysfs */
54048c2ecf20Sopenharmony_ci	rdev->dev.class = &regulator_class;
54058c2ecf20Sopenharmony_ci	rdev->dev.parent = dev;
54068c2ecf20Sopenharmony_ci	dev_set_name(&rdev->dev, "regulator.%lu",
54078c2ecf20Sopenharmony_ci		    (unsigned long) atomic_inc_return(&regulator_no));
54088c2ecf20Sopenharmony_ci	dev_set_drvdata(&rdev->dev, rdev);
54098c2ecf20Sopenharmony_ci
54108c2ecf20Sopenharmony_ci	/* set regulator constraints */
54118c2ecf20Sopenharmony_ci	if (init_data)
54128c2ecf20Sopenharmony_ci		rdev->constraints = kmemdup(&init_data->constraints,
54138c2ecf20Sopenharmony_ci					    sizeof(*rdev->constraints),
54148c2ecf20Sopenharmony_ci					    GFP_KERNEL);
54158c2ecf20Sopenharmony_ci	else
54168c2ecf20Sopenharmony_ci		rdev->constraints = kzalloc(sizeof(*rdev->constraints),
54178c2ecf20Sopenharmony_ci					    GFP_KERNEL);
54188c2ecf20Sopenharmony_ci	if (!rdev->constraints) {
54198c2ecf20Sopenharmony_ci		ret = -ENOMEM;
54208c2ecf20Sopenharmony_ci		goto wash;
54218c2ecf20Sopenharmony_ci	}
54228c2ecf20Sopenharmony_ci
54238c2ecf20Sopenharmony_ci	if (init_data && init_data->supply_regulator)
54248c2ecf20Sopenharmony_ci		rdev->supply_name = init_data->supply_regulator;
54258c2ecf20Sopenharmony_ci	else if (regulator_desc->supply_name)
54268c2ecf20Sopenharmony_ci		rdev->supply_name = regulator_desc->supply_name;
54278c2ecf20Sopenharmony_ci
54288c2ecf20Sopenharmony_ci	ret = set_machine_constraints(rdev);
54298c2ecf20Sopenharmony_ci	if (ret == -EPROBE_DEFER) {
54308c2ecf20Sopenharmony_ci		/* Regulator might be in bypass mode and so needs its supply
54318c2ecf20Sopenharmony_ci		 * to set the constraints */
54328c2ecf20Sopenharmony_ci		/* FIXME: this currently triggers a chicken-and-egg problem
54338c2ecf20Sopenharmony_ci		 * when creating -SUPPLY symlink in sysfs to a regulator
54348c2ecf20Sopenharmony_ci		 * that is just being created */
54358c2ecf20Sopenharmony_ci		ret = regulator_resolve_supply(rdev);
54368c2ecf20Sopenharmony_ci		if (!ret)
54378c2ecf20Sopenharmony_ci			ret = set_machine_constraints(rdev);
54388c2ecf20Sopenharmony_ci		else
54398c2ecf20Sopenharmony_ci			rdev_dbg(rdev, "unable to resolve supply early: %pe\n",
54408c2ecf20Sopenharmony_ci				 ERR_PTR(ret));
54418c2ecf20Sopenharmony_ci	}
54428c2ecf20Sopenharmony_ci	if (ret < 0)
54438c2ecf20Sopenharmony_ci		goto wash;
54448c2ecf20Sopenharmony_ci
54458c2ecf20Sopenharmony_ci	ret = regulator_init_coupling(rdev);
54468c2ecf20Sopenharmony_ci	if (ret < 0)
54478c2ecf20Sopenharmony_ci		goto wash;
54488c2ecf20Sopenharmony_ci
54498c2ecf20Sopenharmony_ci	/* add consumers devices */
54508c2ecf20Sopenharmony_ci	if (init_data) {
54518c2ecf20Sopenharmony_ci		for (i = 0; i < init_data->num_consumer_supplies; i++) {
54528c2ecf20Sopenharmony_ci			ret = set_consumer_device_supply(rdev,
54538c2ecf20Sopenharmony_ci				init_data->consumer_supplies[i].dev_name,
54548c2ecf20Sopenharmony_ci				init_data->consumer_supplies[i].supply);
54558c2ecf20Sopenharmony_ci			if (ret < 0) {
54568c2ecf20Sopenharmony_ci				dev_err(dev, "Failed to set supply %s\n",
54578c2ecf20Sopenharmony_ci					init_data->consumer_supplies[i].supply);
54588c2ecf20Sopenharmony_ci				goto unset_supplies;
54598c2ecf20Sopenharmony_ci			}
54608c2ecf20Sopenharmony_ci		}
54618c2ecf20Sopenharmony_ci	}
54628c2ecf20Sopenharmony_ci
54638c2ecf20Sopenharmony_ci	if (!rdev->desc->ops->get_voltage &&
54648c2ecf20Sopenharmony_ci	    !rdev->desc->ops->list_voltage &&
54658c2ecf20Sopenharmony_ci	    !rdev->desc->fixed_uV)
54668c2ecf20Sopenharmony_ci		rdev->is_switch = true;
54678c2ecf20Sopenharmony_ci
54688c2ecf20Sopenharmony_ci	ret = device_add(&rdev->dev);
54698c2ecf20Sopenharmony_ci	if (ret != 0)
54708c2ecf20Sopenharmony_ci		goto unset_supplies;
54718c2ecf20Sopenharmony_ci
54728c2ecf20Sopenharmony_ci	rdev_init_debugfs(rdev);
54738c2ecf20Sopenharmony_ci
54748c2ecf20Sopenharmony_ci	/* try to resolve regulators coupling since a new one was registered */
54758c2ecf20Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
54768c2ecf20Sopenharmony_ci	regulator_resolve_coupling(rdev);
54778c2ecf20Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
54788c2ecf20Sopenharmony_ci
54798c2ecf20Sopenharmony_ci	/* try to resolve regulators supply since a new one was registered */
54808c2ecf20Sopenharmony_ci	class_for_each_device(&regulator_class, NULL, NULL,
54818c2ecf20Sopenharmony_ci			      regulator_register_resolve_supply);
54828c2ecf20Sopenharmony_ci	kfree(config);
54838c2ecf20Sopenharmony_ci	return rdev;
54848c2ecf20Sopenharmony_ci
54858c2ecf20Sopenharmony_ciunset_supplies:
54868c2ecf20Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
54878c2ecf20Sopenharmony_ci	unset_regulator_supplies(rdev);
54888c2ecf20Sopenharmony_ci	regulator_remove_coupling(rdev);
54898c2ecf20Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
54908c2ecf20Sopenharmony_ciwash:
54918c2ecf20Sopenharmony_ci	regulator_put(rdev->supply);
54928c2ecf20Sopenharmony_ci	kfree(rdev->coupling_desc.coupled_rdevs);
54938c2ecf20Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
54948c2ecf20Sopenharmony_ci	regulator_ena_gpio_free(rdev);
54958c2ecf20Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
54968c2ecf20Sopenharmony_ciclean:
54978c2ecf20Sopenharmony_ci	if (dangling_of_gpiod)
54988c2ecf20Sopenharmony_ci		gpiod_put(config->ena_gpiod);
54998c2ecf20Sopenharmony_ci	kfree(config);
55008c2ecf20Sopenharmony_ci	put_device(&rdev->dev);
55018c2ecf20Sopenharmony_cirinse:
55028c2ecf20Sopenharmony_ci	if (dangling_cfg_gpiod)
55038c2ecf20Sopenharmony_ci		gpiod_put(cfg->ena_gpiod);
55048c2ecf20Sopenharmony_ci	return ERR_PTR(ret);
55058c2ecf20Sopenharmony_ci}
55068c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_register);
55078c2ecf20Sopenharmony_ci
55088c2ecf20Sopenharmony_ci/**
55098c2ecf20Sopenharmony_ci * regulator_unregister - unregister regulator
55108c2ecf20Sopenharmony_ci * @rdev: regulator to unregister
55118c2ecf20Sopenharmony_ci *
55128c2ecf20Sopenharmony_ci * Called by regulator drivers to unregister a regulator.
55138c2ecf20Sopenharmony_ci */
55148c2ecf20Sopenharmony_civoid regulator_unregister(struct regulator_dev *rdev)
55158c2ecf20Sopenharmony_ci{
55168c2ecf20Sopenharmony_ci	if (rdev == NULL)
55178c2ecf20Sopenharmony_ci		return;
55188c2ecf20Sopenharmony_ci
55198c2ecf20Sopenharmony_ci	if (rdev->supply) {
55208c2ecf20Sopenharmony_ci		while (rdev->use_count--)
55218c2ecf20Sopenharmony_ci			regulator_disable(rdev->supply);
55228c2ecf20Sopenharmony_ci		regulator_put(rdev->supply);
55238c2ecf20Sopenharmony_ci	}
55248c2ecf20Sopenharmony_ci
55258c2ecf20Sopenharmony_ci	flush_work(&rdev->disable_work.work);
55268c2ecf20Sopenharmony_ci
55278c2ecf20Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
55288c2ecf20Sopenharmony_ci
55298c2ecf20Sopenharmony_ci	WARN_ON(rdev->open_count);
55308c2ecf20Sopenharmony_ci	regulator_remove_coupling(rdev);
55318c2ecf20Sopenharmony_ci	unset_regulator_supplies(rdev);
55328c2ecf20Sopenharmony_ci	list_del(&rdev->list);
55338c2ecf20Sopenharmony_ci	regulator_ena_gpio_free(rdev);
55348c2ecf20Sopenharmony_ci	device_unregister(&rdev->dev);
55358c2ecf20Sopenharmony_ci
55368c2ecf20Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
55378c2ecf20Sopenharmony_ci}
55388c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_unregister);
55398c2ecf20Sopenharmony_ci
55408c2ecf20Sopenharmony_ci#ifdef CONFIG_SUSPEND
55418c2ecf20Sopenharmony_ci/**
55428c2ecf20Sopenharmony_ci * regulator_suspend - prepare regulators for system wide suspend
55438c2ecf20Sopenharmony_ci * @dev: ``&struct device`` pointer that is passed to _regulator_suspend()
55448c2ecf20Sopenharmony_ci *
55458c2ecf20Sopenharmony_ci * Configure each regulator with it's suspend operating parameters for state.
55468c2ecf20Sopenharmony_ci */
55478c2ecf20Sopenharmony_cistatic int regulator_suspend(struct device *dev)
55488c2ecf20Sopenharmony_ci{
55498c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
55508c2ecf20Sopenharmony_ci	suspend_state_t state = pm_suspend_target_state;
55518c2ecf20Sopenharmony_ci	int ret;
55528c2ecf20Sopenharmony_ci	const struct regulator_state *rstate;
55538c2ecf20Sopenharmony_ci
55548c2ecf20Sopenharmony_ci	rstate = regulator_get_suspend_state_check(rdev, state);
55558c2ecf20Sopenharmony_ci	if (!rstate)
55568c2ecf20Sopenharmony_ci		return 0;
55578c2ecf20Sopenharmony_ci
55588c2ecf20Sopenharmony_ci	regulator_lock(rdev);
55598c2ecf20Sopenharmony_ci	ret = __suspend_set_state(rdev, rstate);
55608c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
55618c2ecf20Sopenharmony_ci
55628c2ecf20Sopenharmony_ci	return ret;
55638c2ecf20Sopenharmony_ci}
55648c2ecf20Sopenharmony_ci
55658c2ecf20Sopenharmony_cistatic int regulator_resume(struct device *dev)
55668c2ecf20Sopenharmony_ci{
55678c2ecf20Sopenharmony_ci	suspend_state_t state = pm_suspend_target_state;
55688c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
55698c2ecf20Sopenharmony_ci	struct regulator_state *rstate;
55708c2ecf20Sopenharmony_ci	int ret = 0;
55718c2ecf20Sopenharmony_ci
55728c2ecf20Sopenharmony_ci	rstate = regulator_get_suspend_state(rdev, state);
55738c2ecf20Sopenharmony_ci	if (rstate == NULL)
55748c2ecf20Sopenharmony_ci		return 0;
55758c2ecf20Sopenharmony_ci
55768c2ecf20Sopenharmony_ci	/* Avoid grabbing the lock if we don't need to */
55778c2ecf20Sopenharmony_ci	if (!rdev->desc->ops->resume)
55788c2ecf20Sopenharmony_ci		return 0;
55798c2ecf20Sopenharmony_ci
55808c2ecf20Sopenharmony_ci	regulator_lock(rdev);
55818c2ecf20Sopenharmony_ci
55828c2ecf20Sopenharmony_ci	if (rstate->enabled == ENABLE_IN_SUSPEND ||
55838c2ecf20Sopenharmony_ci	    rstate->enabled == DISABLE_IN_SUSPEND)
55848c2ecf20Sopenharmony_ci		ret = rdev->desc->ops->resume(rdev);
55858c2ecf20Sopenharmony_ci
55868c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
55878c2ecf20Sopenharmony_ci
55888c2ecf20Sopenharmony_ci	return ret;
55898c2ecf20Sopenharmony_ci}
55908c2ecf20Sopenharmony_ci#else /* !CONFIG_SUSPEND */
55918c2ecf20Sopenharmony_ci
55928c2ecf20Sopenharmony_ci#define regulator_suspend	NULL
55938c2ecf20Sopenharmony_ci#define regulator_resume	NULL
55948c2ecf20Sopenharmony_ci
55958c2ecf20Sopenharmony_ci#endif /* !CONFIG_SUSPEND */
55968c2ecf20Sopenharmony_ci
55978c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
55988c2ecf20Sopenharmony_cistatic const struct dev_pm_ops __maybe_unused regulator_pm_ops = {
55998c2ecf20Sopenharmony_ci	.suspend	= regulator_suspend,
56008c2ecf20Sopenharmony_ci	.resume		= regulator_resume,
56018c2ecf20Sopenharmony_ci};
56028c2ecf20Sopenharmony_ci#endif
56038c2ecf20Sopenharmony_ci
56048c2ecf20Sopenharmony_cistruct class regulator_class = {
56058c2ecf20Sopenharmony_ci	.name = "regulator",
56068c2ecf20Sopenharmony_ci	.dev_release = regulator_dev_release,
56078c2ecf20Sopenharmony_ci	.dev_groups = regulator_dev_groups,
56088c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
56098c2ecf20Sopenharmony_ci	.pm = &regulator_pm_ops,
56108c2ecf20Sopenharmony_ci#endif
56118c2ecf20Sopenharmony_ci};
56128c2ecf20Sopenharmony_ci/**
56138c2ecf20Sopenharmony_ci * regulator_has_full_constraints - the system has fully specified constraints
56148c2ecf20Sopenharmony_ci *
56158c2ecf20Sopenharmony_ci * Calling this function will cause the regulator API to disable all
56168c2ecf20Sopenharmony_ci * regulators which have a zero use count and don't have an always_on
56178c2ecf20Sopenharmony_ci * constraint in a late_initcall.
56188c2ecf20Sopenharmony_ci *
56198c2ecf20Sopenharmony_ci * The intention is that this will become the default behaviour in a
56208c2ecf20Sopenharmony_ci * future kernel release so users are encouraged to use this facility
56218c2ecf20Sopenharmony_ci * now.
56228c2ecf20Sopenharmony_ci */
56238c2ecf20Sopenharmony_civoid regulator_has_full_constraints(void)
56248c2ecf20Sopenharmony_ci{
56258c2ecf20Sopenharmony_ci	has_full_constraints = 1;
56268c2ecf20Sopenharmony_ci}
56278c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_has_full_constraints);
56288c2ecf20Sopenharmony_ci
56298c2ecf20Sopenharmony_ci/**
56308c2ecf20Sopenharmony_ci * rdev_get_drvdata - get rdev regulator driver data
56318c2ecf20Sopenharmony_ci * @rdev: regulator
56328c2ecf20Sopenharmony_ci *
56338c2ecf20Sopenharmony_ci * Get rdev regulator driver private data. This call can be used in the
56348c2ecf20Sopenharmony_ci * regulator driver context.
56358c2ecf20Sopenharmony_ci */
56368c2ecf20Sopenharmony_civoid *rdev_get_drvdata(struct regulator_dev *rdev)
56378c2ecf20Sopenharmony_ci{
56388c2ecf20Sopenharmony_ci	return rdev->reg_data;
56398c2ecf20Sopenharmony_ci}
56408c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rdev_get_drvdata);
56418c2ecf20Sopenharmony_ci
56428c2ecf20Sopenharmony_ci/**
56438c2ecf20Sopenharmony_ci * regulator_get_drvdata - get regulator driver data
56448c2ecf20Sopenharmony_ci * @regulator: regulator
56458c2ecf20Sopenharmony_ci *
56468c2ecf20Sopenharmony_ci * Get regulator driver private data. This call can be used in the consumer
56478c2ecf20Sopenharmony_ci * driver context when non API regulator specific functions need to be called.
56488c2ecf20Sopenharmony_ci */
56498c2ecf20Sopenharmony_civoid *regulator_get_drvdata(struct regulator *regulator)
56508c2ecf20Sopenharmony_ci{
56518c2ecf20Sopenharmony_ci	return regulator->rdev->reg_data;
56528c2ecf20Sopenharmony_ci}
56538c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_drvdata);
56548c2ecf20Sopenharmony_ci
56558c2ecf20Sopenharmony_ci/**
56568c2ecf20Sopenharmony_ci * regulator_set_drvdata - set regulator driver data
56578c2ecf20Sopenharmony_ci * @regulator: regulator
56588c2ecf20Sopenharmony_ci * @data: data
56598c2ecf20Sopenharmony_ci */
56608c2ecf20Sopenharmony_civoid regulator_set_drvdata(struct regulator *regulator, void *data)
56618c2ecf20Sopenharmony_ci{
56628c2ecf20Sopenharmony_ci	regulator->rdev->reg_data = data;
56638c2ecf20Sopenharmony_ci}
56648c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_set_drvdata);
56658c2ecf20Sopenharmony_ci
56668c2ecf20Sopenharmony_ci/**
56678c2ecf20Sopenharmony_ci * regulator_get_id - get regulator ID
56688c2ecf20Sopenharmony_ci * @rdev: regulator
56698c2ecf20Sopenharmony_ci */
56708c2ecf20Sopenharmony_ciint rdev_get_id(struct regulator_dev *rdev)
56718c2ecf20Sopenharmony_ci{
56728c2ecf20Sopenharmony_ci	return rdev->desc->id;
56738c2ecf20Sopenharmony_ci}
56748c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rdev_get_id);
56758c2ecf20Sopenharmony_ci
56768c2ecf20Sopenharmony_cistruct device *rdev_get_dev(struct regulator_dev *rdev)
56778c2ecf20Sopenharmony_ci{
56788c2ecf20Sopenharmony_ci	return &rdev->dev;
56798c2ecf20Sopenharmony_ci}
56808c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rdev_get_dev);
56818c2ecf20Sopenharmony_ci
56828c2ecf20Sopenharmony_cistruct regmap *rdev_get_regmap(struct regulator_dev *rdev)
56838c2ecf20Sopenharmony_ci{
56848c2ecf20Sopenharmony_ci	return rdev->regmap;
56858c2ecf20Sopenharmony_ci}
56868c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(rdev_get_regmap);
56878c2ecf20Sopenharmony_ci
56888c2ecf20Sopenharmony_civoid *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
56898c2ecf20Sopenharmony_ci{
56908c2ecf20Sopenharmony_ci	return reg_init_data->driver_data;
56918c2ecf20Sopenharmony_ci}
56928c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
56938c2ecf20Sopenharmony_ci
56948c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
56958c2ecf20Sopenharmony_cistatic int supply_map_show(struct seq_file *sf, void *data)
56968c2ecf20Sopenharmony_ci{
56978c2ecf20Sopenharmony_ci	struct regulator_map *map;
56988c2ecf20Sopenharmony_ci
56998c2ecf20Sopenharmony_ci	list_for_each_entry(map, &regulator_map_list, list) {
57008c2ecf20Sopenharmony_ci		seq_printf(sf, "%s -> %s.%s\n",
57018c2ecf20Sopenharmony_ci				rdev_get_name(map->regulator), map->dev_name,
57028c2ecf20Sopenharmony_ci				map->supply);
57038c2ecf20Sopenharmony_ci	}
57048c2ecf20Sopenharmony_ci
57058c2ecf20Sopenharmony_ci	return 0;
57068c2ecf20Sopenharmony_ci}
57078c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(supply_map);
57088c2ecf20Sopenharmony_ci
57098c2ecf20Sopenharmony_cistruct summary_data {
57108c2ecf20Sopenharmony_ci	struct seq_file *s;
57118c2ecf20Sopenharmony_ci	struct regulator_dev *parent;
57128c2ecf20Sopenharmony_ci	int level;
57138c2ecf20Sopenharmony_ci};
57148c2ecf20Sopenharmony_ci
57158c2ecf20Sopenharmony_cistatic void regulator_summary_show_subtree(struct seq_file *s,
57168c2ecf20Sopenharmony_ci					   struct regulator_dev *rdev,
57178c2ecf20Sopenharmony_ci					   int level);
57188c2ecf20Sopenharmony_ci
57198c2ecf20Sopenharmony_cistatic int regulator_summary_show_children(struct device *dev, void *data)
57208c2ecf20Sopenharmony_ci{
57218c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
57228c2ecf20Sopenharmony_ci	struct summary_data *summary_data = data;
57238c2ecf20Sopenharmony_ci
57248c2ecf20Sopenharmony_ci	if (rdev->supply && rdev->supply->rdev == summary_data->parent)
57258c2ecf20Sopenharmony_ci		regulator_summary_show_subtree(summary_data->s, rdev,
57268c2ecf20Sopenharmony_ci					       summary_data->level + 1);
57278c2ecf20Sopenharmony_ci
57288c2ecf20Sopenharmony_ci	return 0;
57298c2ecf20Sopenharmony_ci}
57308c2ecf20Sopenharmony_ci
57318c2ecf20Sopenharmony_cistatic void regulator_summary_show_subtree(struct seq_file *s,
57328c2ecf20Sopenharmony_ci					   struct regulator_dev *rdev,
57338c2ecf20Sopenharmony_ci					   int level)
57348c2ecf20Sopenharmony_ci{
57358c2ecf20Sopenharmony_ci	struct regulation_constraints *c;
57368c2ecf20Sopenharmony_ci	struct regulator *consumer;
57378c2ecf20Sopenharmony_ci	struct summary_data summary_data;
57388c2ecf20Sopenharmony_ci	unsigned int opmode;
57398c2ecf20Sopenharmony_ci
57408c2ecf20Sopenharmony_ci	if (!rdev)
57418c2ecf20Sopenharmony_ci		return;
57428c2ecf20Sopenharmony_ci
57438c2ecf20Sopenharmony_ci	opmode = _regulator_get_mode_unlocked(rdev);
57448c2ecf20Sopenharmony_ci	seq_printf(s, "%*s%-*s %3d %4d %6d %7s ",
57458c2ecf20Sopenharmony_ci		   level * 3 + 1, "",
57468c2ecf20Sopenharmony_ci		   30 - level * 3, rdev_get_name(rdev),
57478c2ecf20Sopenharmony_ci		   rdev->use_count, rdev->open_count, rdev->bypass_count,
57488c2ecf20Sopenharmony_ci		   regulator_opmode_to_str(opmode));
57498c2ecf20Sopenharmony_ci
57508c2ecf20Sopenharmony_ci	seq_printf(s, "%5dmV ", regulator_get_voltage_rdev(rdev) / 1000);
57518c2ecf20Sopenharmony_ci	seq_printf(s, "%5dmA ",
57528c2ecf20Sopenharmony_ci		   _regulator_get_current_limit_unlocked(rdev) / 1000);
57538c2ecf20Sopenharmony_ci
57548c2ecf20Sopenharmony_ci	c = rdev->constraints;
57558c2ecf20Sopenharmony_ci	if (c) {
57568c2ecf20Sopenharmony_ci		switch (rdev->desc->type) {
57578c2ecf20Sopenharmony_ci		case REGULATOR_VOLTAGE:
57588c2ecf20Sopenharmony_ci			seq_printf(s, "%5dmV %5dmV ",
57598c2ecf20Sopenharmony_ci				   c->min_uV / 1000, c->max_uV / 1000);
57608c2ecf20Sopenharmony_ci			break;
57618c2ecf20Sopenharmony_ci		case REGULATOR_CURRENT:
57628c2ecf20Sopenharmony_ci			seq_printf(s, "%5dmA %5dmA ",
57638c2ecf20Sopenharmony_ci				   c->min_uA / 1000, c->max_uA / 1000);
57648c2ecf20Sopenharmony_ci			break;
57658c2ecf20Sopenharmony_ci		}
57668c2ecf20Sopenharmony_ci	}
57678c2ecf20Sopenharmony_ci
57688c2ecf20Sopenharmony_ci	seq_puts(s, "\n");
57698c2ecf20Sopenharmony_ci
57708c2ecf20Sopenharmony_ci	list_for_each_entry(consumer, &rdev->consumer_list, list) {
57718c2ecf20Sopenharmony_ci		if (consumer->dev && consumer->dev->class == &regulator_class)
57728c2ecf20Sopenharmony_ci			continue;
57738c2ecf20Sopenharmony_ci
57748c2ecf20Sopenharmony_ci		seq_printf(s, "%*s%-*s ",
57758c2ecf20Sopenharmony_ci			   (level + 1) * 3 + 1, "",
57768c2ecf20Sopenharmony_ci			   30 - (level + 1) * 3,
57778c2ecf20Sopenharmony_ci			   consumer->supply_name ? consumer->supply_name :
57788c2ecf20Sopenharmony_ci			   consumer->dev ? dev_name(consumer->dev) : "deviceless");
57798c2ecf20Sopenharmony_ci
57808c2ecf20Sopenharmony_ci		switch (rdev->desc->type) {
57818c2ecf20Sopenharmony_ci		case REGULATOR_VOLTAGE:
57828c2ecf20Sopenharmony_ci			seq_printf(s, "%3d %33dmA%c%5dmV %5dmV",
57838c2ecf20Sopenharmony_ci				   consumer->enable_count,
57848c2ecf20Sopenharmony_ci				   consumer->uA_load / 1000,
57858c2ecf20Sopenharmony_ci				   consumer->uA_load && !consumer->enable_count ?
57868c2ecf20Sopenharmony_ci				   '*' : ' ',
57878c2ecf20Sopenharmony_ci				   consumer->voltage[PM_SUSPEND_ON].min_uV / 1000,
57888c2ecf20Sopenharmony_ci				   consumer->voltage[PM_SUSPEND_ON].max_uV / 1000);
57898c2ecf20Sopenharmony_ci			break;
57908c2ecf20Sopenharmony_ci		case REGULATOR_CURRENT:
57918c2ecf20Sopenharmony_ci			break;
57928c2ecf20Sopenharmony_ci		}
57938c2ecf20Sopenharmony_ci
57948c2ecf20Sopenharmony_ci		seq_puts(s, "\n");
57958c2ecf20Sopenharmony_ci	}
57968c2ecf20Sopenharmony_ci
57978c2ecf20Sopenharmony_ci	summary_data.s = s;
57988c2ecf20Sopenharmony_ci	summary_data.level = level;
57998c2ecf20Sopenharmony_ci	summary_data.parent = rdev;
58008c2ecf20Sopenharmony_ci
58018c2ecf20Sopenharmony_ci	class_for_each_device(&regulator_class, NULL, &summary_data,
58028c2ecf20Sopenharmony_ci			      regulator_summary_show_children);
58038c2ecf20Sopenharmony_ci}
58048c2ecf20Sopenharmony_ci
58058c2ecf20Sopenharmony_cistruct summary_lock_data {
58068c2ecf20Sopenharmony_ci	struct ww_acquire_ctx *ww_ctx;
58078c2ecf20Sopenharmony_ci	struct regulator_dev **new_contended_rdev;
58088c2ecf20Sopenharmony_ci	struct regulator_dev **old_contended_rdev;
58098c2ecf20Sopenharmony_ci};
58108c2ecf20Sopenharmony_ci
58118c2ecf20Sopenharmony_cistatic int regulator_summary_lock_one(struct device *dev, void *data)
58128c2ecf20Sopenharmony_ci{
58138c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
58148c2ecf20Sopenharmony_ci	struct summary_lock_data *lock_data = data;
58158c2ecf20Sopenharmony_ci	int ret = 0;
58168c2ecf20Sopenharmony_ci
58178c2ecf20Sopenharmony_ci	if (rdev != *lock_data->old_contended_rdev) {
58188c2ecf20Sopenharmony_ci		ret = regulator_lock_nested(rdev, lock_data->ww_ctx);
58198c2ecf20Sopenharmony_ci
58208c2ecf20Sopenharmony_ci		if (ret == -EDEADLK)
58218c2ecf20Sopenharmony_ci			*lock_data->new_contended_rdev = rdev;
58228c2ecf20Sopenharmony_ci		else
58238c2ecf20Sopenharmony_ci			WARN_ON_ONCE(ret);
58248c2ecf20Sopenharmony_ci	} else {
58258c2ecf20Sopenharmony_ci		*lock_data->old_contended_rdev = NULL;
58268c2ecf20Sopenharmony_ci	}
58278c2ecf20Sopenharmony_ci
58288c2ecf20Sopenharmony_ci	return ret;
58298c2ecf20Sopenharmony_ci}
58308c2ecf20Sopenharmony_ci
58318c2ecf20Sopenharmony_cistatic int regulator_summary_unlock_one(struct device *dev, void *data)
58328c2ecf20Sopenharmony_ci{
58338c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
58348c2ecf20Sopenharmony_ci	struct summary_lock_data *lock_data = data;
58358c2ecf20Sopenharmony_ci
58368c2ecf20Sopenharmony_ci	if (lock_data) {
58378c2ecf20Sopenharmony_ci		if (rdev == *lock_data->new_contended_rdev)
58388c2ecf20Sopenharmony_ci			return -EDEADLK;
58398c2ecf20Sopenharmony_ci	}
58408c2ecf20Sopenharmony_ci
58418c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
58428c2ecf20Sopenharmony_ci
58438c2ecf20Sopenharmony_ci	return 0;
58448c2ecf20Sopenharmony_ci}
58458c2ecf20Sopenharmony_ci
58468c2ecf20Sopenharmony_cistatic int regulator_summary_lock_all(struct ww_acquire_ctx *ww_ctx,
58478c2ecf20Sopenharmony_ci				      struct regulator_dev **new_contended_rdev,
58488c2ecf20Sopenharmony_ci				      struct regulator_dev **old_contended_rdev)
58498c2ecf20Sopenharmony_ci{
58508c2ecf20Sopenharmony_ci	struct summary_lock_data lock_data;
58518c2ecf20Sopenharmony_ci	int ret;
58528c2ecf20Sopenharmony_ci
58538c2ecf20Sopenharmony_ci	lock_data.ww_ctx = ww_ctx;
58548c2ecf20Sopenharmony_ci	lock_data.new_contended_rdev = new_contended_rdev;
58558c2ecf20Sopenharmony_ci	lock_data.old_contended_rdev = old_contended_rdev;
58568c2ecf20Sopenharmony_ci
58578c2ecf20Sopenharmony_ci	ret = class_for_each_device(&regulator_class, NULL, &lock_data,
58588c2ecf20Sopenharmony_ci				    regulator_summary_lock_one);
58598c2ecf20Sopenharmony_ci	if (ret)
58608c2ecf20Sopenharmony_ci		class_for_each_device(&regulator_class, NULL, &lock_data,
58618c2ecf20Sopenharmony_ci				      regulator_summary_unlock_one);
58628c2ecf20Sopenharmony_ci
58638c2ecf20Sopenharmony_ci	return ret;
58648c2ecf20Sopenharmony_ci}
58658c2ecf20Sopenharmony_ci
58668c2ecf20Sopenharmony_cistatic void regulator_summary_lock(struct ww_acquire_ctx *ww_ctx)
58678c2ecf20Sopenharmony_ci{
58688c2ecf20Sopenharmony_ci	struct regulator_dev *new_contended_rdev = NULL;
58698c2ecf20Sopenharmony_ci	struct regulator_dev *old_contended_rdev = NULL;
58708c2ecf20Sopenharmony_ci	int err;
58718c2ecf20Sopenharmony_ci
58728c2ecf20Sopenharmony_ci	mutex_lock(&regulator_list_mutex);
58738c2ecf20Sopenharmony_ci
58748c2ecf20Sopenharmony_ci	ww_acquire_init(ww_ctx, &regulator_ww_class);
58758c2ecf20Sopenharmony_ci
58768c2ecf20Sopenharmony_ci	do {
58778c2ecf20Sopenharmony_ci		if (new_contended_rdev) {
58788c2ecf20Sopenharmony_ci			ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx);
58798c2ecf20Sopenharmony_ci			old_contended_rdev = new_contended_rdev;
58808c2ecf20Sopenharmony_ci			old_contended_rdev->ref_cnt++;
58818c2ecf20Sopenharmony_ci			old_contended_rdev->mutex_owner = current;
58828c2ecf20Sopenharmony_ci		}
58838c2ecf20Sopenharmony_ci
58848c2ecf20Sopenharmony_ci		err = regulator_summary_lock_all(ww_ctx,
58858c2ecf20Sopenharmony_ci						 &new_contended_rdev,
58868c2ecf20Sopenharmony_ci						 &old_contended_rdev);
58878c2ecf20Sopenharmony_ci
58888c2ecf20Sopenharmony_ci		if (old_contended_rdev)
58898c2ecf20Sopenharmony_ci			regulator_unlock(old_contended_rdev);
58908c2ecf20Sopenharmony_ci
58918c2ecf20Sopenharmony_ci	} while (err == -EDEADLK);
58928c2ecf20Sopenharmony_ci
58938c2ecf20Sopenharmony_ci	ww_acquire_done(ww_ctx);
58948c2ecf20Sopenharmony_ci}
58958c2ecf20Sopenharmony_ci
58968c2ecf20Sopenharmony_cistatic void regulator_summary_unlock(struct ww_acquire_ctx *ww_ctx)
58978c2ecf20Sopenharmony_ci{
58988c2ecf20Sopenharmony_ci	class_for_each_device(&regulator_class, NULL, NULL,
58998c2ecf20Sopenharmony_ci			      regulator_summary_unlock_one);
59008c2ecf20Sopenharmony_ci	ww_acquire_fini(ww_ctx);
59018c2ecf20Sopenharmony_ci
59028c2ecf20Sopenharmony_ci	mutex_unlock(&regulator_list_mutex);
59038c2ecf20Sopenharmony_ci}
59048c2ecf20Sopenharmony_ci
59058c2ecf20Sopenharmony_cistatic int regulator_summary_show_roots(struct device *dev, void *data)
59068c2ecf20Sopenharmony_ci{
59078c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
59088c2ecf20Sopenharmony_ci	struct seq_file *s = data;
59098c2ecf20Sopenharmony_ci
59108c2ecf20Sopenharmony_ci	if (!rdev->supply)
59118c2ecf20Sopenharmony_ci		regulator_summary_show_subtree(s, rdev, 0);
59128c2ecf20Sopenharmony_ci
59138c2ecf20Sopenharmony_ci	return 0;
59148c2ecf20Sopenharmony_ci}
59158c2ecf20Sopenharmony_ci
59168c2ecf20Sopenharmony_cistatic int regulator_summary_show(struct seq_file *s, void *data)
59178c2ecf20Sopenharmony_ci{
59188c2ecf20Sopenharmony_ci	struct ww_acquire_ctx ww_ctx;
59198c2ecf20Sopenharmony_ci
59208c2ecf20Sopenharmony_ci	seq_puts(s, " regulator                      use open bypass  opmode voltage current     min     max\n");
59218c2ecf20Sopenharmony_ci	seq_puts(s, "---------------------------------------------------------------------------------------\n");
59228c2ecf20Sopenharmony_ci
59238c2ecf20Sopenharmony_ci	regulator_summary_lock(&ww_ctx);
59248c2ecf20Sopenharmony_ci
59258c2ecf20Sopenharmony_ci	class_for_each_device(&regulator_class, NULL, s,
59268c2ecf20Sopenharmony_ci			      regulator_summary_show_roots);
59278c2ecf20Sopenharmony_ci
59288c2ecf20Sopenharmony_ci	regulator_summary_unlock(&ww_ctx);
59298c2ecf20Sopenharmony_ci
59308c2ecf20Sopenharmony_ci	return 0;
59318c2ecf20Sopenharmony_ci}
59328c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(regulator_summary);
59338c2ecf20Sopenharmony_ci#endif /* CONFIG_DEBUG_FS */
59348c2ecf20Sopenharmony_ci
59358c2ecf20Sopenharmony_cistatic int __init regulator_init(void)
59368c2ecf20Sopenharmony_ci{
59378c2ecf20Sopenharmony_ci	int ret;
59388c2ecf20Sopenharmony_ci
59398c2ecf20Sopenharmony_ci	ret = class_register(&regulator_class);
59408c2ecf20Sopenharmony_ci
59418c2ecf20Sopenharmony_ci	debugfs_root = debugfs_create_dir("regulator", NULL);
59428c2ecf20Sopenharmony_ci	if (IS_ERR(debugfs_root))
59438c2ecf20Sopenharmony_ci		pr_debug("regulator: Failed to create debugfs directory\n");
59448c2ecf20Sopenharmony_ci
59458c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
59468c2ecf20Sopenharmony_ci	debugfs_create_file("supply_map", 0444, debugfs_root, NULL,
59478c2ecf20Sopenharmony_ci			    &supply_map_fops);
59488c2ecf20Sopenharmony_ci
59498c2ecf20Sopenharmony_ci	debugfs_create_file("regulator_summary", 0444, debugfs_root,
59508c2ecf20Sopenharmony_ci			    NULL, &regulator_summary_fops);
59518c2ecf20Sopenharmony_ci#endif
59528c2ecf20Sopenharmony_ci	regulator_dummy_init();
59538c2ecf20Sopenharmony_ci
59548c2ecf20Sopenharmony_ci	regulator_coupler_register(&generic_regulator_coupler);
59558c2ecf20Sopenharmony_ci
59568c2ecf20Sopenharmony_ci	return ret;
59578c2ecf20Sopenharmony_ci}
59588c2ecf20Sopenharmony_ci
59598c2ecf20Sopenharmony_ci/* init early to allow our consumers to complete system booting */
59608c2ecf20Sopenharmony_cicore_initcall(regulator_init);
59618c2ecf20Sopenharmony_ci
59628c2ecf20Sopenharmony_cistatic int regulator_late_cleanup(struct device *dev, void *data)
59638c2ecf20Sopenharmony_ci{
59648c2ecf20Sopenharmony_ci	struct regulator_dev *rdev = dev_to_rdev(dev);
59658c2ecf20Sopenharmony_ci	struct regulation_constraints *c = rdev->constraints;
59668c2ecf20Sopenharmony_ci	int ret;
59678c2ecf20Sopenharmony_ci
59688c2ecf20Sopenharmony_ci	if (c && c->always_on)
59698c2ecf20Sopenharmony_ci		return 0;
59708c2ecf20Sopenharmony_ci
59718c2ecf20Sopenharmony_ci	if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS))
59728c2ecf20Sopenharmony_ci		return 0;
59738c2ecf20Sopenharmony_ci
59748c2ecf20Sopenharmony_ci	regulator_lock(rdev);
59758c2ecf20Sopenharmony_ci
59768c2ecf20Sopenharmony_ci	if (rdev->use_count)
59778c2ecf20Sopenharmony_ci		goto unlock;
59788c2ecf20Sopenharmony_ci
59798c2ecf20Sopenharmony_ci	/* If reading the status failed, assume that it's off. */
59808c2ecf20Sopenharmony_ci	if (_regulator_is_enabled(rdev) <= 0)
59818c2ecf20Sopenharmony_ci		goto unlock;
59828c2ecf20Sopenharmony_ci
59838c2ecf20Sopenharmony_ci	if (have_full_constraints()) {
59848c2ecf20Sopenharmony_ci		/* We log since this may kill the system if it goes
59858c2ecf20Sopenharmony_ci		 * wrong. */
59868c2ecf20Sopenharmony_ci		rdev_info(rdev, "disabling\n");
59878c2ecf20Sopenharmony_ci		ret = _regulator_do_disable(rdev);
59888c2ecf20Sopenharmony_ci		if (ret != 0)
59898c2ecf20Sopenharmony_ci			rdev_err(rdev, "couldn't disable: %pe\n", ERR_PTR(ret));
59908c2ecf20Sopenharmony_ci	} else {
59918c2ecf20Sopenharmony_ci		/* The intention is that in future we will
59928c2ecf20Sopenharmony_ci		 * assume that full constraints are provided
59938c2ecf20Sopenharmony_ci		 * so warn even if we aren't going to do
59948c2ecf20Sopenharmony_ci		 * anything here.
59958c2ecf20Sopenharmony_ci		 */
59968c2ecf20Sopenharmony_ci		rdev_warn(rdev, "incomplete constraints, leaving on\n");
59978c2ecf20Sopenharmony_ci	}
59988c2ecf20Sopenharmony_ci
59998c2ecf20Sopenharmony_ciunlock:
60008c2ecf20Sopenharmony_ci	regulator_unlock(rdev);
60018c2ecf20Sopenharmony_ci
60028c2ecf20Sopenharmony_ci	return 0;
60038c2ecf20Sopenharmony_ci}
60048c2ecf20Sopenharmony_ci
60058c2ecf20Sopenharmony_cistatic void regulator_init_complete_work_function(struct work_struct *work)
60068c2ecf20Sopenharmony_ci{
60078c2ecf20Sopenharmony_ci	/*
60088c2ecf20Sopenharmony_ci	 * Regulators may had failed to resolve their input supplies
60098c2ecf20Sopenharmony_ci	 * when were registered, either because the input supply was
60108c2ecf20Sopenharmony_ci	 * not registered yet or because its parent device was not
60118c2ecf20Sopenharmony_ci	 * bound yet. So attempt to resolve the input supplies for
60128c2ecf20Sopenharmony_ci	 * pending regulators before trying to disable unused ones.
60138c2ecf20Sopenharmony_ci	 */
60148c2ecf20Sopenharmony_ci	class_for_each_device(&regulator_class, NULL, NULL,
60158c2ecf20Sopenharmony_ci			      regulator_register_resolve_supply);
60168c2ecf20Sopenharmony_ci
60178c2ecf20Sopenharmony_ci	/* If we have a full configuration then disable any regulators
60188c2ecf20Sopenharmony_ci	 * we have permission to change the status for and which are
60198c2ecf20Sopenharmony_ci	 * not in use or always_on.  This is effectively the default
60208c2ecf20Sopenharmony_ci	 * for DT and ACPI as they have full constraints.
60218c2ecf20Sopenharmony_ci	 */
60228c2ecf20Sopenharmony_ci	class_for_each_device(&regulator_class, NULL, NULL,
60238c2ecf20Sopenharmony_ci			      regulator_late_cleanup);
60248c2ecf20Sopenharmony_ci}
60258c2ecf20Sopenharmony_ci
60268c2ecf20Sopenharmony_cistatic DECLARE_DELAYED_WORK(regulator_init_complete_work,
60278c2ecf20Sopenharmony_ci			    regulator_init_complete_work_function);
60288c2ecf20Sopenharmony_ci
60298c2ecf20Sopenharmony_cistatic int __init regulator_init_complete(void)
60308c2ecf20Sopenharmony_ci{
60318c2ecf20Sopenharmony_ci	/*
60328c2ecf20Sopenharmony_ci	 * Since DT doesn't provide an idiomatic mechanism for
60338c2ecf20Sopenharmony_ci	 * enabling full constraints and since it's much more natural
60348c2ecf20Sopenharmony_ci	 * with DT to provide them just assume that a DT enabled
60358c2ecf20Sopenharmony_ci	 * system has full constraints.
60368c2ecf20Sopenharmony_ci	 */
60378c2ecf20Sopenharmony_ci	if (of_have_populated_dt())
60388c2ecf20Sopenharmony_ci		has_full_constraints = true;
60398c2ecf20Sopenharmony_ci
60408c2ecf20Sopenharmony_ci	/*
60418c2ecf20Sopenharmony_ci	 * We punt completion for an arbitrary amount of time since
60428c2ecf20Sopenharmony_ci	 * systems like distros will load many drivers from userspace
60438c2ecf20Sopenharmony_ci	 * so consumers might not always be ready yet, this is
60448c2ecf20Sopenharmony_ci	 * particularly an issue with laptops where this might bounce
60458c2ecf20Sopenharmony_ci	 * the display off then on.  Ideally we'd get a notification
60468c2ecf20Sopenharmony_ci	 * from userspace when this happens but we don't so just wait
60478c2ecf20Sopenharmony_ci	 * a bit and hope we waited long enough.  It'd be better if
60488c2ecf20Sopenharmony_ci	 * we'd only do this on systems that need it, and a kernel
60498c2ecf20Sopenharmony_ci	 * command line option might be useful.
60508c2ecf20Sopenharmony_ci	 */
60518c2ecf20Sopenharmony_ci	schedule_delayed_work(&regulator_init_complete_work,
60528c2ecf20Sopenharmony_ci			      msecs_to_jiffies(30000));
60538c2ecf20Sopenharmony_ci
60548c2ecf20Sopenharmony_ci	return 0;
60558c2ecf20Sopenharmony_ci}
60568c2ecf20Sopenharmony_cilate_initcall_sync(regulator_init_complete);
6057