forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
kernel/drivers/clk/ti/dpll3xxx.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * OMAP3/4 - specific DPLL control functions
34 *
....@@ -12,10 +13,6 @@
1213 *
1314 * Parts of this code are based on code written by
1415 * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
15
- *
16
- * This program is free software; you can redistribute it and/or modify
17
- * it under the terms of the GNU General Public License version 2 as
18
- * published by the Free Software Foundation.
1916 */
2017
2118 #include <linux/kernel.h>
....@@ -731,7 +728,7 @@
731728 do {
732729 do {
733730 hw = clk_hw_get_parent(hw);
734
- } while (hw && (clk_hw_get_flags(hw) & CLK_IS_BASIC));
731
+ } while (hw && (!omap2_clk_is_hw_omap(hw)));
735732 if (!hw)
736733 break;
737734 pclk = to_clk_hw_omap(hw);
....@@ -782,6 +779,130 @@
782779 return rate;
783780 }
784781
782
+/**
783
+ * omap3_core_dpll_save_context - Save the m and n values of the divider
784
+ * @hw: pointer struct clk_hw
785
+ *
786
+ * Before the dpll registers are lost save the last rounded rate m and n
787
+ * and the enable mask.
788
+ */
789
+int omap3_core_dpll_save_context(struct clk_hw *hw)
790
+{
791
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
792
+ struct dpll_data *dd;
793
+ u32 v;
794
+
795
+ dd = clk->dpll_data;
796
+
797
+ v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
798
+ clk->context = (v & dd->enable_mask) >> __ffs(dd->enable_mask);
799
+
800
+ if (clk->context == DPLL_LOCKED) {
801
+ v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg);
802
+ dd->last_rounded_m = (v & dd->mult_mask) >>
803
+ __ffs(dd->mult_mask);
804
+ dd->last_rounded_n = ((v & dd->div1_mask) >>
805
+ __ffs(dd->div1_mask)) + 1;
806
+ }
807
+
808
+ return 0;
809
+}
810
+
811
+/**
812
+ * omap3_core_dpll_restore_context - restore the m and n values of the divider
813
+ * @hw: pointer struct clk_hw
814
+ *
815
+ * Restore the last rounded rate m and n
816
+ * and the enable mask.
817
+ */
818
+void omap3_core_dpll_restore_context(struct clk_hw *hw)
819
+{
820
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
821
+ const struct dpll_data *dd;
822
+ u32 v;
823
+
824
+ dd = clk->dpll_data;
825
+
826
+ if (clk->context == DPLL_LOCKED) {
827
+ _omap3_dpll_write_clken(clk, 0x4);
828
+ _omap3_wait_dpll_status(clk, 0);
829
+
830
+ v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg);
831
+ v &= ~(dd->mult_mask | dd->div1_mask);
832
+ v |= dd->last_rounded_m << __ffs(dd->mult_mask);
833
+ v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask);
834
+ ti_clk_ll_ops->clk_writel(v, &dd->mult_div1_reg);
835
+
836
+ _omap3_dpll_write_clken(clk, DPLL_LOCKED);
837
+ _omap3_wait_dpll_status(clk, 1);
838
+ } else {
839
+ _omap3_dpll_write_clken(clk, clk->context);
840
+ }
841
+}
842
+
843
+/**
844
+ * omap3_non_core_dpll_save_context - Save the m and n values of the divider
845
+ * @hw: pointer struct clk_hw
846
+ *
847
+ * Before the dpll registers are lost save the last rounded rate m and n
848
+ * and the enable mask.
849
+ */
850
+int omap3_noncore_dpll_save_context(struct clk_hw *hw)
851
+{
852
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
853
+ struct dpll_data *dd;
854
+ u32 v;
855
+
856
+ dd = clk->dpll_data;
857
+
858
+ v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
859
+ clk->context = (v & dd->enable_mask) >> __ffs(dd->enable_mask);
860
+
861
+ if (clk->context == DPLL_LOCKED) {
862
+ v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg);
863
+ dd->last_rounded_m = (v & dd->mult_mask) >>
864
+ __ffs(dd->mult_mask);
865
+ dd->last_rounded_n = ((v & dd->div1_mask) >>
866
+ __ffs(dd->div1_mask)) + 1;
867
+ }
868
+
869
+ return 0;
870
+}
871
+
872
+/**
873
+ * omap3_core_dpll_restore_context - restore the m and n values of the divider
874
+ * @hw: pointer struct clk_hw
875
+ *
876
+ * Restore the last rounded rate m and n
877
+ * and the enable mask.
878
+ */
879
+void omap3_noncore_dpll_restore_context(struct clk_hw *hw)
880
+{
881
+ struct clk_hw_omap *clk = to_clk_hw_omap(hw);
882
+ const struct dpll_data *dd;
883
+ u32 ctrl, mult_div1;
884
+
885
+ dd = clk->dpll_data;
886
+
887
+ ctrl = ti_clk_ll_ops->clk_readl(&dd->control_reg);
888
+ mult_div1 = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg);
889
+
890
+ if (clk->context == ((ctrl & dd->enable_mask) >>
891
+ __ffs(dd->enable_mask)) &&
892
+ dd->last_rounded_m == ((mult_div1 & dd->mult_mask) >>
893
+ __ffs(dd->mult_mask)) &&
894
+ dd->last_rounded_n == ((mult_div1 & dd->div1_mask) >>
895
+ __ffs(dd->div1_mask)) + 1) {
896
+ /* nothing to be done */
897
+ return;
898
+ }
899
+
900
+ if (clk->context == DPLL_LOCKED)
901
+ omap3_noncore_dpll_program(clk, 0);
902
+ else
903
+ _omap3_dpll_write_clken(clk, clk->context);
904
+}
905
+
785906 /* OMAP3/4 non-CORE DPLL clkops */
786907 const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
787908 .allow_idle = omap3_dpll_allow_idle,