mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
soc: rockchip: opp_select: Add support to get pvtpll pvtm
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com> Change-Id: If718c854bbf752026c259314ed5230026302f0d2
This commit is contained in:
@@ -53,9 +53,11 @@ struct pvtm_config {
|
||||
unsigned int num;
|
||||
unsigned int err;
|
||||
unsigned int ref_temp;
|
||||
unsigned int offset;
|
||||
int temp_prop[2];
|
||||
const char *tz_name;
|
||||
struct thermal_zone_device *tz;
|
||||
struct regmap *grf;
|
||||
};
|
||||
|
||||
struct lkg_conversion_table {
|
||||
@@ -300,17 +302,9 @@ static int rockchip_parse_pvtm_config(struct device_node *np,
|
||||
return -EINVAL;
|
||||
if (of_property_read_u32(np, "rockchip,pvtm-volt", &pvtm->volt))
|
||||
return -EINVAL;
|
||||
if (of_property_read_u32_array(np, "rockchip,pvtm-ch", pvtm->ch, 2))
|
||||
return -EINVAL;
|
||||
if (pvtm->ch[0] >= PVTM_CH_MAX || pvtm->ch[1] >= PVTM_SUB_CH_MAX)
|
||||
return -EINVAL;
|
||||
if (of_property_read_u32(np, "rockchip,pvtm-sample-time",
|
||||
&pvtm->sample_time))
|
||||
return -EINVAL;
|
||||
if (of_property_read_u32(np, "rockchip,pvtm-number", &pvtm->num))
|
||||
return -EINVAL;
|
||||
if (of_property_read_u32(np, "rockchip,pvtm-error", &pvtm->err))
|
||||
return -EINVAL;
|
||||
if (of_property_read_u32(np, "rockchip,pvtm-ref-temp", &pvtm->ref_temp))
|
||||
return -EINVAL;
|
||||
if (of_property_read_u32_array(np, "rockchip,pvtm-temp-prop",
|
||||
@@ -327,6 +321,23 @@ static int rockchip_parse_pvtm_config(struct device_node *np,
|
||||
return -EINVAL;
|
||||
if (!pvtm->tz->ops->get_temp)
|
||||
return -EINVAL;
|
||||
if (of_property_read_bool(np, "rockchip,pvtm-pvtpll")) {
|
||||
if (of_property_read_u32(np, "rockchip,pvtm-offset",
|
||||
&pvtm->offset))
|
||||
return -EINVAL;
|
||||
pvtm->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
|
||||
if (IS_ERR(pvtm->grf))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
if (of_property_read_u32_array(np, "rockchip,pvtm-ch", pvtm->ch, 2))
|
||||
return -EINVAL;
|
||||
if (pvtm->ch[0] >= PVTM_CH_MAX || pvtm->ch[1] >= PVTM_SUB_CH_MAX)
|
||||
return -EINVAL;
|
||||
if (of_property_read_u32(np, "rockchip,pvtm-number", &pvtm->num))
|
||||
return -EINVAL;
|
||||
if (of_property_read_u32(np, "rockchip,pvtm-error", &pvtm->err))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -697,6 +708,82 @@ next:
|
||||
EXPORT_SYMBOL(rockchip_of_get_lkg_sel);
|
||||
|
||||
|
||||
static int rockchip_get_pvtm_pvtpll(struct device *dev, struct device_node *np,
|
||||
char *reg_name)
|
||||
{
|
||||
struct regulator *reg;
|
||||
struct clk *clk;
|
||||
struct pvtm_config *pvtm;
|
||||
unsigned long old_freq;
|
||||
unsigned int old_volt;
|
||||
int cur_temp, diff_temp, prop_temp, diff_value;
|
||||
int pvtm_value = 0;
|
||||
int ret = 0;
|
||||
|
||||
pvtm = kzalloc(sizeof(*pvtm), GFP_KERNEL);
|
||||
if (!pvtm)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = rockchip_parse_pvtm_config(np, pvtm);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
clk = clk_get(dev, NULL);
|
||||
if (IS_ERR_OR_NULL(clk)) {
|
||||
dev_warn(dev, "Failed to get clk\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
reg = regulator_get_optional(dev, reg_name);
|
||||
if (IS_ERR_OR_NULL(reg)) {
|
||||
dev_warn(dev, "Failed to get reg\n");
|
||||
clk_put(clk);
|
||||
goto out;
|
||||
}
|
||||
old_freq = clk_get_rate(clk);
|
||||
old_volt = regulator_get_voltage(reg);
|
||||
|
||||
ret = clk_set_rate(clk, pvtm->freq * 1000);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to set pvtm freq\n");
|
||||
goto put_reg;
|
||||
}
|
||||
ret = regulator_set_voltage(reg, pvtm->volt, pvtm->volt);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to set pvtm_volt\n");
|
||||
goto restore_clk;
|
||||
}
|
||||
usleep_range(pvtm->sample_time, pvtm->sample_time + 100);
|
||||
|
||||
ret = regmap_read(pvtm->grf, pvtm->offset, &pvtm_value);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to get pvtm from 0x%x\n", pvtm->offset);
|
||||
goto resetore_volt;
|
||||
}
|
||||
pvtm->tz->ops->get_temp(pvtm->tz, &cur_temp);
|
||||
diff_temp = (cur_temp / 1000 - pvtm->ref_temp);
|
||||
if (diff_temp < 0)
|
||||
prop_temp = pvtm->temp_prop[0];
|
||||
else
|
||||
prop_temp = pvtm->temp_prop[1];
|
||||
diff_value = diff_temp * prop_temp / 1000;
|
||||
pvtm_value += diff_value;
|
||||
|
||||
dev_info(dev, "pvtm=%d\n", pvtm_value);
|
||||
|
||||
resetore_volt:
|
||||
regulator_set_voltage(reg, old_volt, old_volt);
|
||||
restore_clk:
|
||||
clk_set_rate(clk, old_freq);
|
||||
put_reg:
|
||||
regulator_put(reg);
|
||||
clk_put(clk);
|
||||
out:
|
||||
kfree(pvtm);
|
||||
|
||||
return pvtm_value;
|
||||
}
|
||||
|
||||
static int rockchip_get_pvtm(struct device *dev, struct device_node *np,
|
||||
char *reg_name)
|
||||
{
|
||||
@@ -752,7 +839,10 @@ void rockchip_of_get_pvtm_sel(struct device *dev, struct device_node *np,
|
||||
char name[NAME_MAX];
|
||||
int pvtm, ret;
|
||||
|
||||
pvtm = rockchip_get_pvtm(dev, np, reg_name);
|
||||
if (of_property_read_bool(np, "rockchip,pvtm-pvtpll"))
|
||||
pvtm = rockchip_get_pvtm_pvtpll(dev, np, reg_name);
|
||||
else
|
||||
pvtm = rockchip_get_pvtm(dev, np, reg_name);
|
||||
if (pvtm <= 0)
|
||||
return;
|
||||
|
||||
@@ -1263,6 +1353,11 @@ int rockchip_init_opp_table(struct device *dev, struct rockchip_opp_info *info,
|
||||
}
|
||||
}
|
||||
info->num_clks = num_clks;
|
||||
ret = clk_bulk_prepare_enable(info->num_clks, info->clks);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable opp clks\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (info->data && info->data->set_read_margin) {
|
||||
info->current_rm = UINT_MAX;
|
||||
@@ -1287,9 +1382,13 @@ next:
|
||||
ret = dev_pm_opp_of_add_table(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Invalid operating-points in device tree.\n");
|
||||
goto out;
|
||||
goto dis_opp_clk;
|
||||
}
|
||||
rockchip_adjust_power_scale(dev, scale);
|
||||
|
||||
dis_opp_clk:
|
||||
if (info && info->clks)
|
||||
clk_bulk_disable_unprepare(info->num_clks, info->clks);
|
||||
out:
|
||||
of_node_put(np);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user