hc
2023-11-06 e3e12f52b214121840b44c91de5b3e5af5d3eb84
kernel/drivers/soc/rockchip/rockchip_opp_select.c
....@@ -6,8 +6,10 @@
66 #include <linux/clk.h>
77 #include <linux/cpufreq.h>
88 #include <linux/devfreq.h>
9
+#include <linux/mfd/syscon.h>
910 #include <linux/module.h>
1011 #include <linux/nvmem-consumer.h>
12
+#include <linux/regmap.h>
1113 #include <linux/regulator/consumer.h>
1214 #include <linux/slab.h>
1315 #include <linux/soc/rockchip/pvtm.h>
....@@ -51,15 +53,24 @@
5153 unsigned int num;
5254 unsigned int err;
5355 unsigned int ref_temp;
56
+ unsigned int offset;
5457 int temp_prop[2];
5558 const char *tz_name;
5659 struct thermal_zone_device *tz;
60
+ struct regmap *grf;
5761 };
5862
5963 struct lkg_conversion_table {
6064 int temp;
6165 int conv;
6266 };
67
+
68
+struct otp_opp_info {
69
+ u16 min_freq;
70
+ u16 max_freq;
71
+ u8 volt;
72
+ u8 length;
73
+} __packed;
6374
6475 #define PVTM_CH_MAX 8
6576 #define PVTM_SUB_CH_MAX 8
....@@ -298,16 +309,8 @@
298309 return -EINVAL;
299310 if (of_property_read_u32(np, "rockchip,pvtm-volt", &pvtm->volt))
300311 return -EINVAL;
301
- if (of_property_read_u32_array(np, "rockchip,pvtm-ch", pvtm->ch, 2))
302
- return -EINVAL;
303
- if (pvtm->ch[0] >= PVTM_CH_MAX || pvtm->ch[1] >= PVTM_SUB_CH_MAX)
304
- return -EINVAL;
305312 if (of_property_read_u32(np, "rockchip,pvtm-sample-time",
306313 &pvtm->sample_time))
307
- return -EINVAL;
308
- if (of_property_read_u32(np, "rockchip,pvtm-number", &pvtm->num))
309
- return -EINVAL;
310
- if (of_property_read_u32(np, "rockchip,pvtm-error", &pvtm->err))
311314 return -EINVAL;
312315 if (of_property_read_u32(np, "rockchip,pvtm-ref-temp", &pvtm->ref_temp))
313316 return -EINVAL;
....@@ -324,6 +327,23 @@
324327 if (IS_ERR(pvtm->tz))
325328 return -EINVAL;
326329 if (!pvtm->tz->ops->get_temp)
330
+ return -EINVAL;
331
+ if (of_property_read_bool(np, "rockchip,pvtm-pvtpll")) {
332
+ if (of_property_read_u32(np, "rockchip,pvtm-offset",
333
+ &pvtm->offset))
334
+ return -EINVAL;
335
+ pvtm->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
336
+ if (IS_ERR(pvtm->grf))
337
+ return -EINVAL;
338
+ return 0;
339
+ }
340
+ if (of_property_read_u32_array(np, "rockchip,pvtm-ch", pvtm->ch, 2))
341
+ return -EINVAL;
342
+ if (pvtm->ch[0] >= PVTM_CH_MAX || pvtm->ch[1] >= PVTM_SUB_CH_MAX)
343
+ return -EINVAL;
344
+ if (of_property_read_u32(np, "rockchip,pvtm-number", &pvtm->num))
345
+ return -EINVAL;
346
+ if (of_property_read_u32(np, "rockchip,pvtm-error", &pvtm->err))
327347 return -EINVAL;
328348
329349 return 0;
....@@ -415,7 +435,7 @@
415435 cur_temp, *target_value, avg_value, diff_value);
416436
417437 resetore_volt:
418
- regulator_set_voltage(reg, old_volt, old_volt);
438
+ regulator_set_voltage(reg, old_volt, INT_MAX);
419439 restore_clk:
420440 clk_set_rate(clk, old_freq);
421441 pvtm_value_out:
....@@ -694,6 +714,81 @@
694714 }
695715 EXPORT_SYMBOL(rockchip_of_get_lkg_sel);
696716
717
+static int rockchip_get_pvtm_pvtpll(struct device *dev, struct device_node *np,
718
+ char *reg_name)
719
+{
720
+ struct regulator *reg;
721
+ struct clk *clk;
722
+ struct pvtm_config *pvtm;
723
+ unsigned long old_freq;
724
+ unsigned int old_volt;
725
+ int cur_temp, diff_temp, prop_temp, diff_value;
726
+ int pvtm_value = 0;
727
+ int ret = 0;
728
+
729
+ pvtm = kzalloc(sizeof(*pvtm), GFP_KERNEL);
730
+ if (!pvtm)
731
+ return -ENOMEM;
732
+
733
+ ret = rockchip_parse_pvtm_config(np, pvtm);
734
+ if (ret)
735
+ goto out;
736
+
737
+ clk = clk_get(dev, NULL);
738
+ if (IS_ERR_OR_NULL(clk)) {
739
+ dev_warn(dev, "Failed to get clk\n");
740
+ goto out;
741
+ }
742
+
743
+ reg = regulator_get_optional(dev, reg_name);
744
+ if (IS_ERR_OR_NULL(reg)) {
745
+ dev_warn(dev, "Failed to get reg\n");
746
+ clk_put(clk);
747
+ goto out;
748
+ }
749
+ old_freq = clk_get_rate(clk);
750
+ old_volt = regulator_get_voltage(reg);
751
+
752
+ ret = clk_set_rate(clk, pvtm->freq * 1000);
753
+ if (ret) {
754
+ dev_err(dev, "Failed to set pvtm freq\n");
755
+ goto put_reg;
756
+ }
757
+ ret = regulator_set_voltage(reg, pvtm->volt, INT_MAX);
758
+ if (ret) {
759
+ dev_err(dev, "Failed to set pvtm_volt\n");
760
+ goto restore_clk;
761
+ }
762
+ usleep_range(pvtm->sample_time, pvtm->sample_time + 100);
763
+
764
+ ret = regmap_read(pvtm->grf, pvtm->offset, &pvtm_value);
765
+ if (ret < 0) {
766
+ dev_err(dev, "failed to get pvtm from 0x%x\n", pvtm->offset);
767
+ goto resetore_volt;
768
+ }
769
+ pvtm->tz->ops->get_temp(pvtm->tz, &cur_temp);
770
+ diff_temp = (cur_temp / 1000 - pvtm->ref_temp);
771
+ if (diff_temp < 0)
772
+ prop_temp = pvtm->temp_prop[0];
773
+ else
774
+ prop_temp = pvtm->temp_prop[1];
775
+ diff_value = diff_temp * prop_temp / 1000;
776
+ pvtm_value += diff_value;
777
+
778
+ dev_info(dev, "pvtm=%d\n", pvtm_value);
779
+
780
+resetore_volt:
781
+ regulator_set_voltage(reg, old_volt, INT_MAX);
782
+restore_clk:
783
+ clk_set_rate(clk, old_freq);
784
+put_reg:
785
+ regulator_put(reg);
786
+ clk_put(clk);
787
+out:
788
+ kfree(pvtm);
789
+
790
+ return pvtm_value;
791
+}
697792
698793 static int rockchip_get_pvtm(struct device *dev, struct device_node *np,
699794 char *reg_name)
....@@ -750,7 +845,10 @@
750845 char name[NAME_MAX];
751846 int pvtm, ret;
752847
753
- pvtm = rockchip_get_pvtm(dev, np, reg_name);
848
+ if (of_property_read_bool(np, "rockchip,pvtm-pvtpll"))
849
+ pvtm = rockchip_get_pvtm_pvtpll(dev, np, reg_name);
850
+ else
851
+ pvtm = rockchip_get_pvtm(dev, np, reg_name);
754852 if (pvtm <= 0)
755853 return;
756854
....@@ -910,8 +1008,9 @@
9101008 struct sel_table *irdrop_table = NULL;
9111009 struct opp_table *opp_table;
9121010 struct dev_pm_opp *opp;
1011
+ unsigned long tmp_safe_rate = 0;
9131012 int evb_irdrop = 0, board_irdrop, delta_irdrop;
914
- int tmp_safe_rate = 0, opp_rate, i, ret = 0;
1013
+ int opp_rate, i, ret = 0;
9151014 u32 max_volt = UINT_MAX;
9161015 bool reach_max_volt = false;
9171016
....@@ -1003,6 +1102,44 @@
10031102 mutex_unlock(&opp_table->lock);
10041103 }
10051104
1105
+static void rockchip_adjust_opp_by_otp(struct device *dev,
1106
+ struct device_node *np)
1107
+{
1108
+ struct dev_pm_opp *opp;
1109
+ struct opp_table *opp_table;
1110
+ struct otp_opp_info opp_info = {};
1111
+ int ret;
1112
+
1113
+ ret = rockchip_nvmem_cell_read_common(np, "opp-info", &opp_info,
1114
+ sizeof(opp_info));
1115
+ if (ret || !opp_info.volt)
1116
+ return;
1117
+
1118
+ dev_info(dev, "adjust opp-table by otp: min=%uM, max=%uM, volt=%umV\n",
1119
+ opp_info.min_freq, opp_info.max_freq, opp_info.volt);
1120
+
1121
+ opp_table = dev_pm_opp_get_opp_table(dev);
1122
+ if (!opp_table)
1123
+ return;
1124
+
1125
+ mutex_lock(&opp_table->lock);
1126
+ list_for_each_entry(opp, &opp_table->opp_list, node) {
1127
+ if (!opp->available)
1128
+ continue;
1129
+ if (opp->rate < opp_info.min_freq * 1000000)
1130
+ continue;
1131
+ if (opp->rate > opp_info.max_freq * 1000000)
1132
+ continue;
1133
+
1134
+ opp->supplies->u_volt += opp_info.volt * 1000;
1135
+ if (opp->supplies->u_volt > opp->supplies->u_volt_max)
1136
+ opp->supplies->u_volt = opp->supplies->u_volt_max;
1137
+ }
1138
+ mutex_unlock(&opp_table->lock);
1139
+
1140
+ dev_pm_opp_put_opp_table(opp_table);
1141
+}
1142
+
10061143 static int rockchip_adjust_opp_table(struct device *dev,
10071144 unsigned long scale_rate)
10081145 {
....@@ -1049,6 +1186,7 @@
10491186 of_property_read_u32(np, "rockchip,avs-enable", &avs);
10501187 of_property_read_u32(np, "rockchip,avs", &avs);
10511188 of_property_read_u32(np, "rockchip,avs-scale", &avs_scale);
1189
+ rockchip_adjust_opp_by_otp(dev, np);
10521190 rockchip_adjust_opp_by_mbist_vmin(dev, np);
10531191 rockchip_adjust_opp_by_irdrop(dev, np, &safe_rate, &max_rate);
10541192