1211 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) 2014 MundoReader S.L.4 * Author: Heiko Stuebner <heiko@sntech.de>5 *6 * Copyright (c) 2015 Rockchip Electronics Co. Ltd.7 * Author: Xing Zheng <zhengxing@rock-chips.com>8 */9 10#include <asm/div64.h>11#include <linux/slab.h>12#include <linux/io.h>13#include <linux/delay.h>14#include <linux/clk-provider.h>15#include <linux/iopoll.h>16#include <linux/regmap.h>17#include <linux/clk.h>18#include "clk.h"19 20#define PLL_MODE_MASK 0x321#define PLL_MODE_SLOW 0x022#define PLL_MODE_NORM 0x123#define PLL_MODE_DEEP 0x224#define PLL_RK3328_MODE_MASK 0x125 26struct rockchip_clk_pll {27 struct clk_hw hw;28 29 struct clk_mux pll_mux;30 const struct clk_ops *pll_mux_ops;31 32 struct notifier_block clk_nb;33 34 void __iomem *reg_base;35 int lock_offset;36 unsigned int lock_shift;37 enum rockchip_pll_type type;38 u8 flags;39 const struct rockchip_pll_rate_table *rate_table;40 unsigned int rate_count;41 spinlock_t *lock;42 43 struct rockchip_clk_provider *ctx;44};45 46#define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw)47#define to_rockchip_clk_pll_nb(nb) \48 container_of(nb, struct rockchip_clk_pll, clk_nb)49 50static const struct rockchip_pll_rate_table *rockchip_get_pll_settings(51 struct rockchip_clk_pll *pll, unsigned long rate)52{53 const struct rockchip_pll_rate_table *rate_table = pll->rate_table;54 int i;55 56 for (i = 0; i < pll->rate_count; i++) {57 if (rate == rate_table[i].rate)58 return &rate_table[i];59 }60 61 return NULL;62}63 64static long rockchip_pll_round_rate(struct clk_hw *hw,65 unsigned long drate, unsigned long *prate)66{67 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);68 const struct rockchip_pll_rate_table *rate_table = pll->rate_table;69 int i;70 71 /* Assumming rate_table is in descending order */72 for (i = 0; i < pll->rate_count; i++) {73 if (drate >= rate_table[i].rate)74 return rate_table[i].rate;75 }76 77 /* return minimum supported value */78 return rate_table[i - 1].rate;79}80 81/*82 * Wait for the pll to reach the locked state.83 * The calling set_rate function is responsible for making sure the84 * grf regmap is available.85 */86static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)87{88 struct regmap *grf = pll->ctx->grf;89 unsigned int val;90 int ret;91 92 ret = regmap_read_poll_timeout(grf, pll->lock_offset, val,93 val & BIT(pll->lock_shift), 0, 1000);94 if (ret)95 pr_err("%s: timeout waiting for pll to lock\n", __func__);96 97 return ret;98}99 100/*101 * PLL used in RK3036102 */103 104#define RK3036_PLLCON(i) (i * 0x4)105#define RK3036_PLLCON0_FBDIV_MASK 0xfff106#define RK3036_PLLCON0_FBDIV_SHIFT 0107#define RK3036_PLLCON0_POSTDIV1_MASK 0x7108#define RK3036_PLLCON0_POSTDIV1_SHIFT 12109#define RK3036_PLLCON1_REFDIV_MASK 0x3f110#define RK3036_PLLCON1_REFDIV_SHIFT 0111#define RK3036_PLLCON1_POSTDIV2_MASK 0x7112#define RK3036_PLLCON1_POSTDIV2_SHIFT 6113#define RK3036_PLLCON1_LOCK_STATUS BIT(10)114#define RK3036_PLLCON1_DSMPD_MASK 0x1115#define RK3036_PLLCON1_DSMPD_SHIFT 12116#define RK3036_PLLCON1_PWRDOWN BIT(13)117#define RK3036_PLLCON2_FRAC_MASK 0xffffff118#define RK3036_PLLCON2_FRAC_SHIFT 0119 120static int rockchip_rk3036_pll_wait_lock(struct rockchip_clk_pll *pll)121{122 u32 pllcon;123 int ret;124 125 /*126 * Lock time typical 250, max 500 input clock cycles @24MHz127 * So define a very safe maximum of 1000us, meaning 24000 cycles.128 */129 ret = readl_relaxed_poll_timeout(pll->reg_base + RK3036_PLLCON(1),130 pllcon,131 pllcon & RK3036_PLLCON1_LOCK_STATUS,132 0, 1000);133 if (ret)134 pr_err("%s: timeout waiting for pll to lock\n", __func__);135 136 return ret;137}138 139static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll,140 struct rockchip_pll_rate_table *rate)141{142 u32 pllcon;143 144 pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(0));145 rate->fbdiv = ((pllcon >> RK3036_PLLCON0_FBDIV_SHIFT)146 & RK3036_PLLCON0_FBDIV_MASK);147 rate->postdiv1 = ((pllcon >> RK3036_PLLCON0_POSTDIV1_SHIFT)148 & RK3036_PLLCON0_POSTDIV1_MASK);149 150 pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(1));151 rate->refdiv = ((pllcon >> RK3036_PLLCON1_REFDIV_SHIFT)152 & RK3036_PLLCON1_REFDIV_MASK);153 rate->postdiv2 = ((pllcon >> RK3036_PLLCON1_POSTDIV2_SHIFT)154 & RK3036_PLLCON1_POSTDIV2_MASK);155 rate->dsmpd = ((pllcon >> RK3036_PLLCON1_DSMPD_SHIFT)156 & RK3036_PLLCON1_DSMPD_MASK);157 158 pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2));159 rate->frac = ((pllcon >> RK3036_PLLCON2_FRAC_SHIFT)160 & RK3036_PLLCON2_FRAC_MASK);161}162 163static unsigned long rockchip_rk3036_pll_recalc_rate(struct clk_hw *hw,164 unsigned long prate)165{166 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);167 struct rockchip_pll_rate_table cur;168 u64 rate64 = prate;169 170 rockchip_rk3036_pll_get_params(pll, &cur);171 172 rate64 *= cur.fbdiv;173 do_div(rate64, cur.refdiv);174 175 if (cur.dsmpd == 0) {176 /* fractional mode */177 u64 frac_rate64 = prate * cur.frac;178 179 do_div(frac_rate64, cur.refdiv);180 rate64 += frac_rate64 >> 24;181 }182 183 do_div(rate64, cur.postdiv1);184 do_div(rate64, cur.postdiv2);185 186 return (unsigned long)rate64;187}188 189static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll,190 const struct rockchip_pll_rate_table *rate)191{192 const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;193 struct clk_mux *pll_mux = &pll->pll_mux;194 struct rockchip_pll_rate_table cur;195 u32 pllcon;196 int rate_change_remuxed = 0;197 int cur_parent;198 int ret;199 200 pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",201 __func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv,202 rate->postdiv2, rate->dsmpd, rate->frac);203 204 rockchip_rk3036_pll_get_params(pll, &cur);205 cur.rate = 0;206 207 cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);208 if (cur_parent == PLL_MODE_NORM) {209 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);210 rate_change_remuxed = 1;211 }212 213 /* update pll values */214 writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3036_PLLCON0_FBDIV_MASK,215 RK3036_PLLCON0_FBDIV_SHIFT) |216 HIWORD_UPDATE(rate->postdiv1, RK3036_PLLCON0_POSTDIV1_MASK,217 RK3036_PLLCON0_POSTDIV1_SHIFT),218 pll->reg_base + RK3036_PLLCON(0));219 220 writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3036_PLLCON1_REFDIV_MASK,221 RK3036_PLLCON1_REFDIV_SHIFT) |222 HIWORD_UPDATE(rate->postdiv2, RK3036_PLLCON1_POSTDIV2_MASK,223 RK3036_PLLCON1_POSTDIV2_SHIFT) |224 HIWORD_UPDATE(rate->dsmpd, RK3036_PLLCON1_DSMPD_MASK,225 RK3036_PLLCON1_DSMPD_SHIFT),226 pll->reg_base + RK3036_PLLCON(1));227 228 /* GPLL CON2 is not HIWORD_MASK */229 pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2));230 pllcon &= ~(RK3036_PLLCON2_FRAC_MASK << RK3036_PLLCON2_FRAC_SHIFT);231 pllcon |= rate->frac << RK3036_PLLCON2_FRAC_SHIFT;232 writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2));233 234 /* wait for the pll to lock */235 ret = rockchip_rk3036_pll_wait_lock(pll);236 if (ret) {237 pr_warn("%s: pll update unsuccessful, trying to restore old params\n",238 __func__);239 rockchip_rk3036_pll_set_params(pll, &cur);240 }241 242 if (rate_change_remuxed)243 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);244 245 return ret;246}247 248static int rockchip_rk3036_pll_set_rate(struct clk_hw *hw, unsigned long drate,249 unsigned long prate)250{251 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);252 const struct rockchip_pll_rate_table *rate;253 254 pr_debug("%s: changing %s to %lu with a parent rate of %lu\n",255 __func__, __clk_get_name(hw->clk), drate, prate);256 257 /* Get required rate settings from table */258 rate = rockchip_get_pll_settings(pll, drate);259 if (!rate) {260 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,261 drate, __clk_get_name(hw->clk));262 return -EINVAL;263 }264 265 return rockchip_rk3036_pll_set_params(pll, rate);266}267 268static int rockchip_rk3036_pll_enable(struct clk_hw *hw)269{270 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);271 272 writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0),273 pll->reg_base + RK3036_PLLCON(1));274 rockchip_rk3036_pll_wait_lock(pll);275 276 return 0;277}278 279static void rockchip_rk3036_pll_disable(struct clk_hw *hw)280{281 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);282 283 writel(HIWORD_UPDATE(RK3036_PLLCON1_PWRDOWN,284 RK3036_PLLCON1_PWRDOWN, 0),285 pll->reg_base + RK3036_PLLCON(1));286}287 288static int rockchip_rk3036_pll_is_enabled(struct clk_hw *hw)289{290 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);291 u32 pllcon = readl(pll->reg_base + RK3036_PLLCON(1));292 293 return !(pllcon & RK3036_PLLCON1_PWRDOWN);294}295 296static int rockchip_rk3036_pll_init(struct clk_hw *hw)297{298 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);299 const struct rockchip_pll_rate_table *rate;300 struct rockchip_pll_rate_table cur;301 unsigned long drate;302 303 if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))304 return 0;305 306 drate = clk_hw_get_rate(hw);307 rate = rockchip_get_pll_settings(pll, drate);308 309 /* when no rate setting for the current rate, rely on clk_set_rate */310 if (!rate)311 return 0;312 313 rockchip_rk3036_pll_get_params(pll, &cur);314 315 pr_debug("%s: pll %s@%lu: Hz\n", __func__, __clk_get_name(hw->clk),316 drate);317 pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",318 cur.fbdiv, cur.postdiv1, cur.refdiv, cur.postdiv2,319 cur.dsmpd, cur.frac);320 pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",321 rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2,322 rate->dsmpd, rate->frac);323 324 if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 ||325 rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 ||326 rate->dsmpd != cur.dsmpd ||327 (!cur.dsmpd && (rate->frac != cur.frac))) {328 struct clk *parent = clk_get_parent(hw->clk);329 330 if (!parent) {331 pr_warn("%s: parent of %s not available\n",332 __func__, __clk_get_name(hw->clk));333 return 0;334 }335 336 pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",337 __func__, __clk_get_name(hw->clk));338 rockchip_rk3036_pll_set_params(pll, rate);339 }340 341 return 0;342}343 344static const struct clk_ops rockchip_rk3036_pll_clk_norate_ops = {345 .recalc_rate = rockchip_rk3036_pll_recalc_rate,346 .enable = rockchip_rk3036_pll_enable,347 .disable = rockchip_rk3036_pll_disable,348 .is_enabled = rockchip_rk3036_pll_is_enabled,349};350 351static const struct clk_ops rockchip_rk3036_pll_clk_ops = {352 .recalc_rate = rockchip_rk3036_pll_recalc_rate,353 .round_rate = rockchip_pll_round_rate,354 .set_rate = rockchip_rk3036_pll_set_rate,355 .enable = rockchip_rk3036_pll_enable,356 .disable = rockchip_rk3036_pll_disable,357 .is_enabled = rockchip_rk3036_pll_is_enabled,358 .init = rockchip_rk3036_pll_init,359};360 361/*362 * PLL used in RK3066, RK3188 and RK3288363 */364 365#define RK3066_PLL_RESET_DELAY(nr) ((nr * 500) / 24 + 1)366 367#define RK3066_PLLCON(i) (i * 0x4)368#define RK3066_PLLCON0_OD_MASK 0xf369#define RK3066_PLLCON0_OD_SHIFT 0370#define RK3066_PLLCON0_NR_MASK 0x3f371#define RK3066_PLLCON0_NR_SHIFT 8372#define RK3066_PLLCON1_NF_MASK 0x1fff373#define RK3066_PLLCON1_NF_SHIFT 0374#define RK3066_PLLCON2_NB_MASK 0xfff375#define RK3066_PLLCON2_NB_SHIFT 0376#define RK3066_PLLCON3_RESET (1 << 5)377#define RK3066_PLLCON3_PWRDOWN (1 << 1)378#define RK3066_PLLCON3_BYPASS (1 << 0)379 380static void rockchip_rk3066_pll_get_params(struct rockchip_clk_pll *pll,381 struct rockchip_pll_rate_table *rate)382{383 u32 pllcon;384 385 pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0));386 rate->nr = ((pllcon >> RK3066_PLLCON0_NR_SHIFT)387 & RK3066_PLLCON0_NR_MASK) + 1;388 rate->no = ((pllcon >> RK3066_PLLCON0_OD_SHIFT)389 & RK3066_PLLCON0_OD_MASK) + 1;390 391 pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1));392 rate->nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT)393 & RK3066_PLLCON1_NF_MASK) + 1;394 395 pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2));396 rate->nb = ((pllcon >> RK3066_PLLCON2_NB_SHIFT)397 & RK3066_PLLCON2_NB_MASK) + 1;398}399 400static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw,401 unsigned long prate)402{403 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);404 struct rockchip_pll_rate_table cur;405 u64 rate64 = prate;406 u32 pllcon;407 408 pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(3));409 if (pllcon & RK3066_PLLCON3_BYPASS) {410 pr_debug("%s: pll %s is bypassed\n", __func__,411 clk_hw_get_name(hw));412 return prate;413 }414 415 rockchip_rk3066_pll_get_params(pll, &cur);416 417 rate64 *= cur.nf;418 do_div(rate64, cur.nr);419 do_div(rate64, cur.no);420 421 return (unsigned long)rate64;422}423 424static int rockchip_rk3066_pll_set_params(struct rockchip_clk_pll *pll,425 const struct rockchip_pll_rate_table *rate)426{427 const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;428 struct clk_mux *pll_mux = &pll->pll_mux;429 struct rockchip_pll_rate_table cur;430 int rate_change_remuxed = 0;431 int cur_parent;432 int ret;433 434 pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n",435 __func__, rate->rate, rate->nr, rate->no, rate->nf);436 437 rockchip_rk3066_pll_get_params(pll, &cur);438 cur.rate = 0;439 440 cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);441 if (cur_parent == PLL_MODE_NORM) {442 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);443 rate_change_remuxed = 1;444 }445 446 /* enter reset mode */447 writel(HIWORD_UPDATE(RK3066_PLLCON3_RESET, RK3066_PLLCON3_RESET, 0),448 pll->reg_base + RK3066_PLLCON(3));449 450 /* update pll values */451 writel(HIWORD_UPDATE(rate->nr - 1, RK3066_PLLCON0_NR_MASK,452 RK3066_PLLCON0_NR_SHIFT) |453 HIWORD_UPDATE(rate->no - 1, RK3066_PLLCON0_OD_MASK,454 RK3066_PLLCON0_OD_SHIFT),455 pll->reg_base + RK3066_PLLCON(0));456 457 writel_relaxed(HIWORD_UPDATE(rate->nf - 1, RK3066_PLLCON1_NF_MASK,458 RK3066_PLLCON1_NF_SHIFT),459 pll->reg_base + RK3066_PLLCON(1));460 writel_relaxed(HIWORD_UPDATE(rate->nb - 1, RK3066_PLLCON2_NB_MASK,461 RK3066_PLLCON2_NB_SHIFT),462 pll->reg_base + RK3066_PLLCON(2));463 464 /* leave reset and wait the reset_delay */465 writel(HIWORD_UPDATE(0, RK3066_PLLCON3_RESET, 0),466 pll->reg_base + RK3066_PLLCON(3));467 udelay(RK3066_PLL_RESET_DELAY(rate->nr));468 469 /* wait for the pll to lock */470 ret = rockchip_pll_wait_lock(pll);471 if (ret) {472 pr_warn("%s: pll update unsuccessful, trying to restore old params\n",473 __func__);474 rockchip_rk3066_pll_set_params(pll, &cur);475 }476 477 if (rate_change_remuxed)478 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);479 480 return ret;481}482 483static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,484 unsigned long prate)485{486 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);487 const struct rockchip_pll_rate_table *rate;488 489 pr_debug("%s: changing %s to %lu with a parent rate of %lu\n",490 __func__, clk_hw_get_name(hw), drate, prate);491 492 /* Get required rate settings from table */493 rate = rockchip_get_pll_settings(pll, drate);494 if (!rate) {495 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,496 drate, clk_hw_get_name(hw));497 return -EINVAL;498 }499 500 return rockchip_rk3066_pll_set_params(pll, rate);501}502 503static int rockchip_rk3066_pll_enable(struct clk_hw *hw)504{505 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);506 507 writel(HIWORD_UPDATE(0, RK3066_PLLCON3_PWRDOWN, 0),508 pll->reg_base + RK3066_PLLCON(3));509 rockchip_pll_wait_lock(pll);510 511 return 0;512}513 514static void rockchip_rk3066_pll_disable(struct clk_hw *hw)515{516 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);517 518 writel(HIWORD_UPDATE(RK3066_PLLCON3_PWRDOWN,519 RK3066_PLLCON3_PWRDOWN, 0),520 pll->reg_base + RK3066_PLLCON(3));521}522 523static int rockchip_rk3066_pll_is_enabled(struct clk_hw *hw)524{525 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);526 u32 pllcon = readl(pll->reg_base + RK3066_PLLCON(3));527 528 return !(pllcon & RK3066_PLLCON3_PWRDOWN);529}530 531static int rockchip_rk3066_pll_init(struct clk_hw *hw)532{533 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);534 const struct rockchip_pll_rate_table *rate;535 struct rockchip_pll_rate_table cur;536 unsigned long drate;537 538 if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))539 return 0;540 541 drate = clk_hw_get_rate(hw);542 rate = rockchip_get_pll_settings(pll, drate);543 544 /* when no rate setting for the current rate, rely on clk_set_rate */545 if (!rate)546 return 0;547 548 rockchip_rk3066_pll_get_params(pll, &cur);549 550 pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), nb(%d:%d)\n",551 __func__, clk_hw_get_name(hw), drate, rate->nr, cur.nr,552 rate->no, cur.no, rate->nf, cur.nf, rate->nb, cur.nb);553 if (rate->nr != cur.nr || rate->no != cur.no || rate->nf != cur.nf554 || rate->nb != cur.nb) {555 pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",556 __func__, clk_hw_get_name(hw));557 rockchip_rk3066_pll_set_params(pll, rate);558 }559 560 return 0;561}562 563static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = {564 .recalc_rate = rockchip_rk3066_pll_recalc_rate,565 .enable = rockchip_rk3066_pll_enable,566 .disable = rockchip_rk3066_pll_disable,567 .is_enabled = rockchip_rk3066_pll_is_enabled,568};569 570static const struct clk_ops rockchip_rk3066_pll_clk_ops = {571 .recalc_rate = rockchip_rk3066_pll_recalc_rate,572 .round_rate = rockchip_pll_round_rate,573 .set_rate = rockchip_rk3066_pll_set_rate,574 .enable = rockchip_rk3066_pll_enable,575 .disable = rockchip_rk3066_pll_disable,576 .is_enabled = rockchip_rk3066_pll_is_enabled,577 .init = rockchip_rk3066_pll_init,578};579 580/*581 * PLL used in RK3399582 */583 584#define RK3399_PLLCON(i) (i * 0x4)585#define RK3399_PLLCON0_FBDIV_MASK 0xfff586#define RK3399_PLLCON0_FBDIV_SHIFT 0587#define RK3399_PLLCON1_REFDIV_MASK 0x3f588#define RK3399_PLLCON1_REFDIV_SHIFT 0589#define RK3399_PLLCON1_POSTDIV1_MASK 0x7590#define RK3399_PLLCON1_POSTDIV1_SHIFT 8591#define RK3399_PLLCON1_POSTDIV2_MASK 0x7592#define RK3399_PLLCON1_POSTDIV2_SHIFT 12593#define RK3399_PLLCON2_FRAC_MASK 0xffffff594#define RK3399_PLLCON2_FRAC_SHIFT 0595#define RK3399_PLLCON2_LOCK_STATUS BIT(31)596#define RK3399_PLLCON3_PWRDOWN BIT(0)597#define RK3399_PLLCON3_DSMPD_MASK 0x1598#define RK3399_PLLCON3_DSMPD_SHIFT 3599 600static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll)601{602 u32 pllcon;603 int ret;604 605 /*606 * Lock time typical 250, max 500 input clock cycles @24MHz607 * So define a very safe maximum of 1000us, meaning 24000 cycles.608 */609 ret = readl_relaxed_poll_timeout(pll->reg_base + RK3399_PLLCON(2),610 pllcon,611 pllcon & RK3399_PLLCON2_LOCK_STATUS,612 0, 1000);613 if (ret)614 pr_err("%s: timeout waiting for pll to lock\n", __func__);615 616 return ret;617}618 619static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll,620 struct rockchip_pll_rate_table *rate)621{622 u32 pllcon;623 624 pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(0));625 rate->fbdiv = ((pllcon >> RK3399_PLLCON0_FBDIV_SHIFT)626 & RK3399_PLLCON0_FBDIV_MASK);627 628 pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(1));629 rate->refdiv = ((pllcon >> RK3399_PLLCON1_REFDIV_SHIFT)630 & RK3399_PLLCON1_REFDIV_MASK);631 rate->postdiv1 = ((pllcon >> RK3399_PLLCON1_POSTDIV1_SHIFT)632 & RK3399_PLLCON1_POSTDIV1_MASK);633 rate->postdiv2 = ((pllcon >> RK3399_PLLCON1_POSTDIV2_SHIFT)634 & RK3399_PLLCON1_POSTDIV2_MASK);635 636 pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2));637 rate->frac = ((pllcon >> RK3399_PLLCON2_FRAC_SHIFT)638 & RK3399_PLLCON2_FRAC_MASK);639 640 pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(3));641 rate->dsmpd = ((pllcon >> RK3399_PLLCON3_DSMPD_SHIFT)642 & RK3399_PLLCON3_DSMPD_MASK);643}644 645static unsigned long rockchip_rk3399_pll_recalc_rate(struct clk_hw *hw,646 unsigned long prate)647{648 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);649 struct rockchip_pll_rate_table cur;650 u64 rate64 = prate;651 652 rockchip_rk3399_pll_get_params(pll, &cur);653 654 rate64 *= cur.fbdiv;655 do_div(rate64, cur.refdiv);656 657 if (cur.dsmpd == 0) {658 /* fractional mode */659 u64 frac_rate64 = prate * cur.frac;660 661 do_div(frac_rate64, cur.refdiv);662 rate64 += frac_rate64 >> 24;663 }664 665 do_div(rate64, cur.postdiv1);666 do_div(rate64, cur.postdiv2);667 668 return (unsigned long)rate64;669}670 671static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll,672 const struct rockchip_pll_rate_table *rate)673{674 const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;675 struct clk_mux *pll_mux = &pll->pll_mux;676 struct rockchip_pll_rate_table cur;677 u32 pllcon;678 int rate_change_remuxed = 0;679 int cur_parent;680 int ret;681 682 pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",683 __func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv,684 rate->postdiv2, rate->dsmpd, rate->frac);685 686 rockchip_rk3399_pll_get_params(pll, &cur);687 cur.rate = 0;688 689 cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);690 if (cur_parent == PLL_MODE_NORM) {691 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);692 rate_change_remuxed = 1;693 }694 695 /* update pll values */696 writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3399_PLLCON0_FBDIV_MASK,697 RK3399_PLLCON0_FBDIV_SHIFT),698 pll->reg_base + RK3399_PLLCON(0));699 700 writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3399_PLLCON1_REFDIV_MASK,701 RK3399_PLLCON1_REFDIV_SHIFT) |702 HIWORD_UPDATE(rate->postdiv1, RK3399_PLLCON1_POSTDIV1_MASK,703 RK3399_PLLCON1_POSTDIV1_SHIFT) |704 HIWORD_UPDATE(rate->postdiv2, RK3399_PLLCON1_POSTDIV2_MASK,705 RK3399_PLLCON1_POSTDIV2_SHIFT),706 pll->reg_base + RK3399_PLLCON(1));707 708 /* xPLL CON2 is not HIWORD_MASK */709 pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2));710 pllcon &= ~(RK3399_PLLCON2_FRAC_MASK << RK3399_PLLCON2_FRAC_SHIFT);711 pllcon |= rate->frac << RK3399_PLLCON2_FRAC_SHIFT;712 writel_relaxed(pllcon, pll->reg_base + RK3399_PLLCON(2));713 714 writel_relaxed(HIWORD_UPDATE(rate->dsmpd, RK3399_PLLCON3_DSMPD_MASK,715 RK3399_PLLCON3_DSMPD_SHIFT),716 pll->reg_base + RK3399_PLLCON(3));717 718 /* wait for the pll to lock */719 ret = rockchip_rk3399_pll_wait_lock(pll);720 if (ret) {721 pr_warn("%s: pll update unsuccessful, trying to restore old params\n",722 __func__);723 rockchip_rk3399_pll_set_params(pll, &cur);724 }725 726 if (rate_change_remuxed)727 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);728 729 return ret;730}731 732static int rockchip_rk3399_pll_set_rate(struct clk_hw *hw, unsigned long drate,733 unsigned long prate)734{735 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);736 const struct rockchip_pll_rate_table *rate;737 738 pr_debug("%s: changing %s to %lu with a parent rate of %lu\n",739 __func__, __clk_get_name(hw->clk), drate, prate);740 741 /* Get required rate settings from table */742 rate = rockchip_get_pll_settings(pll, drate);743 if (!rate) {744 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,745 drate, __clk_get_name(hw->clk));746 return -EINVAL;747 }748 749 return rockchip_rk3399_pll_set_params(pll, rate);750}751 752static int rockchip_rk3399_pll_enable(struct clk_hw *hw)753{754 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);755 756 writel(HIWORD_UPDATE(0, RK3399_PLLCON3_PWRDOWN, 0),757 pll->reg_base + RK3399_PLLCON(3));758 rockchip_rk3399_pll_wait_lock(pll);759 760 return 0;761}762 763static void rockchip_rk3399_pll_disable(struct clk_hw *hw)764{765 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);766 767 writel(HIWORD_UPDATE(RK3399_PLLCON3_PWRDOWN,768 RK3399_PLLCON3_PWRDOWN, 0),769 pll->reg_base + RK3399_PLLCON(3));770}771 772static int rockchip_rk3399_pll_is_enabled(struct clk_hw *hw)773{774 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);775 u32 pllcon = readl(pll->reg_base + RK3399_PLLCON(3));776 777 return !(pllcon & RK3399_PLLCON3_PWRDOWN);778}779 780static int rockchip_rk3399_pll_init(struct clk_hw *hw)781{782 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);783 const struct rockchip_pll_rate_table *rate;784 struct rockchip_pll_rate_table cur;785 unsigned long drate;786 787 if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))788 return 0;789 790 drate = clk_hw_get_rate(hw);791 rate = rockchip_get_pll_settings(pll, drate);792 793 /* when no rate setting for the current rate, rely on clk_set_rate */794 if (!rate)795 return 0;796 797 rockchip_rk3399_pll_get_params(pll, &cur);798 799 pr_debug("%s: pll %s@%lu: Hz\n", __func__, __clk_get_name(hw->clk),800 drate);801 pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",802 cur.fbdiv, cur.postdiv1, cur.refdiv, cur.postdiv2,803 cur.dsmpd, cur.frac);804 pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",805 rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2,806 rate->dsmpd, rate->frac);807 808 if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 ||809 rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 ||810 rate->dsmpd != cur.dsmpd ||811 (!cur.dsmpd && (rate->frac != cur.frac))) {812 struct clk *parent = clk_get_parent(hw->clk);813 814 if (!parent) {815 pr_warn("%s: parent of %s not available\n",816 __func__, __clk_get_name(hw->clk));817 return 0;818 }819 820 pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",821 __func__, __clk_get_name(hw->clk));822 rockchip_rk3399_pll_set_params(pll, rate);823 }824 825 return 0;826}827 828static const struct clk_ops rockchip_rk3399_pll_clk_norate_ops = {829 .recalc_rate = rockchip_rk3399_pll_recalc_rate,830 .enable = rockchip_rk3399_pll_enable,831 .disable = rockchip_rk3399_pll_disable,832 .is_enabled = rockchip_rk3399_pll_is_enabled,833};834 835static const struct clk_ops rockchip_rk3399_pll_clk_ops = {836 .recalc_rate = rockchip_rk3399_pll_recalc_rate,837 .round_rate = rockchip_pll_round_rate,838 .set_rate = rockchip_rk3399_pll_set_rate,839 .enable = rockchip_rk3399_pll_enable,840 .disable = rockchip_rk3399_pll_disable,841 .is_enabled = rockchip_rk3399_pll_is_enabled,842 .init = rockchip_rk3399_pll_init,843};844 845/*846 * PLL used in RK3588847 */848 849#define RK3588_PLLCON(i) (i * 0x4)850#define RK3588_PLLCON0_M_MASK 0x3ff851#define RK3588_PLLCON0_M_SHIFT 0852#define RK3588_PLLCON1_P_MASK 0x3f853#define RK3588_PLLCON1_P_SHIFT 0854#define RK3588_PLLCON1_S_MASK 0x7855#define RK3588_PLLCON1_S_SHIFT 6856#define RK3588_PLLCON2_K_MASK 0xffff857#define RK3588_PLLCON2_K_SHIFT 0858#define RK3588_PLLCON1_PWRDOWN BIT(13)859#define RK3588_PLLCON6_LOCK_STATUS BIT(15)860 861static int rockchip_rk3588_pll_wait_lock(struct rockchip_clk_pll *pll)862{863 u32 pllcon;864 int ret;865 866 /*867 * Lock time typical 250, max 500 input clock cycles @24MHz868 * So define a very safe maximum of 1000us, meaning 24000 cycles.869 */870 ret = readl_relaxed_poll_timeout(pll->reg_base + RK3588_PLLCON(6),871 pllcon,872 pllcon & RK3588_PLLCON6_LOCK_STATUS,873 0, 1000);874 if (ret)875 pr_err("%s: timeout waiting for pll to lock\n", __func__);876 877 return ret;878}879 880static void rockchip_rk3588_pll_get_params(struct rockchip_clk_pll *pll,881 struct rockchip_pll_rate_table *rate)882{883 u32 pllcon;884 885 pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(0));886 rate->m = ((pllcon >> RK3588_PLLCON0_M_SHIFT) & RK3588_PLLCON0_M_MASK);887 888 pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(1));889 rate->p = ((pllcon >> RK3588_PLLCON1_P_SHIFT) & RK3588_PLLCON1_P_MASK);890 rate->s = ((pllcon >> RK3588_PLLCON1_S_SHIFT) & RK3588_PLLCON1_S_MASK);891 892 pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(2));893 rate->k = ((pllcon >> RK3588_PLLCON2_K_SHIFT) & RK3588_PLLCON2_K_MASK);894}895 896static unsigned long rockchip_rk3588_pll_recalc_rate(struct clk_hw *hw, unsigned long prate)897{898 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);899 struct rockchip_pll_rate_table cur;900 u64 rate64 = prate, postdiv;901 902 rockchip_rk3588_pll_get_params(pll, &cur);903 904 rate64 *= cur.m;905 do_div(rate64, cur.p);906 907 if (cur.k) {908 /* fractional mode */909 u64 frac_rate64 = prate * cur.k;910 911 postdiv = cur.p * 65535;912 do_div(frac_rate64, postdiv);913 rate64 += frac_rate64;914 }915 rate64 = rate64 >> cur.s;916 917 if (pll->type == pll_rk3588_ddr)918 return (unsigned long)rate64 * 2;919 else920 return (unsigned long)rate64;921}922 923static int rockchip_rk3588_pll_set_params(struct rockchip_clk_pll *pll,924 const struct rockchip_pll_rate_table *rate)925{926 const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;927 struct clk_mux *pll_mux = &pll->pll_mux;928 struct rockchip_pll_rate_table cur;929 int rate_change_remuxed = 0;930 int cur_parent;931 int ret;932 933 pr_debug("%s: rate settings for %lu p: %d, m: %d, s: %d, k: %d\n",934 __func__, rate->rate, rate->p, rate->m, rate->s, rate->k);935 936 rockchip_rk3588_pll_get_params(pll, &cur);937 cur.rate = 0;938 939 if (pll->type == pll_rk3588) {940 cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);941 if (cur_parent == PLL_MODE_NORM) {942 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);943 rate_change_remuxed = 1;944 }945 }946 947 /* set pll power down */948 writel(HIWORD_UPDATE(RK3588_PLLCON1_PWRDOWN,949 RK3588_PLLCON1_PWRDOWN, 0),950 pll->reg_base + RK3399_PLLCON(1));951 952 /* update pll values */953 writel_relaxed(HIWORD_UPDATE(rate->m, RK3588_PLLCON0_M_MASK, RK3588_PLLCON0_M_SHIFT),954 pll->reg_base + RK3399_PLLCON(0));955 956 writel_relaxed(HIWORD_UPDATE(rate->p, RK3588_PLLCON1_P_MASK, RK3588_PLLCON1_P_SHIFT) |957 HIWORD_UPDATE(rate->s, RK3588_PLLCON1_S_MASK, RK3588_PLLCON1_S_SHIFT),958 pll->reg_base + RK3399_PLLCON(1));959 960 writel_relaxed(HIWORD_UPDATE(rate->k, RK3588_PLLCON2_K_MASK, RK3588_PLLCON2_K_SHIFT),961 pll->reg_base + RK3399_PLLCON(2));962 963 /* set pll power up */964 writel(HIWORD_UPDATE(0, RK3588_PLLCON1_PWRDOWN, 0),965 pll->reg_base + RK3588_PLLCON(1));966 967 /* wait for the pll to lock */968 ret = rockchip_rk3588_pll_wait_lock(pll);969 if (ret) {970 pr_warn("%s: pll update unsuccessful, trying to restore old params\n",971 __func__);972 rockchip_rk3588_pll_set_params(pll, &cur);973 }974 975 if ((pll->type == pll_rk3588) && rate_change_remuxed)976 pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);977 978 return ret;979}980 981static int rockchip_rk3588_pll_set_rate(struct clk_hw *hw, unsigned long drate,982 unsigned long prate)983{984 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);985 const struct rockchip_pll_rate_table *rate;986 987 pr_debug("%s: changing %s to %lu with a parent rate of %lu\n",988 __func__, __clk_get_name(hw->clk), drate, prate);989 990 /* Get required rate settings from table */991 rate = rockchip_get_pll_settings(pll, drate);992 if (!rate) {993 pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,994 drate, __clk_get_name(hw->clk));995 return -EINVAL;996 }997 998 return rockchip_rk3588_pll_set_params(pll, rate);999}1000 1001static int rockchip_rk3588_pll_enable(struct clk_hw *hw)1002{1003 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);1004 1005 writel(HIWORD_UPDATE(0, RK3588_PLLCON1_PWRDOWN, 0),1006 pll->reg_base + RK3588_PLLCON(1));1007 rockchip_rk3588_pll_wait_lock(pll);1008 1009 return 0;1010}1011 1012static void rockchip_rk3588_pll_disable(struct clk_hw *hw)1013{1014 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);1015 1016 writel(HIWORD_UPDATE(RK3588_PLLCON1_PWRDOWN, RK3588_PLLCON1_PWRDOWN, 0),1017 pll->reg_base + RK3588_PLLCON(1));1018}1019 1020static int rockchip_rk3588_pll_is_enabled(struct clk_hw *hw)1021{1022 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);1023 u32 pllcon = readl(pll->reg_base + RK3588_PLLCON(1));1024 1025 return !(pllcon & RK3588_PLLCON1_PWRDOWN);1026}1027 1028static int rockchip_rk3588_pll_init(struct clk_hw *hw)1029{1030 struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);1031 1032 if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))1033 return 0;1034 1035 return 0;1036}1037 1038static const struct clk_ops rockchip_rk3588_pll_clk_norate_ops = {1039 .recalc_rate = rockchip_rk3588_pll_recalc_rate,1040 .enable = rockchip_rk3588_pll_enable,1041 .disable = rockchip_rk3588_pll_disable,1042 .is_enabled = rockchip_rk3588_pll_is_enabled,1043};1044 1045static const struct clk_ops rockchip_rk3588_pll_clk_ops = {1046 .recalc_rate = rockchip_rk3588_pll_recalc_rate,1047 .round_rate = rockchip_pll_round_rate,1048 .set_rate = rockchip_rk3588_pll_set_rate,1049 .enable = rockchip_rk3588_pll_enable,1050 .disable = rockchip_rk3588_pll_disable,1051 .is_enabled = rockchip_rk3588_pll_is_enabled,1052 .init = rockchip_rk3588_pll_init,1053};1054 1055/*1056 * Common registering of pll clocks1057 */1058 1059struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,1060 enum rockchip_pll_type pll_type,1061 const char *name, const char *const *parent_names,1062 u8 num_parents, int con_offset, int grf_lock_offset,1063 int lock_shift, int mode_offset, int mode_shift,1064 struct rockchip_pll_rate_table *rate_table,1065 unsigned long flags, u8 clk_pll_flags)1066{1067 const char *pll_parents[3];1068 struct clk_init_data init;1069 struct rockchip_clk_pll *pll;1070 struct clk_mux *pll_mux;1071 struct clk *pll_clk, *mux_clk;1072 char pll_name[20];1073 1074 if ((pll_type != pll_rk3328 && num_parents != 2) ||1075 (pll_type == pll_rk3328 && num_parents != 1)) {1076 pr_err("%s: needs two parent clocks\n", __func__);1077 return ERR_PTR(-EINVAL);1078 }1079 1080 /* name the actual pll */1081 snprintf(pll_name, sizeof(pll_name), "pll_%s", name);1082 1083 pll = kzalloc(sizeof(*pll), GFP_KERNEL);1084 if (!pll)1085 return ERR_PTR(-ENOMEM);1086 1087 /* create the mux on top of the real pll */1088 pll->pll_mux_ops = &clk_mux_ops;1089 pll_mux = &pll->pll_mux;1090 pll_mux->reg = ctx->reg_base + mode_offset;1091 pll_mux->shift = mode_shift;1092 if (pll_type == pll_rk3328)1093 pll_mux->mask = PLL_RK3328_MODE_MASK;1094 else1095 pll_mux->mask = PLL_MODE_MASK;1096 pll_mux->flags = 0;1097 pll_mux->lock = &ctx->lock;1098 pll_mux->hw.init = &init;1099 1100 if (pll_type == pll_rk3036 ||1101 pll_type == pll_rk3066 ||1102 pll_type == pll_rk3328 ||1103 pll_type == pll_rk3399 ||1104 pll_type == pll_rk3588)1105 pll_mux->flags |= CLK_MUX_HIWORD_MASK;1106 1107 /* the actual muxing is xin24m, pll-output, xin32k */1108 pll_parents[0] = parent_names[0];1109 pll_parents[1] = pll_name;1110 pll_parents[2] = parent_names[1];1111 1112 init.name = name;1113 init.flags = CLK_SET_RATE_PARENT;1114 init.ops = pll->pll_mux_ops;1115 init.parent_names = pll_parents;1116 if (pll_type == pll_rk3328)1117 init.num_parents = 2;1118 else1119 init.num_parents = ARRAY_SIZE(pll_parents);1120 1121 mux_clk = clk_register(NULL, &pll_mux->hw);1122 if (IS_ERR(mux_clk))1123 goto err_mux;1124 1125 /* now create the actual pll */1126 init.name = pll_name;1127 1128 /* keep all plls untouched for now */1129 init.flags = flags | CLK_IGNORE_UNUSED;1130 1131 init.parent_names = &parent_names[0];1132 init.num_parents = 1;1133 1134 if (rate_table) {1135 int len;1136 1137 /* find count of rates in rate_table */1138 for (len = 0; rate_table[len].rate != 0; )1139 len++;1140 1141 pll->rate_count = len;1142 pll->rate_table = kmemdup_array(rate_table,1143 pll->rate_count,1144 sizeof(*pll->rate_table),1145 GFP_KERNEL);1146 WARN(!pll->rate_table,1147 "%s: could not allocate rate table for %s\n",1148 __func__, name);1149 }1150 1151 switch (pll_type) {1152 case pll_rk3036:1153 case pll_rk3328:1154 if (!pll->rate_table)1155 init.ops = &rockchip_rk3036_pll_clk_norate_ops;1156 else1157 init.ops = &rockchip_rk3036_pll_clk_ops;1158 break;1159 case pll_rk3066:1160 if (!pll->rate_table || IS_ERR(ctx->grf))1161 init.ops = &rockchip_rk3066_pll_clk_norate_ops;1162 else1163 init.ops = &rockchip_rk3066_pll_clk_ops;1164 break;1165 case pll_rk3399:1166 if (!pll->rate_table)1167 init.ops = &rockchip_rk3399_pll_clk_norate_ops;1168 else1169 init.ops = &rockchip_rk3399_pll_clk_ops;1170 break;1171 case pll_rk3588:1172 case pll_rk3588_core:1173 case pll_rk3588_ddr:1174 if (!pll->rate_table)1175 init.ops = &rockchip_rk3588_pll_clk_norate_ops;1176 else1177 init.ops = &rockchip_rk3588_pll_clk_ops;1178 init.flags = flags;1179 break;1180 default:1181 pr_warn("%s: Unknown pll type for pll clk %s\n",1182 __func__, name);1183 }1184 1185 pll->hw.init = &init;1186 pll->type = pll_type;1187 pll->reg_base = ctx->reg_base + con_offset;1188 pll->lock_offset = grf_lock_offset;1189 pll->lock_shift = lock_shift;1190 pll->flags = clk_pll_flags;1191 pll->lock = &ctx->lock;1192 pll->ctx = ctx;1193 1194 pll_clk = clk_register(NULL, &pll->hw);1195 if (IS_ERR(pll_clk)) {1196 pr_err("%s: failed to register pll clock %s : %ld\n",1197 __func__, name, PTR_ERR(pll_clk));1198 goto err_pll;1199 }1200 1201 return mux_clk;1202 1203err_pll:1204 kfree(pll->rate_table);1205 clk_unregister(mux_clk);1206 mux_clk = pll_clk;1207err_mux:1208 kfree(pll);1209 return mux_clk;1210}1211