diff options
author | Pankaj Dubey <pankaj.dubey@samsung.com> | 2014-03-12 10:56:45 -0400 |
---|---|---|
committer | Tomasz Figa <t.figa@samsung.com> | 2014-05-14 13:16:54 -0400 |
commit | 8432984732b59b333706fceb4cfb5123140be827 (patch) | |
tree | 35e490c270a68d9bbce7ceadcfaf0de03b31f572 | |
parent | 976face4b46ab36b04312b4e404d160296716d46 (diff) |
clk/samsung: add support for pll2550xx
exynos5260 use pll2550xx and it has different bit fields
for P,M,S values as compared to pll2550. Support for
pll2550xx is added here.
Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
Signed-off-by: Rahul Sharma <rahul.sharma@samsung.com>
Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
-rw-r--r-- | drivers/clk/samsung/clk-pll.c | 108 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-pll.h | 1 |
2 files changed, 109 insertions, 0 deletions
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 1f310be17742..18e42ef56ea6 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c | |||
@@ -947,6 +947,108 @@ struct clk * __init samsung_clk_register_pll2550x(const char *name, | |||
947 | return clk; | 947 | return clk; |
948 | } | 948 | } |
949 | 949 | ||
950 | /* | ||
951 | * PLL2550xx Clock Type | ||
952 | */ | ||
953 | |||
954 | /* Maximum lock time can be 270 * PDIV cycles */ | ||
955 | #define PLL2550XX_LOCK_FACTOR 270 | ||
956 | |||
957 | #define PLL2550XX_M_MASK 0x3FF | ||
958 | #define PLL2550XX_P_MASK 0x3F | ||
959 | #define PLL2550XX_S_MASK 0x7 | ||
960 | #define PLL2550XX_LOCK_STAT_MASK 0x1 | ||
961 | #define PLL2550XX_M_SHIFT 9 | ||
962 | #define PLL2550XX_P_SHIFT 3 | ||
963 | #define PLL2550XX_S_SHIFT 0 | ||
964 | #define PLL2550XX_LOCK_STAT_SHIFT 21 | ||
965 | |||
966 | static unsigned long samsung_pll2550xx_recalc_rate(struct clk_hw *hw, | ||
967 | unsigned long parent_rate) | ||
968 | { | ||
969 | struct samsung_clk_pll *pll = to_clk_pll(hw); | ||
970 | u32 mdiv, pdiv, sdiv, pll_con; | ||
971 | u64 fvco = parent_rate; | ||
972 | |||
973 | pll_con = __raw_readl(pll->con_reg); | ||
974 | mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK; | ||
975 | pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK; | ||
976 | sdiv = (pll_con >> PLL2550XX_S_SHIFT) & PLL2550XX_S_MASK; | ||
977 | |||
978 | fvco *= mdiv; | ||
979 | do_div(fvco, (pdiv << sdiv)); | ||
980 | |||
981 | return (unsigned long)fvco; | ||
982 | } | ||
983 | |||
984 | static inline bool samsung_pll2550xx_mp_change(u32 mdiv, u32 pdiv, u32 pll_con) | ||
985 | { | ||
986 | u32 old_mdiv, old_pdiv; | ||
987 | |||
988 | old_mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK; | ||
989 | old_pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK; | ||
990 | |||
991 | return mdiv != old_mdiv || pdiv != old_pdiv; | ||
992 | } | ||
993 | |||
994 | static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate, | ||
995 | unsigned long prate) | ||
996 | { | ||
997 | struct samsung_clk_pll *pll = to_clk_pll(hw); | ||
998 | const struct samsung_pll_rate_table *rate; | ||
999 | u32 tmp; | ||
1000 | |||
1001 | /* Get required rate settings from table */ | ||
1002 | rate = samsung_get_pll_settings(pll, drate); | ||
1003 | if (!rate) { | ||
1004 | pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, | ||
1005 | drate, __clk_get_name(hw->clk)); | ||
1006 | return -EINVAL; | ||
1007 | } | ||
1008 | |||
1009 | tmp = __raw_readl(pll->con_reg); | ||
1010 | |||
1011 | if (!(samsung_pll2550xx_mp_change(rate->mdiv, rate->pdiv, tmp))) { | ||
1012 | /* If only s change, change just s value only*/ | ||
1013 | tmp &= ~(PLL2550XX_S_MASK << PLL2550XX_S_SHIFT); | ||
1014 | tmp |= rate->sdiv << PLL2550XX_S_SHIFT; | ||
1015 | __raw_writel(tmp, pll->con_reg); | ||
1016 | |||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
1020 | /* Set PLL lock time. */ | ||
1021 | __raw_writel(rate->pdiv * PLL2550XX_LOCK_FACTOR, pll->lock_reg); | ||
1022 | |||
1023 | /* Change PLL PMS values */ | ||
1024 | tmp &= ~((PLL2550XX_M_MASK << PLL2550XX_M_SHIFT) | | ||
1025 | (PLL2550XX_P_MASK << PLL2550XX_P_SHIFT) | | ||
1026 | (PLL2550XX_S_MASK << PLL2550XX_S_SHIFT)); | ||
1027 | tmp |= (rate->mdiv << PLL2550XX_M_SHIFT) | | ||
1028 | (rate->pdiv << PLL2550XX_P_SHIFT) | | ||
1029 | (rate->sdiv << PLL2550XX_S_SHIFT); | ||
1030 | __raw_writel(tmp, pll->con_reg); | ||
1031 | |||
1032 | /* wait_lock_time */ | ||
1033 | do { | ||
1034 | cpu_relax(); | ||
1035 | tmp = __raw_readl(pll->con_reg); | ||
1036 | } while (!(tmp & (PLL2550XX_LOCK_STAT_MASK | ||
1037 | << PLL2550XX_LOCK_STAT_SHIFT))); | ||
1038 | |||
1039 | return 0; | ||
1040 | } | ||
1041 | |||
1042 | static const struct clk_ops samsung_pll2550xx_clk_ops = { | ||
1043 | .recalc_rate = samsung_pll2550xx_recalc_rate, | ||
1044 | .round_rate = samsung_pll_round_rate, | ||
1045 | .set_rate = samsung_pll2550xx_set_rate, | ||
1046 | }; | ||
1047 | |||
1048 | static const struct clk_ops samsung_pll2550xx_clk_min_ops = { | ||
1049 | .recalc_rate = samsung_pll2550xx_recalc_rate, | ||
1050 | }; | ||
1051 | |||
950 | static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, | 1052 | static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, |
951 | struct samsung_pll_clock *pll_clk, | 1053 | struct samsung_pll_clock *pll_clk, |
952 | void __iomem *base) | 1054 | void __iomem *base) |
@@ -1049,6 +1151,12 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, | |||
1049 | else | 1151 | else |
1050 | init.ops = &samsung_s3c2440_mpll_clk_ops; | 1152 | init.ops = &samsung_s3c2440_mpll_clk_ops; |
1051 | break; | 1153 | break; |
1154 | case pll_2550xx: | ||
1155 | if (!pll->rate_table) | ||
1156 | init.ops = &samsung_pll2550xx_clk_min_ops; | ||
1157 | else | ||
1158 | init.ops = &samsung_pll2550xx_clk_ops; | ||
1159 | break; | ||
1052 | default: | 1160 | default: |
1053 | pr_warn("%s: Unknown pll type for pll clk %s\n", | 1161 | pr_warn("%s: Unknown pll type for pll clk %s\n", |
1054 | __func__, pll_clk->name); | 1162 | __func__, pll_clk->name); |
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index 6428bcc6df6f..ec4bc1d45e31 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h | |||
@@ -31,6 +31,7 @@ enum samsung_pll_type { | |||
31 | pll_s3c2410_mpll, | 31 | pll_s3c2410_mpll, |
32 | pll_s3c2410_upll, | 32 | pll_s3c2410_upll, |
33 | pll_s3c2440_mpll, | 33 | pll_s3c2440_mpll, |
34 | pll_2550xx, | ||
34 | }; | 35 | }; |
35 | 36 | ||
36 | #define PLL_35XX_RATE(_rate, _m, _p, _s) \ | 37 | #define PLL_35XX_RATE(_rate, _m, _p, _s) \ |