790 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Copyright (C) 2019 Microchip Technology Inc.4 *5 */6 7#include <linux/bitfield.h>8#include <linux/clk.h>9#include <linux/clk-provider.h>10#include <linux/clkdev.h>11#include <linux/clk/at91_pmc.h>12#include <linux/of.h>13#include <linux/mfd/syscon.h>14#include <linux/regmap.h>15 16#include "pmc.h"17 18#define PMC_PLL_CTRL0_DIV_MSK GENMASK(7, 0)19#define PMC_PLL_CTRL1_MUL_MSK GENMASK(31, 24)20#define PMC_PLL_CTRL1_FRACR_MSK GENMASK(21, 0)21 22#define PLL_DIV_MAX (FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, UINT_MAX) + 1)23#define UPLL_DIV 224#define PLL_MUL_MAX (FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, UINT_MAX) + 1)25 26#define PLL_MAX_ID 727 28struct sam9x60_pll_core {29 struct regmap *regmap;30 spinlock_t *lock;31 const struct clk_pll_characteristics *characteristics;32 const struct clk_pll_layout *layout;33 struct clk_hw hw;34 u8 id;35};36 37struct sam9x60_frac {38 struct sam9x60_pll_core core;39 struct at91_clk_pms pms;40 u32 frac;41 u16 mul;42};43 44struct sam9x60_div {45 struct sam9x60_pll_core core;46 struct at91_clk_pms pms;47 u8 div;48 u8 safe_div;49};50 51#define to_sam9x60_pll_core(hw) container_of(hw, struct sam9x60_pll_core, hw)52#define to_sam9x60_frac(core) container_of(core, struct sam9x60_frac, core)53#define to_sam9x60_div(core) container_of(core, struct sam9x60_div, core)54 55static struct sam9x60_div *notifier_div;56 57static inline bool sam9x60_pll_ready(struct regmap *regmap, int id)58{59 unsigned int status;60 61 regmap_read(regmap, AT91_PMC_PLL_ISR0, &status);62 63 return !!(status & BIT(id));64}65 66static bool sam9x60_frac_pll_ready(struct regmap *regmap, u8 id)67{68 return sam9x60_pll_ready(regmap, id);69}70 71static unsigned long sam9x60_frac_pll_recalc_rate(struct clk_hw *hw,72 unsigned long parent_rate)73{74 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);75 struct sam9x60_frac *frac = to_sam9x60_frac(core);76 unsigned long freq;77 78 freq = parent_rate * (frac->mul + 1) +79 DIV_ROUND_CLOSEST_ULL((u64)parent_rate * frac->frac, (1 << 22));80 81 if (core->layout->div2)82 freq >>= 1;83 84 return freq;85}86 87static int sam9x60_frac_pll_set(struct sam9x60_pll_core *core)88{89 struct sam9x60_frac *frac = to_sam9x60_frac(core);90 struct regmap *regmap = core->regmap;91 unsigned int val, cfrac, cmul;92 unsigned long flags;93 94 spin_lock_irqsave(core->lock, flags);95 96 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,97 AT91_PMC_PLL_UPDT_ID_MSK, core->id);98 regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);99 cmul = (val & core->layout->mul_mask) >> core->layout->mul_shift;100 cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift;101 102 if (sam9x60_frac_pll_ready(regmap, core->id) &&103 (cmul == frac->mul && cfrac == frac->frac))104 goto unlock;105 106 /* Recommended value for PMC_PLL_ACR */107 if (core->characteristics->upll)108 val = AT91_PMC_PLL_ACR_DEFAULT_UPLL;109 else110 val = AT91_PMC_PLL_ACR_DEFAULT_PLLA;111 regmap_write(regmap, AT91_PMC_PLL_ACR, val);112 113 regmap_write(regmap, AT91_PMC_PLL_CTRL1,114 (frac->mul << core->layout->mul_shift) |115 (frac->frac << core->layout->frac_shift));116 117 if (core->characteristics->upll) {118 /* Enable the UTMI internal bandgap */119 val |= AT91_PMC_PLL_ACR_UTMIBG;120 regmap_write(regmap, AT91_PMC_PLL_ACR, val);121 122 udelay(10);123 124 /* Enable the UTMI internal regulator */125 val |= AT91_PMC_PLL_ACR_UTMIVR;126 regmap_write(regmap, AT91_PMC_PLL_ACR, val);127 128 udelay(10);129 }130 131 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,132 AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,133 AT91_PMC_PLL_UPDT_UPDATE | core->id);134 135 regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,136 AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL,137 AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL);138 139 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,140 AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,141 AT91_PMC_PLL_UPDT_UPDATE | core->id);142 143 while (!sam9x60_pll_ready(regmap, core->id))144 cpu_relax();145 146unlock:147 spin_unlock_irqrestore(core->lock, flags);148 149 return 0;150}151 152static int sam9x60_frac_pll_prepare(struct clk_hw *hw)153{154 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);155 156 return sam9x60_frac_pll_set(core);157}158 159static void sam9x60_frac_pll_unprepare(struct clk_hw *hw)160{161 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);162 struct regmap *regmap = core->regmap;163 unsigned long flags;164 165 spin_lock_irqsave(core->lock, flags);166 167 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,168 AT91_PMC_PLL_UPDT_ID_MSK, core->id);169 170 regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0, AT91_PMC_PLL_CTRL0_ENPLL, 0);171 172 if (core->characteristics->upll)173 regmap_update_bits(regmap, AT91_PMC_PLL_ACR,174 AT91_PMC_PLL_ACR_UTMIBG | AT91_PMC_PLL_ACR_UTMIVR, 0);175 176 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,177 AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,178 AT91_PMC_PLL_UPDT_UPDATE | core->id);179 180 spin_unlock_irqrestore(core->lock, flags);181}182 183static int sam9x60_frac_pll_is_prepared(struct clk_hw *hw)184{185 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);186 187 return sam9x60_pll_ready(core->regmap, core->id);188}189 190static long sam9x60_frac_pll_compute_mul_frac(struct sam9x60_pll_core *core,191 unsigned long rate,192 unsigned long parent_rate,193 bool update)194{195 struct sam9x60_frac *frac = to_sam9x60_frac(core);196 unsigned long tmprate, remainder;197 unsigned long nmul = 0;198 unsigned long nfrac = 0;199 200 if (rate < core->characteristics->core_output[0].min ||201 rate > core->characteristics->core_output[0].max)202 return -ERANGE;203 204 /*205 * Calculate the multiplier associated with the current206 * divider that provide the closest rate to the requested one.207 */208 nmul = mult_frac(rate, 1, parent_rate);209 tmprate = mult_frac(parent_rate, nmul, 1);210 remainder = rate - tmprate;211 212 if (remainder) {213 nfrac = DIV_ROUND_CLOSEST_ULL((u64)remainder * (1 << 22),214 parent_rate);215 216 tmprate += DIV_ROUND_CLOSEST_ULL((u64)nfrac * parent_rate,217 (1 << 22));218 }219 220 /* Check if resulted rate is a valid. */221 if (tmprate < core->characteristics->core_output[0].min ||222 tmprate > core->characteristics->core_output[0].max)223 return -ERANGE;224 225 if (update) {226 frac->mul = nmul - 1;227 frac->frac = nfrac;228 }229 230 return tmprate;231}232 233static long sam9x60_frac_pll_round_rate(struct clk_hw *hw, unsigned long rate,234 unsigned long *parent_rate)235{236 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);237 238 return sam9x60_frac_pll_compute_mul_frac(core, rate, *parent_rate, false);239}240 241static int sam9x60_frac_pll_set_rate(struct clk_hw *hw, unsigned long rate,242 unsigned long parent_rate)243{244 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);245 246 return sam9x60_frac_pll_compute_mul_frac(core, rate, parent_rate, true);247}248 249static int sam9x60_frac_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,250 unsigned long parent_rate)251{252 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);253 struct sam9x60_frac *frac = to_sam9x60_frac(core);254 struct regmap *regmap = core->regmap;255 unsigned long irqflags;256 unsigned int val, cfrac, cmul;257 long ret;258 259 ret = sam9x60_frac_pll_compute_mul_frac(core, rate, parent_rate, true);260 if (ret <= 0)261 return ret;262 263 spin_lock_irqsave(core->lock, irqflags);264 265 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,266 core->id);267 regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);268 cmul = (val & core->layout->mul_mask) >> core->layout->mul_shift;269 cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift;270 271 if (cmul == frac->mul && cfrac == frac->frac)272 goto unlock;273 274 regmap_write(regmap, AT91_PMC_PLL_CTRL1,275 (frac->mul << core->layout->mul_shift) |276 (frac->frac << core->layout->frac_shift));277 278 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,279 AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,280 AT91_PMC_PLL_UPDT_UPDATE | core->id);281 282 regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,283 AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL,284 AT91_PMC_PLL_CTRL0_ENLOCK |285 AT91_PMC_PLL_CTRL0_ENPLL);286 287 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,288 AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,289 AT91_PMC_PLL_UPDT_UPDATE | core->id);290 291 while (!sam9x60_pll_ready(regmap, core->id))292 cpu_relax();293 294unlock:295 spin_unlock_irqrestore(core->lock, irqflags);296 297 return ret;298}299 300static int sam9x60_frac_pll_save_context(struct clk_hw *hw)301{302 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);303 struct sam9x60_frac *frac = to_sam9x60_frac(core);304 305 frac->pms.status = sam9x60_pll_ready(core->regmap, core->id);306 307 return 0;308}309 310static void sam9x60_frac_pll_restore_context(struct clk_hw *hw)311{312 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);313 struct sam9x60_frac *frac = to_sam9x60_frac(core);314 315 if (frac->pms.status)316 sam9x60_frac_pll_set(core);317}318 319static const struct clk_ops sam9x60_frac_pll_ops = {320 .prepare = sam9x60_frac_pll_prepare,321 .unprepare = sam9x60_frac_pll_unprepare,322 .is_prepared = sam9x60_frac_pll_is_prepared,323 .recalc_rate = sam9x60_frac_pll_recalc_rate,324 .round_rate = sam9x60_frac_pll_round_rate,325 .set_rate = sam9x60_frac_pll_set_rate,326 .save_context = sam9x60_frac_pll_save_context,327 .restore_context = sam9x60_frac_pll_restore_context,328};329 330static const struct clk_ops sam9x60_frac_pll_ops_chg = {331 .prepare = sam9x60_frac_pll_prepare,332 .unprepare = sam9x60_frac_pll_unprepare,333 .is_prepared = sam9x60_frac_pll_is_prepared,334 .recalc_rate = sam9x60_frac_pll_recalc_rate,335 .round_rate = sam9x60_frac_pll_round_rate,336 .set_rate = sam9x60_frac_pll_set_rate_chg,337 .save_context = sam9x60_frac_pll_save_context,338 .restore_context = sam9x60_frac_pll_restore_context,339};340 341/* This function should be called with spinlock acquired. */342static void sam9x60_div_pll_set_div(struct sam9x60_pll_core *core, u32 div,343 bool enable)344{345 struct regmap *regmap = core->regmap;346 u32 ena_msk = enable ? core->layout->endiv_mask : 0;347 u32 ena_val = enable ? (1 << core->layout->endiv_shift) : 0;348 349 regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,350 core->layout->div_mask | ena_msk,351 (div << core->layout->div_shift) | ena_val);352 353 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,354 AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,355 AT91_PMC_PLL_UPDT_UPDATE | core->id);356 357 while (!sam9x60_pll_ready(regmap, core->id))358 cpu_relax();359}360 361static int sam9x60_div_pll_set(struct sam9x60_pll_core *core)362{363 struct sam9x60_div *div = to_sam9x60_div(core);364 struct regmap *regmap = core->regmap;365 unsigned long flags;366 unsigned int val, cdiv;367 368 spin_lock_irqsave(core->lock, flags);369 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,370 AT91_PMC_PLL_UPDT_ID_MSK, core->id);371 regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);372 cdiv = (val & core->layout->div_mask) >> core->layout->div_shift;373 374 /* Stop if enabled an nothing changed. */375 if (!!(val & core->layout->endiv_mask) && cdiv == div->div)376 goto unlock;377 378 sam9x60_div_pll_set_div(core, div->div, 1);379 380unlock:381 spin_unlock_irqrestore(core->lock, flags);382 383 return 0;384}385 386static int sam9x60_div_pll_prepare(struct clk_hw *hw)387{388 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);389 390 return sam9x60_div_pll_set(core);391}392 393static void sam9x60_div_pll_unprepare(struct clk_hw *hw)394{395 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);396 struct regmap *regmap = core->regmap;397 unsigned long flags;398 399 spin_lock_irqsave(core->lock, flags);400 401 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,402 AT91_PMC_PLL_UPDT_ID_MSK, core->id);403 404 regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,405 core->layout->endiv_mask, 0);406 407 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,408 AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,409 AT91_PMC_PLL_UPDT_UPDATE | core->id);410 411 spin_unlock_irqrestore(core->lock, flags);412}413 414static int sam9x60_div_pll_is_prepared(struct clk_hw *hw)415{416 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);417 struct regmap *regmap = core->regmap;418 unsigned long flags;419 unsigned int val;420 421 spin_lock_irqsave(core->lock, flags);422 423 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,424 AT91_PMC_PLL_UPDT_ID_MSK, core->id);425 regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);426 427 spin_unlock_irqrestore(core->lock, flags);428 429 return !!(val & core->layout->endiv_mask);430}431 432static unsigned long sam9x60_div_pll_recalc_rate(struct clk_hw *hw,433 unsigned long parent_rate)434{435 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);436 struct sam9x60_div *div = to_sam9x60_div(core);437 438 return DIV_ROUND_CLOSEST_ULL(parent_rate, (div->div + 1));439}440 441static unsigned long sam9x60_fixed_div_pll_recalc_rate(struct clk_hw *hw,442 unsigned long parent_rate)443{444 return parent_rate >> 1;445}446 447static long sam9x60_div_pll_compute_div(struct sam9x60_pll_core *core,448 unsigned long *parent_rate,449 unsigned long rate)450{451 const struct clk_pll_characteristics *characteristics =452 core->characteristics;453 struct clk_hw *parent = clk_hw_get_parent(&core->hw);454 unsigned long tmp_rate, tmp_parent_rate, tmp_diff;455 long best_diff = -1, best_rate = -EINVAL;456 u32 divid;457 458 if (!rate)459 return 0;460 461 if (rate < characteristics->output[0].min ||462 rate > characteristics->output[0].max)463 return -ERANGE;464 465 for (divid = 1; divid < core->layout->div_mask; divid++) {466 tmp_parent_rate = clk_hw_round_rate(parent, rate * divid);467 if (!tmp_parent_rate)468 continue;469 470 tmp_rate = DIV_ROUND_CLOSEST_ULL(tmp_parent_rate, divid);471 tmp_diff = abs(rate - tmp_rate);472 473 if (best_diff < 0 || best_diff > tmp_diff) {474 *parent_rate = tmp_parent_rate;475 best_rate = tmp_rate;476 best_diff = tmp_diff;477 }478 479 if (!best_diff)480 break;481 }482 483 if (best_rate < characteristics->output[0].min ||484 best_rate > characteristics->output[0].max)485 return -ERANGE;486 487 return best_rate;488}489 490static long sam9x60_div_pll_round_rate(struct clk_hw *hw, unsigned long rate,491 unsigned long *parent_rate)492{493 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);494 495 return sam9x60_div_pll_compute_div(core, parent_rate, rate);496}497 498static int sam9x60_div_pll_set_rate(struct clk_hw *hw, unsigned long rate,499 unsigned long parent_rate)500{501 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);502 struct sam9x60_div *div = to_sam9x60_div(core);503 504 div->div = DIV_ROUND_CLOSEST(parent_rate, rate) - 1;505 506 return 0;507}508 509static int sam9x60_div_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,510 unsigned long parent_rate)511{512 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);513 struct sam9x60_div *div = to_sam9x60_div(core);514 struct regmap *regmap = core->regmap;515 unsigned long irqflags;516 unsigned int val, cdiv;517 518 div->div = DIV_ROUND_CLOSEST(parent_rate, rate) - 1;519 520 spin_lock_irqsave(core->lock, irqflags);521 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,522 core->id);523 regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);524 cdiv = (val & core->layout->div_mask) >> core->layout->div_shift;525 526 /* Stop if nothing changed. */527 if (cdiv == div->div)528 goto unlock;529 530 sam9x60_div_pll_set_div(core, div->div, 0);531 532unlock:533 spin_unlock_irqrestore(core->lock, irqflags);534 535 return 0;536}537 538static int sam9x60_div_pll_save_context(struct clk_hw *hw)539{540 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);541 struct sam9x60_div *div = to_sam9x60_div(core);542 543 div->pms.status = sam9x60_div_pll_is_prepared(hw);544 545 return 0;546}547 548static void sam9x60_div_pll_restore_context(struct clk_hw *hw)549{550 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);551 struct sam9x60_div *div = to_sam9x60_div(core);552 553 if (div->pms.status)554 sam9x60_div_pll_set(core);555}556 557static int sam9x60_div_pll_notifier_fn(struct notifier_block *notifier,558 unsigned long code, void *data)559{560 struct sam9x60_div *div = notifier_div;561 struct sam9x60_pll_core core = div->core;562 struct regmap *regmap = core.regmap;563 unsigned long irqflags;564 u32 val, cdiv;565 int ret = NOTIFY_DONE;566 567 if (code != PRE_RATE_CHANGE)568 return ret;569 570 /*571 * We switch to safe divider to avoid overclocking of other domains572 * feed by us while the frac PLL (our parent) is changed.573 */574 div->div = div->safe_div;575 576 spin_lock_irqsave(core.lock, irqflags);577 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,578 core.id);579 regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);580 cdiv = (val & core.layout->div_mask) >> core.layout->div_shift;581 582 /* Stop if nothing changed. */583 if (cdiv == div->safe_div)584 goto unlock;585 586 sam9x60_div_pll_set_div(&core, div->div, 0);587 ret = NOTIFY_OK;588 589unlock:590 spin_unlock_irqrestore(core.lock, irqflags);591 592 return ret;593}594 595static struct notifier_block sam9x60_div_pll_notifier = {596 .notifier_call = sam9x60_div_pll_notifier_fn,597};598 599static const struct clk_ops sam9x60_div_pll_ops = {600 .prepare = sam9x60_div_pll_prepare,601 .unprepare = sam9x60_div_pll_unprepare,602 .is_prepared = sam9x60_div_pll_is_prepared,603 .recalc_rate = sam9x60_div_pll_recalc_rate,604 .round_rate = sam9x60_div_pll_round_rate,605 .set_rate = sam9x60_div_pll_set_rate,606 .save_context = sam9x60_div_pll_save_context,607 .restore_context = sam9x60_div_pll_restore_context,608};609 610static const struct clk_ops sam9x60_div_pll_ops_chg = {611 .prepare = sam9x60_div_pll_prepare,612 .unprepare = sam9x60_div_pll_unprepare,613 .is_prepared = sam9x60_div_pll_is_prepared,614 .recalc_rate = sam9x60_div_pll_recalc_rate,615 .round_rate = sam9x60_div_pll_round_rate,616 .set_rate = sam9x60_div_pll_set_rate_chg,617 .save_context = sam9x60_div_pll_save_context,618 .restore_context = sam9x60_div_pll_restore_context,619};620 621static const struct clk_ops sam9x60_fixed_div_pll_ops = {622 .prepare = sam9x60_div_pll_prepare,623 .unprepare = sam9x60_div_pll_unprepare,624 .is_prepared = sam9x60_div_pll_is_prepared,625 .recalc_rate = sam9x60_fixed_div_pll_recalc_rate,626 .round_rate = sam9x60_div_pll_round_rate,627 .save_context = sam9x60_div_pll_save_context,628 .restore_context = sam9x60_div_pll_restore_context,629};630 631struct clk_hw * __init632sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,633 const char *name, const char *parent_name,634 struct clk_hw *parent_hw, u8 id,635 const struct clk_pll_characteristics *characteristics,636 const struct clk_pll_layout *layout, u32 flags)637{638 struct sam9x60_frac *frac;639 struct clk_hw *hw;640 struct clk_init_data init = {};641 unsigned long parent_rate, irqflags;642 unsigned int val;643 int ret;644 645 if (id > PLL_MAX_ID || !lock || !parent_hw)646 return ERR_PTR(-EINVAL);647 648 frac = kzalloc(sizeof(*frac), GFP_KERNEL);649 if (!frac)650 return ERR_PTR(-ENOMEM);651 652 init.name = name;653 if (parent_name)654 init.parent_names = &parent_name;655 else656 init.parent_hws = (const struct clk_hw **)&parent_hw;657 init.num_parents = 1;658 if (flags & CLK_SET_RATE_GATE)659 init.ops = &sam9x60_frac_pll_ops;660 else661 init.ops = &sam9x60_frac_pll_ops_chg;662 663 init.flags = flags;664 665 frac->core.id = id;666 frac->core.hw.init = &init;667 frac->core.characteristics = characteristics;668 frac->core.layout = layout;669 frac->core.regmap = regmap;670 frac->core.lock = lock;671 672 spin_lock_irqsave(frac->core.lock, irqflags);673 if (sam9x60_pll_ready(regmap, id)) {674 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,675 AT91_PMC_PLL_UPDT_ID_MSK, id);676 regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);677 frac->mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, val);678 frac->frac = FIELD_GET(PMC_PLL_CTRL1_FRACR_MSK, val);679 } else {680 /*681 * This means the PLL is not setup by bootloaders. In this682 * case we need to set the minimum rate for it. Otherwise683 * a clock child of this PLL may be enabled before setting684 * its rate leading to enabling this PLL with unsupported685 * rate. This will lead to PLL not being locked at all.686 */687 parent_rate = clk_hw_get_rate(parent_hw);688 if (!parent_rate) {689 hw = ERR_PTR(-EINVAL);690 goto free;691 }692 693 ret = sam9x60_frac_pll_compute_mul_frac(&frac->core,694 characteristics->core_output[0].min,695 parent_rate, true);696 if (ret < 0) {697 hw = ERR_PTR(ret);698 goto free;699 }700 }701 spin_unlock_irqrestore(frac->core.lock, irqflags);702 703 hw = &frac->core.hw;704 ret = clk_hw_register(NULL, hw);705 if (ret) {706 kfree(frac);707 hw = ERR_PTR(ret);708 }709 710 return hw;711 712free:713 spin_unlock_irqrestore(frac->core.lock, irqflags);714 kfree(frac);715 return hw;716}717 718struct clk_hw * __init719sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,720 const char *name, const char *parent_name,721 struct clk_hw *parent_hw, u8 id,722 const struct clk_pll_characteristics *characteristics,723 const struct clk_pll_layout *layout, u32 flags,724 u32 safe_div)725{726 struct sam9x60_div *div;727 struct clk_hw *hw;728 struct clk_init_data init = {};729 unsigned long irqflags;730 unsigned int val;731 int ret;732 733 /* We only support one changeable PLL. */734 if (id > PLL_MAX_ID || !lock || (safe_div && notifier_div))735 return ERR_PTR(-EINVAL);736 737 if (safe_div >= PLL_DIV_MAX)738 safe_div = PLL_DIV_MAX - 1;739 740 div = kzalloc(sizeof(*div), GFP_KERNEL);741 if (!div)742 return ERR_PTR(-ENOMEM);743 744 init.name = name;745 if (parent_hw)746 init.parent_hws = (const struct clk_hw **)&parent_hw;747 else748 init.parent_names = &parent_name;749 init.num_parents = 1;750 751 if (layout->div2)752 init.ops = &sam9x60_fixed_div_pll_ops;753 else if (flags & CLK_SET_RATE_GATE)754 init.ops = &sam9x60_div_pll_ops;755 else756 init.ops = &sam9x60_div_pll_ops_chg;757 758 init.flags = flags;759 760 div->core.id = id;761 div->core.hw.init = &init;762 div->core.characteristics = characteristics;763 div->core.layout = layout;764 div->core.regmap = regmap;765 div->core.lock = lock;766 div->safe_div = safe_div;767 768 spin_lock_irqsave(div->core.lock, irqflags);769 770 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,771 AT91_PMC_PLL_UPDT_ID_MSK, id);772 regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);773 div->div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, val);774 775 spin_unlock_irqrestore(div->core.lock, irqflags);776 777 hw = &div->core.hw;778 ret = clk_hw_register(NULL, hw);779 if (ret) {780 kfree(div);781 hw = ERR_PTR(ret);782 } else if (div->safe_div) {783 notifier_div = div;784 clk_notifier_register(hw->clk, &sam9x60_div_pll_notifier);785 }786 787 return hw;788}789 790