您现在的位置是:首页 >学无止境 >了解/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()
电源管理分成静态和动态:静态不需要改变电压电流,只需要开关电源;动态是根据需要改变电压电流。
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;