diff options
Diffstat (limited to 'drivers')
| -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) \ |
