From 7d07b3ae8ddad407913c5301877e694430a3263f Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 23 Nov 2023 08:24:31 +0000
Subject: [PATCH] add build kerneldeb
---
kernel/drivers/soc/rockchip/rockchip_opp_select.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 149 insertions(+), 11 deletions(-)
diff --git a/kernel/drivers/soc/rockchip/rockchip_opp_select.c b/kernel/drivers/soc/rockchip/rockchip_opp_select.c
index 1520e2f..02bcf82 100644
--- a/kernel/drivers/soc/rockchip/rockchip_opp_select.c
+++ b/kernel/drivers/soc/rockchip/rockchip_opp_select.c
@@ -6,8 +6,10 @@
#include <linux/clk.h>
#include <linux/cpufreq.h>
#include <linux/devfreq.h>
+#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/nvmem-consumer.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/soc/rockchip/pvtm.h>
@@ -51,15 +53,24 @@
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 {
int temp;
int conv;
};
+
+struct otp_opp_info {
+ u16 min_freq;
+ u16 max_freq;
+ u8 volt;
+ u8 length;
+} __packed;
#define PVTM_CH_MAX 8
#define PVTM_SUB_CH_MAX 8
@@ -298,16 +309,8 @@
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;
@@ -324,6 +327,23 @@
if (IS_ERR(pvtm->tz))
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;
@@ -415,7 +435,7 @@
cur_temp, *target_value, avg_value, diff_value);
resetore_volt:
- regulator_set_voltage(reg, old_volt, old_volt);
+ regulator_set_voltage(reg, old_volt, INT_MAX);
restore_clk:
clk_set_rate(clk, old_freq);
pvtm_value_out:
@@ -694,6 +714,81 @@
}
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, INT_MAX);
+ 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, INT_MAX);
+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)
@@ -750,7 +845,10 @@
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;
@@ -910,8 +1008,9 @@
struct sel_table *irdrop_table = NULL;
struct opp_table *opp_table;
struct dev_pm_opp *opp;
+ unsigned long tmp_safe_rate = 0;
int evb_irdrop = 0, board_irdrop, delta_irdrop;
- int tmp_safe_rate = 0, opp_rate, i, ret = 0;
+ int opp_rate, i, ret = 0;
u32 max_volt = UINT_MAX;
bool reach_max_volt = false;
@@ -1003,6 +1102,44 @@
mutex_unlock(&opp_table->lock);
}
+static void rockchip_adjust_opp_by_otp(struct device *dev,
+ struct device_node *np)
+{
+ struct dev_pm_opp *opp;
+ struct opp_table *opp_table;
+ struct otp_opp_info opp_info = {};
+ int ret;
+
+ ret = rockchip_nvmem_cell_read_common(np, "opp-info", &opp_info,
+ sizeof(opp_info));
+ if (ret || !opp_info.volt)
+ return;
+
+ dev_info(dev, "adjust opp-table by otp: min=%uM, max=%uM, volt=%umV\n",
+ opp_info.min_freq, opp_info.max_freq, opp_info.volt);
+
+ 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->available)
+ continue;
+ if (opp->rate < opp_info.min_freq * 1000000)
+ continue;
+ if (opp->rate > opp_info.max_freq * 1000000)
+ continue;
+
+ opp->supplies->u_volt += opp_info.volt * 1000;
+ if (opp->supplies->u_volt > opp->supplies->u_volt_max)
+ opp->supplies->u_volt = opp->supplies->u_volt_max;
+ }
+ mutex_unlock(&opp_table->lock);
+
+ dev_pm_opp_put_opp_table(opp_table);
+}
+
static int rockchip_adjust_opp_table(struct device *dev,
unsigned long scale_rate)
{
@@ -1049,6 +1186,7 @@
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_otp(dev, np);
rockchip_adjust_opp_by_mbist_vmin(dev, np);
rockchip_adjust_opp_by_irdrop(dev, np, &safe_rate, &max_rate);
--
Gitblit v1.6.2