541 lines · c
1// SPDX-License-Identifier: (GPL-2.0 OR MIT)2/*3 * Copyright 2018 NXP.4 *5 * This driver supports the SCCG plls found in the imx8m SOCs6 *7 * Documentation for this SCCG pll can be found at:8 * https://www.nxp.com/docs/en/reference-manual/IMX8MDQLQRM.pdf#page=8349 */10 11#include <linux/clk-provider.h>12#include <linux/err.h>13#include <linux/export.h>14#include <linux/io.h>15#include <linux/iopoll.h>16#include <linux/slab.h>17#include <linux/bitfield.h>18 19#include "clk.h"20 21/* PLL CFGs */22#define PLL_CFG0 0x023#define PLL_CFG1 0x424#define PLL_CFG2 0x825 26#define PLL_DIVF1_MASK GENMASK(18, 13)27#define PLL_DIVF2_MASK GENMASK(12, 7)28#define PLL_DIVR1_MASK GENMASK(27, 25)29#define PLL_DIVR2_MASK GENMASK(24, 19)30#define PLL_DIVQ_MASK GENMASK(6, 1)31#define PLL_REF_MASK GENMASK(2, 0)32 33#define PLL_LOCK_MASK BIT(31)34#define PLL_PD_MASK BIT(7)35 36/* These are the specification limits for the SSCG PLL */37#define PLL_REF_MIN_FREQ 25000000UL38#define PLL_REF_MAX_FREQ 235000000UL39 40#define PLL_STAGE1_MIN_FREQ 1600000000UL41#define PLL_STAGE1_MAX_FREQ 2400000000UL42 43#define PLL_STAGE1_REF_MIN_FREQ 25000000UL44#define PLL_STAGE1_REF_MAX_FREQ 54000000UL45 46#define PLL_STAGE2_MIN_FREQ 1200000000UL47#define PLL_STAGE2_MAX_FREQ 2400000000UL48 49#define PLL_STAGE2_REF_MIN_FREQ 54000000UL50#define PLL_STAGE2_REF_MAX_FREQ 75000000UL51 52#define PLL_OUT_MIN_FREQ 20000000UL53#define PLL_OUT_MAX_FREQ 1200000000UL54 55#define PLL_DIVR1_MAX 756#define PLL_DIVR2_MAX 6357#define PLL_DIVF1_MAX 6358#define PLL_DIVF2_MAX 6359#define PLL_DIVQ_MAX 6360 61#define PLL_BYPASS_NONE 0x062#define PLL_BYPASS1 0x263#define PLL_BYPASS2 0x164 65#define SSCG_PLL_BYPASS1_MASK BIT(5)66#define SSCG_PLL_BYPASS2_MASK BIT(4)67#define SSCG_PLL_BYPASS_MASK GENMASK(5, 4)68 69#define PLL_SCCG_LOCK_TIMEOUT 7070 71struct clk_sscg_pll_setup {72 int divr1, divf1;73 int divr2, divf2;74 int divq;75 int bypass;76 uint64_t vco1;77 uint64_t vco2;78 uint64_t fout;79 uint64_t ref;80 uint64_t ref_div1;81 uint64_t ref_div2;82 uint64_t fout_request;83 int fout_error;84};85 86struct clk_sscg_pll {87 struct clk_hw hw;88 const struct clk_ops ops;89 void __iomem *base;90 struct clk_sscg_pll_setup setup;91 u8 parent;92 u8 bypass1;93 u8 bypass2;94};95 96#define to_clk_sscg_pll(_hw) container_of(_hw, struct clk_sscg_pll, hw)97 98static int clk_sscg_pll_wait_lock(struct clk_sscg_pll *pll)99{100 u32 val;101 102 val = readl_relaxed(pll->base + PLL_CFG0);103 104 /* don't wait for lock if all plls are bypassed */105 if (!(val & SSCG_PLL_BYPASS2_MASK))106 return readl_poll_timeout(pll->base, val, val & PLL_LOCK_MASK,107 0, PLL_SCCG_LOCK_TIMEOUT);108 109 return 0;110}111 112static int clk_sscg_pll2_check_match(struct clk_sscg_pll_setup *setup,113 struct clk_sscg_pll_setup *temp_setup)114{115 int new_diff = temp_setup->fout - temp_setup->fout_request;116 int diff = temp_setup->fout_error;117 118 if (abs(diff) > abs(new_diff)) {119 temp_setup->fout_error = new_diff;120 memcpy(setup, temp_setup, sizeof(struct clk_sscg_pll_setup));121 122 if (temp_setup->fout_request == temp_setup->fout)123 return 0;124 }125 return -1;126}127 128static int clk_sscg_divq_lookup(struct clk_sscg_pll_setup *setup,129 struct clk_sscg_pll_setup *temp_setup)130{131 int ret = -EINVAL;132 133 for (temp_setup->divq = 0; temp_setup->divq <= PLL_DIVQ_MAX;134 temp_setup->divq++) {135 temp_setup->vco2 = temp_setup->vco1;136 do_div(temp_setup->vco2, temp_setup->divr2 + 1);137 temp_setup->vco2 *= 2;138 temp_setup->vco2 *= temp_setup->divf2 + 1;139 if (temp_setup->vco2 >= PLL_STAGE2_MIN_FREQ &&140 temp_setup->vco2 <= PLL_STAGE2_MAX_FREQ) {141 temp_setup->fout = temp_setup->vco2;142 do_div(temp_setup->fout, 2 * (temp_setup->divq + 1));143 144 ret = clk_sscg_pll2_check_match(setup, temp_setup);145 if (!ret) {146 temp_setup->bypass = PLL_BYPASS1;147 return ret;148 }149 }150 }151 152 return ret;153}154 155static int clk_sscg_divf2_lookup(struct clk_sscg_pll_setup *setup,156 struct clk_sscg_pll_setup *temp_setup)157{158 int ret = -EINVAL;159 160 for (temp_setup->divf2 = 0; temp_setup->divf2 <= PLL_DIVF2_MAX;161 temp_setup->divf2++) {162 ret = clk_sscg_divq_lookup(setup, temp_setup);163 if (!ret)164 return ret;165 }166 167 return ret;168}169 170static int clk_sscg_divr2_lookup(struct clk_sscg_pll_setup *setup,171 struct clk_sscg_pll_setup *temp_setup)172{173 int ret = -EINVAL;174 175 for (temp_setup->divr2 = 0; temp_setup->divr2 <= PLL_DIVR2_MAX;176 temp_setup->divr2++) {177 temp_setup->ref_div2 = temp_setup->vco1;178 do_div(temp_setup->ref_div2, temp_setup->divr2 + 1);179 if (temp_setup->ref_div2 >= PLL_STAGE2_REF_MIN_FREQ &&180 temp_setup->ref_div2 <= PLL_STAGE2_REF_MAX_FREQ) {181 ret = clk_sscg_divf2_lookup(setup, temp_setup);182 if (!ret)183 return ret;184 }185 }186 187 return ret;188}189 190static int clk_sscg_pll2_find_setup(struct clk_sscg_pll_setup *setup,191 struct clk_sscg_pll_setup *temp_setup,192 uint64_t ref)193{194 int ret;195 196 if (ref < PLL_STAGE1_MIN_FREQ || ref > PLL_STAGE1_MAX_FREQ)197 return -EINVAL;198 199 temp_setup->vco1 = ref;200 201 ret = clk_sscg_divr2_lookup(setup, temp_setup);202 return ret;203}204 205static int clk_sscg_divf1_lookup(struct clk_sscg_pll_setup *setup,206 struct clk_sscg_pll_setup *temp_setup)207{208 int ret = -EINVAL;209 210 for (temp_setup->divf1 = 0; temp_setup->divf1 <= PLL_DIVF1_MAX;211 temp_setup->divf1++) {212 uint64_t vco1 = temp_setup->ref;213 214 do_div(vco1, temp_setup->divr1 + 1);215 vco1 *= 2;216 vco1 *= temp_setup->divf1 + 1;217 218 ret = clk_sscg_pll2_find_setup(setup, temp_setup, vco1);219 if (!ret) {220 temp_setup->bypass = PLL_BYPASS_NONE;221 return ret;222 }223 }224 225 return ret;226}227 228static int clk_sscg_divr1_lookup(struct clk_sscg_pll_setup *setup,229 struct clk_sscg_pll_setup *temp_setup)230{231 int ret = -EINVAL;232 233 for (temp_setup->divr1 = 0; temp_setup->divr1 <= PLL_DIVR1_MAX;234 temp_setup->divr1++) {235 temp_setup->ref_div1 = temp_setup->ref;236 do_div(temp_setup->ref_div1, temp_setup->divr1 + 1);237 if (temp_setup->ref_div1 >= PLL_STAGE1_REF_MIN_FREQ &&238 temp_setup->ref_div1 <= PLL_STAGE1_REF_MAX_FREQ) {239 ret = clk_sscg_divf1_lookup(setup, temp_setup);240 if (!ret)241 return ret;242 }243 }244 245 return ret;246}247 248static int clk_sscg_pll1_find_setup(struct clk_sscg_pll_setup *setup,249 struct clk_sscg_pll_setup *temp_setup,250 uint64_t ref)251{252 int ret;253 254 if (ref < PLL_REF_MIN_FREQ || ref > PLL_REF_MAX_FREQ)255 return -EINVAL;256 257 temp_setup->ref = ref;258 259 ret = clk_sscg_divr1_lookup(setup, temp_setup);260 261 return ret;262}263 264static int clk_sscg_pll_find_setup(struct clk_sscg_pll_setup *setup,265 uint64_t prate,266 uint64_t rate, int try_bypass)267{268 struct clk_sscg_pll_setup temp_setup;269 int ret = -EINVAL;270 271 memset(&temp_setup, 0, sizeof(struct clk_sscg_pll_setup));272 memset(setup, 0, sizeof(struct clk_sscg_pll_setup));273 274 temp_setup.fout_error = PLL_OUT_MAX_FREQ;275 temp_setup.fout_request = rate;276 277 switch (try_bypass) {278 case PLL_BYPASS2:279 if (prate == rate) {280 setup->bypass = PLL_BYPASS2;281 setup->fout = rate;282 ret = 0;283 }284 break;285 case PLL_BYPASS1:286 ret = clk_sscg_pll2_find_setup(setup, &temp_setup, prate);287 break;288 case PLL_BYPASS_NONE:289 ret = clk_sscg_pll1_find_setup(setup, &temp_setup, prate);290 break;291 }292 293 return ret;294}295 296static int clk_sscg_pll_is_prepared(struct clk_hw *hw)297{298 struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);299 300 u32 val = readl_relaxed(pll->base + PLL_CFG0);301 302 return (val & PLL_PD_MASK) ? 0 : 1;303}304 305static int clk_sscg_pll_prepare(struct clk_hw *hw)306{307 struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);308 u32 val;309 310 val = readl_relaxed(pll->base + PLL_CFG0);311 val &= ~PLL_PD_MASK;312 writel_relaxed(val, pll->base + PLL_CFG0);313 314 return clk_sscg_pll_wait_lock(pll);315}316 317static void clk_sscg_pll_unprepare(struct clk_hw *hw)318{319 struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);320 u32 val;321 322 val = readl_relaxed(pll->base + PLL_CFG0);323 val |= PLL_PD_MASK;324 writel_relaxed(val, pll->base + PLL_CFG0);325}326 327static unsigned long clk_sscg_pll_recalc_rate(struct clk_hw *hw,328 unsigned long parent_rate)329{330 struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);331 u32 val, divr1, divf1, divr2, divf2, divq;332 u64 temp64;333 334 val = readl_relaxed(pll->base + PLL_CFG2);335 divr1 = FIELD_GET(PLL_DIVR1_MASK, val);336 divr2 = FIELD_GET(PLL_DIVR2_MASK, val);337 divf1 = FIELD_GET(PLL_DIVF1_MASK, val);338 divf2 = FIELD_GET(PLL_DIVF2_MASK, val);339 divq = FIELD_GET(PLL_DIVQ_MASK, val);340 341 temp64 = parent_rate;342 343 val = readl(pll->base + PLL_CFG0);344 if (val & SSCG_PLL_BYPASS2_MASK) {345 temp64 = parent_rate;346 } else if (val & SSCG_PLL_BYPASS1_MASK) {347 temp64 *= divf2;348 do_div(temp64, (divr2 + 1) * (divq + 1));349 } else {350 temp64 *= 2;351 temp64 *= (divf1 + 1) * (divf2 + 1);352 do_div(temp64, (divr1 + 1) * (divr2 + 1) * (divq + 1));353 }354 355 return temp64;356}357 358static int clk_sscg_pll_set_rate(struct clk_hw *hw, unsigned long rate,359 unsigned long parent_rate)360{361 struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);362 struct clk_sscg_pll_setup *setup = &pll->setup;363 u32 val;364 365 /* set bypass here too since the parent might be the same */366 val = readl(pll->base + PLL_CFG0);367 val &= ~SSCG_PLL_BYPASS_MASK;368 val |= FIELD_PREP(SSCG_PLL_BYPASS_MASK, setup->bypass);369 writel(val, pll->base + PLL_CFG0);370 371 val = readl_relaxed(pll->base + PLL_CFG2);372 val &= ~(PLL_DIVF1_MASK | PLL_DIVF2_MASK);373 val &= ~(PLL_DIVR1_MASK | PLL_DIVR2_MASK | PLL_DIVQ_MASK);374 val |= FIELD_PREP(PLL_DIVF1_MASK, setup->divf1);375 val |= FIELD_PREP(PLL_DIVF2_MASK, setup->divf2);376 val |= FIELD_PREP(PLL_DIVR1_MASK, setup->divr1);377 val |= FIELD_PREP(PLL_DIVR2_MASK, setup->divr2);378 val |= FIELD_PREP(PLL_DIVQ_MASK, setup->divq);379 writel_relaxed(val, pll->base + PLL_CFG2);380 381 return clk_sscg_pll_wait_lock(pll);382}383 384static u8 clk_sscg_pll_get_parent(struct clk_hw *hw)385{386 struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);387 u32 val;388 u8 ret = pll->parent;389 390 val = readl(pll->base + PLL_CFG0);391 if (val & SSCG_PLL_BYPASS2_MASK)392 ret = pll->bypass2;393 else if (val & SSCG_PLL_BYPASS1_MASK)394 ret = pll->bypass1;395 return ret;396}397 398static int clk_sscg_pll_set_parent(struct clk_hw *hw, u8 index)399{400 struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);401 u32 val;402 403 val = readl(pll->base + PLL_CFG0);404 val &= ~SSCG_PLL_BYPASS_MASK;405 val |= FIELD_PREP(SSCG_PLL_BYPASS_MASK, pll->setup.bypass);406 writel(val, pll->base + PLL_CFG0);407 408 return clk_sscg_pll_wait_lock(pll);409}410 411static int __clk_sscg_pll_determine_rate(struct clk_hw *hw,412 struct clk_rate_request *req,413 uint64_t min,414 uint64_t max,415 uint64_t rate,416 int bypass)417{418 struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);419 struct clk_sscg_pll_setup *setup = &pll->setup;420 struct clk_hw *parent_hw = NULL;421 int bypass_parent_index;422 int ret;423 424 req->max_rate = max;425 req->min_rate = min;426 427 switch (bypass) {428 case PLL_BYPASS2:429 bypass_parent_index = pll->bypass2;430 break;431 case PLL_BYPASS1:432 bypass_parent_index = pll->bypass1;433 break;434 default:435 bypass_parent_index = pll->parent;436 break;437 }438 439 parent_hw = clk_hw_get_parent_by_index(hw, bypass_parent_index);440 ret = __clk_determine_rate(parent_hw, req);441 if (!ret) {442 ret = clk_sscg_pll_find_setup(setup, req->rate,443 rate, bypass);444 }445 446 req->best_parent_hw = parent_hw;447 req->best_parent_rate = req->rate;448 req->rate = setup->fout;449 450 return ret;451}452 453static int clk_sscg_pll_determine_rate(struct clk_hw *hw,454 struct clk_rate_request *req)455{456 struct clk_sscg_pll *pll = to_clk_sscg_pll(hw);457 struct clk_sscg_pll_setup *setup = &pll->setup;458 uint64_t rate = req->rate;459 uint64_t min = req->min_rate;460 uint64_t max = req->max_rate;461 int ret;462 463 if (rate < PLL_OUT_MIN_FREQ || rate > PLL_OUT_MAX_FREQ)464 return -EINVAL;465 466 ret = __clk_sscg_pll_determine_rate(hw, req, req->rate, req->rate,467 rate, PLL_BYPASS2);468 if (!ret)469 return ret;470 471 ret = __clk_sscg_pll_determine_rate(hw, req, PLL_STAGE1_REF_MIN_FREQ,472 PLL_STAGE1_REF_MAX_FREQ, rate,473 PLL_BYPASS1);474 if (!ret)475 return ret;476 477 ret = __clk_sscg_pll_determine_rate(hw, req, PLL_REF_MIN_FREQ,478 PLL_REF_MAX_FREQ, rate,479 PLL_BYPASS_NONE);480 if (!ret)481 return ret;482 483 if (setup->fout >= min && setup->fout <= max)484 ret = 0;485 486 return ret;487}488 489static const struct clk_ops clk_sscg_pll_ops = {490 .prepare = clk_sscg_pll_prepare,491 .unprepare = clk_sscg_pll_unprepare,492 .is_prepared = clk_sscg_pll_is_prepared,493 .recalc_rate = clk_sscg_pll_recalc_rate,494 .set_rate = clk_sscg_pll_set_rate,495 .set_parent = clk_sscg_pll_set_parent,496 .get_parent = clk_sscg_pll_get_parent,497 .determine_rate = clk_sscg_pll_determine_rate,498};499 500struct clk_hw *imx_clk_hw_sscg_pll(const char *name,501 const char * const *parent_names,502 u8 num_parents,503 u8 parent, u8 bypass1, u8 bypass2,504 void __iomem *base,505 unsigned long flags)506{507 struct clk_sscg_pll *pll;508 struct clk_init_data init;509 struct clk_hw *hw;510 int ret;511 512 pll = kzalloc(sizeof(*pll), GFP_KERNEL);513 if (!pll)514 return ERR_PTR(-ENOMEM);515 516 pll->parent = parent;517 pll->bypass1 = bypass1;518 pll->bypass2 = bypass2;519 520 pll->base = base;521 init.name = name;522 init.ops = &clk_sscg_pll_ops;523 524 init.flags = flags;525 init.parent_names = parent_names;526 init.num_parents = num_parents;527 528 pll->hw.init = &init;529 530 hw = &pll->hw;531 532 ret = clk_hw_register(NULL, hw);533 if (ret) {534 kfree(pll);535 return ERR_PTR(ret);536 }537 538 return hw;539}540EXPORT_SYMBOL_GPL(imx_clk_hw_sscg_pll);541