.. | .. |
---|
32 | 32 | # define PLL_LOCK_DET BIT(31) |
---|
33 | 33 | |
---|
34 | 34 | #define PLL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_L_VAL]) |
---|
| 35 | +#define PLL_CAL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_L_VAL]) |
---|
35 | 36 | #define PLL_ALPHA_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL]) |
---|
36 | 37 | #define PLL_ALPHA_VAL_U(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL_U]) |
---|
37 | 38 | |
---|
.. | .. |
---|
44 | 45 | # define PLL_VCO_MASK 0x3 |
---|
45 | 46 | |
---|
46 | 47 | #define PLL_USER_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U]) |
---|
| 48 | +#define PLL_USER_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U1]) |
---|
47 | 49 | |
---|
48 | 50 | #define PLL_CONFIG_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL]) |
---|
49 | 51 | #define PLL_CONFIG_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U]) |
---|
| 52 | +#define PLL_CONFIG_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U1]) |
---|
50 | 53 | #define PLL_TEST_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL]) |
---|
51 | 54 | #define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U]) |
---|
| 55 | +#define PLL_TEST_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U1]) |
---|
52 | 56 | #define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS]) |
---|
53 | 57 | #define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE]) |
---|
54 | 58 | #define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC]) |
---|
.. | .. |
---|
96 | 100 | [PLL_OFF_OPMODE] = 0x2c, |
---|
97 | 101 | [PLL_OFF_FRAC] = 0x38, |
---|
98 | 102 | }, |
---|
| 103 | + [CLK_ALPHA_PLL_TYPE_TRION] = { |
---|
| 104 | + [PLL_OFF_L_VAL] = 0x04, |
---|
| 105 | + [PLL_OFF_CAL_L_VAL] = 0x08, |
---|
| 106 | + [PLL_OFF_USER_CTL] = 0x0c, |
---|
| 107 | + [PLL_OFF_USER_CTL_U] = 0x10, |
---|
| 108 | + [PLL_OFF_USER_CTL_U1] = 0x14, |
---|
| 109 | + [PLL_OFF_CONFIG_CTL] = 0x18, |
---|
| 110 | + [PLL_OFF_CONFIG_CTL_U] = 0x1c, |
---|
| 111 | + [PLL_OFF_CONFIG_CTL_U1] = 0x20, |
---|
| 112 | + [PLL_OFF_TEST_CTL] = 0x24, |
---|
| 113 | + [PLL_OFF_TEST_CTL_U] = 0x28, |
---|
| 114 | + [PLL_OFF_TEST_CTL_U1] = 0x2c, |
---|
| 115 | + [PLL_OFF_STATUS] = 0x30, |
---|
| 116 | + [PLL_OFF_OPMODE] = 0x38, |
---|
| 117 | + [PLL_OFF_ALPHA_VAL] = 0x40, |
---|
| 118 | + }, |
---|
99 | 119 | }; |
---|
100 | 120 | EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); |
---|
101 | 121 | |
---|
.. | .. |
---|
114 | 134 | #define PLL_HUAYRA_N_MASK 0xff |
---|
115 | 135 | #define PLL_HUAYRA_ALPHA_WIDTH 16 |
---|
116 | 136 | |
---|
117 | | -#define FABIA_OPMODE_STANDBY 0x0 |
---|
118 | | -#define FABIA_OPMODE_RUN 0x1 |
---|
| 137 | +#define PLL_STANDBY 0x0 |
---|
| 138 | +#define PLL_RUN 0x1 |
---|
| 139 | +#define PLL_OUT_MASK 0x7 |
---|
| 140 | +#define PLL_RATE_MARGIN 500 |
---|
119 | 141 | |
---|
120 | | -#define FABIA_PLL_OUT_MASK 0x7 |
---|
121 | | -#define FABIA_PLL_RATE_MARGIN 500 |
---|
| 142 | +/* TRION PLL specific settings and offsets */ |
---|
| 143 | +#define TRION_PLL_CAL_VAL 0x44 |
---|
| 144 | +#define TRION_PCAL_DONE BIT(26) |
---|
| 145 | + |
---|
| 146 | +/* LUCID PLL specific settings and offsets */ |
---|
| 147 | +#define LUCID_PCAL_DONE BIT(27) |
---|
122 | 148 | |
---|
123 | 149 | #define pll_alpha_width(p) \ |
---|
124 | 150 | ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \ |
---|
.. | .. |
---|
220 | 246 | if (pll->flags & SUPPORTS_FSM_MODE) |
---|
221 | 247 | qcom_pll_set_fsm_mode(regmap, PLL_MODE(pll), 6, 0); |
---|
222 | 248 | } |
---|
| 249 | +EXPORT_SYMBOL_GPL(clk_alpha_pll_configure); |
---|
223 | 250 | |
---|
224 | 251 | static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw) |
---|
225 | 252 | { |
---|
.. | .. |
---|
519 | 546 | rate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); |
---|
520 | 547 | vco = alpha_pll_find_vco(pll, rate); |
---|
521 | 548 | if (pll->vco_table && !vco) { |
---|
522 | | - pr_err("alpha pll not in a valid vco range\n"); |
---|
| 549 | + pr_err("%s: alpha pll not in a valid vco range\n", |
---|
| 550 | + clk_hw_get_name(hw)); |
---|
523 | 551 | return -EINVAL; |
---|
524 | 552 | } |
---|
525 | 553 | |
---|
.. | .. |
---|
581 | 609 | alpha_huayra_pll_calc_rate(u64 prate, u32 l, u32 a) |
---|
582 | 610 | { |
---|
583 | 611 | /* |
---|
584 | | - * a contains 16 bit alpha_val in two’s compliment number in the range |
---|
| 612 | + * a contains 16 bit alpha_val in two’s complement number in the range |
---|
585 | 613 | * of [-0.5, 0.5). |
---|
586 | 614 | */ |
---|
587 | 615 | if (a >= BIT(PLL_HUAYRA_ALPHA_WIDTH - 1)) |
---|
.. | .. |
---|
613 | 641 | quotient++; |
---|
614 | 642 | |
---|
615 | 643 | /* |
---|
616 | | - * alpha_val should be in two’s compliment number in the range |
---|
| 644 | + * alpha_val should be in two’s complement number in the range |
---|
617 | 645 | * of [-0.5, 0.5) so if quotient >= 0.5 then increment the l value |
---|
618 | 646 | * since alpha value will be subtracted in this case. |
---|
619 | 647 | */ |
---|
.. | .. |
---|
638 | 666 | regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &alpha); |
---|
639 | 667 | /* |
---|
640 | 668 | * Depending upon alpha_mode, it can be treated as M/N value or |
---|
641 | | - * as a two’s compliment number. When alpha_mode=1, |
---|
| 669 | + * as a two’s complement number. When alpha_mode=1, |
---|
642 | 670 | * pll_alpha_val<15:8>=M and pll_apla_val<7:0>=N |
---|
643 | 671 | * |
---|
644 | 672 | * Fout=FIN*(L+(M/N)) |
---|
.. | .. |
---|
646 | 674 | * M is a signed number (-128 to 127) and N is unsigned |
---|
647 | 675 | * (0 to 255). M/N has to be within +/-0.5. |
---|
648 | 676 | * |
---|
649 | | - * When alpha_mode=0, it is a two’s compliment number in the |
---|
| 677 | + * When alpha_mode=0, it is a two’s complement number in the |
---|
650 | 678 | * range [-0.5, 0.5). |
---|
651 | 679 | * |
---|
652 | 680 | * Fout=FIN*(L+(alpha_val)/2^16) |
---|
653 | 681 | * |
---|
654 | | - * where alpha_val is two’s compliment number. |
---|
| 682 | + * where alpha_val is two’s complement number. |
---|
655 | 683 | */ |
---|
656 | 684 | if (!(ctl & PLL_ALPHA_MODE)) |
---|
657 | 685 | return alpha_huayra_pll_calc_rate(rate, l, alpha); |
---|
.. | .. |
---|
697 | 725 | */ |
---|
698 | 726 | if (clk_alpha_pll_is_enabled(hw)) { |
---|
699 | 727 | if (cur_alpha != a) { |
---|
700 | | - pr_err("clock needs to be gated %s\n", |
---|
| 728 | + pr_err("%s: clock needs to be gated\n", |
---|
701 | 729 | clk_hw_get_name(hw)); |
---|
702 | 730 | return -EBUSY; |
---|
703 | 731 | } |
---|
.. | .. |
---|
729 | 757 | return alpha_huayra_pll_round_rate(rate, *prate, &l, &a); |
---|
730 | 758 | } |
---|
731 | 759 | |
---|
| 760 | +static int trion_pll_is_enabled(struct clk_alpha_pll *pll, |
---|
| 761 | + struct regmap *regmap) |
---|
| 762 | +{ |
---|
| 763 | + u32 mode_regval, opmode_regval; |
---|
| 764 | + int ret; |
---|
| 765 | + |
---|
| 766 | + ret = regmap_read(regmap, PLL_MODE(pll), &mode_regval); |
---|
| 767 | + ret |= regmap_read(regmap, PLL_OPMODE(pll), &opmode_regval); |
---|
| 768 | + if (ret) |
---|
| 769 | + return 0; |
---|
| 770 | + |
---|
| 771 | + return ((opmode_regval & PLL_RUN) && (mode_regval & PLL_OUTCTRL)); |
---|
| 772 | +} |
---|
| 773 | + |
---|
| 774 | +static int clk_trion_pll_is_enabled(struct clk_hw *hw) |
---|
| 775 | +{ |
---|
| 776 | + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); |
---|
| 777 | + |
---|
| 778 | + return trion_pll_is_enabled(pll, pll->clkr.regmap); |
---|
| 779 | +} |
---|
| 780 | + |
---|
| 781 | +static int clk_trion_pll_enable(struct clk_hw *hw) |
---|
| 782 | +{ |
---|
| 783 | + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); |
---|
| 784 | + struct regmap *regmap = pll->clkr.regmap; |
---|
| 785 | + u32 val; |
---|
| 786 | + int ret; |
---|
| 787 | + |
---|
| 788 | + ret = regmap_read(regmap, PLL_MODE(pll), &val); |
---|
| 789 | + if (ret) |
---|
| 790 | + return ret; |
---|
| 791 | + |
---|
| 792 | + /* If in FSM mode, just vote for it */ |
---|
| 793 | + if (val & PLL_VOTE_FSM_ENA) { |
---|
| 794 | + ret = clk_enable_regmap(hw); |
---|
| 795 | + if (ret) |
---|
| 796 | + return ret; |
---|
| 797 | + return wait_for_pll_enable_active(pll); |
---|
| 798 | + } |
---|
| 799 | + |
---|
| 800 | + /* Set operation mode to RUN */ |
---|
| 801 | + regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN); |
---|
| 802 | + |
---|
| 803 | + ret = wait_for_pll_enable_lock(pll); |
---|
| 804 | + if (ret) |
---|
| 805 | + return ret; |
---|
| 806 | + |
---|
| 807 | + /* Enable the PLL outputs */ |
---|
| 808 | + ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), |
---|
| 809 | + PLL_OUT_MASK, PLL_OUT_MASK); |
---|
| 810 | + if (ret) |
---|
| 811 | + return ret; |
---|
| 812 | + |
---|
| 813 | + /* Enable the global PLL outputs */ |
---|
| 814 | + return regmap_update_bits(regmap, PLL_MODE(pll), |
---|
| 815 | + PLL_OUTCTRL, PLL_OUTCTRL); |
---|
| 816 | +} |
---|
| 817 | + |
---|
| 818 | +static void clk_trion_pll_disable(struct clk_hw *hw) |
---|
| 819 | +{ |
---|
| 820 | + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); |
---|
| 821 | + struct regmap *regmap = pll->clkr.regmap; |
---|
| 822 | + u32 val; |
---|
| 823 | + int ret; |
---|
| 824 | + |
---|
| 825 | + ret = regmap_read(regmap, PLL_MODE(pll), &val); |
---|
| 826 | + if (ret) |
---|
| 827 | + return; |
---|
| 828 | + |
---|
| 829 | + /* If in FSM mode, just unvote it */ |
---|
| 830 | + if (val & PLL_VOTE_FSM_ENA) { |
---|
| 831 | + clk_disable_regmap(hw); |
---|
| 832 | + return; |
---|
| 833 | + } |
---|
| 834 | + |
---|
| 835 | + /* Disable the global PLL output */ |
---|
| 836 | + ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); |
---|
| 837 | + if (ret) |
---|
| 838 | + return; |
---|
| 839 | + |
---|
| 840 | + /* Disable the PLL outputs */ |
---|
| 841 | + ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), |
---|
| 842 | + PLL_OUT_MASK, 0); |
---|
| 843 | + if (ret) |
---|
| 844 | + return; |
---|
| 845 | + |
---|
| 846 | + /* Place the PLL mode in STANDBY */ |
---|
| 847 | + regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); |
---|
| 848 | + regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); |
---|
| 849 | +} |
---|
| 850 | + |
---|
| 851 | +static unsigned long |
---|
| 852 | +clk_trion_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) |
---|
| 853 | +{ |
---|
| 854 | + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); |
---|
| 855 | + u32 l, frac, alpha_width = pll_alpha_width(pll); |
---|
| 856 | + |
---|
| 857 | + regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); |
---|
| 858 | + regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &frac); |
---|
| 859 | + |
---|
| 860 | + return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width); |
---|
| 861 | +} |
---|
| 862 | + |
---|
| 863 | +const struct clk_ops clk_alpha_pll_fixed_ops = { |
---|
| 864 | + .enable = clk_alpha_pll_enable, |
---|
| 865 | + .disable = clk_alpha_pll_disable, |
---|
| 866 | + .is_enabled = clk_alpha_pll_is_enabled, |
---|
| 867 | + .recalc_rate = clk_alpha_pll_recalc_rate, |
---|
| 868 | +}; |
---|
| 869 | +EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_ops); |
---|
| 870 | + |
---|
732 | 871 | const struct clk_ops clk_alpha_pll_ops = { |
---|
733 | 872 | .enable = clk_alpha_pll_enable, |
---|
734 | 873 | .disable = clk_alpha_pll_disable, |
---|
.. | .. |
---|
758 | 897 | .set_rate = clk_alpha_pll_hwfsm_set_rate, |
---|
759 | 898 | }; |
---|
760 | 899 | EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops); |
---|
| 900 | + |
---|
| 901 | +const struct clk_ops clk_alpha_pll_fixed_trion_ops = { |
---|
| 902 | + .enable = clk_trion_pll_enable, |
---|
| 903 | + .disable = clk_trion_pll_disable, |
---|
| 904 | + .is_enabled = clk_trion_pll_is_enabled, |
---|
| 905 | + .recalc_rate = clk_trion_pll_recalc_rate, |
---|
| 906 | + .round_rate = clk_alpha_pll_round_rate, |
---|
| 907 | +}; |
---|
| 908 | +EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_trion_ops); |
---|
761 | 909 | |
---|
762 | 910 | static unsigned long |
---|
763 | 911 | clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) |
---|
.. | .. |
---|
831 | 979 | int div; |
---|
832 | 980 | |
---|
833 | 981 | /* 16 -> 0xf, 8 -> 0x7, 4 -> 0x3, 2 -> 0x1, 1 -> 0x0 */ |
---|
834 | | - div = DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1; |
---|
| 982 | + div = DIV_ROUND_UP_ULL(parent_rate, rate) - 1; |
---|
835 | 983 | |
---|
836 | 984 | return regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), |
---|
837 | 985 | PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT, |
---|
.. | .. |
---|
865 | 1013 | if (config->config_ctl_val) |
---|
866 | 1014 | regmap_write(regmap, PLL_CONFIG_CTL(pll), |
---|
867 | 1015 | config->config_ctl_val); |
---|
| 1016 | + |
---|
| 1017 | + if (config->config_ctl_hi_val) |
---|
| 1018 | + regmap_write(regmap, PLL_CONFIG_CTL_U(pll), |
---|
| 1019 | + config->config_ctl_hi_val); |
---|
| 1020 | + |
---|
| 1021 | + if (config->user_ctl_val) |
---|
| 1022 | + regmap_write(regmap, PLL_USER_CTL(pll), config->user_ctl_val); |
---|
| 1023 | + |
---|
| 1024 | + if (config->user_ctl_hi_val) |
---|
| 1025 | + regmap_write(regmap, PLL_USER_CTL_U(pll), |
---|
| 1026 | + config->user_ctl_hi_val); |
---|
| 1027 | + |
---|
| 1028 | + if (config->test_ctl_val) |
---|
| 1029 | + regmap_write(regmap, PLL_TEST_CTL(pll), |
---|
| 1030 | + config->test_ctl_val); |
---|
| 1031 | + |
---|
| 1032 | + if (config->test_ctl_hi_val) |
---|
| 1033 | + regmap_write(regmap, PLL_TEST_CTL_U(pll), |
---|
| 1034 | + config->test_ctl_hi_val); |
---|
868 | 1035 | |
---|
869 | 1036 | if (config->post_div_mask) { |
---|
870 | 1037 | mask = config->post_div_mask; |
---|
.. | .. |
---|
903 | 1070 | return ret; |
---|
904 | 1071 | |
---|
905 | 1072 | /* Skip If PLL is already running */ |
---|
906 | | - if ((opmode_val & FABIA_OPMODE_RUN) && (val & PLL_OUTCTRL)) |
---|
| 1073 | + if ((opmode_val & PLL_RUN) && (val & PLL_OUTCTRL)) |
---|
907 | 1074 | return 0; |
---|
908 | 1075 | |
---|
909 | 1076 | ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); |
---|
910 | 1077 | if (ret) |
---|
911 | 1078 | return ret; |
---|
912 | 1079 | |
---|
913 | | - ret = regmap_write(regmap, PLL_OPMODE(pll), FABIA_OPMODE_STANDBY); |
---|
| 1080 | + ret = regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); |
---|
914 | 1081 | if (ret) |
---|
915 | 1082 | return ret; |
---|
916 | 1083 | |
---|
.. | .. |
---|
919 | 1086 | if (ret) |
---|
920 | 1087 | return ret; |
---|
921 | 1088 | |
---|
922 | | - ret = regmap_write(regmap, PLL_OPMODE(pll), FABIA_OPMODE_RUN); |
---|
| 1089 | + ret = regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN); |
---|
923 | 1090 | if (ret) |
---|
924 | 1091 | return ret; |
---|
925 | 1092 | |
---|
.. | .. |
---|
928 | 1095 | return ret; |
---|
929 | 1096 | |
---|
930 | 1097 | ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), |
---|
931 | | - FABIA_PLL_OUT_MASK, FABIA_PLL_OUT_MASK); |
---|
| 1098 | + PLL_OUT_MASK, PLL_OUT_MASK); |
---|
932 | 1099 | if (ret) |
---|
933 | 1100 | return ret; |
---|
934 | 1101 | |
---|
.. | .. |
---|
958 | 1125 | return; |
---|
959 | 1126 | |
---|
960 | 1127 | /* Disable main outputs */ |
---|
961 | | - ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), FABIA_PLL_OUT_MASK, |
---|
962 | | - 0); |
---|
| 1128 | + ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, 0); |
---|
963 | 1129 | if (ret) |
---|
964 | 1130 | return; |
---|
965 | 1131 | |
---|
966 | 1132 | /* Place the PLL in STANDBY */ |
---|
967 | | - regmap_write(regmap, PLL_OPMODE(pll), FABIA_OPMODE_STANDBY); |
---|
| 1133 | + regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); |
---|
968 | 1134 | } |
---|
969 | 1135 | |
---|
970 | 1136 | static unsigned long alpha_pll_fabia_recalc_rate(struct clk_hw *hw, |
---|
.. | .. |
---|
983 | 1149 | unsigned long prate) |
---|
984 | 1150 | { |
---|
985 | 1151 | struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); |
---|
986 | | - u32 val, l, alpha_width = pll_alpha_width(pll); |
---|
| 1152 | + u32 l, alpha_width = pll_alpha_width(pll); |
---|
987 | 1153 | u64 a; |
---|
988 | | - unsigned long rrate; |
---|
989 | | - int ret = 0; |
---|
990 | | - |
---|
991 | | - ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); |
---|
992 | | - if (ret) |
---|
993 | | - return ret; |
---|
| 1154 | + unsigned long rrate, max = rate + PLL_RATE_MARGIN; |
---|
994 | 1155 | |
---|
995 | 1156 | rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); |
---|
996 | 1157 | |
---|
.. | .. |
---|
998 | 1159 | * Due to limited number of bits for fractional rate programming, the |
---|
999 | 1160 | * rounded up rate could be marginally higher than the requested rate. |
---|
1000 | 1161 | */ |
---|
1001 | | - if (rrate > (rate + FABIA_PLL_RATE_MARGIN) || rrate < rate) { |
---|
1002 | | - pr_err("Call set rate on the PLL with rounded rates!\n"); |
---|
| 1162 | + if (rrate > (rate + PLL_RATE_MARGIN) || rrate < rate) { |
---|
| 1163 | + pr_err("%s: Rounded rate %lu not within range [%lu, %lu)\n", |
---|
| 1164 | + clk_hw_get_name(hw), rrate, rate, max); |
---|
1003 | 1165 | return -EINVAL; |
---|
1004 | 1166 | } |
---|
1005 | 1167 | |
---|
.. | .. |
---|
1009 | 1171 | return __clk_alpha_pll_update_latch(pll); |
---|
1010 | 1172 | } |
---|
1011 | 1173 | |
---|
| 1174 | +static int alpha_pll_fabia_prepare(struct clk_hw *hw) |
---|
| 1175 | +{ |
---|
| 1176 | + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); |
---|
| 1177 | + const struct pll_vco *vco; |
---|
| 1178 | + struct clk_hw *parent_hw; |
---|
| 1179 | + unsigned long cal_freq, rrate; |
---|
| 1180 | + u32 cal_l, val, alpha_width = pll_alpha_width(pll); |
---|
| 1181 | + const char *name = clk_hw_get_name(hw); |
---|
| 1182 | + u64 a; |
---|
| 1183 | + int ret; |
---|
| 1184 | + |
---|
| 1185 | + /* Check if calibration needs to be done i.e. PLL is in reset */ |
---|
| 1186 | + ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); |
---|
| 1187 | + if (ret) |
---|
| 1188 | + return ret; |
---|
| 1189 | + |
---|
| 1190 | + /* Return early if calibration is not needed. */ |
---|
| 1191 | + if (val & PLL_RESET_N) |
---|
| 1192 | + return 0; |
---|
| 1193 | + |
---|
| 1194 | + vco = alpha_pll_find_vco(pll, clk_hw_get_rate(hw)); |
---|
| 1195 | + if (!vco) { |
---|
| 1196 | + pr_err("%s: alpha pll not in a valid vco range\n", name); |
---|
| 1197 | + return -EINVAL; |
---|
| 1198 | + } |
---|
| 1199 | + |
---|
| 1200 | + cal_freq = DIV_ROUND_CLOSEST((pll->vco_table[0].min_freq + |
---|
| 1201 | + pll->vco_table[0].max_freq) * 54, 100); |
---|
| 1202 | + |
---|
| 1203 | + parent_hw = clk_hw_get_parent(hw); |
---|
| 1204 | + if (!parent_hw) |
---|
| 1205 | + return -EINVAL; |
---|
| 1206 | + |
---|
| 1207 | + rrate = alpha_pll_round_rate(cal_freq, clk_hw_get_rate(parent_hw), |
---|
| 1208 | + &cal_l, &a, alpha_width); |
---|
| 1209 | + /* |
---|
| 1210 | + * Due to a limited number of bits for fractional rate programming, the |
---|
| 1211 | + * rounded up rate could be marginally higher than the requested rate. |
---|
| 1212 | + */ |
---|
| 1213 | + if (rrate > (cal_freq + PLL_RATE_MARGIN) || rrate < cal_freq) |
---|
| 1214 | + return -EINVAL; |
---|
| 1215 | + |
---|
| 1216 | + /* Setup PLL for calibration frequency */ |
---|
| 1217 | + regmap_write(pll->clkr.regmap, PLL_CAL_L_VAL(pll), cal_l); |
---|
| 1218 | + |
---|
| 1219 | + /* Bringup the PLL at calibration frequency */ |
---|
| 1220 | + ret = clk_alpha_pll_enable(hw); |
---|
| 1221 | + if (ret) { |
---|
| 1222 | + pr_err("%s: alpha pll calibration failed\n", name); |
---|
| 1223 | + return ret; |
---|
| 1224 | + } |
---|
| 1225 | + |
---|
| 1226 | + clk_alpha_pll_disable(hw); |
---|
| 1227 | + |
---|
| 1228 | + return 0; |
---|
| 1229 | +} |
---|
| 1230 | + |
---|
1012 | 1231 | const struct clk_ops clk_alpha_pll_fabia_ops = { |
---|
| 1232 | + .prepare = alpha_pll_fabia_prepare, |
---|
1013 | 1233 | .enable = alpha_pll_fabia_enable, |
---|
1014 | 1234 | .disable = alpha_pll_fabia_disable, |
---|
1015 | 1235 | .is_enabled = clk_alpha_pll_is_enabled, |
---|
.. | .. |
---|
1035 | 1255 | u32 i, div = 1, val; |
---|
1036 | 1256 | int ret; |
---|
1037 | 1257 | |
---|
1038 | | - if (!pll->post_div_table) { |
---|
1039 | | - pr_err("Missing the post_div_table for the PLL\n"); |
---|
1040 | | - return -EINVAL; |
---|
1041 | | - } |
---|
1042 | | - |
---|
1043 | 1258 | ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val); |
---|
1044 | 1259 | if (ret) |
---|
1045 | 1260 | return ret; |
---|
.. | .. |
---|
1057 | 1272 | return (parent_rate / div); |
---|
1058 | 1273 | } |
---|
1059 | 1274 | |
---|
| 1275 | +static unsigned long |
---|
| 1276 | +clk_trion_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) |
---|
| 1277 | +{ |
---|
| 1278 | + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); |
---|
| 1279 | + struct regmap *regmap = pll->clkr.regmap; |
---|
| 1280 | + u32 i, div = 1, val; |
---|
| 1281 | + |
---|
| 1282 | + regmap_read(regmap, PLL_USER_CTL(pll), &val); |
---|
| 1283 | + |
---|
| 1284 | + val >>= pll->post_div_shift; |
---|
| 1285 | + val &= PLL_POST_DIV_MASK(pll); |
---|
| 1286 | + |
---|
| 1287 | + for (i = 0; i < pll->num_post_div; i++) { |
---|
| 1288 | + if (pll->post_div_table[i].val == val) { |
---|
| 1289 | + div = pll->post_div_table[i].div; |
---|
| 1290 | + break; |
---|
| 1291 | + } |
---|
| 1292 | + } |
---|
| 1293 | + |
---|
| 1294 | + return (parent_rate / div); |
---|
| 1295 | +} |
---|
| 1296 | + |
---|
| 1297 | +static long |
---|
| 1298 | +clk_trion_pll_postdiv_round_rate(struct clk_hw *hw, unsigned long rate, |
---|
| 1299 | + unsigned long *prate) |
---|
| 1300 | +{ |
---|
| 1301 | + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); |
---|
| 1302 | + |
---|
| 1303 | + return divider_round_rate(hw, rate, prate, pll->post_div_table, |
---|
| 1304 | + pll->width, CLK_DIVIDER_ROUND_CLOSEST); |
---|
| 1305 | +}; |
---|
| 1306 | + |
---|
| 1307 | +static int |
---|
| 1308 | +clk_trion_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, |
---|
| 1309 | + unsigned long parent_rate) |
---|
| 1310 | +{ |
---|
| 1311 | + struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); |
---|
| 1312 | + struct regmap *regmap = pll->clkr.regmap; |
---|
| 1313 | + int i, val = 0, div; |
---|
| 1314 | + |
---|
| 1315 | + div = DIV_ROUND_UP_ULL(parent_rate, rate); |
---|
| 1316 | + for (i = 0; i < pll->num_post_div; i++) { |
---|
| 1317 | + if (pll->post_div_table[i].div == div) { |
---|
| 1318 | + val = pll->post_div_table[i].val; |
---|
| 1319 | + break; |
---|
| 1320 | + } |
---|
| 1321 | + } |
---|
| 1322 | + |
---|
| 1323 | + return regmap_update_bits(regmap, PLL_USER_CTL(pll), |
---|
| 1324 | + PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT, |
---|
| 1325 | + val << PLL_POST_DIV_SHIFT); |
---|
| 1326 | +} |
---|
| 1327 | + |
---|
| 1328 | +const struct clk_ops clk_alpha_pll_postdiv_trion_ops = { |
---|
| 1329 | + .recalc_rate = clk_trion_pll_postdiv_recalc_rate, |
---|
| 1330 | + .round_rate = clk_trion_pll_postdiv_round_rate, |
---|
| 1331 | + .set_rate = clk_trion_pll_postdiv_set_rate, |
---|
| 1332 | +}; |
---|
| 1333 | +EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_trion_ops); |
---|
| 1334 | + |
---|
1060 | 1335 | static long clk_alpha_pll_postdiv_fabia_round_rate(struct clk_hw *hw, |
---|
1061 | 1336 | unsigned long rate, unsigned long *prate) |
---|
1062 | 1337 | { |
---|
1063 | 1338 | struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); |
---|
1064 | | - |
---|
1065 | | - if (!pll->post_div_table) { |
---|
1066 | | - pr_err("Missing the post_div_table for the PLL\n"); |
---|
1067 | | - return -EINVAL; |
---|
1068 | | - } |
---|
1069 | 1339 | |
---|
1070 | 1340 | return divider_round_rate(hw, rate, prate, pll->post_div_table, |
---|
1071 | 1341 | pll->width, CLK_DIVIDER_ROUND_CLOSEST); |
---|
.. | .. |
---|
1088 | 1358 | if (val & PLL_VOTE_FSM_ENA) |
---|
1089 | 1359 | return 0; |
---|
1090 | 1360 | |
---|
1091 | | - if (!pll->post_div_table) { |
---|
1092 | | - pr_err("Missing the post_div_table for the PLL\n"); |
---|
1093 | | - return -EINVAL; |
---|
1094 | | - } |
---|
1095 | | - |
---|
1096 | | - div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); |
---|
| 1361 | + div = DIV_ROUND_UP_ULL(parent_rate, rate); |
---|
1097 | 1362 | for (i = 0; i < pll->num_post_div; i++) { |
---|
1098 | 1363 | if (pll->post_div_table[i].div == div) { |
---|
1099 | 1364 | val = pll->post_div_table[i].val; |
---|
.. | .. |
---|
1112 | 1377 | .set_rate = clk_alpha_pll_postdiv_fabia_set_rate, |
---|
1113 | 1378 | }; |
---|
1114 | 1379 | EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_fabia_ops); |
---|
| 1380 | + |
---|
| 1381 | +/** |
---|
| 1382 | + * clk_trion_pll_configure - configure the trion pll |
---|
| 1383 | + * |
---|
| 1384 | + * @pll: clk alpha pll |
---|
| 1385 | + * @regmap: register map |
---|
| 1386 | + * @config: configuration to apply for pll |
---|
| 1387 | + */ |
---|
| 1388 | +void clk_trion_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, |
---|
| 1389 | + const struct alpha_pll_config *config) |
---|
| 1390 | +{ |
---|
| 1391 | + if (config->l) |
---|
| 1392 | + regmap_write(regmap, PLL_L_VAL(pll), config->l); |
---|
| 1393 | + |
---|
| 1394 | + regmap_write(regmap, PLL_CAL_L_VAL(pll), TRION_PLL_CAL_VAL); |
---|
| 1395 | + |
---|
| 1396 | + if (config->alpha) |
---|
| 1397 | + regmap_write(regmap, PLL_ALPHA_VAL(pll), config->alpha); |
---|
| 1398 | + |
---|
| 1399 | + if (config->config_ctl_val) |
---|
| 1400 | + regmap_write(regmap, PLL_CONFIG_CTL(pll), |
---|
| 1401 | + config->config_ctl_val); |
---|
| 1402 | + |
---|
| 1403 | + if (config->config_ctl_hi_val) |
---|
| 1404 | + regmap_write(regmap, PLL_CONFIG_CTL_U(pll), |
---|
| 1405 | + config->config_ctl_hi_val); |
---|
| 1406 | + |
---|
| 1407 | + if (config->config_ctl_hi1_val) |
---|
| 1408 | + regmap_write(regmap, PLL_CONFIG_CTL_U1(pll), |
---|
| 1409 | + config->config_ctl_hi1_val); |
---|
| 1410 | + |
---|
| 1411 | + if (config->user_ctl_val) |
---|
| 1412 | + regmap_write(regmap, PLL_USER_CTL(pll), |
---|
| 1413 | + config->user_ctl_val); |
---|
| 1414 | + |
---|
| 1415 | + if (config->user_ctl_hi_val) |
---|
| 1416 | + regmap_write(regmap, PLL_USER_CTL_U(pll), |
---|
| 1417 | + config->user_ctl_hi_val); |
---|
| 1418 | + |
---|
| 1419 | + if (config->user_ctl_hi1_val) |
---|
| 1420 | + regmap_write(regmap, PLL_USER_CTL_U1(pll), |
---|
| 1421 | + config->user_ctl_hi1_val); |
---|
| 1422 | + |
---|
| 1423 | + if (config->test_ctl_val) |
---|
| 1424 | + regmap_write(regmap, PLL_TEST_CTL(pll), |
---|
| 1425 | + config->test_ctl_val); |
---|
| 1426 | + |
---|
| 1427 | + if (config->test_ctl_hi_val) |
---|
| 1428 | + regmap_write(regmap, PLL_TEST_CTL_U(pll), |
---|
| 1429 | + config->test_ctl_hi_val); |
---|
| 1430 | + |
---|
| 1431 | + if (config->test_ctl_hi1_val) |
---|
| 1432 | + regmap_write(regmap, PLL_TEST_CTL_U1(pll), |
---|
| 1433 | + config->test_ctl_hi1_val); |
---|
| 1434 | + |
---|
| 1435 | + regmap_update_bits(regmap, PLL_MODE(pll), PLL_UPDATE_BYPASS, |
---|
| 1436 | + PLL_UPDATE_BYPASS); |
---|
| 1437 | + |
---|
| 1438 | + /* Disable PLL output */ |
---|
| 1439 | + regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); |
---|
| 1440 | + |
---|
| 1441 | + /* Set operation mode to OFF */ |
---|
| 1442 | + regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); |
---|
| 1443 | + |
---|
| 1444 | + /* Place the PLL in STANDBY mode */ |
---|
| 1445 | + regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); |
---|
| 1446 | +} |
---|
| 1447 | +EXPORT_SYMBOL_GPL(clk_trion_pll_configure); |
---|
| 1448 | + |
---|
| 1449 | +/* |
---|
| 1450 | + * The TRION PLL requires a power-on self-calibration which happens when the |
---|
| 1451 | + * PLL comes out of reset. Calibrate in case it is not completed. |
---|
| 1452 | + */ |
---|
| 1453 | +static int __alpha_pll_trion_prepare(struct clk_hw *hw, u32 pcal_done) |
---|
| 1454 | +{ |
---|
| 1455 | + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); |
---|
| 1456 | + u32 regval; |
---|
| 1457 | + int ret; |
---|
| 1458 | + |
---|
| 1459 | + /* Return early if calibration is not needed. */ |
---|
| 1460 | + regmap_read(pll->clkr.regmap, PLL_STATUS(pll), ®val); |
---|
| 1461 | + if (regval & pcal_done) |
---|
| 1462 | + return 0; |
---|
| 1463 | + |
---|
| 1464 | + /* On/off to calibrate */ |
---|
| 1465 | + ret = clk_trion_pll_enable(hw); |
---|
| 1466 | + if (!ret) |
---|
| 1467 | + clk_trion_pll_disable(hw); |
---|
| 1468 | + |
---|
| 1469 | + return ret; |
---|
| 1470 | +} |
---|
| 1471 | + |
---|
| 1472 | +static int alpha_pll_trion_prepare(struct clk_hw *hw) |
---|
| 1473 | +{ |
---|
| 1474 | + return __alpha_pll_trion_prepare(hw, TRION_PCAL_DONE); |
---|
| 1475 | +} |
---|
| 1476 | + |
---|
| 1477 | +static int alpha_pll_lucid_prepare(struct clk_hw *hw) |
---|
| 1478 | +{ |
---|
| 1479 | + return __alpha_pll_trion_prepare(hw, LUCID_PCAL_DONE); |
---|
| 1480 | +} |
---|
| 1481 | + |
---|
| 1482 | +static int alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate, |
---|
| 1483 | + unsigned long prate) |
---|
| 1484 | +{ |
---|
| 1485 | + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); |
---|
| 1486 | + unsigned long rrate; |
---|
| 1487 | + u32 regval, l, alpha_width = pll_alpha_width(pll); |
---|
| 1488 | + u64 a; |
---|
| 1489 | + int ret; |
---|
| 1490 | + |
---|
| 1491 | + rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); |
---|
| 1492 | + |
---|
| 1493 | + /* |
---|
| 1494 | + * Due to a limited number of bits for fractional rate programming, the |
---|
| 1495 | + * rounded up rate could be marginally higher than the requested rate. |
---|
| 1496 | + */ |
---|
| 1497 | + if (rrate > (rate + PLL_RATE_MARGIN) || rrate < rate) { |
---|
| 1498 | + pr_err("Call set rate on the PLL with rounded rates!\n"); |
---|
| 1499 | + return -EINVAL; |
---|
| 1500 | + } |
---|
| 1501 | + |
---|
| 1502 | + regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); |
---|
| 1503 | + regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); |
---|
| 1504 | + |
---|
| 1505 | + /* Latch the PLL input */ |
---|
| 1506 | + ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), |
---|
| 1507 | + PLL_UPDATE, PLL_UPDATE); |
---|
| 1508 | + if (ret) |
---|
| 1509 | + return ret; |
---|
| 1510 | + |
---|
| 1511 | + /* Wait for 2 reference cycles before checking the ACK bit. */ |
---|
| 1512 | + udelay(1); |
---|
| 1513 | + regmap_read(pll->clkr.regmap, PLL_MODE(pll), ®val); |
---|
| 1514 | + if (!(regval & ALPHA_PLL_ACK_LATCH)) { |
---|
| 1515 | + pr_err("Lucid PLL latch failed. Output may be unstable!\n"); |
---|
| 1516 | + return -EINVAL; |
---|
| 1517 | + } |
---|
| 1518 | + |
---|
| 1519 | + /* Return the latch input to 0 */ |
---|
| 1520 | + ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), |
---|
| 1521 | + PLL_UPDATE, 0); |
---|
| 1522 | + if (ret) |
---|
| 1523 | + return ret; |
---|
| 1524 | + |
---|
| 1525 | + if (clk_hw_is_enabled(hw)) { |
---|
| 1526 | + ret = wait_for_pll_enable_lock(pll); |
---|
| 1527 | + if (ret) |
---|
| 1528 | + return ret; |
---|
| 1529 | + } |
---|
| 1530 | + |
---|
| 1531 | + /* Wait for PLL output to stabilize */ |
---|
| 1532 | + udelay(100); |
---|
| 1533 | + return 0; |
---|
| 1534 | +} |
---|
| 1535 | + |
---|
| 1536 | +const struct clk_ops clk_alpha_pll_trion_ops = { |
---|
| 1537 | + .prepare = alpha_pll_trion_prepare, |
---|
| 1538 | + .enable = clk_trion_pll_enable, |
---|
| 1539 | + .disable = clk_trion_pll_disable, |
---|
| 1540 | + .is_enabled = clk_trion_pll_is_enabled, |
---|
| 1541 | + .recalc_rate = clk_trion_pll_recalc_rate, |
---|
| 1542 | + .round_rate = clk_alpha_pll_round_rate, |
---|
| 1543 | + .set_rate = alpha_pll_trion_set_rate, |
---|
| 1544 | +}; |
---|
| 1545 | +EXPORT_SYMBOL_GPL(clk_alpha_pll_trion_ops); |
---|
| 1546 | + |
---|
| 1547 | +const struct clk_ops clk_alpha_pll_lucid_ops = { |
---|
| 1548 | + .prepare = alpha_pll_lucid_prepare, |
---|
| 1549 | + .enable = clk_trion_pll_enable, |
---|
| 1550 | + .disable = clk_trion_pll_disable, |
---|
| 1551 | + .is_enabled = clk_trion_pll_is_enabled, |
---|
| 1552 | + .recalc_rate = clk_trion_pll_recalc_rate, |
---|
| 1553 | + .round_rate = clk_alpha_pll_round_rate, |
---|
| 1554 | + .set_rate = alpha_pll_trion_set_rate, |
---|
| 1555 | +}; |
---|
| 1556 | +EXPORT_SYMBOL_GPL(clk_alpha_pll_lucid_ops); |
---|
| 1557 | + |
---|
| 1558 | +const struct clk_ops clk_alpha_pll_postdiv_lucid_ops = { |
---|
| 1559 | + .recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate, |
---|
| 1560 | + .round_rate = clk_alpha_pll_postdiv_fabia_round_rate, |
---|
| 1561 | + .set_rate = clk_alpha_pll_postdiv_fabia_set_rate, |
---|
| 1562 | +}; |
---|
| 1563 | +EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_lucid_ops); |
---|