先看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");
}