linux3.x下采用dts的方式建立设备树,自然给驱动带来很多改变。regulator也有很多变化。
结构体regulator_init_data
struct regulator_init_data {
const char*supply_regulator; 父节点
structregulation_constraints constraints;
intnum_consumer_supplies;//子节点的数量
structregulator_consumer_supply*consumer_supplies;//regulator_consumer_supply指的是regulator树上的叶子节点
int(*regulator_init)(void *driver_data);
void*driver_data;
};
在3.x以前,regulator_consumer_supply会指向如下结构体,最终通过regulator_get(dev,name)来得到regulator的指针,并实现对供电设备的操控。
这个函数最终是通过of_get_regulation_constraints这个函数读取dts的值实现对init_data->constraints的初始化。
static void of_get_regulation_constraints(struct device_node*np,
structregulator_init_data **init_data)
{
const __be32*min_uV, *max_uV, *uV_offset;
const __be32*min_uA, *max_uA, *ramp_delay;
structregulation_constraints *constraints =&(*init_data)->constraints;
constraints->name = of_get_property(np, "regulator-name",NULL);
min_uV =of_get_property(np, "regulator-min-microvolt", NULL);
if(min_uV)
constraints->min_uV = be32_to_cpu(*min_uV);
max_uV =of_get_property(np, "regulator-max-microvolt", NULL);
if(max_uV)
constraints->max_uV = be32_to_cpu(*max_uV);
if(constraints->min_uV != constraints->max_uV)
constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;
if (min_uV&& max_uV && constraints->min_uV ==constraints->max_uV)
constraints->apply_uV = true;
uV_offset =of_get_property(np, "regulator-microvolt-offset", NULL);
if(uV_offset)
constraints->uV_offset = be32_to_cpu(*uV_offset);
min_uA =of_get_property(np, "regulator-min-microamp", NULL);
if(min_uA)
constraints->min_uA = be32_to_cpu(*min_uA);
max_uA =of_get_property(np, "regulator-max-microamp", NULL);
if(max_uA)
constraints->max_uA = be32_to_cpu(*max_uA);
if(constraints->min_uA != constraints->max_uA)
constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT;
if(of_find_property(np, "regulator-boot-on", NULL))
constraints->boot_on = true;
if(of_find_property(np, "regulator-always-on", NULL))
constraints->always_on = true;
else
constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
ramp_delay =of_get_property(np, "regulator-ramp-delay", NULL);
if(ramp_delay)
constraints->ramp_delay = be32_to_cpu(*ramp_delay);
}
却没有对regulator_consumer_supply进行初始化,那如何获得regulator指针,并对regulator进行电压设定呢?
通过regulator.txt我们发现,在regulator的optional properties中有
-supply: phandle to the parent supply /regulator node
看起来这个是用来标记父节点的。那么这个值又是如何使用的呢?才让设备能正确的获得regulator的呢?
在drivers/regulator/core.c中我们发现。
regulator_get->_regulator_get->regulaotr_dev_lookup->list_for_each_entry->of_get_regulator:
snprintf(prop_name, 32, "%s-supply", supply);
regnode = of_parse_phandle(dev->of_node, prop_name, 0);
将我们传如的name,通过组合称name-supply的形式,再读取dts里的值,以此来获得我们需要的regulator的指针。
因此我们需要在dts里组织称类似
***-supply = <$dcdc1>
样子的属性,来表示所有设备的供电关系。
这篇文章的贡献点就是明白linux3.*如何建立供电关系。
结构体regulator_init_data
struct regulator_init_data {
const char*supply_regulator; 父节点
structregulation_constraints constraints;
intnum_consumer_supplies;//子节点的数量
structregulator_consumer_supply*consumer_supplies;//regulator_consumer_supply指的是regulator树上的叶子节点
int(*regulator_init)(void *driver_data);
void*driver_data;
};
在3.x以前,regulator_consumer_supply会指向如下结构体,最终通过regulator_get(dev,name)来得到regulator的指针,并实现对供电设备的操控。
static struct regulator_consumer_supplylp3974_buck3_consumer[]={
REGULATOR_SUPPLY("vdet","s5p-sdo"),
REGULATOR_SUPPLY("vdd_reg","0-003c"),
};
但利用dts组织的结构,我们发现获取regulator_init_data的方式不再是直接准备结构体,而是通过intof_regulator_match(struct device *dev, struct device_node *node,struct of_regulator_match *matches, unsigned intnum_matches)或struct of_get_regulator_init_data(struct device *dev,struct devie_node *node)初始化regulator_init_data.这个函数最终是通过of_get_regulation_constraints这个函数读取dts的值实现对init_data->constraints的初始化。
static void of_get_regulation_constraints(struct device_node*np,
structregulator_init_data **init_data)
{
const __be32*min_uV, *max_uV, *uV_offset;
const __be32*min_uA, *max_uA, *ramp_delay;
structregulation_constraints *constraints =&(*init_data)->constraints;
constraints->name = of_get_property(np, "regulator-name",NULL);
min_uV =of_get_property(np, "regulator-min-microvolt", NULL);
if(min_uV)
constraints->min_uV = be32_to_cpu(*min_uV);
max_uV =of_get_property(np, "regulator-max-microvolt", NULL);
if(max_uV)
constraints->max_uV = be32_to_cpu(*max_uV);
if(constraints->min_uV != constraints->max_uV)
constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;
if (min_uV&& max_uV && constraints->min_uV ==constraints->max_uV)
constraints->apply_uV = true;
uV_offset =of_get_property(np, "regulator-microvolt-offset", NULL);
if(uV_offset)
constraints->uV_offset = be32_to_cpu(*uV_offset);
min_uA =of_get_property(np, "regulator-min-microamp", NULL);
if(min_uA)
constraints->min_uA = be32_to_cpu(*min_uA);
max_uA =of_get_property(np, "regulator-max-microamp", NULL);
if(max_uA)
constraints->max_uA = be32_to_cpu(*max_uA);
if(constraints->min_uA != constraints->max_uA)
constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT;
if(of_find_property(np, "regulator-boot-on", NULL))
constraints->boot_on = true;
if(of_find_property(np, "regulator-always-on", NULL))
constraints->always_on = true;
else
constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
ramp_delay =of_get_property(np, "regulator-ramp-delay", NULL);
if(ramp_delay)
constraints->ramp_delay = be32_to_cpu(*ramp_delay);
}
却没有对regulator_consumer_supply进行初始化,那如何获得regulator指针,并对regulator进行电压设定呢?
通过regulator.txt我们发现,在regulator的optional properties中有
-supply: phandle to the parent supply /regulator node
看起来这个是用来标记父节点的。那么这个值又是如何使用的呢?才让设备能正确的获得regulator的呢?
在drivers/regulator/core.c中我们发现。
regulator_get->_regulator_get->regulaotr_dev_lookup->list_for_each_entry->of_get_regulator:
snprintf(prop_name, 32, "%s-supply", supply);
regnode = of_parse_phandle(dev->of_node, prop_name, 0);
将我们传如的name,通过组合称name-supply的形式,再读取dts里的值,以此来获得我们需要的regulator的指针。
因此我们需要在dts里组织称类似
***-supply = <$dcdc1>
样子的属性,来表示所有设备的供电关系。
这篇文章的贡献点就是明白linux3.*如何建立供电关系。