0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/clk.h>
0011 #include <linux/clk-provider.h>
0012 #include <linux/slab.h>
0013 #include "clk-zynqmp.h"
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #define to_zynqmp_clk_divider(_hw) \
0026 container_of(_hw, struct zynqmp_clk_divider, hw)
0027
0028 #define CLK_FRAC BIT(13)
0029 #define CUSTOM_FLAG_CLK_FRAC BIT(0)
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 struct zynqmp_clk_divider {
0041 struct clk_hw hw;
0042 u8 flags;
0043 bool is_frac;
0044 u32 clk_id;
0045 u32 div_type;
0046 u16 max_div;
0047 };
0048
0049 static inline int zynqmp_divider_get_val(unsigned long parent_rate,
0050 unsigned long rate, u16 flags)
0051 {
0052 int up, down;
0053 unsigned long up_rate, down_rate;
0054
0055 if (flags & CLK_DIVIDER_POWER_OF_TWO) {
0056 up = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
0057 down = DIV_ROUND_DOWN_ULL((u64)parent_rate, rate);
0058
0059 up = __roundup_pow_of_two(up);
0060 down = __rounddown_pow_of_two(down);
0061
0062 up_rate = DIV_ROUND_UP_ULL((u64)parent_rate, up);
0063 down_rate = DIV_ROUND_UP_ULL((u64)parent_rate, down);
0064
0065 return (rate - up_rate) <= (down_rate - rate) ? up : down;
0066
0067 } else {
0068 return DIV_ROUND_CLOSEST(parent_rate, rate);
0069 }
0070 }
0071
0072
0073
0074
0075
0076
0077
0078
0079 static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw *hw,
0080 unsigned long parent_rate)
0081 {
0082 struct zynqmp_clk_divider *divider = to_zynqmp_clk_divider(hw);
0083 const char *clk_name = clk_hw_get_name(hw);
0084 u32 clk_id = divider->clk_id;
0085 u32 div_type = divider->div_type;
0086 u32 div, value;
0087 int ret;
0088
0089 ret = zynqmp_pm_clock_getdivider(clk_id, &div);
0090
0091 if (ret)
0092 pr_debug("%s() get divider failed for %s, ret = %d\n",
0093 __func__, clk_name, ret);
0094
0095 if (div_type == TYPE_DIV1)
0096 value = div & 0xFFFF;
0097 else
0098 value = div >> 16;
0099
0100 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
0101 value = 1 << value;
0102
0103 if (!value) {
0104 WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO),
0105 "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
0106 clk_name);
0107 return parent_rate;
0108 }
0109
0110 return DIV_ROUND_UP_ULL(parent_rate, value);
0111 }
0112
0113 static void zynqmp_get_divider2_val(struct clk_hw *hw,
0114 unsigned long rate,
0115 struct zynqmp_clk_divider *divider,
0116 int *bestdiv)
0117 {
0118 int div1;
0119 int div2;
0120 long error = LONG_MAX;
0121 unsigned long div1_prate;
0122 struct clk_hw *div1_parent_hw;
0123 struct clk_hw *div2_parent_hw = clk_hw_get_parent(hw);
0124 struct zynqmp_clk_divider *pdivider =
0125 to_zynqmp_clk_divider(div2_parent_hw);
0126
0127 if (!pdivider)
0128 return;
0129
0130 div1_parent_hw = clk_hw_get_parent(div2_parent_hw);
0131 if (!div1_parent_hw)
0132 return;
0133
0134 div1_prate = clk_hw_get_rate(div1_parent_hw);
0135 *bestdiv = 1;
0136 for (div1 = 1; div1 <= pdivider->max_div;) {
0137 for (div2 = 1; div2 <= divider->max_div;) {
0138 long new_error = ((div1_prate / div1) / div2) - rate;
0139
0140 if (abs(new_error) < abs(error)) {
0141 *bestdiv = div2;
0142 error = new_error;
0143 }
0144 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
0145 div2 = div2 << 1;
0146 else
0147 div2++;
0148 }
0149 if (pdivider->flags & CLK_DIVIDER_POWER_OF_TWO)
0150 div1 = div1 << 1;
0151 else
0152 div1++;
0153 }
0154 }
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164 static long zynqmp_clk_divider_round_rate(struct clk_hw *hw,
0165 unsigned long rate,
0166 unsigned long *prate)
0167 {
0168 struct zynqmp_clk_divider *divider = to_zynqmp_clk_divider(hw);
0169 const char *clk_name = clk_hw_get_name(hw);
0170 u32 clk_id = divider->clk_id;
0171 u32 div_type = divider->div_type;
0172 u32 bestdiv;
0173 int ret;
0174
0175
0176 if (divider->flags & CLK_DIVIDER_READ_ONLY) {
0177 ret = zynqmp_pm_clock_getdivider(clk_id, &bestdiv);
0178
0179 if (ret)
0180 pr_debug("%s() get divider failed for %s, ret = %d\n",
0181 __func__, clk_name, ret);
0182 if (div_type == TYPE_DIV1)
0183 bestdiv = bestdiv & 0xFFFF;
0184 else
0185 bestdiv = bestdiv >> 16;
0186
0187 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
0188 bestdiv = 1 << bestdiv;
0189
0190 return DIV_ROUND_UP_ULL((u64)*prate, bestdiv);
0191 }
0192
0193 bestdiv = zynqmp_divider_get_val(*prate, rate, divider->flags);
0194
0195
0196
0197
0198
0199
0200 if (div_type == TYPE_DIV2 &&
0201 (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
0202 zynqmp_get_divider2_val(hw, rate, divider, &bestdiv);
0203 }
0204
0205 if ((clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) && divider->is_frac)
0206 bestdiv = rate % *prate ? 1 : bestdiv;
0207
0208 bestdiv = min_t(u32, bestdiv, divider->max_div);
0209 *prate = rate * bestdiv;
0210
0211 return rate;
0212 }
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222 static int zynqmp_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
0223 unsigned long parent_rate)
0224 {
0225 struct zynqmp_clk_divider *divider = to_zynqmp_clk_divider(hw);
0226 const char *clk_name = clk_hw_get_name(hw);
0227 u32 clk_id = divider->clk_id;
0228 u32 div_type = divider->div_type;
0229 u32 value, div;
0230 int ret;
0231
0232 value = zynqmp_divider_get_val(parent_rate, rate, divider->flags);
0233 if (div_type == TYPE_DIV1) {
0234 div = value & 0xFFFF;
0235 div |= 0xffff << 16;
0236 } else {
0237 div = 0xffff;
0238 div |= value << 16;
0239 }
0240
0241 if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
0242 div = __ffs(div);
0243
0244 ret = zynqmp_pm_clock_setdivider(clk_id, div);
0245
0246 if (ret)
0247 pr_debug("%s() set divider failed for %s, ret = %d\n",
0248 __func__, clk_name, ret);
0249
0250 return ret;
0251 }
0252
0253 static const struct clk_ops zynqmp_clk_divider_ops = {
0254 .recalc_rate = zynqmp_clk_divider_recalc_rate,
0255 .round_rate = zynqmp_clk_divider_round_rate,
0256 .set_rate = zynqmp_clk_divider_set_rate,
0257 };
0258
0259 static const struct clk_ops zynqmp_clk_divider_ro_ops = {
0260 .recalc_rate = zynqmp_clk_divider_recalc_rate,
0261 .round_rate = zynqmp_clk_divider_round_rate,
0262 };
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272 static u32 zynqmp_clk_get_max_divisor(u32 clk_id, u32 type)
0273 {
0274 struct zynqmp_pm_query_data qdata = {0};
0275 u32 ret_payload[PAYLOAD_ARG_CNT];
0276 int ret;
0277
0278 qdata.qid = PM_QID_CLOCK_GET_MAX_DIVISOR;
0279 qdata.arg1 = clk_id;
0280 qdata.arg2 = type;
0281 ret = zynqmp_pm_query_data(qdata, ret_payload);
0282
0283
0284
0285
0286 if (ret)
0287 return U16_MAX;
0288
0289 return ret_payload[1];
0290 }
0291
0292 static inline unsigned long zynqmp_clk_map_divider_ccf_flags(
0293 const u32 zynqmp_type_flag)
0294 {
0295 unsigned long ccf_flag = 0;
0296
0297 if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_ONE_BASED)
0298 ccf_flag |= CLK_DIVIDER_ONE_BASED;
0299 if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_POWER_OF_TWO)
0300 ccf_flag |= CLK_DIVIDER_POWER_OF_TWO;
0301 if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_ALLOW_ZERO)
0302 ccf_flag |= CLK_DIVIDER_ALLOW_ZERO;
0303 if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_POWER_OF_TWO)
0304 ccf_flag |= CLK_DIVIDER_HIWORD_MASK;
0305 if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_ROUND_CLOSEST)
0306 ccf_flag |= CLK_DIVIDER_ROUND_CLOSEST;
0307 if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_READ_ONLY)
0308 ccf_flag |= CLK_DIVIDER_READ_ONLY;
0309 if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_MAX_AT_ZERO)
0310 ccf_flag |= CLK_DIVIDER_MAX_AT_ZERO;
0311
0312 return ccf_flag;
0313 }
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325 struct clk_hw *zynqmp_clk_register_divider(const char *name,
0326 u32 clk_id,
0327 const char * const *parents,
0328 u8 num_parents,
0329 const struct clock_topology *nodes)
0330 {
0331 struct zynqmp_clk_divider *div;
0332 struct clk_hw *hw;
0333 struct clk_init_data init;
0334 int ret;
0335
0336
0337 div = kzalloc(sizeof(*div), GFP_KERNEL);
0338 if (!div)
0339 return ERR_PTR(-ENOMEM);
0340
0341 init.name = name;
0342 if (nodes->type_flag & CLK_DIVIDER_READ_ONLY)
0343 init.ops = &zynqmp_clk_divider_ro_ops;
0344 else
0345 init.ops = &zynqmp_clk_divider_ops;
0346
0347 init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag);
0348
0349 init.parent_names = parents;
0350 init.num_parents = 1;
0351
0352
0353 div->is_frac = !!((nodes->flag & CLK_FRAC) |
0354 (nodes->custom_type_flag & CUSTOM_FLAG_CLK_FRAC));
0355 div->flags = zynqmp_clk_map_divider_ccf_flags(nodes->type_flag);
0356 div->hw.init = &init;
0357 div->clk_id = clk_id;
0358 div->div_type = nodes->type;
0359
0360
0361
0362
0363
0364 div->max_div = zynqmp_clk_get_max_divisor(clk_id, nodes->type);
0365
0366 hw = &div->hw;
0367 ret = clk_hw_register(NULL, hw);
0368 if (ret) {
0369 kfree(div);
0370 hw = ERR_PTR(ret);
0371 }
0372
0373 return hw;
0374 }