Regulator debugging under Linux

First look at the small demo used by the regulator, such as

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);
If regulator_get cannot find the power supply, it will return an invalid power supply. This result is not what we want, and regulator_get_exclusive can be used instead.

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);
If the power is shared and other users have not turned off the power, calling regulator_disable cannot turn off the power.

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,如

Each node has the following properties

cpu0-cpu user name
device
max_microvolts maximum voltage
microvolts
min_microvolts minimum voltage
name power supply name
num_users current number of users (use_count)
of_node dts configuration information        
power
state current state (on or off)
subsystem
suspend_disk_state
suspend_mem_state
suspend_standby_state   
type power supply type (voltage or current )
uevent

See /d/regulator/regulator_summary for all power sources, such as

use is the same as the above num_users(use_count) (_regulator_enable+1 _regulator_disable-1) This parameter can indicate the current status of the LDO

open current open times (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--; .. . } If you cannot confirm that the power is turned off abnormally, you can add the following function to the power switch of the platform to track the power switch status.




 






 






 






like

static int mt6357_regulator_disable(struct regulator_dev *rdev)
{     int ret = 0;     pr_info("QQQQQQQQQQQQQQQQQQQQQQ==%s\n",rdev_get_name(rdev));     if(strncmp(rdev_get_name(rdev),"vldo28",strlen("vldo28 "))==0)         WARN(1,"mt6370_ldo_disable\n"); } The knowledge points of the article match the official knowledge files, and you can further ————————————————— Copyright statement: This article is an original article by CSDN blogger "That Meteor", which follows the CC 4.0 BY-SA copyright agreement. For reprinting, please attach the original source link and this statement. Original link: https://blog.csdn.net/mike8825/article/details/88768889








The basic content of the kernel design:

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

Guess you like

Origin blog.csdn.net/u012294613/article/details/130511566