0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <linux/clk.h>
0034 #include <linux/clk-provider.h>
0035 #include <linux/clk/at91_pmc.h>
0036 #include <linux/of.h>
0037 #include <linux/mfd/syscon.h>
0038 #include <linux/regmap.h>
0039 #include <linux/slab.h>
0040
0041 #include "pmc.h"
0042
0043 #define AUDIO_PLL_DIV_FRAC BIT(22)
0044 #define AUDIO_PLL_ND_MAX (AT91_PMC_AUDIO_PLL_ND_MASK >> \
0045 AT91_PMC_AUDIO_PLL_ND_OFFSET)
0046
0047 #define AUDIO_PLL_QDPAD(qd, div) ((AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV(qd) & \
0048 AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MASK) | \
0049 (AT91_PMC_AUDIO_PLL_QDPAD_DIV(div) & \
0050 AT91_PMC_AUDIO_PLL_QDPAD_DIV_MASK))
0051
0052 #define AUDIO_PLL_QDPMC_MAX (AT91_PMC_AUDIO_PLL_QDPMC_MASK >> \
0053 AT91_PMC_AUDIO_PLL_QDPMC_OFFSET)
0054
0055 #define AUDIO_PLL_FOUT_MIN 620000000UL
0056 #define AUDIO_PLL_FOUT_MAX 700000000UL
0057
0058 struct clk_audio_frac {
0059 struct clk_hw hw;
0060 struct regmap *regmap;
0061 u32 fracr;
0062 u8 nd;
0063 };
0064
0065 struct clk_audio_pad {
0066 struct clk_hw hw;
0067 struct regmap *regmap;
0068 u8 qdaudio;
0069 u8 div;
0070 };
0071
0072 struct clk_audio_pmc {
0073 struct clk_hw hw;
0074 struct regmap *regmap;
0075 u8 qdpmc;
0076 };
0077
0078 #define to_clk_audio_frac(hw) container_of(hw, struct clk_audio_frac, hw)
0079 #define to_clk_audio_pad(hw) container_of(hw, struct clk_audio_pad, hw)
0080 #define to_clk_audio_pmc(hw) container_of(hw, struct clk_audio_pmc, hw)
0081
0082 static int clk_audio_pll_frac_enable(struct clk_hw *hw)
0083 {
0084 struct clk_audio_frac *frac = to_clk_audio_frac(hw);
0085
0086 regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0,
0087 AT91_PMC_AUDIO_PLL_RESETN, 0);
0088 regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0,
0089 AT91_PMC_AUDIO_PLL_RESETN,
0090 AT91_PMC_AUDIO_PLL_RESETN);
0091 regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL1,
0092 AT91_PMC_AUDIO_PLL_FRACR_MASK, frac->fracr);
0093
0094
0095
0096
0097
0098 regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0,
0099 AT91_PMC_AUDIO_PLL_PLLEN |
0100 AT91_PMC_AUDIO_PLL_ND_MASK,
0101 AT91_PMC_AUDIO_PLL_PLLEN |
0102 AT91_PMC_AUDIO_PLL_ND(frac->nd));
0103
0104 return 0;
0105 }
0106
0107 static int clk_audio_pll_pad_enable(struct clk_hw *hw)
0108 {
0109 struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw);
0110
0111 regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL1,
0112 AT91_PMC_AUDIO_PLL_QDPAD_MASK,
0113 AUDIO_PLL_QDPAD(apad_ck->qdaudio, apad_ck->div));
0114 regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL0,
0115 AT91_PMC_AUDIO_PLL_PADEN, AT91_PMC_AUDIO_PLL_PADEN);
0116
0117 return 0;
0118 }
0119
0120 static int clk_audio_pll_pmc_enable(struct clk_hw *hw)
0121 {
0122 struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw);
0123
0124 regmap_update_bits(apmc_ck->regmap, AT91_PMC_AUDIO_PLL0,
0125 AT91_PMC_AUDIO_PLL_PMCEN |
0126 AT91_PMC_AUDIO_PLL_QDPMC_MASK,
0127 AT91_PMC_AUDIO_PLL_PMCEN |
0128 AT91_PMC_AUDIO_PLL_QDPMC(apmc_ck->qdpmc));
0129 return 0;
0130 }
0131
0132 static void clk_audio_pll_frac_disable(struct clk_hw *hw)
0133 {
0134 struct clk_audio_frac *frac = to_clk_audio_frac(hw);
0135
0136 regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0,
0137 AT91_PMC_AUDIO_PLL_PLLEN, 0);
0138
0139 regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0,
0140 AT91_PMC_AUDIO_PLL_RESETN, 0);
0141 }
0142
0143 static void clk_audio_pll_pad_disable(struct clk_hw *hw)
0144 {
0145 struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw);
0146
0147 regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL0,
0148 AT91_PMC_AUDIO_PLL_PADEN, 0);
0149 }
0150
0151 static void clk_audio_pll_pmc_disable(struct clk_hw *hw)
0152 {
0153 struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw);
0154
0155 regmap_update_bits(apmc_ck->regmap, AT91_PMC_AUDIO_PLL0,
0156 AT91_PMC_AUDIO_PLL_PMCEN, 0);
0157 }
0158
0159 static unsigned long clk_audio_pll_fout(unsigned long parent_rate,
0160 unsigned long nd, unsigned long fracr)
0161 {
0162 unsigned long long fr = (unsigned long long)parent_rate * fracr;
0163
0164 pr_debug("A PLL: %s, fr = %llu\n", __func__, fr);
0165
0166 fr = DIV_ROUND_CLOSEST_ULL(fr, AUDIO_PLL_DIV_FRAC);
0167
0168 pr_debug("A PLL: %s, fr = %llu\n", __func__, fr);
0169
0170 return parent_rate * (nd + 1) + fr;
0171 }
0172
0173 static unsigned long clk_audio_pll_frac_recalc_rate(struct clk_hw *hw,
0174 unsigned long parent_rate)
0175 {
0176 struct clk_audio_frac *frac = to_clk_audio_frac(hw);
0177 unsigned long fout;
0178
0179 fout = clk_audio_pll_fout(parent_rate, frac->nd, frac->fracr);
0180
0181 pr_debug("A PLL: %s, fout = %lu (nd = %u, fracr = %lu)\n", __func__,
0182 fout, frac->nd, (unsigned long)frac->fracr);
0183
0184 return fout;
0185 }
0186
0187 static unsigned long clk_audio_pll_pad_recalc_rate(struct clk_hw *hw,
0188 unsigned long parent_rate)
0189 {
0190 struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw);
0191 unsigned long apad_rate = 0;
0192
0193 if (apad_ck->qdaudio && apad_ck->div)
0194 apad_rate = parent_rate / (apad_ck->qdaudio * apad_ck->div);
0195
0196 pr_debug("A PLL/PAD: %s, apad_rate = %lu (div = %u, qdaudio = %u)\n",
0197 __func__, apad_rate, apad_ck->div, apad_ck->qdaudio);
0198
0199 return apad_rate;
0200 }
0201
0202 static unsigned long clk_audio_pll_pmc_recalc_rate(struct clk_hw *hw,
0203 unsigned long parent_rate)
0204 {
0205 struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw);
0206 unsigned long apmc_rate = 0;
0207
0208 apmc_rate = parent_rate / (apmc_ck->qdpmc + 1);
0209
0210 pr_debug("A PLL/PMC: %s, apmc_rate = %lu (qdpmc = %u)\n", __func__,
0211 apmc_rate, apmc_ck->qdpmc);
0212
0213 return apmc_rate;
0214 }
0215
0216 static int clk_audio_pll_frac_compute_frac(unsigned long rate,
0217 unsigned long parent_rate,
0218 unsigned long *nd,
0219 unsigned long *fracr)
0220 {
0221 unsigned long long tmp, rem;
0222
0223 if (!rate)
0224 return -EINVAL;
0225
0226 tmp = rate;
0227 rem = do_div(tmp, parent_rate);
0228 if (!tmp || tmp >= AUDIO_PLL_ND_MAX)
0229 return -EINVAL;
0230
0231 *nd = tmp - 1;
0232
0233 tmp = rem * AUDIO_PLL_DIV_FRAC;
0234 tmp = DIV_ROUND_CLOSEST_ULL(tmp, parent_rate);
0235 if (tmp > AT91_PMC_AUDIO_PLL_FRACR_MASK)
0236 return -EINVAL;
0237
0238
0239 *fracr = (unsigned long)tmp;
0240
0241 return 0;
0242 }
0243
0244 static int clk_audio_pll_frac_determine_rate(struct clk_hw *hw,
0245 struct clk_rate_request *req)
0246 {
0247 unsigned long fracr, nd;
0248 int ret;
0249
0250 pr_debug("A PLL: %s, rate = %lu (parent_rate = %lu)\n", __func__,
0251 req->rate, req->best_parent_rate);
0252
0253 req->rate = clamp(req->rate, AUDIO_PLL_FOUT_MIN, AUDIO_PLL_FOUT_MAX);
0254
0255 req->min_rate = max(req->min_rate, AUDIO_PLL_FOUT_MIN);
0256 req->max_rate = min(req->max_rate, AUDIO_PLL_FOUT_MAX);
0257
0258 ret = clk_audio_pll_frac_compute_frac(req->rate, req->best_parent_rate,
0259 &nd, &fracr);
0260 if (ret)
0261 return ret;
0262
0263 req->rate = clk_audio_pll_fout(req->best_parent_rate, nd, fracr);
0264
0265 req->best_parent_hw = clk_hw_get_parent(hw);
0266
0267 pr_debug("A PLL: %s, best_rate = %lu (nd = %lu, fracr = %lu)\n",
0268 __func__, req->rate, nd, fracr);
0269
0270 return 0;
0271 }
0272
0273 static long clk_audio_pll_pad_round_rate(struct clk_hw *hw, unsigned long rate,
0274 unsigned long *parent_rate)
0275 {
0276 struct clk_hw *pclk = clk_hw_get_parent(hw);
0277 long best_rate = -EINVAL;
0278 unsigned long best_parent_rate;
0279 unsigned long tmp_qd;
0280 u32 div;
0281 long tmp_rate;
0282 int tmp_diff;
0283 int best_diff = -1;
0284
0285 pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n", __func__,
0286 rate, *parent_rate);
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301 for (tmp_qd = 1; tmp_qd < AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX; tmp_qd++)
0302 for (div = 2; div <= 3; div++) {
0303 if (div == 2 && tmp_qd % 3 == 0)
0304 continue;
0305
0306 best_parent_rate = clk_hw_round_rate(pclk,
0307 rate * tmp_qd * div);
0308 tmp_rate = best_parent_rate / (div * tmp_qd);
0309 tmp_diff = abs(rate - tmp_rate);
0310
0311 if (best_diff < 0 || best_diff > tmp_diff) {
0312 *parent_rate = best_parent_rate;
0313 best_rate = tmp_rate;
0314 best_diff = tmp_diff;
0315 }
0316 }
0317
0318 pr_debug("A PLL/PAD: %s, best_rate = %ld, best_parent_rate = %lu\n",
0319 __func__, best_rate, best_parent_rate);
0320
0321 return best_rate;
0322 }
0323
0324 static long clk_audio_pll_pmc_round_rate(struct clk_hw *hw, unsigned long rate,
0325 unsigned long *parent_rate)
0326 {
0327 struct clk_hw *pclk = clk_hw_get_parent(hw);
0328 long best_rate = -EINVAL;
0329 unsigned long best_parent_rate = 0;
0330 u32 tmp_qd = 0, div;
0331 long tmp_rate;
0332 int tmp_diff;
0333 int best_diff = -1;
0334
0335 pr_debug("A PLL/PMC: %s, rate = %lu (parent_rate = %lu)\n", __func__,
0336 rate, *parent_rate);
0337
0338 if (!rate)
0339 return 0;
0340
0341 best_parent_rate = clk_round_rate(pclk->clk, 1);
0342 div = max(best_parent_rate / rate, 1UL);
0343 for (; div <= AUDIO_PLL_QDPMC_MAX; div++) {
0344 best_parent_rate = clk_round_rate(pclk->clk, rate * div);
0345 tmp_rate = best_parent_rate / div;
0346 tmp_diff = abs(rate - tmp_rate);
0347
0348 if (best_diff < 0 || best_diff > tmp_diff) {
0349 *parent_rate = best_parent_rate;
0350 best_rate = tmp_rate;
0351 best_diff = tmp_diff;
0352 tmp_qd = div;
0353 if (!best_diff)
0354 break;
0355 }
0356 }
0357
0358 pr_debug("A PLL/PMC: %s, best_rate = %ld, best_parent_rate = %lu (qd = %d)\n",
0359 __func__, best_rate, *parent_rate, tmp_qd - 1);
0360
0361 return best_rate;
0362 }
0363
0364 static int clk_audio_pll_frac_set_rate(struct clk_hw *hw, unsigned long rate,
0365 unsigned long parent_rate)
0366 {
0367 struct clk_audio_frac *frac = to_clk_audio_frac(hw);
0368 unsigned long fracr, nd;
0369 int ret;
0370
0371 pr_debug("A PLL: %s, rate = %lu (parent_rate = %lu)\n", __func__, rate,
0372 parent_rate);
0373
0374 if (rate < AUDIO_PLL_FOUT_MIN || rate > AUDIO_PLL_FOUT_MAX)
0375 return -EINVAL;
0376
0377 ret = clk_audio_pll_frac_compute_frac(rate, parent_rate, &nd, &fracr);
0378 if (ret)
0379 return ret;
0380
0381 frac->nd = nd;
0382 frac->fracr = fracr;
0383
0384 return 0;
0385 }
0386
0387 static int clk_audio_pll_pad_set_rate(struct clk_hw *hw, unsigned long rate,
0388 unsigned long parent_rate)
0389 {
0390 struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw);
0391 u8 tmp_div;
0392
0393 pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n", __func__,
0394 rate, parent_rate);
0395
0396 if (!rate)
0397 return -EINVAL;
0398
0399 tmp_div = parent_rate / rate;
0400 if (tmp_div % 3 == 0) {
0401 apad_ck->qdaudio = tmp_div / 3;
0402 apad_ck->div = 3;
0403 } else {
0404 apad_ck->qdaudio = tmp_div / 2;
0405 apad_ck->div = 2;
0406 }
0407
0408 return 0;
0409 }
0410
0411 static int clk_audio_pll_pmc_set_rate(struct clk_hw *hw, unsigned long rate,
0412 unsigned long parent_rate)
0413 {
0414 struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw);
0415
0416 if (!rate)
0417 return -EINVAL;
0418
0419 pr_debug("A PLL/PMC: %s, rate = %lu (parent_rate = %lu)\n", __func__,
0420 rate, parent_rate);
0421
0422 apmc_ck->qdpmc = parent_rate / rate - 1;
0423
0424 return 0;
0425 }
0426
0427 static const struct clk_ops audio_pll_frac_ops = {
0428 .enable = clk_audio_pll_frac_enable,
0429 .disable = clk_audio_pll_frac_disable,
0430 .recalc_rate = clk_audio_pll_frac_recalc_rate,
0431 .determine_rate = clk_audio_pll_frac_determine_rate,
0432 .set_rate = clk_audio_pll_frac_set_rate,
0433 };
0434
0435 static const struct clk_ops audio_pll_pad_ops = {
0436 .enable = clk_audio_pll_pad_enable,
0437 .disable = clk_audio_pll_pad_disable,
0438 .recalc_rate = clk_audio_pll_pad_recalc_rate,
0439 .round_rate = clk_audio_pll_pad_round_rate,
0440 .set_rate = clk_audio_pll_pad_set_rate,
0441 };
0442
0443 static const struct clk_ops audio_pll_pmc_ops = {
0444 .enable = clk_audio_pll_pmc_enable,
0445 .disable = clk_audio_pll_pmc_disable,
0446 .recalc_rate = clk_audio_pll_pmc_recalc_rate,
0447 .round_rate = clk_audio_pll_pmc_round_rate,
0448 .set_rate = clk_audio_pll_pmc_set_rate,
0449 };
0450
0451 struct clk_hw * __init
0452 at91_clk_register_audio_pll_frac(struct regmap *regmap, const char *name,
0453 const char *parent_name)
0454 {
0455 struct clk_audio_frac *frac_ck;
0456 struct clk_init_data init = {};
0457 int ret;
0458
0459 frac_ck = kzalloc(sizeof(*frac_ck), GFP_KERNEL);
0460 if (!frac_ck)
0461 return ERR_PTR(-ENOMEM);
0462
0463 init.name = name;
0464 init.ops = &audio_pll_frac_ops;
0465 init.parent_names = &parent_name;
0466 init.num_parents = 1;
0467 init.flags = CLK_SET_RATE_GATE;
0468
0469 frac_ck->hw.init = &init;
0470 frac_ck->regmap = regmap;
0471
0472 ret = clk_hw_register(NULL, &frac_ck->hw);
0473 if (ret) {
0474 kfree(frac_ck);
0475 return ERR_PTR(ret);
0476 }
0477
0478 return &frac_ck->hw;
0479 }
0480
0481 struct clk_hw * __init
0482 at91_clk_register_audio_pll_pad(struct regmap *regmap, const char *name,
0483 const char *parent_name)
0484 {
0485 struct clk_audio_pad *apad_ck;
0486 struct clk_init_data init;
0487 int ret;
0488
0489 apad_ck = kzalloc(sizeof(*apad_ck), GFP_KERNEL);
0490 if (!apad_ck)
0491 return ERR_PTR(-ENOMEM);
0492
0493 init.name = name;
0494 init.ops = &audio_pll_pad_ops;
0495 init.parent_names = &parent_name;
0496 init.num_parents = 1;
0497 init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
0498 CLK_SET_RATE_PARENT;
0499
0500 apad_ck->hw.init = &init;
0501 apad_ck->regmap = regmap;
0502
0503 ret = clk_hw_register(NULL, &apad_ck->hw);
0504 if (ret) {
0505 kfree(apad_ck);
0506 return ERR_PTR(ret);
0507 }
0508
0509 return &apad_ck->hw;
0510 }
0511
0512 struct clk_hw * __init
0513 at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name,
0514 const char *parent_name)
0515 {
0516 struct clk_audio_pmc *apmc_ck;
0517 struct clk_init_data init;
0518 int ret;
0519
0520 apmc_ck = kzalloc(sizeof(*apmc_ck), GFP_KERNEL);
0521 if (!apmc_ck)
0522 return ERR_PTR(-ENOMEM);
0523
0524 init.name = name;
0525 init.ops = &audio_pll_pmc_ops;
0526 init.parent_names = &parent_name;
0527 init.num_parents = 1;
0528 init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
0529 CLK_SET_RATE_PARENT;
0530
0531 apmc_ck->hw.init = &init;
0532 apmc_ck->regmap = regmap;
0533
0534 ret = clk_hw_register(NULL, &apmc_ck->hw);
0535 if (ret) {
0536 kfree(apmc_ck);
0537 return ERR_PTR(ret);
0538 }
0539
0540 return &apmc_ck->hw;
0541 }