您现在的位置是:首页 >学无止境 >了解/linux-5.4.31/drivers/regulator/devres.c中的devm_regulator_get()和devm_regulator_bulk_get()网站首页学无止境

了解/linux-5.4.31/drivers/regulator/devres.c中的devm_regulator_get()和devm_regulator_bulk_get()

LaoZhangGong123 2025-03-07 00:01:03
简介了解/linux-5.4.31/drivers/regulator/devres.c中的devm_regulator_get()和devm_regulator_bulk_get()

电源管理分成静态和动态:静态不需要改变电压电流,只需要开关电源;动态是根据需要改变电压电流。

struct regulator *devm_regulator_get(struct device *dev, const char *id);

//分配设备资源数据,获取内部稳压器,注册设备资源

举例:

pb->power_supply = devm_regulator_get(&pdev->dev, "power");

//分配设备资源数据,获取内部稳压器,注册设备资源

int devm_regulator_bulk_get(struct device *dev, int num_consumers,

    struct regulator_bulk_data *consumers)

//分配设备资源数据,获取多个稳压器,注册设备资源

举例:

sii902x->supplies[0].supply = "iovcc";//稳压器的名字

sii902x->supplies[1].supply = "cvcc12";//稳压器的名字

ret=devm_regulator_bulk_get(dev,ARRAY_SIZE(sii902x->supplies),sii902x->supplies);

/*分配设备资源数据,获取多个稳压器,注册设备资源;

ARRAY_SIZE()用来计算数组元素的个数;

sii902x->supplies表示稳压器的名字

1、打开“drivers/regulator/core.c”

/**

查找并获得内部稳压器;

 * regulator_get - lookup and obtain a reference to a regulator.

 * @dev: device for regulator "consumer"

 * @id: Supply name or regulator ID.

 *

 * Returns a struct regulator corresponding to the regulator producer,

 * or IS_ERR() condition containing errno.

 *

 * Use of supply names configured via regulator_set_device_supply() is

 * strongly encouraged.  It is recommended that the supply name used

 * should match the name used for the supply and/or the relevant

 * device pins in the datasheet.

 */

struct regulator *regulator_get(struct device *dev, const char *id)

{

return _regulator_get(dev, id, NORMAL_GET);

}

/*查找并获得内部稳压器; Internal regulator request function */

struct regulator *_regulator_get(struct device *dev, const char *id,

 enum regulator_get_type get_type)

{

struct regulator_dev *rdev;

struct regulator *regulator;

const char *devname = dev ? dev_name(dev) : "deviceless";

int ret;

if (get_type >= MAX_GET_TYPE) {

dev_err(dev, "invalid type %d in %s ", get_type, __func__);

return ERR_PTR(-EINVAL);

}

if (id == NULL) {

pr_err("get() with no identifier ");

return ERR_PTR(-EINVAL);

}

rdev = regulator_dev_lookup(dev, id);

if (IS_ERR(rdev)) {

ret = PTR_ERR(rdev);

/*

 * If regulator_dev_lookup() fails with error other

 * than -ENODEV our job here is done, we simply return it.

 */

if (ret != -ENODEV)return ERR_PTR(ret);

if (!have_full_constraints()) {

dev_warn(dev,

 "incomplete constraints, dummy supplies not allowed ");

return ERR_PTR(-ENODEV);

}

switch (get_type) {

case NORMAL_GET:

/*

 * Assume that a regulator is physically present and

 * enabled, even if it isn't hooked up, and just

 * provide a dummy.

 */

dev_warn(dev,

 "%s supply %s not found, using dummy regulator ",

 devname, id);

rdev = dummy_regulator_rdev;

get_device(&rdev->dev);

break;

case EXCLUSIVE_GET:

dev_warn(dev,

 "dummy supplies not allowed for exclusive requests ");

/* fall through */

default:

return ERR_PTR(-ENODEV);

}

}

if (rdev->exclusive) {

regulator = ERR_PTR(-EPERM);

put_device(&rdev->dev);

return regulator;

}

if (get_type == EXCLUSIVE_GET && rdev->open_count) {

regulator = ERR_PTR(-EBUSY);

put_device(&rdev->dev);

return regulator;

}

mutex_lock(®ulator_list_mutex);

ret = (rdev->coupling_desc.n_resolved != rdev->coupling_desc.n_coupled);

mutex_unlock(®ulator_list_mutex);/* 解锁,释放互斥锁 */

if (ret != 0) {

regulator = ERR_PTR(-EPROBE_DEFER);

put_device(&rdev->dev);

return regulator;

}

ret = regulator_resolve_supply(rdev);

if (ret < 0) {

regulator = ERR_PTR(ret);

put_device(&rdev->dev);

return regulator;

}

if (!try_module_get(rdev->owner)) {

regulator = ERR_PTR(-EPROBE_DEFER);

put_device(&rdev->dev);

return regulator;

}

regulator = create_regulator(rdev, dev, id);

if (regulator == NULL) {

regulator = ERR_PTR(-ENOMEM);

module_put(rdev->owner);

put_device(&rdev->dev);

return regulator;

}

rdev->open_count++;

if (get_type == EXCLUSIVE_GET) {

rdev->exclusive = 1;

ret = _regulator_is_enabled(rdev);

if (ret > 0)

rdev->use_count = 1;

else

rdev->use_count = 0;

}

device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS);

return regulator;

}

/*释放稳压器

 * regulator_put - "free" the regulator source

 * @regulator: regulator source

 *

 * Note: drivers must ensure that all regulator_enable calls made on this

 * regulator source are balanced by regulator_disable calls prior to calling

 * this function.

 */

void regulator_put(struct regulator *regulator)

{

mutex_lock(®ulator_list_mutex);/* 上锁 */

_regulator_put(regulator);//释放稳压器

mutex_unlock(®ulator_list_mutex);/* 解锁,释放互斥锁 */

}

/* regulator_list_mutex lock held by regulator_put() */

static void _regulator_put(struct regulator *regulator)

{

struct regulator_dev *rdev;

if (IS_ERR_OR_NULL(regulator))return;

lockdep_assert_held_once(®ulator_list_mutex);

/* Docs say you must disable before calling regulator_put() */

WARN_ON(regulator->enable_count);

rdev = regulator->rdev;

debugfs_remove_recursive(regulator->debugfs);

if (regulator->dev) {

device_link_remove(regulator->dev, &rdev->dev);

/* remove any sysfs entries */

sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);

}

regulator_lock(rdev);

list_del(®ulator->list);

rdev->open_count--;

rdev->exclusive = 0;

regulator_unlock(rdev);

kfree_const(regulator->supply_name);

kfree(regulator);

module_put(rdev->owner);

put_device(&rdev->dev);

}

/*使能稳压器输出

 * regulator_enable - enable regulator output

 * @regulator: regulator source

 *

 * Request that the regulator be enabled with the regulator output at

 * the predefined voltage or current value.  Calls to regulator_enable()

 * must be balanced with calls to regulator_disable().

 *

 * NOTE: the output value can be set by other drivers, boot loader or may be

 * hardwired in the regulator.

 */

int regulator_enable(struct regulator *regulator)

{

struct regulator_dev *rdev = regulator->rdev;

struct ww_acquire_ctx ww_ctx;

int ret;

regulator_lock_dependent(rdev, &ww_ctx);

ret = _regulator_enable(regulator);

regulator_unlock_dependent(rdev, &ww_ctx);

return ret;

}

/*使能稳压器输出 locks held by regulator_enable() */

static int _regulator_enable(struct regulator *regulator)

{

struct regulator_dev *rdev = regulator->rdev;

int ret;

lockdep_assert_held_once(&rdev->mutex.base);

if (rdev->use_count == 0 && rdev->supply) {

ret = _regulator_enable(rdev->supply);

if (ret < 0)

return ret;

}

/* balance only if there are regulators coupled */

if (rdev->coupling_desc.n_coupled > 1) {

ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);

if (ret < 0)

goto err_disable_supply;

}

ret = _regulator_handle_consumer_enable(regulator);

if (ret < 0)

goto err_disable_supply;

if (rdev->use_count == 0) {

/* The regulator may on if it's not switchable or left on */

ret = _regulator_is_enabled(rdev);

if (ret == -EINVAL || ret == 0) {

if (!regulator_ops_is_valid(rdev,

REGULATOR_CHANGE_STATUS)) {

ret = -EPERM;

goto err_consumer_disable;

}

ret = _regulator_do_enable(rdev);

if (ret < 0)

goto err_consumer_disable;

_notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE,

     NULL);

} else if (ret < 0) {

rdev_err(rdev, "is_enabled() failed: %d ", ret);

goto err_consumer_disable;

}

/* Fallthrough on positive return values - already enabled */

}

rdev->use_count++;

return 0;

err_consumer_disable:

_regulator_handle_consumer_disable(regulator);

err_disable_supply:

if (rdev->use_count == 0 && rdev->supply)

_regulator_disable(rdev->supply);

return ret;

}

/*稳压器输出使能了吗?

 * regulator_is_enabled - is the regulator output enabled

 * @regulator: regulator source

 *

 * Returns positive if the regulator driver backing the source/client

 * has requested that the device be enabled, zero if it hasn't, else a

 * negative errno code.

 *

 * Note that the device backing this regulator handle can have multiple

 * users, so it might be enabled even if regulator_enable() was never

 * called for this particular source.

 */

int regulator_is_enabled(struct regulator *regulator)

{

int ret;

if (regulator->always_on)

return 1;

regulator_lock(regulator->rdev);

ret = _regulator_is_enabled(regulator->rdev);

regulator_unlock(regulator->rdev);

return ret;

}

/*不使能稳压器输出

 * regulator_disable - disable regulator output

 * @regulator: regulator source

 *

 * Disable the regulator output voltage or current.  Calls to

 * regulator_enable() must be balanced with calls to

 * regulator_disable().

 *

 * NOTE: this will only disable the regulator output if no other consumer

 * devices have it enabled, the regulator device supports disabling and

 * machine constraints permit this operation.

 */

int regulator_disable(struct regulator *regulator)

{

struct regulator_dev *rdev = regulator->rdev;

struct ww_acquire_ctx ww_ctx;

int ret;

regulator_lock_dependent(rdev, &ww_ctx);

ret = _regulator_disable(regulator);

regulator_unlock_dependent(rdev, &ww_ctx);

return ret;

}

/*强制不使能稳压器输出

 * regulator_force_disable - force disable regulator output

 * @regulator: regulator source

 *

 * Forcibly disable the regulator output voltage or current.

 * NOTE: this *will* disable the regulator output even if other consumer

 * devices have it enabled. This should be used for situations when device

 * damage will likely occur if the regulator is not disabled (e.g. over temp).

 */

int regulator_force_disable(struct regulator *regulator)

{

struct regulator_dev *rdev = regulator->rdev;

struct ww_acquire_ctx ww_ctx;

int ret;

regulator_lock_dependent(rdev, &ww_ctx);

ret = _regulator_force_disable(regulator->rdev);

if (rdev->coupling_desc.n_coupled > 1)

regulator_balance_voltage(rdev, PM_SUSPEND_ON);

if (regulator->uA_load) {

regulator->uA_load = 0;

ret = drms_uA_update(rdev);

}

if (rdev->use_count != 0 && rdev->supply)

_regulator_disable(rdev->supply);

regulator_unlock_dependent(rdev, &ww_ctx);

return ret;

}

/*设置稳压器输出电压

 * regulator_set_voltage - set regulator output voltage

 * @regulator: regulator source

 * @min_uV: Minimum required voltage in uV

 * @max_uV: Maximum acceptable voltage in uV

 *

 * Sets a voltage regulator to the desired output voltage. This can be set

 * during any regulator state. IOW, regulator can be disabled or enabled.

 *

 * If the regulator is enabled then the voltage will change to the new value

 * immediately otherwise if the regulator is disabled the regulator will

 * output at the new voltage when enabled.

 *

 * NOTE: If the regulator is shared between several devices then the lowest

 * request voltage that meets the system constraints will be used.

 * Regulator system constraints must be set for this regulator before

 * calling this function otherwise this call will fail.

 */

int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)

{

struct ww_acquire_ctx ww_ctx;

int ret;

regulator_lock_dependent(regulator->rdev, &ww_ctx);

ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV,

     PM_SUSPEND_ON);

regulator_unlock_dependent(regulator->rdev, &ww_ctx);

return ret;

}

/*获取稳压器输出电压

 * regulator_get_voltage - get regulator output voltage

 * @regulator: regulator source

 *

 * This returns the current regulator voltage in uV.

 *

 * NOTE: If the regulator is disabled it will return the voltage value. This

 * function should not be used to determine regulator state.

 */

int regulator_get_voltage(struct regulator *regulator)

{

struct ww_acquire_ctx ww_ctx;

int ret;

regulator_lock_dependent(regulator->rdev, &ww_ctx);

ret = regulator_get_voltage_rdev(regulator->rdev);

regulator_unlock_dependent(regulator->rdev, &ww_ctx);

return ret;

}

/*获取多稳压器数量,数量保存到consumers

 * regulator_bulk_get - get multiple regulator consumers

 *

 * @dev:           Device to supply

 * @num_consumers: Number of consumers to register

 * @consumers:     Configuration of consumers; clients are stored here.

 *

 * @return 0 on success, an errno on failure.

 *

 * This helper function allows drivers to get several regulator

 * consumers in one operation.  If any of the regulators cannot be

 * acquired then any regulators that were allocated will be freed

 * before returning to the caller.

 */

int regulator_bulk_get(struct device *dev, int num_consumers,

       struct regulator_bulk_data *consumers)

{

int i;

int ret;

for (i = 0; i < num_consumers; i++)

consumers[i].consumer = NULL;

for (i = 0; i < num_consumers; i++) {

consumers[i].consumer = regulator_get(dev,

      consumers[i].supply);

if (IS_ERR(consumers[i].consumer)) {

ret = PTR_ERR(consumers[i].consumer);

consumers[i].consumer = NULL;

goto err;

}

}

return 0;

err:

if (ret != -EPROBE_DEFER)

dev_err(dev, "Failed to get supply '%s': %d ",

consumers[i].supply, ret);

else

dev_dbg(dev, "Failed to get supply '%s', deferring ",

consumers[i].supply);

while (--i >= 0)

regulator_put(consumers[i].consumer);

return ret;

}

2、打开“arch/arm/boot/dts/stm32mp157d-atk.dts”

v1v2_hdmi:regulator-v1v2-hdmi {

compatible ="regulator-fixed";

regulator-name ="v1v2_hdmi";

regulator-min-microvolt=<1200000>;

regulator-max-microvolt=<1200000>;

regulator-always-on;

regulator-boot-on;

};

3、打开“drivers/regulator/devres.c”

/*分配设备资源数据,获取多个稳压器,注册设备资源

 * devm_regulator_bulk_get - managed get multiple regulator consumers

 *

 * @dev:           Device to supply

 * @num_consumers: Number of consumers to register

 * @consumers:     Configuration of consumers; clients are stored here.

 *

 * @return 0 on success, an errno on failure.

 *

 * This helper function allows drivers to get several regulator

 * consumers in one operation with management, the regulators will

 * automatically be freed when the device is unbound.  If any of the

 * regulators cannot be acquired then any regulators that were

 * allocated will be freed before returning to the caller.

 */

int devm_regulator_bulk_get(struct device *dev, int num_consumers,

    struct regulator_bulk_data *consumers)

{

struct regulator_bulk_devres *devres;

int ret;

devres = devres_alloc(devm_regulator_bulk_release,sizeof(*devres), GFP_KERNEL);

//分配设备资源数据

if (!devres)

return -ENOMEM;

ret = regulator_bulk_get(dev, num_consumers, consumers);

//获取多个稳压器数量,数量保存到consumers

if (!ret) {

devres->consumers = consumers;

devres->num_consumers = num_consumers;

devres_add(dev, devres);//注册设备资源

} else {

devres_free(devres);//释放设备资源数据

}

return ret;

}

/**

分配设备资源数据,获取内部稳压器,注册设备资源

 * devm_regulator_get - Resource managed regulator_get()

 * @dev: device for regulator "consumer"

 * @id: Supply name or regulator ID.

 *

 * Managed regulator_get(). Regulators returned from this function are

 * automatically regulator_put() on driver detach. See regulator_get() for more

 * information.

 */

struct regulator *devm_regulator_get(struct device *dev, const char *id)

{

return _devm_regulator_get(dev, id, NORMAL_GET);

}

//分配设备资源数据,获取内部稳压器,注册设备资源

static struct regulator *_devm_regulator_get(struct device *dev, const char *id,  int get_type)

{

struct regulator **ptr, *regulator;

ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);

//分配设备资源数据

if (!ptr)

return ERR_PTR(-ENOMEM);

regulator = _regulator_get(dev, id, get_type);//获取内部稳压器

if (!IS_ERR(regulator)) {

*ptr = regulator;

devres_add(dev, ptr);//注册设备资源

} else {

devres_free(ptr);

}

return regulator;

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。