Linux下的regulator调试

先看regulator使用的小demo,如

i2c8{
    touchscreen@28 {
           vddcama-supply = <&xxxxx>;
    };
}
int ret;
struct regulator *power;
static int ts_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
    power=regulator_get(&client->dev,"vddcama");
    if (IS_ERR(power)) {
        ret = PTR_ERR(power);
        dev_err(dev, "Failed to request vddcama: %d\n", ret);
  }
    ret=regulator_set_voltage(power, 1800000, 1800000);//mV
    ret=regulator_enable(power);
    ret=regulator_disable(power);
}
/**
 * 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, false, true);
}
EXPORT_SYMBOL_GPL(regulator_get);
regulator_get如果找不到该电源,换返回一个无效的电源,该结果不是我们想要的,可使用regulator_get_exclusive代替。

static struct regulator *_regulator_get(struct device *dev, const char *id,
                    bool exclusive, bool allow_dummy)
{
    if (have_full_constraints() && allow_dummy) {
        pr_warn("%s supply %s not found, using dummy regulator\n",
            devname, id);
 
        rdev = dummy_regulator_rdev;
        get_device(&rdev->dev);
        goto found;
    /* Don't log an error when called from regulator_get_optional() */
    } else if (!have_full_constraints() || exclusive) {
        dev_warn(dev, "dummy supplies not allowed\n");
    }

struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
{
    return _regulator_get(dev, id, true, false);
}
EXPORT_SYMBOL_GPL(regulator_get_exclusive);
如果是共享电源,其他使用者没有关闭电源,调用regulator_disable不能关闭电源。

int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
{
    int ret = 0;
 
    regulator_lock_supply(regulator->rdev);
 
    ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV);
 
    regulator_unlock_supply(regulator->rdev);
 
    return ret;
}
EXPORT_SYMBOL_GPL(regulator_set_voltage);
 
int regulator_disable(struct regulator *regulator)
{
    struct regulator_dev *rdev = regulator->rdev;
    int ret = 0;
 
    if (regulator->always_on)
        return 0;
 
    mutex_lock(&rdev->mutex);
    ret = _regulator_disable(rdev);
    mutex_unlock(&rdev->mutex);
 
    if (ret == 0 && rdev->supply)
        regulator_disable(rdev->supply);
 
    return ret;
}
 
/**
 * 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;
    int ret = 0;
 
    if (regulator->always_on)
        return 0;
 
    if (rdev->supply) {
        ret = regulator_enable(rdev->supply);
        if (ret != 0)
            return ret;
    }
 
    mutex_lock(&rdev->mutex);
    ret = _regulator_enable(rdev);
    mutex_unlock(&rdev->mutex);
 
    if (ret != 0 && rdev->supply)
        regulator_disable(rdev->supply);
 
    return ret;
}
EXPORT_SYMBOL_GPL(regulator_enable);
/sys/class/regulator下有所有的regular,如

每个节点有如下的属性

cpu0-cpu                   使用者名字
device
max_microvolts       最大电压
microvolts
min_microvolts       最小电压
name                            电源名字
num_users               当前的使用者数量(use_count)
of_node                     dts配置信息        
power
state                           当前状态(打开或关闭)
subsystem
suspend_disk_state
suspend_mem_state
suspend_standby_state   
type                        电源类型(电压或电流)
uevent

查看/d/regulator/regulator_summary有所有电源的信息,如

use 同上面的num_users(use_count)  (_regulator_enable+1   _regulator_disable-1)该参数可表明当前ldo的开光状态

open当前打开次数(open_count)(_regulator_get+1    _regulator_put-1)
 

static int _regulator_disable(struct regulator_dev *rdev)
{
...
    rdev->use_count--;
...
}
 
static int _regulator_enable(struct regulator_dev *rdev)
{
...
    rdev->use_count++;
...
}
 
struct regulator *_regulator_get(struct device *dev, const char *id,enum regulator_get_type get_type)
{
...
    rdev->open_count++;
...
}
 
static void _regulator_put(struct regulator *regulator)
{
...
    rdev->open_count--;
...
}
如果无法确认电源被异常关闭的情况 ,可以在平台的电源开关中加入如下函数,来追踪电源的开关状态。

static int mt6357_regulator_disable(struct regulator_dev *rdev)
{
    int ret = 0;
    pr_info("QQQQQQQQQQQQQQQQQQQQQQQQQQ==%s\n",rdev_get_name(rdev));
    if(strncmp(rdev_get_name(rdev),"vldo28",strlen("vldo28"))==0)
        WARN(1,"mt6370_ldo_disable\n");
}
文章知识点与官方知识档案匹配,可进一
————————————————
版权声明:本文为CSDN博主「那颗流星」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mike8825/article/details/88768889

内核设计的基本内容:

https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-regulator

猜你喜欢

转载自blog.csdn.net/u012294613/article/details/130511566