diff options
author | Rahul Sharma <rahul.sharma@samsung.com> | 2014-03-12 10:56:46 -0400 |
---|---|---|
committer | Tomasz Figa <t.figa@samsung.com> | 2014-05-14 13:16:54 -0400 |
commit | eefe119b81eb1afb6e815818ad119cdd2d442fd3 (patch) | |
tree | 69e37fd063f6563a4c1522797b9bd74704272ca5 | |
parent | 8432984732b59b333706fceb4cfb5123140be827 (diff) |
clk/samsung: add support for pll2650xx
Add support for pll2650xx in samsung pll file. This PLL variant
is close to pll36xx but uses CON2 registers instead of CON1.
Aud_pll in Exynos5260 is pll2650xx and uses this code.
Signed-off-by: Rahul Sharma <rahul.sharma@samsung.com>
Reviewed-by: Pankaj Dubey <pankaj.dubey@samsung.com>
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
-rw-r--r-- | drivers/clk/samsung/clk-pll.c | 101 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-pll.h | 1 |
2 files changed, 102 insertions, 0 deletions
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 18e42ef56ea6..b07fad2a9167 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c | |||
@@ -1049,6 +1049,101 @@ static const struct clk_ops samsung_pll2550xx_clk_min_ops = { | |||
1049 | .recalc_rate = samsung_pll2550xx_recalc_rate, | 1049 | .recalc_rate = samsung_pll2550xx_recalc_rate, |
1050 | }; | 1050 | }; |
1051 | 1051 | ||
1052 | /* | ||
1053 | * PLL2650XX Clock Type | ||
1054 | */ | ||
1055 | |||
1056 | /* Maximum lock time can be 3000 * PDIV cycles */ | ||
1057 | #define PLL2650XX_LOCK_FACTOR 3000 | ||
1058 | |||
1059 | #define PLL2650XX_MDIV_SHIFT 9 | ||
1060 | #define PLL2650XX_PDIV_SHIFT 3 | ||
1061 | #define PLL2650XX_SDIV_SHIFT 0 | ||
1062 | #define PLL2650XX_KDIV_SHIFT 0 | ||
1063 | #define PLL2650XX_MDIV_MASK 0x1ff | ||
1064 | #define PLL2650XX_PDIV_MASK 0x3f | ||
1065 | #define PLL2650XX_SDIV_MASK 0x7 | ||
1066 | #define PLL2650XX_KDIV_MASK 0xffff | ||
1067 | #define PLL2650XX_PLL_ENABLE_SHIFT 23 | ||
1068 | #define PLL2650XX_PLL_LOCKTIME_SHIFT 21 | ||
1069 | #define PLL2650XX_PLL_FOUTMASK_SHIFT 31 | ||
1070 | |||
1071 | static unsigned long samsung_pll2650xx_recalc_rate(struct clk_hw *hw, | ||
1072 | unsigned long parent_rate) | ||
1073 | { | ||
1074 | struct samsung_clk_pll *pll = to_clk_pll(hw); | ||
1075 | u32 mdiv, pdiv, sdiv, pll_con0, pll_con2; | ||
1076 | s16 kdiv; | ||
1077 | u64 fvco = parent_rate; | ||
1078 | |||
1079 | pll_con0 = __raw_readl(pll->con_reg); | ||
1080 | pll_con2 = __raw_readl(pll->con_reg + 8); | ||
1081 | mdiv = (pll_con0 >> PLL2650XX_MDIV_SHIFT) & PLL2650XX_MDIV_MASK; | ||
1082 | pdiv = (pll_con0 >> PLL2650XX_PDIV_SHIFT) & PLL2650XX_PDIV_MASK; | ||
1083 | sdiv = (pll_con0 >> PLL2650XX_SDIV_SHIFT) & PLL2650XX_SDIV_MASK; | ||
1084 | kdiv = (s16)(pll_con2 & PLL2650XX_KDIV_MASK); | ||
1085 | |||
1086 | fvco *= (mdiv << 16) + kdiv; | ||
1087 | do_div(fvco, (pdiv << sdiv)); | ||
1088 | fvco >>= 16; | ||
1089 | |||
1090 | return (unsigned long)fvco; | ||
1091 | } | ||
1092 | |||
1093 | static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate, | ||
1094 | unsigned long parent_rate) | ||
1095 | { | ||
1096 | struct samsung_clk_pll *pll = to_clk_pll(hw); | ||
1097 | u32 tmp, pll_con0, pll_con2; | ||
1098 | const struct samsung_pll_rate_table *rate; | ||
1099 | |||
1100 | rate = samsung_get_pll_settings(pll, drate); | ||
1101 | if (!rate) { | ||
1102 | pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, | ||
1103 | drate, __clk_get_name(hw->clk)); | ||
1104 | return -EINVAL; | ||
1105 | } | ||
1106 | |||
1107 | pll_con0 = __raw_readl(pll->con_reg); | ||
1108 | pll_con2 = __raw_readl(pll->con_reg + 8); | ||
1109 | |||
1110 | /* Change PLL PMS values */ | ||
1111 | pll_con0 &= ~(PLL2650XX_MDIV_MASK << PLL2650XX_MDIV_SHIFT | | ||
1112 | PLL2650XX_PDIV_MASK << PLL2650XX_PDIV_SHIFT | | ||
1113 | PLL2650XX_SDIV_MASK << PLL2650XX_SDIV_SHIFT); | ||
1114 | pll_con0 |= rate->mdiv << PLL2650XX_MDIV_SHIFT; | ||
1115 | pll_con0 |= rate->pdiv << PLL2650XX_PDIV_SHIFT; | ||
1116 | pll_con0 |= rate->sdiv << PLL2650XX_SDIV_SHIFT; | ||
1117 | pll_con0 |= 1 << PLL2650XX_PLL_ENABLE_SHIFT; | ||
1118 | pll_con0 |= 1 << PLL2650XX_PLL_FOUTMASK_SHIFT; | ||
1119 | |||
1120 | pll_con2 &= ~(PLL2650XX_KDIV_MASK << PLL2650XX_KDIV_SHIFT); | ||
1121 | pll_con2 |= ((~(rate->kdiv) + 1) & PLL2650XX_KDIV_MASK) | ||
1122 | << PLL2650XX_KDIV_SHIFT; | ||
1123 | |||
1124 | /* Set PLL lock time. */ | ||
1125 | __raw_writel(PLL2650XX_LOCK_FACTOR * rate->pdiv, pll->lock_reg); | ||
1126 | |||
1127 | __raw_writel(pll_con0, pll->con_reg); | ||
1128 | __raw_writel(pll_con2, pll->con_reg + 8); | ||
1129 | |||
1130 | do { | ||
1131 | tmp = __raw_readl(pll->con_reg); | ||
1132 | } while (!(tmp & (0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT))); | ||
1133 | |||
1134 | return 0; | ||
1135 | } | ||
1136 | |||
1137 | static const struct clk_ops samsung_pll2650xx_clk_ops = { | ||
1138 | .recalc_rate = samsung_pll2650xx_recalc_rate, | ||
1139 | .set_rate = samsung_pll2650xx_set_rate, | ||
1140 | .round_rate = samsung_pll_round_rate, | ||
1141 | }; | ||
1142 | |||
1143 | static const struct clk_ops samsung_pll2650xx_clk_min_ops = { | ||
1144 | .recalc_rate = samsung_pll2650xx_recalc_rate, | ||
1145 | }; | ||
1146 | |||
1052 | static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, | 1147 | static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, |
1053 | struct samsung_pll_clock *pll_clk, | 1148 | struct samsung_pll_clock *pll_clk, |
1054 | void __iomem *base) | 1149 | void __iomem *base) |
@@ -1157,6 +1252,12 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, | |||
1157 | else | 1252 | else |
1158 | init.ops = &samsung_pll2550xx_clk_ops; | 1253 | init.ops = &samsung_pll2550xx_clk_ops; |
1159 | break; | 1254 | break; |
1255 | case pll_2650xx: | ||
1256 | if (!pll->rate_table) | ||
1257 | init.ops = &samsung_pll2650xx_clk_min_ops; | ||
1258 | else | ||
1259 | init.ops = &samsung_pll2650xx_clk_ops; | ||
1260 | break; | ||
1160 | default: | 1261 | default: |
1161 | pr_warn("%s: Unknown pll type for pll clk %s\n", | 1262 | pr_warn("%s: Unknown pll type for pll clk %s\n", |
1162 | __func__, pll_clk->name); | 1263 | __func__, pll_clk->name); |
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index ec4bc1d45e31..c0ed4d41fd90 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h | |||
@@ -32,6 +32,7 @@ enum samsung_pll_type { | |||
32 | pll_s3c2410_upll, | 32 | pll_s3c2410_upll, |
33 | pll_s3c2440_mpll, | 33 | pll_s3c2440_mpll, |
34 | pll_2550xx, | 34 | pll_2550xx, |
35 | pll_2650xx, | ||
35 | }; | 36 | }; |
36 | 37 | ||
37 | #define PLL_35XX_RATE(_rate, _m, _p, _s) \ | 38 | #define PLL_35XX_RATE(_rate, _m, _p, _s) \ |