mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
soc: rockchip: opp_select: adjust opp-table by pvtm and mbist_vmin
1. support get pvtm from otp. 2. adjust opp-table by mbist_vmit which is get from otp. Change-Id: Ie3703873880b65b2af03ae474065d541c7f9d605 Signed-off-by: Liang Chen <cl@rock-chips.com>
This commit is contained in:
@@ -149,6 +149,49 @@ int rockchip_get_efuse_value(struct device_node *np, char *porp_name,
|
||||
}
|
||||
EXPORT_SYMBOL(rockchip_get_efuse_value);
|
||||
|
||||
static int rockchip_nvmem_cell_read_common(struct device_node *np,
|
||||
const char *cell_id,
|
||||
void *val, size_t count)
|
||||
{
|
||||
struct nvmem_cell *cell;
|
||||
void *buf;
|
||||
size_t len;
|
||||
|
||||
cell = of_nvmem_cell_get(np, cell_id);
|
||||
if (IS_ERR(cell))
|
||||
return PTR_ERR(cell);
|
||||
|
||||
buf = nvmem_cell_read(cell, &len);
|
||||
if (IS_ERR(buf)) {
|
||||
nvmem_cell_put(cell);
|
||||
return PTR_ERR(buf);
|
||||
}
|
||||
if (len != count) {
|
||||
kfree(buf);
|
||||
nvmem_cell_put(cell);
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(val, buf, count);
|
||||
kfree(buf);
|
||||
nvmem_cell_put(cell);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_nvmem_cell_read_u8(struct device_node *np,
|
||||
const char *cell_id,
|
||||
u8 *val)
|
||||
{
|
||||
return rockchip_nvmem_cell_read_common(np, cell_id, val, sizeof(*val));
|
||||
}
|
||||
|
||||
static int rockchip_nvmem_cell_read_u16(struct device_node *np,
|
||||
const char *cell_id,
|
||||
u16 *val)
|
||||
{
|
||||
return rockchip_nvmem_cell_read_common(np, cell_id, val, sizeof(*val));
|
||||
}
|
||||
|
||||
static int rockchip_get_sel_table(struct device_node *np, char *porp_name,
|
||||
struct sel_table **table)
|
||||
{
|
||||
@@ -326,23 +369,12 @@ static int rockchip_get_pvtm_specific_value(struct device *dev,
|
||||
{
|
||||
struct pvtm_config *pvtm;
|
||||
unsigned long old_freq;
|
||||
unsigned int old_volt, ch[2];
|
||||
unsigned int old_volt;
|
||||
int cur_temp, diff_temp;
|
||||
int cur_value, total_value, avg_value, diff_value;
|
||||
int min_value, max_value;
|
||||
int ret = 0, i = 0, retry = 2;
|
||||
|
||||
if (of_property_read_u32_array(np, "rockchip,pvtm-ch", ch, 2))
|
||||
return -EINVAL;
|
||||
|
||||
if (ch[0] >= PVTM_CH_MAX || ch[1] >= PVTM_SUB_CH_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
if (pvtm_value[ch[0]][ch[1]]) {
|
||||
*target_value = pvtm_value[ch[0]][ch[1]];
|
||||
return 0;
|
||||
}
|
||||
|
||||
pvtm = kzalloc(sizeof(*pvtm), GFP_KERNEL);
|
||||
if (!pvtm)
|
||||
return -ENOMEM;
|
||||
@@ -689,33 +721,65 @@ next:
|
||||
}
|
||||
EXPORT_SYMBOL(rockchip_of_get_lkg_sel);
|
||||
|
||||
void rockchip_of_get_pvtm_sel(struct device *dev, struct device_node *np,
|
||||
char *reg_name, int process,
|
||||
int *volt_sel, int *scale_sel)
|
||||
|
||||
static int rockchip_get_pvtm(struct device *dev, struct device_node *np,
|
||||
char *reg_name)
|
||||
{
|
||||
struct property *prop = NULL;
|
||||
struct regulator *reg;
|
||||
struct clk *clk;
|
||||
int pvtm = -EINVAL, ret;
|
||||
char name[NAME_MAX];
|
||||
unsigned int ch[2];
|
||||
int pvtm = 0;
|
||||
u16 tmp = 0;
|
||||
|
||||
if (!rockchip_nvmem_cell_read_u16(np, "pvtm", &tmp) && tmp) {
|
||||
pvtm = 10 * tmp;
|
||||
dev_info(dev, "pvtm = %d, from nvmem\n", pvtm);
|
||||
return pvtm;
|
||||
}
|
||||
|
||||
if (of_property_read_u32_array(np, "rockchip,pvtm-ch", ch, 2))
|
||||
return -EINVAL;
|
||||
|
||||
if (ch[0] >= PVTM_CH_MAX || ch[1] >= PVTM_SUB_CH_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
if (pvtm_value[ch[0]][ch[1]]) {
|
||||
dev_info(dev, "pvtm = %d, form pvtm_value\n", pvtm_value[ch[0]][ch[1]]);
|
||||
return pvtm_value[ch[0]][ch[1]];
|
||||
}
|
||||
|
||||
clk = clk_get(dev, NULL);
|
||||
if (IS_ERR_OR_NULL(clk)) {
|
||||
dev_warn(dev, "Failed to get clk\n");
|
||||
return;
|
||||
return PTR_ERR_OR_ZERO(clk);
|
||||
}
|
||||
|
||||
reg = regulator_get_optional(dev, reg_name);
|
||||
if (IS_ERR_OR_NULL(reg)) {
|
||||
dev_warn(dev, "Failed to get reg\n");
|
||||
goto clk_err;
|
||||
clk_put(clk);
|
||||
return PTR_ERR_OR_ZERO(reg);
|
||||
}
|
||||
|
||||
ret = rockchip_get_pvtm_specific_value(dev, np, clk, reg, &pvtm);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get pvtm\n");
|
||||
goto out;
|
||||
}
|
||||
rockchip_get_pvtm_specific_value(dev, np, clk, reg, &pvtm);
|
||||
|
||||
regulator_put(reg);
|
||||
clk_put(clk);
|
||||
|
||||
return pvtm;
|
||||
}
|
||||
|
||||
void rockchip_of_get_pvtm_sel(struct device *dev, struct device_node *np,
|
||||
char *reg_name, int process,
|
||||
int *volt_sel, int *scale_sel)
|
||||
{
|
||||
struct property *prop = NULL;
|
||||
char name[NAME_MAX];
|
||||
int pvtm, ret;
|
||||
|
||||
pvtm = rockchip_get_pvtm(dev, np, reg_name);
|
||||
if (pvtm <= 0)
|
||||
return;
|
||||
|
||||
if (!volt_sel)
|
||||
goto next;
|
||||
@@ -732,7 +796,7 @@ void rockchip_of_get_pvtm_sel(struct device *dev, struct device_node *np,
|
||||
|
||||
next:
|
||||
if (!scale_sel)
|
||||
goto out;
|
||||
return;
|
||||
if (process >= 0) {
|
||||
snprintf(name, sizeof(name),
|
||||
"rockchip,p%d-pvtm-scaling-sel", process);
|
||||
@@ -743,11 +807,6 @@ next:
|
||||
ret = rockchip_get_sel(np, name, pvtm, scale_sel);
|
||||
if (!ret)
|
||||
dev_info(dev, "pvtm-scale=%d\n", *scale_sel);
|
||||
|
||||
out:
|
||||
regulator_put(reg);
|
||||
clk_err:
|
||||
clk_put(clk);
|
||||
}
|
||||
EXPORT_SYMBOL(rockchip_of_get_pvtm_sel);
|
||||
|
||||
@@ -940,6 +999,37 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rockchip_adjust_opp_by_mbist_vmin(struct device *dev,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct opp_table *opp_table;
|
||||
struct dev_pm_opp *opp;
|
||||
u32 vmin = 0;
|
||||
u8 index = 0;
|
||||
|
||||
if (rockchip_nvmem_cell_read_u8(np, "mbist-vmin", &index))
|
||||
return;
|
||||
|
||||
if (!index)
|
||||
return;
|
||||
|
||||
if (of_property_read_u32_index(np, "mbist-vmin", index-1, &vmin))
|
||||
return;
|
||||
|
||||
opp_table = dev_pm_opp_get_opp_table(dev);
|
||||
if (!opp_table)
|
||||
return;
|
||||
|
||||
mutex_lock(&opp_table->lock);
|
||||
list_for_each_entry(opp, &opp_table->opp_list, node) {
|
||||
if (opp->supplies->u_volt < vmin) {
|
||||
opp->supplies->u_volt = vmin;
|
||||
opp->supplies->u_volt_min = vmin;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&opp_table->lock);
|
||||
}
|
||||
|
||||
static int rockchip_adjust_opp_table(struct device *dev,
|
||||
unsigned long scale_rate)
|
||||
{
|
||||
@@ -986,6 +1076,7 @@ int rockchip_adjust_power_scale(struct device *dev, int scale)
|
||||
of_property_read_u32(np, "rockchip,avs-enable", &avs);
|
||||
of_property_read_u32(np, "rockchip,avs", &avs);
|
||||
of_property_read_u32(np, "rockchip,avs-scale", &avs_scale);
|
||||
rockchip_adjust_opp_by_mbist_vmin(dev, np);
|
||||
rockchip_adjust_opp_by_irdrop(dev, np, &safe_rate, &max_rate);
|
||||
|
||||
dev_info(dev, "avs=%d\n", avs);
|
||||
|
||||
Reference in New Issue
Block a user