19
19
#include <linux/reset.h>
20
20
#include <linux/workqueue.h>
21
21
22
+ #include <soc/tegra/fuse.h>
23
+
22
24
#include "governor.h"
23
25
24
26
#define ACTMON_GLB_STATUS 0x0
@@ -155,6 +157,7 @@ struct tegra_devfreq_device {
155
157
156
158
struct tegra_devfreq {
157
159
struct devfreq * devfreq ;
160
+ struct opp_table * opp_table ;
158
161
159
162
struct reset_control * reset ;
160
163
struct clk * clock ;
@@ -612,34 +615,19 @@ static void tegra_actmon_stop(struct tegra_devfreq *tegra)
612
615
static int tegra_devfreq_target (struct device * dev , unsigned long * freq ,
613
616
u32 flags )
614
617
{
615
- struct tegra_devfreq * tegra = dev_get_drvdata (dev );
616
- struct devfreq * devfreq = tegra -> devfreq ;
617
618
struct dev_pm_opp * opp ;
618
- unsigned long rate ;
619
- int err ;
619
+ int ret ;
620
620
621
621
opp = devfreq_recommended_opp (dev , freq , flags );
622
622
if (IS_ERR (opp )) {
623
623
dev_err (dev , "Failed to find opp for %lu Hz\n" , * freq );
624
624
return PTR_ERR (opp );
625
625
}
626
- rate = dev_pm_opp_get_freq (opp );
627
- dev_pm_opp_put (opp );
628
-
629
- err = clk_set_min_rate (tegra -> emc_clock , rate * KHZ );
630
- if (err )
631
- return err ;
632
-
633
- err = clk_set_rate (tegra -> emc_clock , 0 );
634
- if (err )
635
- goto restore_min_rate ;
636
626
637
- return 0 ;
638
-
639
- restore_min_rate :
640
- clk_set_min_rate (tegra -> emc_clock , devfreq -> previous_freq );
627
+ ret = dev_pm_opp_set_bw (dev , opp );
628
+ dev_pm_opp_put (opp );
641
629
642
- return err ;
630
+ return ret ;
643
631
}
644
632
645
633
static int tegra_devfreq_get_dev_status (struct device * dev ,
@@ -655,7 +643,7 @@ static int tegra_devfreq_get_dev_status(struct device *dev,
655
643
stat -> private_data = tegra ;
656
644
657
645
/* The below are to be used by the other governors */
658
- stat -> current_frequency = cur_freq ;
646
+ stat -> current_frequency = cur_freq * KHZ ;
659
647
660
648
actmon_dev = & tegra -> devices [MCALL ];
661
649
@@ -705,7 +693,12 @@ static int tegra_governor_get_target(struct devfreq *devfreq,
705
693
target_freq = max (target_freq , dev -> target_freq );
706
694
}
707
695
708
- * freq = target_freq ;
696
+ /*
697
+ * tegra-devfreq driver operates with KHz units, while OPP table
698
+ * entries use Hz units. Hence we need to convert the units for the
699
+ * devfreq core.
700
+ */
701
+ * freq = target_freq * KHZ ;
709
702
710
703
return 0 ;
711
704
}
@@ -774,6 +767,7 @@ static struct devfreq_governor tegra_devfreq_governor = {
774
767
775
768
static int tegra_devfreq_probe (struct platform_device * pdev )
776
769
{
770
+ u32 hw_version = BIT (tegra_sku_info .soc_speedo_id );
777
771
struct tegra_devfreq_device * dev ;
778
772
struct tegra_devfreq * tegra ;
779
773
struct devfreq * devfreq ;
@@ -822,11 +816,25 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
822
816
return err ;
823
817
}
824
818
819
+ tegra -> opp_table = dev_pm_opp_set_supported_hw (& pdev -> dev ,
820
+ & hw_version , 1 );
821
+ err = PTR_ERR_OR_ZERO (tegra -> opp_table );
822
+ if (err ) {
823
+ dev_err (& pdev -> dev , "Failed to set supported HW: %d\n" , err );
824
+ return err ;
825
+ }
826
+
827
+ err = dev_pm_opp_of_add_table (& pdev -> dev );
828
+ if (err ) {
829
+ dev_err (& pdev -> dev , "Failed to add OPP table: %d\n" , err );
830
+ goto put_hw ;
831
+ }
832
+
825
833
err = clk_prepare_enable (tegra -> clock );
826
834
if (err ) {
827
835
dev_err (& pdev -> dev ,
828
836
"Failed to prepare and enable ACTMON clock\n" );
829
- return err ;
837
+ goto remove_table ;
830
838
}
831
839
832
840
err = reset_control_reset (tegra -> reset );
@@ -850,23 +858,6 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
850
858
dev -> regs = tegra -> regs + dev -> config -> offset ;
851
859
}
852
860
853
- for (rate = 0 ; rate <= tegra -> max_freq * KHZ ; rate ++ ) {
854
- rate = clk_round_rate (tegra -> emc_clock , rate );
855
-
856
- if (rate < 0 ) {
857
- dev_err (& pdev -> dev ,
858
- "Failed to round clock rate: %ld\n" , rate );
859
- err = rate ;
860
- goto remove_opps ;
861
- }
862
-
863
- err = dev_pm_opp_add (& pdev -> dev , rate / KHZ , 0 );
864
- if (err ) {
865
- dev_err (& pdev -> dev , "Failed to add OPP: %d\n" , err );
866
- goto remove_opps ;
867
- }
868
- }
869
-
870
861
platform_set_drvdata (pdev , tegra );
871
862
872
863
tegra -> clk_rate_change_nb .notifier_call = tegra_actmon_clk_notify_cb ;
@@ -882,7 +873,6 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
882
873
}
883
874
884
875
tegra_devfreq_profile .initial_freq = clk_get_rate (tegra -> emc_clock );
885
- tegra_devfreq_profile .initial_freq /= KHZ ;
886
876
887
877
devfreq = devfreq_add_device (& pdev -> dev , & tegra_devfreq_profile ,
888
878
"tegra_actmon" , NULL );
@@ -902,6 +892,10 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
902
892
reset_control_reset (tegra -> reset );
903
893
disable_clk :
904
894
clk_disable_unprepare (tegra -> clock );
895
+ remove_table :
896
+ dev_pm_opp_of_remove_table (& pdev -> dev );
897
+ put_hw :
898
+ dev_pm_opp_put_supported_hw (tegra -> opp_table );
905
899
906
900
return err ;
907
901
}
@@ -913,11 +907,12 @@ static int tegra_devfreq_remove(struct platform_device *pdev)
913
907
devfreq_remove_device (tegra -> devfreq );
914
908
devfreq_remove_governor (& tegra_devfreq_governor );
915
909
916
- dev_pm_opp_remove_all_dynamic (& pdev -> dev );
917
-
918
910
reset_control_reset (tegra -> reset );
919
911
clk_disable_unprepare (tegra -> clock );
920
912
913
+ dev_pm_opp_of_remove_table (& pdev -> dev );
914
+ dev_pm_opp_put_supported_hw (tegra -> opp_table );
915
+
921
916
return 0 ;
922
917
}
923
918
0 commit comments