hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/soc/rockchip/rockchip_opp_select.c
....@@ -3,6 +3,7 @@
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>
....@@ -714,6 +715,327 @@
714715 }
715716 EXPORT_SYMBOL(rockchip_of_get_lkg_sel);
716717
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
+
7171039 static int rockchip_get_pvtm_pvtpll(struct device *dev, struct device_node *np,
7181040 char *reg_name)
7191041 {
....@@ -725,6 +1047,11 @@
7251047 int cur_temp, diff_temp, prop_temp, diff_value;
7261048 int pvtm_value = 0;
7271049 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
+ }
7281055
7291056 pvtm = kzalloc(sizeof(*pvtm), GFP_KERNEL);
7301057 if (!pvtm)
....@@ -911,39 +1238,61 @@
9111238 }
9121239 EXPORT_SYMBOL(rockchip_of_get_bin_volt_sel);
9131240
914
-void rockchip_get_soc_info(struct device *dev,
915
- const struct of_device_id *matches,
916
- int *bin, int *process)
1241
+void rockchip_get_opp_data(const struct of_device_id *matches,
1242
+ struct rockchip_opp_info *info)
9171243 {
9181244 const struct of_device_id *match;
919
- struct device_node *np;
9201245 struct device_node *node;
921
- int (*get_soc_info)(struct device *dev, struct device_node *np,
922
- int *bin, int *process);
923
- int ret = 0;
924
-
925
- if (!matches)
926
- return;
927
-
928
- np = of_parse_phandle(dev->of_node, "operating-points-v2", 0);
929
- if (!np) {
930
- dev_warn(dev, "OPP-v2 not supported\n");
931
- return;
932
- }
9331246
9341247 node = of_find_node_by_path("/");
9351248 match = of_match_node(matches, node);
936
- if (match && match->data) {
937
- get_soc_info = match->data;
938
- ret = get_soc_info(dev, np, bin, process);
939
- if (ret)
940
- 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);
9411286 }
9421287
943
- of_node_put(node);
944
- 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;
9451294 }
946
-EXPORT_SYMBOL(rockchip_get_soc_info);
1295
+EXPORT_SYMBOL(rockchip_get_volt_rm_table);
9471296
9481297 void rockchip_get_scale_volt_sel(struct device *dev, char *lkg_name,
9491298 char *reg_name, int bin, int process,
....@@ -1026,6 +1375,8 @@
10261375
10271376 mutex_lock(&opp_table->lock);
10281377 list_for_each_entry(opp, &opp_table->opp_list, node) {
1378
+ if (!opp->available)
1379
+ continue;
10291380 if (!irdrop_table) {
10301381 delta_irdrop = 0;
10311382 } else {
....@@ -1094,6 +1445,8 @@
10941445
10951446 mutex_lock(&opp_table->lock);
10961447 list_for_each_entry(opp, &opp_table->opp_list, node) {
1448
+ if (!opp->available)
1449
+ continue;
10971450 if (opp->supplies->u_volt < vmin) {
10981451 opp->supplies->u_volt = vmin;
10991452 opp->supplies->u_volt_min = vmin;
....@@ -1161,7 +1514,7 @@
11611514 goto out;
11621515 }
11631516 if (opp->rate > scale_rate)
1164
- dev_pm_opp_remove(dev, opp->rate);
1517
+ dev_pm_opp_disable(dev, opp->rate);
11651518 dev_pm_opp_put(opp);
11661519 }
11671520 out:
....@@ -1256,14 +1609,154 @@
12561609 }
12571610 EXPORT_SYMBOL(rockchip_adjust_power_scale);
12581611
1259
-int rockchip_init_opp_table(struct device *dev,
1260
- 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,
12611753 char *lkg_name, char *reg_name)
12621754 {
12631755 struct device_node *np;
12641756 int bin = -EINVAL, process = -EINVAL;
12651757 int scale = 0, volt_sel = -EINVAL;
1266
- int ret = 0;
1758
+ int ret = 0, num_clks = 0, i;
1759
+ u32 freq;
12671760
12681761 /* Get OPP descriptor node */
12691762 np = of_parse_phandle(dev->of_node, "operating-points-v2", 0);
....@@ -1271,20 +1764,73 @@
12711764 dev_dbg(dev, "Failed to find operating-points-v2\n");
12721765 return -ENOENT;
12731766 }
1274
- of_node_put(np);
1767
+ if (!info)
1768
+ goto next;
1769
+ info->dev = dev;
12751770
1276
- 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:
12771813 rockchip_get_scale_volt_sel(dev, lkg_name, reg_name, bin, process,
12781814 &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);
12791817 rockchip_set_opp_prop_name(dev, process, volt_sel);
12801818 ret = dev_pm_opp_of_add_table(dev);
12811819 if (ret) {
12821820 dev_err(dev, "Invalid operating-points in device tree.\n");
1283
- return ret;
1821
+ goto dis_opp_clk;
12841822 }
12851823 rockchip_adjust_power_scale(dev, scale);
1824
+ rockchip_pvtpll_calibrate_opp(info);
1825
+ rockchip_pvtpll_add_length(info);
12861826
1287
- 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;
12881834 }
12891835 EXPORT_SYMBOL(rockchip_init_opp_table);
12901836