hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/soc/rockchip/rockchip_opp_select.c
....@@ -3,11 +3,14 @@
33 *
44 * SPDX-License-Identifier: GPL-2.0+
55 */
6
+//#define DEBUG
67 #include <linux/clk.h>
78 #include <linux/cpufreq.h>
89 #include <linux/devfreq.h>
10
+#include <linux/mfd/syscon.h>
911 #include <linux/module.h>
1012 #include <linux/nvmem-consumer.h>
13
+#include <linux/regmap.h>
1114 #include <linux/regulator/consumer.h>
1215 #include <linux/slab.h>
1316 #include <linux/soc/rockchip/pvtm.h>
....@@ -51,15 +54,24 @@
5154 unsigned int num;
5255 unsigned int err;
5356 unsigned int ref_temp;
57
+ unsigned int offset;
5458 int temp_prop[2];
5559 const char *tz_name;
5660 struct thermal_zone_device *tz;
61
+ struct regmap *grf;
5762 };
5863
5964 struct lkg_conversion_table {
6065 int temp;
6166 int conv;
6267 };
68
+
69
+struct otp_opp_info {
70
+ u16 min_freq;
71
+ u16 max_freq;
72
+ u8 volt;
73
+ u8 length;
74
+} __packed;
6375
6476 #define PVTM_CH_MAX 8
6577 #define PVTM_SUB_CH_MAX 8
....@@ -298,16 +310,8 @@
298310 return -EINVAL;
299311 if (of_property_read_u32(np, "rockchip,pvtm-volt", &pvtm->volt))
300312 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;
305313 if (of_property_read_u32(np, "rockchip,pvtm-sample-time",
306314 &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))
311315 return -EINVAL;
312316 if (of_property_read_u32(np, "rockchip,pvtm-ref-temp", &pvtm->ref_temp))
313317 return -EINVAL;
....@@ -324,6 +328,23 @@
324328 if (IS_ERR(pvtm->tz))
325329 return -EINVAL;
326330 if (!pvtm->tz->ops->get_temp)
331
+ return -EINVAL;
332
+ if (of_property_read_bool(np, "rockchip,pvtm-pvtpll")) {
333
+ if (of_property_read_u32(np, "rockchip,pvtm-offset",
334
+ &pvtm->offset))
335
+ return -EINVAL;
336
+ pvtm->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
337
+ if (IS_ERR(pvtm->grf))
338
+ return -EINVAL;
339
+ return 0;
340
+ }
341
+ if (of_property_read_u32_array(np, "rockchip,pvtm-ch", pvtm->ch, 2))
342
+ return -EINVAL;
343
+ if (pvtm->ch[0] >= PVTM_CH_MAX || pvtm->ch[1] >= PVTM_SUB_CH_MAX)
344
+ return -EINVAL;
345
+ if (of_property_read_u32(np, "rockchip,pvtm-number", &pvtm->num))
346
+ return -EINVAL;
347
+ if (of_property_read_u32(np, "rockchip,pvtm-error", &pvtm->err))
327348 return -EINVAL;
328349
329350 return 0;
....@@ -415,7 +436,7 @@
415436 cur_temp, *target_value, avg_value, diff_value);
416437
417438 resetore_volt:
418
- regulator_set_voltage(reg, old_volt, old_volt);
439
+ regulator_set_voltage(reg, old_volt, INT_MAX);
419440 restore_clk:
420441 clk_set_rate(clk, old_freq);
421442 pvtm_value_out:
....@@ -694,6 +715,407 @@
694715 }
695716 EXPORT_SYMBOL(rockchip_of_get_lkg_sel);
696717
718
+static unsigned long rockchip_pvtpll_get_rate(struct rockchip_opp_info *info)
719
+{
720
+ unsigned int rate0, rate1, delta;
721
+ int i;
722
+
723
+#define MIN_STABLE_DELTA 3
724
+ regmap_read(info->grf, info->pvtpll_avg_offset, &rate0);
725
+ /* max delay 2ms */
726
+ for (i = 0; i < 20; i++) {
727
+ udelay(100);
728
+ regmap_read(info->grf, info->pvtpll_avg_offset, &rate1);
729
+ delta = abs(rate1 - rate0);
730
+ rate0 = rate1;
731
+ if (delta <= MIN_STABLE_DELTA)
732
+ break;
733
+ }
734
+
735
+ if (delta > MIN_STABLE_DELTA) {
736
+ dev_err(info->dev, "%s: bad delta: %u\n", __func__, delta);
737
+ return 0;
738
+ }
739
+
740
+ return rate0 * 1000000;
741
+}
742
+
743
+static int rockchip_pvtpll_parse_dt(struct rockchip_opp_info *info)
744
+{
745
+ struct device_node *np;
746
+ int ret;
747
+
748
+ np = of_parse_phandle(info->dev->of_node, "operating-points-v2", 0);
749
+ if (!np) {
750
+ dev_warn(info->dev, "OPP-v2 not supported\n");
751
+ return -ENOENT;
752
+ }
753
+
754
+ ret = of_property_read_u32(np, "rockchip,pvtpll-avg-offset", &info->pvtpll_avg_offset);
755
+ if (ret)
756
+ goto out;
757
+
758
+ ret = of_property_read_u32(np, "rockchip,pvtpll-min-rate", &info->pvtpll_min_rate);
759
+ if (ret)
760
+ goto out;
761
+
762
+ ret = of_property_read_u32(np, "rockchip,pvtpll-volt-step", &info->pvtpll_volt_step);
763
+out:
764
+ of_node_put(np);
765
+
766
+ return ret;
767
+}
768
+
769
+static int rockchip_init_pvtpll_info(struct rockchip_opp_info *info)
770
+{
771
+ struct opp_table *opp_table;
772
+ struct dev_pm_opp *opp;
773
+ int i = 0, max_count, ret;
774
+
775
+ ret = rockchip_pvtpll_parse_dt(info);
776
+ if (ret)
777
+ return ret;
778
+
779
+ max_count = dev_pm_opp_get_opp_count(info->dev);
780
+ if (max_count <= 0)
781
+ return max_count ? max_count : -ENODATA;
782
+
783
+ info->opp_table = kcalloc(max_count, sizeof(*info->opp_table), GFP_KERNEL);
784
+ if (!info->opp_table)
785
+ return -ENOMEM;
786
+
787
+ opp_table = dev_pm_opp_get_opp_table(info->dev);
788
+ if (!opp_table) {
789
+ kfree(info->opp_table);
790
+ info->opp_table = NULL;
791
+ return -ENOMEM;
792
+ }
793
+
794
+ mutex_lock(&opp_table->lock);
795
+ list_for_each_entry(opp, &opp_table->opp_list, node) {
796
+ if (!opp->available)
797
+ continue;
798
+
799
+ info->opp_table[i].u_volt = opp->supplies[0].u_volt;
800
+ info->opp_table[i].u_volt_min = opp->supplies[0].u_volt_min;
801
+ info->opp_table[i].u_volt_max = opp->supplies[0].u_volt_max;
802
+ if (opp_table->regulator_count > 1) {
803
+ info->opp_table[i].u_volt_mem = opp->supplies[1].u_volt;
804
+ info->opp_table[i].u_volt_mem_min = opp->supplies[1].u_volt_min;
805
+ info->opp_table[i].u_volt_mem_max = opp->supplies[1].u_volt_max;
806
+ }
807
+ info->opp_table[i++].rate = opp->rate;
808
+ }
809
+ mutex_unlock(&opp_table->lock);
810
+
811
+ dev_pm_opp_put_opp_table(opp_table);
812
+
813
+ return 0;
814
+}
815
+
816
+static int rockchip_pvtpll_set_volt(struct device *dev, struct regulator *reg,
817
+ int target_uV, int max_uV, char *reg_name)
818
+{
819
+ int ret = 0;
820
+
821
+ ret = regulator_set_voltage(reg, target_uV, max_uV);
822
+ if (ret)
823
+ dev_err(dev, "%s: failed to set %s voltage (%d %d uV): %d\n",
824
+ __func__, reg_name, target_uV, max_uV, ret);
825
+
826
+ return ret;
827
+}
828
+
829
+static int rockchip_pvtpll_set_clk(struct device *dev, struct clk *clk,
830
+ unsigned long rate)
831
+{
832
+ int ret = 0;
833
+
834
+ ret = clk_set_rate(clk, rate);
835
+ if (ret)
836
+ dev_err(dev, "%s: failed to set rate %lu Hz, ret:%d\n",
837
+ __func__, rate, ret);
838
+
839
+ return ret;
840
+}
841
+
842
+void rockchip_pvtpll_calibrate_opp(struct rockchip_opp_info *info)
843
+{
844
+ struct opp_table *opp_table;
845
+ struct dev_pm_opp *opp;
846
+ struct regulator *reg = NULL, *reg_mem = NULL;
847
+ unsigned long old_volt = 0, old_volt_mem = 0;
848
+ unsigned long volt = 0, volt_mem = 0;
849
+ unsigned long volt_min, volt_max, volt_mem_min, volt_mem_max;
850
+ unsigned long rate, pvtpll_rate, old_rate, cur_rate, delta0, delta1;
851
+ int i = 0, max_count, step, cur_step, ret;
852
+
853
+ if (!info || !info->grf)
854
+ return;
855
+
856
+ dev_dbg(info->dev, "calibrating opp ...\n");
857
+ ret = rockchip_init_pvtpll_info(info);
858
+ if (ret)
859
+ return;
860
+
861
+ max_count = dev_pm_opp_get_opp_count(info->dev);
862
+ if (max_count <= 0)
863
+ return;
864
+
865
+ opp_table = dev_pm_opp_get_opp_table(info->dev);
866
+ if (!opp_table)
867
+ return;
868
+
869
+ if ((!opp_table->regulators) || IS_ERR(opp_table->clk))
870
+ goto out_put;
871
+
872
+ reg = opp_table->regulators[0];
873
+ old_volt = regulator_get_voltage(reg);
874
+ if (opp_table->regulator_count > 1) {
875
+ reg_mem = opp_table->regulators[1];
876
+ old_volt_mem = regulator_get_voltage(reg_mem);
877
+ if (IS_ERR_VALUE(old_volt_mem))
878
+ goto out_put;
879
+ }
880
+ old_rate = clk_get_rate(opp_table->clk);
881
+ if (IS_ERR_VALUE(old_volt) || IS_ERR_VALUE(old_rate))
882
+ goto out_put;
883
+ cur_rate = old_rate;
884
+
885
+ step = regulator_get_linear_step(reg);
886
+ if (!step || info->pvtpll_volt_step > step)
887
+ step = info->pvtpll_volt_step;
888
+
889
+ if (old_rate > info->pvtpll_min_rate * 1000) {
890
+ if (rockchip_pvtpll_set_clk(info->dev, opp_table->clk,
891
+ info->pvtpll_min_rate * 1000))
892
+ goto out_put;
893
+ }
894
+
895
+ for (i = 0; i < max_count; i++) {
896
+ rate = info->opp_table[i].rate;
897
+ if (rate < 1000 * info->pvtpll_min_rate)
898
+ continue;
899
+
900
+ volt = max(volt, info->opp_table[i].u_volt);
901
+ volt_min = info->opp_table[i].u_volt_min;
902
+ volt_max = info->opp_table[i].u_volt_max;
903
+
904
+ if (opp_table->regulator_count > 1) {
905
+ volt_mem = max(volt_mem, info->opp_table[i].u_volt_mem);
906
+ volt_mem_min = info->opp_table[i].u_volt_mem_min;
907
+ volt_mem_max = info->opp_table[i].u_volt_mem_max;
908
+ if (rockchip_pvtpll_set_volt(info->dev, reg_mem,
909
+ volt_mem, volt_mem_max, "mem"))
910
+ goto out;
911
+ }
912
+ if (rockchip_pvtpll_set_volt(info->dev, reg, volt, volt_max, "vdd"))
913
+ goto out;
914
+
915
+ if (rockchip_pvtpll_set_clk(info->dev, opp_table->clk, rate))
916
+ goto out;
917
+ cur_rate = rate;
918
+ pvtpll_rate = rockchip_pvtpll_get_rate(info);
919
+ if (!pvtpll_rate)
920
+ goto out;
921
+ cur_step = (pvtpll_rate < rate) ? step : -step;
922
+ delta1 = abs(pvtpll_rate - rate);
923
+ do {
924
+ delta0 = delta1;
925
+ volt += cur_step;
926
+ if ((volt < volt_min) || (volt > volt_max))
927
+ break;
928
+ if (opp_table->regulator_count > 1) {
929
+ if (volt > volt_mem_max)
930
+ break;
931
+ else if (volt < volt_mem_min)
932
+ volt_mem = volt_mem_min;
933
+ else
934
+ volt_mem = volt;
935
+ if (rockchip_pvtpll_set_volt(info->dev, reg_mem,
936
+ volt_mem, volt_mem_max,
937
+ "mem"))
938
+ break;
939
+ }
940
+ if (rockchip_pvtpll_set_volt(info->dev, reg, volt,
941
+ volt_max, "vdd"))
942
+ break;
943
+ pvtpll_rate = rockchip_pvtpll_get_rate(info);
944
+ if (!pvtpll_rate)
945
+ goto out;
946
+ delta1 = abs(pvtpll_rate - rate);
947
+ } while (delta1 < delta0);
948
+
949
+ volt -= cur_step;
950
+ info->opp_table[i].u_volt = volt;
951
+ if (opp_table->regulator_count > 1) {
952
+ if (volt < volt_mem_min)
953
+ volt_mem = volt_mem_min;
954
+ else
955
+ volt_mem = volt;
956
+ info->opp_table[i].u_volt_mem = volt_mem;
957
+ }
958
+ }
959
+
960
+ i = 0;
961
+ mutex_lock(&opp_table->lock);
962
+ list_for_each_entry(opp, &opp_table->opp_list, node) {
963
+ if (!opp->available)
964
+ continue;
965
+
966
+ opp->supplies[0].u_volt = info->opp_table[i].u_volt;
967
+ if (opp_table->regulator_count > 1)
968
+ opp->supplies[1].u_volt = info->opp_table[i].u_volt_mem;
969
+ i++;
970
+ }
971
+ mutex_unlock(&opp_table->lock);
972
+ dev_info(info->dev, "opp calibration done\n");
973
+out:
974
+ if (cur_rate > old_rate)
975
+ rockchip_pvtpll_set_clk(info->dev, opp_table->clk, old_rate);
976
+ if (opp_table->regulator_count > 1)
977
+ rockchip_pvtpll_set_volt(info->dev, reg_mem, old_volt_mem,
978
+ INT_MAX, "mem");
979
+ rockchip_pvtpll_set_volt(info->dev, reg, old_volt, INT_MAX, "vdd");
980
+ if (cur_rate < old_rate)
981
+ rockchip_pvtpll_set_clk(info->dev, opp_table->clk, old_rate);
982
+out_put:
983
+ dev_pm_opp_put_opp_table(opp_table);
984
+}
985
+EXPORT_SYMBOL(rockchip_pvtpll_calibrate_opp);
986
+
987
+void rockchip_pvtpll_add_length(struct rockchip_opp_info *info)
988
+{
989
+ struct device_node *np;
990
+ struct opp_table *opp_table;
991
+ struct dev_pm_opp *opp;
992
+ unsigned long old_rate;
993
+ unsigned int min_rate = 0, max_rate = 0, margin = 0;
994
+ u32 opp_flag = 0;
995
+ int ret;
996
+
997
+ if (!info)
998
+ return;
999
+
1000
+ np = of_parse_phandle(info->dev->of_node, "operating-points-v2", 0);
1001
+ if (!np) {
1002
+ dev_warn(info->dev, "OPP-v2 not supported\n");
1003
+ return;
1004
+ }
1005
+
1006
+ if (of_property_read_u32(np, "rockchip,pvtpll-len-min-rate", &min_rate))
1007
+ return;
1008
+ if (of_property_read_u32(np, "rockchip,pvtpll-len-max-rate", &max_rate))
1009
+ return;
1010
+ if (of_property_read_u32(np, "rockchip,pvtpll-len-margin", &margin))
1011
+ return;
1012
+
1013
+ opp_table = dev_pm_opp_get_opp_table(info->dev);
1014
+ if (!opp_table)
1015
+ return;
1016
+ old_rate = clk_get_rate(opp_table->clk);
1017
+ opp_flag = OPP_ADD_LENGTH | ((margin & OPP_LENGTH_MASK) << OPP_LENGTH_SHIFT);
1018
+
1019
+ mutex_lock(&opp_table->lock);
1020
+ list_for_each_entry(opp, &opp_table->opp_list, node) {
1021
+ if (opp->rate < min_rate * 1000 || opp->rate > max_rate * 1000)
1022
+ continue;
1023
+ ret = clk_set_rate(opp_table->clk, opp->rate | opp_flag);
1024
+ if (ret) {
1025
+ dev_err(info->dev,
1026
+ "failed to change %lu len margin %d\n",
1027
+ opp->rate, margin);
1028
+ break;
1029
+ }
1030
+ }
1031
+ mutex_unlock(&opp_table->lock);
1032
+
1033
+ clk_set_rate(opp_table->clk, old_rate);
1034
+
1035
+ dev_pm_opp_put_opp_table(opp_table);
1036
+}
1037
+EXPORT_SYMBOL(rockchip_pvtpll_add_length);
1038
+
1039
+static int rockchip_get_pvtm_pvtpll(struct device *dev, struct device_node *np,
1040
+ char *reg_name)
1041
+{
1042
+ struct regulator *reg;
1043
+ struct clk *clk;
1044
+ struct pvtm_config *pvtm;
1045
+ unsigned long old_freq;
1046
+ unsigned int old_volt;
1047
+ int cur_temp, diff_temp, prop_temp, diff_value;
1048
+ int pvtm_value = 0;
1049
+ int ret = 0;
1050
+
1051
+ if (!rockchip_nvmem_cell_read_u16(np, "pvtm", (u16 *)&pvtm_value) && pvtm_value) {
1052
+ dev_info(dev, "pvtm = %d, get from otp\n", pvtm_value);
1053
+ return pvtm_value;
1054
+ }
1055
+
1056
+ pvtm = kzalloc(sizeof(*pvtm), GFP_KERNEL);
1057
+ if (!pvtm)
1058
+ return -ENOMEM;
1059
+
1060
+ ret = rockchip_parse_pvtm_config(np, pvtm);
1061
+ if (ret)
1062
+ goto out;
1063
+
1064
+ clk = clk_get(dev, NULL);
1065
+ if (IS_ERR_OR_NULL(clk)) {
1066
+ dev_warn(dev, "Failed to get clk\n");
1067
+ goto out;
1068
+ }
1069
+
1070
+ reg = regulator_get_optional(dev, reg_name);
1071
+ if (IS_ERR_OR_NULL(reg)) {
1072
+ dev_warn(dev, "Failed to get reg\n");
1073
+ clk_put(clk);
1074
+ goto out;
1075
+ }
1076
+ old_freq = clk_get_rate(clk);
1077
+ old_volt = regulator_get_voltage(reg);
1078
+
1079
+ ret = clk_set_rate(clk, pvtm->freq * 1000);
1080
+ if (ret) {
1081
+ dev_err(dev, "Failed to set pvtm freq\n");
1082
+ goto put_reg;
1083
+ }
1084
+ ret = regulator_set_voltage(reg, pvtm->volt, INT_MAX);
1085
+ if (ret) {
1086
+ dev_err(dev, "Failed to set pvtm_volt\n");
1087
+ goto restore_clk;
1088
+ }
1089
+ usleep_range(pvtm->sample_time, pvtm->sample_time + 100);
1090
+
1091
+ ret = regmap_read(pvtm->grf, pvtm->offset, &pvtm_value);
1092
+ if (ret < 0) {
1093
+ dev_err(dev, "failed to get pvtm from 0x%x\n", pvtm->offset);
1094
+ goto resetore_volt;
1095
+ }
1096
+ pvtm->tz->ops->get_temp(pvtm->tz, &cur_temp);
1097
+ diff_temp = (cur_temp / 1000 - pvtm->ref_temp);
1098
+ if (diff_temp < 0)
1099
+ prop_temp = pvtm->temp_prop[0];
1100
+ else
1101
+ prop_temp = pvtm->temp_prop[1];
1102
+ diff_value = diff_temp * prop_temp / 1000;
1103
+ pvtm_value += diff_value;
1104
+
1105
+ dev_info(dev, "pvtm=%d\n", pvtm_value);
1106
+
1107
+resetore_volt:
1108
+ regulator_set_voltage(reg, old_volt, INT_MAX);
1109
+restore_clk:
1110
+ clk_set_rate(clk, old_freq);
1111
+put_reg:
1112
+ regulator_put(reg);
1113
+ clk_put(clk);
1114
+out:
1115
+ kfree(pvtm);
1116
+
1117
+ return pvtm_value;
1118
+}
6971119
6981120 static int rockchip_get_pvtm(struct device *dev, struct device_node *np,
6991121 char *reg_name)
....@@ -750,7 +1172,10 @@
7501172 char name[NAME_MAX];
7511173 int pvtm, ret;
7521174
753
- pvtm = rockchip_get_pvtm(dev, np, reg_name);
1175
+ if (of_property_read_bool(np, "rockchip,pvtm-pvtpll"))
1176
+ pvtm = rockchip_get_pvtm_pvtpll(dev, np, reg_name);
1177
+ else
1178
+ pvtm = rockchip_get_pvtm(dev, np, reg_name);
7541179 if (pvtm <= 0)
7551180 return;
7561181
....@@ -813,39 +1238,61 @@
8131238 }
8141239 EXPORT_SYMBOL(rockchip_of_get_bin_volt_sel);
8151240
816
-void rockchip_get_soc_info(struct device *dev,
817
- const struct of_device_id *matches,
818
- int *bin, int *process)
1241
+void rockchip_get_opp_data(const struct of_device_id *matches,
1242
+ struct rockchip_opp_info *info)
8191243 {
8201244 const struct of_device_id *match;
821
- struct device_node *np;
8221245 struct device_node *node;
823
- int (*get_soc_info)(struct device *dev, struct device_node *np,
824
- int *bin, int *process);
825
- int ret = 0;
826
-
827
- if (!matches)
828
- return;
829
-
830
- np = of_parse_phandle(dev->of_node, "operating-points-v2", 0);
831
- if (!np) {
832
- dev_warn(dev, "OPP-v2 not supported\n");
833
- return;
834
- }
8351246
8361247 node = of_find_node_by_path("/");
8371248 match = of_match_node(matches, node);
838
- if (match && match->data) {
839
- get_soc_info = match->data;
840
- ret = get_soc_info(dev, np, bin, process);
841
- if (ret)
842
- dev_err(dev, "Failed to get soc info\n");
1249
+ if (match && match->data)
1250
+ info->data = match->data;
1251
+ of_node_put(node);
1252
+}
1253
+EXPORT_SYMBOL(rockchip_get_opp_data);
1254
+
1255
+int rockchip_get_volt_rm_table(struct device *dev, struct device_node *np,
1256
+ char *porp_name, struct volt_rm_table **table)
1257
+{
1258
+ struct volt_rm_table *rm_table;
1259
+ const struct property *prop;
1260
+ int count, i;
1261
+
1262
+ prop = of_find_property(np, porp_name, NULL);
1263
+ if (!prop)
1264
+ return -EINVAL;
1265
+
1266
+ if (!prop->value)
1267
+ return -ENODATA;
1268
+
1269
+ count = of_property_count_u32_elems(np, porp_name);
1270
+ if (count < 0)
1271
+ return -EINVAL;
1272
+
1273
+ if (count % 2)
1274
+ return -EINVAL;
1275
+
1276
+ rm_table = devm_kzalloc(dev, sizeof(*rm_table) * (count / 2 + 1),
1277
+ GFP_KERNEL);
1278
+ if (!rm_table)
1279
+ return -ENOMEM;
1280
+
1281
+ for (i = 0; i < count / 2; i++) {
1282
+ of_property_read_u32_index(np, porp_name, 2 * i,
1283
+ &rm_table[i].volt);
1284
+ of_property_read_u32_index(np, porp_name, 2 * i + 1,
1285
+ &rm_table[i].rm);
8431286 }
8441287
845
- of_node_put(node);
846
- of_node_put(np);
1288
+ rm_table[i].volt = 0;
1289
+ rm_table[i].rm = VOLT_RM_TABLE_END;
1290
+
1291
+ *table = rm_table;
1292
+
1293
+ return 0;
8471294 }
848
-EXPORT_SYMBOL(rockchip_get_soc_info);
1295
+EXPORT_SYMBOL(rockchip_get_volt_rm_table);
8491296
8501297 void rockchip_get_scale_volt_sel(struct device *dev, char *lkg_name,
8511298 char *reg_name, int bin, int process,
....@@ -910,8 +1357,9 @@
9101357 struct sel_table *irdrop_table = NULL;
9111358 struct opp_table *opp_table;
9121359 struct dev_pm_opp *opp;
1360
+ unsigned long tmp_safe_rate = 0;
9131361 int evb_irdrop = 0, board_irdrop, delta_irdrop;
914
- int tmp_safe_rate = 0, opp_rate, i, ret = 0;
1362
+ int opp_rate, i, ret = 0;
9151363 u32 max_volt = UINT_MAX;
9161364 bool reach_max_volt = false;
9171365
....@@ -927,6 +1375,8 @@
9271375
9281376 mutex_lock(&opp_table->lock);
9291377 list_for_each_entry(opp, &opp_table->opp_list, node) {
1378
+ if (!opp->available)
1379
+ continue;
9301380 if (!irdrop_table) {
9311381 delta_irdrop = 0;
9321382 } else {
....@@ -995,12 +1445,52 @@
9951445
9961446 mutex_lock(&opp_table->lock);
9971447 list_for_each_entry(opp, &opp_table->opp_list, node) {
1448
+ if (!opp->available)
1449
+ continue;
9981450 if (opp->supplies->u_volt < vmin) {
9991451 opp->supplies->u_volt = vmin;
10001452 opp->supplies->u_volt_min = vmin;
10011453 }
10021454 }
10031455 mutex_unlock(&opp_table->lock);
1456
+}
1457
+
1458
+static void rockchip_adjust_opp_by_otp(struct device *dev,
1459
+ struct device_node *np)
1460
+{
1461
+ struct dev_pm_opp *opp;
1462
+ struct opp_table *opp_table;
1463
+ struct otp_opp_info opp_info = {};
1464
+ int ret;
1465
+
1466
+ ret = rockchip_nvmem_cell_read_common(np, "opp-info", &opp_info,
1467
+ sizeof(opp_info));
1468
+ if (ret || !opp_info.volt)
1469
+ return;
1470
+
1471
+ dev_info(dev, "adjust opp-table by otp: min=%uM, max=%uM, volt=%umV\n",
1472
+ opp_info.min_freq, opp_info.max_freq, opp_info.volt);
1473
+
1474
+ opp_table = dev_pm_opp_get_opp_table(dev);
1475
+ if (!opp_table)
1476
+ return;
1477
+
1478
+ mutex_lock(&opp_table->lock);
1479
+ list_for_each_entry(opp, &opp_table->opp_list, node) {
1480
+ if (!opp->available)
1481
+ continue;
1482
+ if (opp->rate < opp_info.min_freq * 1000000)
1483
+ continue;
1484
+ if (opp->rate > opp_info.max_freq * 1000000)
1485
+ continue;
1486
+
1487
+ opp->supplies->u_volt += opp_info.volt * 1000;
1488
+ if (opp->supplies->u_volt > opp->supplies->u_volt_max)
1489
+ opp->supplies->u_volt = opp->supplies->u_volt_max;
1490
+ }
1491
+ mutex_unlock(&opp_table->lock);
1492
+
1493
+ dev_pm_opp_put_opp_table(opp_table);
10041494 }
10051495
10061496 static int rockchip_adjust_opp_table(struct device *dev,
....@@ -1024,7 +1514,7 @@
10241514 goto out;
10251515 }
10261516 if (opp->rate > scale_rate)
1027
- dev_pm_opp_remove(dev, opp->rate);
1517
+ dev_pm_opp_disable(dev, opp->rate);
10281518 dev_pm_opp_put(opp);
10291519 }
10301520 out:
....@@ -1049,6 +1539,7 @@
10491539 of_property_read_u32(np, "rockchip,avs-enable", &avs);
10501540 of_property_read_u32(np, "rockchip,avs", &avs);
10511541 of_property_read_u32(np, "rockchip,avs-scale", &avs_scale);
1542
+ rockchip_adjust_opp_by_otp(dev, np);
10521543 rockchip_adjust_opp_by_mbist_vmin(dev, np);
10531544 rockchip_adjust_opp_by_irdrop(dev, np, &safe_rate, &max_rate);
10541545
....@@ -1118,14 +1609,154 @@
11181609 }
11191610 EXPORT_SYMBOL(rockchip_adjust_power_scale);
11201611
1121
-int rockchip_init_opp_table(struct device *dev,
1122
- const struct of_device_id *matches,
1612
+int rockchip_get_read_margin(struct device *dev,
1613
+ struct rockchip_opp_info *opp_info,
1614
+ unsigned long volt, u32 *target_rm)
1615
+{
1616
+ int i;
1617
+
1618
+ if (!opp_info || !opp_info->volt_rm_tbl)
1619
+ return 0;
1620
+
1621
+ for (i = 0; opp_info->volt_rm_tbl[i].rm != VOLT_RM_TABLE_END; i++) {
1622
+ if (volt >= opp_info->volt_rm_tbl[i].volt) {
1623
+ opp_info->target_rm = opp_info->volt_rm_tbl[i].rm;
1624
+ break;
1625
+ }
1626
+ }
1627
+ *target_rm = opp_info->target_rm;
1628
+
1629
+ return 0;
1630
+}
1631
+EXPORT_SYMBOL(rockchip_get_read_margin);
1632
+
1633
+int rockchip_set_read_margin(struct device *dev,
1634
+ struct rockchip_opp_info *opp_info, u32 rm,
1635
+ bool is_set_rm)
1636
+{
1637
+ if (!is_set_rm || !opp_info)
1638
+ return 0;
1639
+ if (!opp_info || !opp_info->volt_rm_tbl)
1640
+ return 0;
1641
+ if (!opp_info->data || !opp_info->data->set_read_margin)
1642
+ return 0;
1643
+ if (rm == opp_info->current_rm)
1644
+ return 0;
1645
+
1646
+ return opp_info->data->set_read_margin(dev, opp_info, rm);
1647
+}
1648
+EXPORT_SYMBOL(rockchip_set_read_margin);
1649
+
1650
+int rockchip_init_read_margin(struct device *dev,
1651
+ struct rockchip_opp_info *opp_info,
1652
+ char *reg_name)
1653
+{
1654
+ struct clk *clk;
1655
+ struct regulator *reg;
1656
+ unsigned long cur_rate;
1657
+ int cur_volt, ret = 0;
1658
+ u32 target_rm = UINT_MAX;
1659
+
1660
+ reg = regulator_get_optional(dev, reg_name);
1661
+ if (IS_ERR(reg)) {
1662
+ ret = PTR_ERR(reg);
1663
+ if (ret != -EPROBE_DEFER)
1664
+ dev_err(dev, "%s: no regulator (%s) found: %d\n",
1665
+ __func__, reg_name, ret);
1666
+ return ret;
1667
+ }
1668
+ cur_volt = regulator_get_voltage(reg);
1669
+ if (cur_volt < 0) {
1670
+ ret = cur_volt;
1671
+ if (ret != -EPROBE_DEFER)
1672
+ dev_err(dev, "%s: failed to get (%s) volt: %d\n",
1673
+ __func__, reg_name, ret);
1674
+ goto out;
1675
+ }
1676
+
1677
+ clk = clk_get(dev, NULL);
1678
+ if (IS_ERR(clk)) {
1679
+ ret = PTR_ERR(clk);
1680
+ dev_err(dev, "%s: failed to get clk: %d\n", __func__, ret);
1681
+ goto out;
1682
+ }
1683
+ cur_rate = clk_get_rate(clk);
1684
+
1685
+ rockchip_get_read_margin(dev, opp_info, cur_volt, &target_rm);
1686
+ dev_dbg(dev, "cur_rate=%lu, threshold=%lu, cur_volt=%d, target_rm=%d\n",
1687
+ cur_rate, opp_info->intermediate_threshold_freq,
1688
+ cur_volt, target_rm);
1689
+ if (opp_info->intermediate_threshold_freq &&
1690
+ cur_rate > opp_info->intermediate_threshold_freq) {
1691
+ clk_set_rate(clk, opp_info->intermediate_threshold_freq);
1692
+ rockchip_set_read_margin(dev, opp_info, target_rm, true);
1693
+ clk_set_rate(clk, cur_rate);
1694
+ } else {
1695
+ rockchip_set_read_margin(dev, opp_info, target_rm, true);
1696
+ }
1697
+
1698
+ clk_put(clk);
1699
+out:
1700
+ regulator_put(reg);
1701
+
1702
+ return ret;
1703
+}
1704
+EXPORT_SYMBOL(rockchip_init_read_margin);
1705
+
1706
+int rockchip_set_intermediate_rate(struct device *dev,
1707
+ struct rockchip_opp_info *opp_info,
1708
+ struct clk *clk, unsigned long old_freq,
1709
+ unsigned long new_freq, bool is_scaling_up,
1710
+ bool is_set_clk)
1711
+{
1712
+ if (!is_set_clk)
1713
+ return 0;
1714
+ if (!opp_info || !opp_info->volt_rm_tbl)
1715
+ return 0;
1716
+ if (!opp_info->data || !opp_info->data->set_read_margin)
1717
+ return 0;
1718
+ if (opp_info->target_rm == opp_info->current_rm)
1719
+ return 0;
1720
+ /*
1721
+ * There is no need to set intermediate rate if the new voltage
1722
+ * and the current voltage are high voltage.
1723
+ */
1724
+ if ((opp_info->target_rm < opp_info->low_rm) &&
1725
+ (opp_info->current_rm < opp_info->low_rm))
1726
+ return 0;
1727
+
1728
+ if (is_scaling_up) {
1729
+ /*
1730
+ * If scaling up and the current frequency is less than
1731
+ * or equal to intermediate threshold frequency, there is
1732
+ * no need to set intermediate rate.
1733
+ */
1734
+ if (opp_info->intermediate_threshold_freq &&
1735
+ old_freq <= opp_info->intermediate_threshold_freq)
1736
+ return 0;
1737
+ return clk_set_rate(clk, new_freq | OPP_SCALING_UP_INTER);
1738
+ }
1739
+ /*
1740
+ * If scaling down and the new frequency is less than or equal to
1741
+ * intermediate threshold frequency , there is no need to set
1742
+ * intermediate rate and set the new frequency directly.
1743
+ */
1744
+ if (opp_info->intermediate_threshold_freq &&
1745
+ new_freq <= opp_info->intermediate_threshold_freq)
1746
+ return clk_set_rate(clk, new_freq);
1747
+
1748
+ return clk_set_rate(clk, new_freq | OPP_SCALING_DOWN_INTER);
1749
+}
1750
+EXPORT_SYMBOL(rockchip_set_intermediate_rate);
1751
+
1752
+int rockchip_init_opp_table(struct device *dev, struct rockchip_opp_info *info,
11231753 char *lkg_name, char *reg_name)
11241754 {
11251755 struct device_node *np;
11261756 int bin = -EINVAL, process = -EINVAL;
11271757 int scale = 0, volt_sel = -EINVAL;
1128
- int ret = 0;
1758
+ int ret = 0, num_clks = 0, i;
1759
+ u32 freq;
11291760
11301761 /* Get OPP descriptor node */
11311762 np = of_parse_phandle(dev->of_node, "operating-points-v2", 0);
....@@ -1133,20 +1764,73 @@
11331764 dev_dbg(dev, "Failed to find operating-points-v2\n");
11341765 return -ENOENT;
11351766 }
1136
- of_node_put(np);
1767
+ if (!info)
1768
+ goto next;
1769
+ info->dev = dev;
11371770
1138
- rockchip_get_soc_info(dev, matches, &bin, &process);
1771
+ num_clks = of_clk_get_parent_count(np);
1772
+ if (num_clks > 0) {
1773
+ info->clks = devm_kcalloc(dev, num_clks, sizeof(*info->clks),
1774
+ GFP_KERNEL);
1775
+ if (!info->clks) {
1776
+ ret = -ENOMEM;
1777
+ goto out;
1778
+ }
1779
+ for (i = 0; i < num_clks; i++) {
1780
+ info->clks[i].clk = of_clk_get(np, i);
1781
+ if (IS_ERR(info->clks[i].clk)) {
1782
+ ret = PTR_ERR(info->clks[i].clk);
1783
+ dev_err(dev, "%s: failed to get clk %d\n",
1784
+ np->name, i);
1785
+ goto out;
1786
+ }
1787
+ }
1788
+ info->num_clks = num_clks;
1789
+ ret = clk_bulk_prepare_enable(info->num_clks, info->clks);
1790
+ if (ret) {
1791
+ dev_err(dev, "failed to enable opp clks\n");
1792
+ goto out;
1793
+ }
1794
+ }
1795
+ if (info->data && info->data->set_read_margin) {
1796
+ info->current_rm = UINT_MAX;
1797
+ info->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
1798
+ if (IS_ERR(info->grf))
1799
+ info->grf = NULL;
1800
+ rockchip_get_volt_rm_table(dev, np, "volt-mem-read-margin",
1801
+ &info->volt_rm_tbl);
1802
+ of_property_read_u32(np, "low-volt-mem-read-margin",
1803
+ &info->low_rm);
1804
+ if (!of_property_read_u32(np, "intermediate-threshold-freq",
1805
+ &freq))
1806
+ info->intermediate_threshold_freq = freq * 1000;
1807
+ rockchip_init_read_margin(dev, info, reg_name);
1808
+ }
1809
+ if (info->data && info->data->get_soc_info)
1810
+ info->data->get_soc_info(dev, np, &bin, &process);
1811
+
1812
+next:
11391813 rockchip_get_scale_volt_sel(dev, lkg_name, reg_name, bin, process,
11401814 &scale, &volt_sel);
1815
+ if (info && info->data && info->data->set_soc_info)
1816
+ info->data->set_soc_info(dev, np, bin, process, volt_sel);
11411817 rockchip_set_opp_prop_name(dev, process, volt_sel);
11421818 ret = dev_pm_opp_of_add_table(dev);
11431819 if (ret) {
11441820 dev_err(dev, "Invalid operating-points in device tree.\n");
1145
- return ret;
1821
+ goto dis_opp_clk;
11461822 }
11471823 rockchip_adjust_power_scale(dev, scale);
1824
+ rockchip_pvtpll_calibrate_opp(info);
1825
+ rockchip_pvtpll_add_length(info);
11481826
1149
- return 0;
1827
+dis_opp_clk:
1828
+ if (info && info->clks)
1829
+ clk_bulk_disable_unprepare(info->num_clks, info->clks);
1830
+out:
1831
+ of_node_put(np);
1832
+
1833
+ return ret;
11501834 }
11511835 EXPORT_SYMBOL(rockchip_init_opp_table);
11521836