您的位置:首页 > 运维架构

从dts中得到电压和电流赋值给opp table

2017-10-20 14:48 197 查看
驱动中通过dev_pm_opp_of_add_table来从dts中得到cpu工作的电压和电流,例如如下code

ret = dev_pm_opp_of_add_table(dvfs_info->dev);
if (ret) {
dev_err(dvfs_info->dev, "failed to init OPP table: %d\n", ret);
goto err_put_node;
}
cpu电压和电流初始化的code在drivers/base/power/opp/of.c中
int dev_pm_opp_of_add_table(struct device *dev)
{
struct device_node *opp_np;
int ret;

/*
* OPPs have two version of bindings now. The older one is deprecated,
* try for the new binding first.
*/
opp_np = dev_pm_opp_of_get_opp_desc_node(dev);
if (!opp_np) {
/*
* Try old-deprecated bindings for backward compatibility with
* older dtbs.
*/
return _of_add_opp_table_v1(dev);
}

ret = _of_add_opp_table_v2(dev, opp_np);
of_node_put(opp_np);

return ret;
}
从这段code中可以看出opp的code还分为v1和v2两个版本,其中v1的版本比较简单,这里以v1 为例
通过dev_pm_opp_of_add_table来决定是v1还是v2版本,从源码看就是看dts中是否定义operating-points-v2
如果定义的话,就是v2,否则是v1.从这里也可以看到即使v1和v2 同时存在,以v2为准

struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev)
{
/*
* There should be only ONE phandle present in "operating-points-v2"
* property.
*/

return of_parse_phandle(dev->of_node, "operating-points-v2", 0);
}
/* Initializes OPP tables based on old-deprecated bindings */
static int _of_add_opp_table_v1(struct device *dev)
{
struct opp_table *opp_table;
const struct property *prop;
const __be32 *val;
int nr, ret = 0;
//找到opp的属性
prop = of_find_property(dev->of_node, "operating-points", NULL);
if (!prop)
return -ENODEV;
if (!prop->value)
return -ENODATA;

/*
* Each OPP is a set of tuples consisting of frequency and
* voltage like <freq-kHz vol-uV>.
*/
nr = prop->length / sizeof(u32);
if (nr % 2) {
dev_err(dev, "%s: Invalid OPP table\n", __func__);
return -EINVAL;
}

opp_table = dev_pm_opp_get_opp_table(dev);
if (!opp_table)
return -ENOMEM;
//这里从前面的属性拿到电压和电流的初始化值的起始地址
val = prop->value;
while (nr) {
//哈哈哈,重点code,这里看到freq和volt 的初始化都是从dts中得到的
unsigned long freq = be32_to_cpup(val++) * 1000;
unsigned long volt = be32_to_cpup(val++);

ret = _opp_add_v1(opp_table, dev, freq, volt, false);
if (ret) {
dev_err(dev, "%s: Failed to add OPP %ld (%d)\n",
__func__, freq, ret);
_dev_pm_opp_remove_table(opp_table, dev, false);
break;
}
nr -= 2;
}

dev_pm_opp_put_opp_table(opp_table);
return ret;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: