2759 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.4 * Copyright (c) 2021, 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.5 */6 7#include <linux/kernel.h>8#include <linux/export.h>9#include <linux/clk-provider.h>10#include <linux/regmap.h>11#include <linux/delay.h>12 13#include "clk-alpha-pll.h"14#include "common.h"15 16#define PLL_MODE(p) ((p)->offset + 0x0)17# define PLL_OUTCTRL BIT(0)18# define PLL_BYPASSNL BIT(1)19# define PLL_RESET_N BIT(2)20# define PLL_OFFLINE_REQ BIT(7)21# define PLL_LOCK_COUNT_SHIFT 822# define PLL_LOCK_COUNT_MASK 0x3f23# define PLL_BIAS_COUNT_SHIFT 1424# define PLL_BIAS_COUNT_MASK 0x3f25# define PLL_VOTE_FSM_ENA BIT(20)26# define PLL_FSM_ENA BIT(20)27# define PLL_VOTE_FSM_RESET BIT(21)28# define PLL_UPDATE BIT(22)29# define PLL_UPDATE_BYPASS BIT(23)30# define PLL_FSM_LEGACY_MODE BIT(24)31# define PLL_OFFLINE_ACK BIT(28)32# define ALPHA_PLL_ACK_LATCH BIT(29)33# define PLL_ACTIVE_FLAG BIT(30)34# define PLL_LOCK_DET BIT(31)35 36#define PLL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_L_VAL])37#define PLL_CAL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_L_VAL])38#define PLL_ALPHA_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL])39#define PLL_ALPHA_VAL_U(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL_U])40 41#define PLL_USER_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL])42# define PLL_POST_DIV_SHIFT 843# define PLL_POST_DIV_MASK(p) GENMASK((p)->width ? (p)->width - 1 : 3, 0)44# define PLL_ALPHA_MSB BIT(15)45# define PLL_ALPHA_EN BIT(24)46# define PLL_ALPHA_MODE BIT(25)47# define PLL_VCO_SHIFT 2048# define PLL_VCO_MASK 0x349 50#define PLL_USER_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U])51#define PLL_USER_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U1])52 53#define PLL_CONFIG_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL])54#define PLL_CONFIG_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U])55#define PLL_CONFIG_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U1])56#define PLL_CONFIG_CTL_U2(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U2])57#define PLL_TEST_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL])58#define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U])59#define PLL_TEST_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U1])60#define PLL_TEST_CTL_U2(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U2])61#define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS])62#define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE])63#define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC])64 65const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {66 [CLK_ALPHA_PLL_TYPE_DEFAULT] = {67 [PLL_OFF_L_VAL] = 0x04,68 [PLL_OFF_ALPHA_VAL] = 0x08,69 [PLL_OFF_ALPHA_VAL_U] = 0x0c,70 [PLL_OFF_USER_CTL] = 0x10,71 [PLL_OFF_USER_CTL_U] = 0x14,72 [PLL_OFF_CONFIG_CTL] = 0x18,73 [PLL_OFF_TEST_CTL] = 0x1c,74 [PLL_OFF_TEST_CTL_U] = 0x20,75 [PLL_OFF_STATUS] = 0x24,76 },77 [CLK_ALPHA_PLL_TYPE_HUAYRA] = {78 [PLL_OFF_L_VAL] = 0x04,79 [PLL_OFF_ALPHA_VAL] = 0x08,80 [PLL_OFF_USER_CTL] = 0x10,81 [PLL_OFF_CONFIG_CTL] = 0x14,82 [PLL_OFF_CONFIG_CTL_U] = 0x18,83 [PLL_OFF_TEST_CTL] = 0x1c,84 [PLL_OFF_TEST_CTL_U] = 0x20,85 [PLL_OFF_STATUS] = 0x24,86 },87 [CLK_ALPHA_PLL_TYPE_HUAYRA_APSS] = {88 [PLL_OFF_L_VAL] = 0x08,89 [PLL_OFF_ALPHA_VAL] = 0x10,90 [PLL_OFF_USER_CTL] = 0x18,91 [PLL_OFF_CONFIG_CTL] = 0x20,92 [PLL_OFF_CONFIG_CTL_U] = 0x24,93 [PLL_OFF_STATUS] = 0x28,94 [PLL_OFF_TEST_CTL] = 0x30,95 [PLL_OFF_TEST_CTL_U] = 0x34,96 },97 [CLK_ALPHA_PLL_TYPE_HUAYRA_2290] = {98 [PLL_OFF_L_VAL] = 0x04,99 [PLL_OFF_ALPHA_VAL] = 0x08,100 [PLL_OFF_USER_CTL] = 0x0c,101 [PLL_OFF_CONFIG_CTL] = 0x10,102 [PLL_OFF_CONFIG_CTL_U] = 0x14,103 [PLL_OFF_CONFIG_CTL_U1] = 0x18,104 [PLL_OFF_TEST_CTL] = 0x1c,105 [PLL_OFF_TEST_CTL_U] = 0x20,106 [PLL_OFF_TEST_CTL_U1] = 0x24,107 [PLL_OFF_OPMODE] = 0x28,108 [PLL_OFF_STATUS] = 0x38,109 },110 [CLK_ALPHA_PLL_TYPE_BRAMMO] = {111 [PLL_OFF_L_VAL] = 0x04,112 [PLL_OFF_ALPHA_VAL] = 0x08,113 [PLL_OFF_ALPHA_VAL_U] = 0x0c,114 [PLL_OFF_USER_CTL] = 0x10,115 [PLL_OFF_CONFIG_CTL] = 0x18,116 [PLL_OFF_TEST_CTL] = 0x1c,117 [PLL_OFF_STATUS] = 0x24,118 },119 [CLK_ALPHA_PLL_TYPE_FABIA] = {120 [PLL_OFF_L_VAL] = 0x04,121 [PLL_OFF_USER_CTL] = 0x0c,122 [PLL_OFF_USER_CTL_U] = 0x10,123 [PLL_OFF_CONFIG_CTL] = 0x14,124 [PLL_OFF_CONFIG_CTL_U] = 0x18,125 [PLL_OFF_TEST_CTL] = 0x1c,126 [PLL_OFF_TEST_CTL_U] = 0x20,127 [PLL_OFF_STATUS] = 0x24,128 [PLL_OFF_OPMODE] = 0x2c,129 [PLL_OFF_FRAC] = 0x38,130 },131 [CLK_ALPHA_PLL_TYPE_TRION] = {132 [PLL_OFF_L_VAL] = 0x04,133 [PLL_OFF_CAL_L_VAL] = 0x08,134 [PLL_OFF_USER_CTL] = 0x0c,135 [PLL_OFF_USER_CTL_U] = 0x10,136 [PLL_OFF_USER_CTL_U1] = 0x14,137 [PLL_OFF_CONFIG_CTL] = 0x18,138 [PLL_OFF_CONFIG_CTL_U] = 0x1c,139 [PLL_OFF_CONFIG_CTL_U1] = 0x20,140 [PLL_OFF_TEST_CTL] = 0x24,141 [PLL_OFF_TEST_CTL_U] = 0x28,142 [PLL_OFF_TEST_CTL_U1] = 0x2c,143 [PLL_OFF_STATUS] = 0x30,144 [PLL_OFF_OPMODE] = 0x38,145 [PLL_OFF_ALPHA_VAL] = 0x40,146 },147 [CLK_ALPHA_PLL_TYPE_AGERA] = {148 [PLL_OFF_L_VAL] = 0x04,149 [PLL_OFF_ALPHA_VAL] = 0x08,150 [PLL_OFF_USER_CTL] = 0x0c,151 [PLL_OFF_CONFIG_CTL] = 0x10,152 [PLL_OFF_CONFIG_CTL_U] = 0x14,153 [PLL_OFF_TEST_CTL] = 0x18,154 [PLL_OFF_TEST_CTL_U] = 0x1c,155 [PLL_OFF_STATUS] = 0x2c,156 },157 [CLK_ALPHA_PLL_TYPE_ZONDA] = {158 [PLL_OFF_L_VAL] = 0x04,159 [PLL_OFF_ALPHA_VAL] = 0x08,160 [PLL_OFF_USER_CTL] = 0x0c,161 [PLL_OFF_CONFIG_CTL] = 0x10,162 [PLL_OFF_CONFIG_CTL_U] = 0x14,163 [PLL_OFF_CONFIG_CTL_U1] = 0x18,164 [PLL_OFF_TEST_CTL] = 0x1c,165 [PLL_OFF_TEST_CTL_U] = 0x20,166 [PLL_OFF_TEST_CTL_U1] = 0x24,167 [PLL_OFF_OPMODE] = 0x28,168 [PLL_OFF_STATUS] = 0x38,169 },170 [CLK_ALPHA_PLL_TYPE_LUCID_EVO] = {171 [PLL_OFF_OPMODE] = 0x04,172 [PLL_OFF_STATUS] = 0x0c,173 [PLL_OFF_L_VAL] = 0x10,174 [PLL_OFF_ALPHA_VAL] = 0x14,175 [PLL_OFF_USER_CTL] = 0x18,176 [PLL_OFF_USER_CTL_U] = 0x1c,177 [PLL_OFF_CONFIG_CTL] = 0x20,178 [PLL_OFF_CONFIG_CTL_U] = 0x24,179 [PLL_OFF_CONFIG_CTL_U1] = 0x28,180 [PLL_OFF_TEST_CTL] = 0x2c,181 [PLL_OFF_TEST_CTL_U] = 0x30,182 [PLL_OFF_TEST_CTL_U1] = 0x34,183 },184 [CLK_ALPHA_PLL_TYPE_LUCID_OLE] = {185 [PLL_OFF_OPMODE] = 0x04,186 [PLL_OFF_STATE] = 0x08,187 [PLL_OFF_STATUS] = 0x0c,188 [PLL_OFF_L_VAL] = 0x10,189 [PLL_OFF_ALPHA_VAL] = 0x14,190 [PLL_OFF_USER_CTL] = 0x18,191 [PLL_OFF_USER_CTL_U] = 0x1c,192 [PLL_OFF_CONFIG_CTL] = 0x20,193 [PLL_OFF_CONFIG_CTL_U] = 0x24,194 [PLL_OFF_CONFIG_CTL_U1] = 0x28,195 [PLL_OFF_TEST_CTL] = 0x2c,196 [PLL_OFF_TEST_CTL_U] = 0x30,197 [PLL_OFF_TEST_CTL_U1] = 0x34,198 [PLL_OFF_TEST_CTL_U2] = 0x38,199 },200 [CLK_ALPHA_PLL_TYPE_RIVIAN_EVO] = {201 [PLL_OFF_OPMODE] = 0x04,202 [PLL_OFF_STATUS] = 0x0c,203 [PLL_OFF_L_VAL] = 0x10,204 [PLL_OFF_USER_CTL] = 0x14,205 [PLL_OFF_USER_CTL_U] = 0x18,206 [PLL_OFF_CONFIG_CTL] = 0x1c,207 [PLL_OFF_CONFIG_CTL_U] = 0x20,208 [PLL_OFF_CONFIG_CTL_U1] = 0x24,209 [PLL_OFF_TEST_CTL] = 0x28,210 [PLL_OFF_TEST_CTL_U] = 0x2c,211 },212 [CLK_ALPHA_PLL_TYPE_DEFAULT_EVO] = {213 [PLL_OFF_L_VAL] = 0x04,214 [PLL_OFF_ALPHA_VAL] = 0x08,215 [PLL_OFF_ALPHA_VAL_U] = 0x0c,216 [PLL_OFF_TEST_CTL] = 0x10,217 [PLL_OFF_TEST_CTL_U] = 0x14,218 [PLL_OFF_USER_CTL] = 0x18,219 [PLL_OFF_USER_CTL_U] = 0x1c,220 [PLL_OFF_CONFIG_CTL] = 0x20,221 [PLL_OFF_STATUS] = 0x24,222 },223 [CLK_ALPHA_PLL_TYPE_BRAMMO_EVO] = {224 [PLL_OFF_L_VAL] = 0x04,225 [PLL_OFF_ALPHA_VAL] = 0x08,226 [PLL_OFF_ALPHA_VAL_U] = 0x0c,227 [PLL_OFF_TEST_CTL] = 0x10,228 [PLL_OFF_TEST_CTL_U] = 0x14,229 [PLL_OFF_USER_CTL] = 0x18,230 [PLL_OFF_CONFIG_CTL] = 0x1C,231 [PLL_OFF_STATUS] = 0x20,232 },233 [CLK_ALPHA_PLL_TYPE_STROMER] = {234 [PLL_OFF_L_VAL] = 0x08,235 [PLL_OFF_ALPHA_VAL] = 0x10,236 [PLL_OFF_ALPHA_VAL_U] = 0x14,237 [PLL_OFF_USER_CTL] = 0x18,238 [PLL_OFF_USER_CTL_U] = 0x1c,239 [PLL_OFF_CONFIG_CTL] = 0x20,240 [PLL_OFF_STATUS] = 0x28,241 [PLL_OFF_TEST_CTL] = 0x30,242 [PLL_OFF_TEST_CTL_U] = 0x34,243 },244 [CLK_ALPHA_PLL_TYPE_STROMER_PLUS] = {245 [PLL_OFF_L_VAL] = 0x04,246 [PLL_OFF_USER_CTL] = 0x08,247 [PLL_OFF_USER_CTL_U] = 0x0c,248 [PLL_OFF_CONFIG_CTL] = 0x10,249 [PLL_OFF_TEST_CTL] = 0x14,250 [PLL_OFF_TEST_CTL_U] = 0x18,251 [PLL_OFF_STATUS] = 0x1c,252 [PLL_OFF_ALPHA_VAL] = 0x24,253 [PLL_OFF_ALPHA_VAL_U] = 0x28,254 },255 [CLK_ALPHA_PLL_TYPE_ZONDA_OLE] = {256 [PLL_OFF_L_VAL] = 0x04,257 [PLL_OFF_ALPHA_VAL] = 0x08,258 [PLL_OFF_USER_CTL] = 0x0c,259 [PLL_OFF_USER_CTL_U] = 0x10,260 [PLL_OFF_CONFIG_CTL] = 0x14,261 [PLL_OFF_CONFIG_CTL_U] = 0x18,262 [PLL_OFF_CONFIG_CTL_U1] = 0x1c,263 [PLL_OFF_CONFIG_CTL_U2] = 0x20,264 [PLL_OFF_TEST_CTL] = 0x24,265 [PLL_OFF_TEST_CTL_U] = 0x28,266 [PLL_OFF_TEST_CTL_U1] = 0x2c,267 [PLL_OFF_OPMODE] = 0x30,268 [PLL_OFF_STATUS] = 0x3c,269 },270};271EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);272 273/*274 * Even though 40 bits are present, use only 32 for ease of calculation.275 */276#define ALPHA_REG_BITWIDTH 40277#define ALPHA_REG_16BIT_WIDTH 16278#define ALPHA_BITWIDTH 32U279#define ALPHA_SHIFT(w) min(w, ALPHA_BITWIDTH)280 281#define ALPHA_PLL_STATUS_REG_SHIFT 8282 283#define PLL_HUAYRA_M_WIDTH 8284#define PLL_HUAYRA_M_SHIFT 8285#define PLL_HUAYRA_M_MASK 0xff286#define PLL_HUAYRA_N_SHIFT 0287#define PLL_HUAYRA_N_MASK 0xff288#define PLL_HUAYRA_ALPHA_WIDTH 16289 290#define PLL_STANDBY 0x0291#define PLL_RUN 0x1292#define PLL_OUT_MASK 0x7293#define PLL_RATE_MARGIN 500294 295/* TRION PLL specific settings and offsets */296#define TRION_PLL_CAL_VAL 0x44297#define TRION_PCAL_DONE BIT(26)298 299/* LUCID PLL specific settings and offsets */300#define LUCID_PCAL_DONE BIT(27)301 302/* LUCID 5LPE PLL specific settings and offsets */303#define LUCID_5LPE_PCAL_DONE BIT(11)304#define LUCID_5LPE_ALPHA_PLL_ACK_LATCH BIT(13)305#define LUCID_5LPE_PLL_LATCH_INPUT BIT(14)306#define LUCID_5LPE_ENABLE_VOTE_RUN BIT(21)307 308/* LUCID EVO PLL specific settings and offsets */309#define LUCID_EVO_PCAL_NOT_DONE BIT(8)310#define LUCID_EVO_ENABLE_VOTE_RUN BIT(25)311#define LUCID_EVO_PLL_L_VAL_MASK GENMASK(15, 0)312#define LUCID_EVO_PLL_CAL_L_VAL_SHIFT 16313#define LUCID_OLE_PLL_RINGOSC_CAL_L_VAL_SHIFT 24314 315/* ZONDA PLL specific */316#define ZONDA_PLL_OUT_MASK 0xf317#define ZONDA_STAY_IN_CFA BIT(16)318#define ZONDA_PLL_FREQ_LOCK_DET BIT(29)319 320#define pll_alpha_width(p) \321 ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \322 ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH)323 324#define pll_has_64bit_config(p) ((PLL_CONFIG_CTL_U(p) - PLL_CONFIG_CTL(p)) == 4)325 326#define to_clk_alpha_pll(_hw) container_of(to_clk_regmap(_hw), \327 struct clk_alpha_pll, clkr)328 329#define to_clk_alpha_pll_postdiv(_hw) container_of(to_clk_regmap(_hw), \330 struct clk_alpha_pll_postdiv, clkr)331 332static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,333 const char *action)334{335 u32 val;336 int count;337 int ret;338 const char *name = clk_hw_get_name(&pll->clkr.hw);339 340 ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);341 if (ret)342 return ret;343 344 for (count = 200; count > 0; count--) {345 ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);346 if (ret)347 return ret;348 if (inverse && !(val & mask))349 return 0;350 else if ((val & mask) == mask)351 return 0;352 353 udelay(1);354 }355 356 WARN(1, "%s failed to %s!\n", name, action);357 return -ETIMEDOUT;358}359 360#define wait_for_pll_enable_active(pll) \361 wait_for_pll(pll, PLL_ACTIVE_FLAG, 0, "enable")362 363#define wait_for_pll_enable_lock(pll) \364 wait_for_pll(pll, PLL_LOCK_DET, 0, "enable")365 366#define wait_for_zonda_pll_freq_lock(pll) \367 wait_for_pll(pll, ZONDA_PLL_FREQ_LOCK_DET, 0, "freq enable")368 369#define wait_for_pll_disable(pll) \370 wait_for_pll(pll, PLL_ACTIVE_FLAG, 1, "disable")371 372#define wait_for_pll_offline(pll) \373 wait_for_pll(pll, PLL_OFFLINE_ACK, 0, "offline")374 375#define wait_for_pll_update(pll) \376 wait_for_pll(pll, PLL_UPDATE, 1, "update")377 378#define wait_for_pll_update_ack_set(pll) \379 wait_for_pll(pll, ALPHA_PLL_ACK_LATCH, 0, "update_ack_set")380 381#define wait_for_pll_update_ack_clear(pll) \382 wait_for_pll(pll, ALPHA_PLL_ACK_LATCH, 1, "update_ack_clear")383 384static void clk_alpha_pll_write_config(struct regmap *regmap, unsigned int reg,385 unsigned int val)386{387 if (val)388 regmap_write(regmap, reg, val);389}390 391void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,392 const struct alpha_pll_config *config)393{394 u32 val, mask;395 396 regmap_write(regmap, PLL_L_VAL(pll), config->l);397 regmap_write(regmap, PLL_ALPHA_VAL(pll), config->alpha);398 regmap_write(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val);399 400 if (pll_has_64bit_config(pll))401 regmap_write(regmap, PLL_CONFIG_CTL_U(pll),402 config->config_ctl_hi_val);403 404 if (pll_alpha_width(pll) > 32)405 regmap_write(regmap, PLL_ALPHA_VAL_U(pll), config->alpha_hi);406 407 val = config->main_output_mask;408 val |= config->aux_output_mask;409 val |= config->aux2_output_mask;410 val |= config->early_output_mask;411 val |= config->pre_div_val;412 val |= config->post_div_val;413 val |= config->vco_val;414 val |= config->alpha_en_mask;415 val |= config->alpha_mode_mask;416 417 mask = config->main_output_mask;418 mask |= config->aux_output_mask;419 mask |= config->aux2_output_mask;420 mask |= config->early_output_mask;421 mask |= config->pre_div_mask;422 mask |= config->post_div_mask;423 mask |= config->vco_mask;424 425 regmap_update_bits(regmap, PLL_USER_CTL(pll), mask, val);426 427 if (config->test_ctl_mask)428 regmap_update_bits(regmap, PLL_TEST_CTL(pll),429 config->test_ctl_mask,430 config->test_ctl_val);431 else432 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll),433 config->test_ctl_val);434 435 if (config->test_ctl_hi_mask)436 regmap_update_bits(regmap, PLL_TEST_CTL_U(pll),437 config->test_ctl_hi_mask,438 config->test_ctl_hi_val);439 else440 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll),441 config->test_ctl_hi_val);442 443 if (pll->flags & SUPPORTS_FSM_MODE)444 qcom_pll_set_fsm_mode(regmap, PLL_MODE(pll), 6, 0);445}446EXPORT_SYMBOL_GPL(clk_alpha_pll_configure);447 448static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)449{450 int ret;451 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);452 u32 val;453 454 ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);455 if (ret)456 return ret;457 458 val |= PLL_FSM_ENA;459 460 if (pll->flags & SUPPORTS_OFFLINE_REQ)461 val &= ~PLL_OFFLINE_REQ;462 463 ret = regmap_write(pll->clkr.regmap, PLL_MODE(pll), val);464 if (ret)465 return ret;466 467 /* Make sure enable request goes through before waiting for update */468 mb();469 470 return wait_for_pll_enable_active(pll);471}472 473static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw)474{475 int ret;476 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);477 u32 val;478 479 ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);480 if (ret)481 return;482 483 if (pll->flags & SUPPORTS_OFFLINE_REQ) {484 ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),485 PLL_OFFLINE_REQ, PLL_OFFLINE_REQ);486 if (ret)487 return;488 489 ret = wait_for_pll_offline(pll);490 if (ret)491 return;492 }493 494 /* Disable hwfsm */495 ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),496 PLL_FSM_ENA, 0);497 if (ret)498 return;499 500 wait_for_pll_disable(pll);501}502 503static int pll_is_enabled(struct clk_hw *hw, u32 mask)504{505 int ret;506 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);507 u32 val;508 509 ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);510 if (ret)511 return ret;512 513 return !!(val & mask);514}515 516static int clk_alpha_pll_hwfsm_is_enabled(struct clk_hw *hw)517{518 return pll_is_enabled(hw, PLL_ACTIVE_FLAG);519}520 521static int clk_alpha_pll_is_enabled(struct clk_hw *hw)522{523 return pll_is_enabled(hw, PLL_LOCK_DET);524}525 526static int clk_alpha_pll_enable(struct clk_hw *hw)527{528 int ret;529 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);530 u32 val, mask;531 532 mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL;533 ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);534 if (ret)535 return ret;536 537 /* If in FSM mode, just vote for it */538 if (val & PLL_VOTE_FSM_ENA) {539 ret = clk_enable_regmap(hw);540 if (ret)541 return ret;542 return wait_for_pll_enable_active(pll);543 }544 545 /* Skip if already enabled */546 if ((val & mask) == mask)547 return 0;548 549 ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),550 PLL_BYPASSNL, PLL_BYPASSNL);551 if (ret)552 return ret;553 554 /*555 * H/W requires a 5us delay between disabling the bypass and556 * de-asserting the reset.557 */558 mb();559 udelay(5);560 561 ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),562 PLL_RESET_N, PLL_RESET_N);563 if (ret)564 return ret;565 566 ret = wait_for_pll_enable_lock(pll);567 if (ret)568 return ret;569 570 ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll),571 PLL_OUTCTRL, PLL_OUTCTRL);572 573 /* Ensure that the write above goes through before returning. */574 mb();575 return ret;576}577 578static void clk_alpha_pll_disable(struct clk_hw *hw)579{580 int ret;581 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);582 u32 val, mask;583 584 ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);585 if (ret)586 return;587 588 /* If in FSM mode, just unvote it */589 if (val & PLL_VOTE_FSM_ENA) {590 clk_disable_regmap(hw);591 return;592 }593 594 mask = PLL_OUTCTRL;595 regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), mask, 0);596 597 /* Delay of 2 output clock ticks required until output is disabled */598 mb();599 udelay(1);600 601 mask = PLL_RESET_N | PLL_BYPASSNL;602 regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), mask, 0);603}604 605static unsigned long606alpha_pll_calc_rate(u64 prate, u32 l, u32 a, u32 alpha_width)607{608 return (prate * l) + ((prate * a) >> ALPHA_SHIFT(alpha_width));609}610 611static unsigned long612alpha_pll_round_rate(unsigned long rate, unsigned long prate, u32 *l, u64 *a,613 u32 alpha_width)614{615 u64 remainder;616 u64 quotient;617 618 quotient = rate;619 remainder = do_div(quotient, prate);620 *l = quotient;621 622 if (!remainder) {623 *a = 0;624 return rate;625 }626 627 /* Upper ALPHA_BITWIDTH bits of Alpha */628 quotient = remainder << ALPHA_SHIFT(alpha_width);629 630 remainder = do_div(quotient, prate);631 632 if (remainder)633 quotient++;634 635 *a = quotient;636 return alpha_pll_calc_rate(prate, *l, *a, alpha_width);637}638 639static const struct pll_vco *640alpha_pll_find_vco(const struct clk_alpha_pll *pll, unsigned long rate)641{642 const struct pll_vco *v = pll->vco_table;643 const struct pll_vco *end = v + pll->num_vco;644 645 for (; v < end; v++)646 if (rate >= v->min_freq && rate <= v->max_freq)647 return v;648 649 return NULL;650}651 652static unsigned long653clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)654{655 u32 l, low, high, ctl;656 u64 a = 0, prate = parent_rate;657 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);658 u32 alpha_width = pll_alpha_width(pll);659 660 regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);661 662 regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);663 if (ctl & PLL_ALPHA_EN) {664 regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &low);665 if (alpha_width > 32) {666 regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll),667 &high);668 a = (u64)high << 32 | low;669 } else {670 a = low & GENMASK(alpha_width - 1, 0);671 }672 673 if (alpha_width > ALPHA_BITWIDTH)674 a >>= alpha_width - ALPHA_BITWIDTH;675 }676 677 return alpha_pll_calc_rate(prate, l, a, alpha_width);678}679 680 681static int __clk_alpha_pll_update_latch(struct clk_alpha_pll *pll)682{683 int ret;684 u32 mode;685 686 regmap_read(pll->clkr.regmap, PLL_MODE(pll), &mode);687 688 /* Latch the input to the PLL */689 regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_UPDATE,690 PLL_UPDATE);691 692 /* Wait for 2 reference cycle before checking ACK bit */693 udelay(1);694 695 /*696 * PLL will latch the new L, Alpha and freq control word.697 * PLL will respond by raising PLL_ACK_LATCH output when new programming698 * has been latched in and PLL is being updated. When699 * UPDATE_LOGIC_BYPASS bit is not set, PLL_UPDATE will be cleared700 * automatically by hardware when PLL_ACK_LATCH is asserted by PLL.701 */702 if (mode & PLL_UPDATE_BYPASS) {703 ret = wait_for_pll_update_ack_set(pll);704 if (ret)705 return ret;706 707 regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_UPDATE, 0);708 } else {709 ret = wait_for_pll_update(pll);710 if (ret)711 return ret;712 }713 714 ret = wait_for_pll_update_ack_clear(pll);715 if (ret)716 return ret;717 718 /* Wait for PLL output to stabilize */719 udelay(10);720 721 return 0;722}723 724static int clk_alpha_pll_update_latch(struct clk_alpha_pll *pll,725 int (*is_enabled)(struct clk_hw *))726{727 if (!is_enabled(&pll->clkr.hw) ||728 !(pll->flags & SUPPORTS_DYNAMIC_UPDATE))729 return 0;730 731 return __clk_alpha_pll_update_latch(pll);732}733 734static int __clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,735 unsigned long prate,736 int (*is_enabled)(struct clk_hw *))737{738 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);739 const struct pll_vco *vco;740 u32 l, alpha_width = pll_alpha_width(pll);741 u64 a;742 743 rate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);744 vco = alpha_pll_find_vco(pll, rate);745 if (pll->vco_table && !vco) {746 pr_err("%s: alpha pll not in a valid vco range\n",747 clk_hw_get_name(hw));748 return -EINVAL;749 }750 751 regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);752 753 if (alpha_width > ALPHA_BITWIDTH)754 a <<= alpha_width - ALPHA_BITWIDTH;755 756 if (alpha_width > 32)757 regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32);758 759 regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);760 761 if (vco) {762 regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),763 PLL_VCO_MASK << PLL_VCO_SHIFT,764 vco->val << PLL_VCO_SHIFT);765 }766 767 regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),768 PLL_ALPHA_EN, PLL_ALPHA_EN);769 770 return clk_alpha_pll_update_latch(pll, is_enabled);771}772 773static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,774 unsigned long prate)775{776 return __clk_alpha_pll_set_rate(hw, rate, prate,777 clk_alpha_pll_is_enabled);778}779 780static int clk_alpha_pll_hwfsm_set_rate(struct clk_hw *hw, unsigned long rate,781 unsigned long prate)782{783 return __clk_alpha_pll_set_rate(hw, rate, prate,784 clk_alpha_pll_hwfsm_is_enabled);785}786 787static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,788 unsigned long *prate)789{790 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);791 u32 l, alpha_width = pll_alpha_width(pll);792 u64 a;793 unsigned long min_freq, max_freq;794 795 rate = alpha_pll_round_rate(rate, *prate, &l, &a, alpha_width);796 if (!pll->vco_table || alpha_pll_find_vco(pll, rate))797 return rate;798 799 min_freq = pll->vco_table[0].min_freq;800 max_freq = pll->vco_table[pll->num_vco - 1].max_freq;801 802 return clamp(rate, min_freq, max_freq);803}804 805void clk_huayra_2290_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,806 const struct alpha_pll_config *config)807{808 u32 val;809 810 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val);811 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val);812 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val);813 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val);814 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val);815 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val);816 clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l);817 clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha);818 clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), config->user_ctl_val);819 820 /* Set PLL_BYPASSNL */821 regmap_update_bits(regmap, PLL_MODE(pll), PLL_BYPASSNL, PLL_BYPASSNL);822 regmap_read(regmap, PLL_MODE(pll), &val);823 824 /* Wait 5 us between setting BYPASS and deasserting reset */825 udelay(5);826 827 /* Take PLL out from reset state */828 regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);829 regmap_read(regmap, PLL_MODE(pll), &val);830 831 /* Wait 50us for PLL_LOCK_DET bit to go high */832 usleep_range(50, 55);833 834 /* Enable PLL output */835 regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL);836}837EXPORT_SYMBOL_GPL(clk_huayra_2290_pll_configure);838 839static unsigned long840alpha_huayra_pll_calc_rate(u64 prate, u32 l, u32 a)841{842 /*843 * a contains 16 bit alpha_val in two’s complement number in the range844 * of [-0.5, 0.5).845 */846 if (a >= BIT(PLL_HUAYRA_ALPHA_WIDTH - 1))847 l -= 1;848 849 return (prate * l) + (prate * a >> PLL_HUAYRA_ALPHA_WIDTH);850}851 852static unsigned long853alpha_huayra_pll_round_rate(unsigned long rate, unsigned long prate,854 u32 *l, u32 *a)855{856 u64 remainder;857 u64 quotient;858 859 quotient = rate;860 remainder = do_div(quotient, prate);861 *l = quotient;862 863 if (!remainder) {864 *a = 0;865 return rate;866 }867 868 quotient = remainder << PLL_HUAYRA_ALPHA_WIDTH;869 remainder = do_div(quotient, prate);870 871 if (remainder)872 quotient++;873 874 /*875 * alpha_val should be in two’s complement number in the range876 * of [-0.5, 0.5) so if quotient >= 0.5 then increment the l value877 * since alpha value will be subtracted in this case.878 */879 if (quotient >= BIT(PLL_HUAYRA_ALPHA_WIDTH - 1))880 *l += 1;881 882 *a = quotient;883 return alpha_huayra_pll_calc_rate(prate, *l, *a);884}885 886static unsigned long887alpha_pll_huayra_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)888{889 u64 rate = parent_rate, tmp;890 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);891 u32 l, alpha = 0, ctl, alpha_m, alpha_n;892 893 regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);894 regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);895 896 if (ctl & PLL_ALPHA_EN) {897 regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &alpha);898 /*899 * Depending upon alpha_mode, it can be treated as M/N value or900 * as a two’s complement number. When alpha_mode=1,901 * pll_alpha_val<15:8>=M and pll_apla_val<7:0>=N902 *903 * Fout=FIN*(L+(M/N))904 *905 * M is a signed number (-128 to 127) and N is unsigned906 * (0 to 255). M/N has to be within +/-0.5.907 *908 * When alpha_mode=0, it is a two’s complement number in the909 * range [-0.5, 0.5).910 *911 * Fout=FIN*(L+(alpha_val)/2^16)912 *913 * where alpha_val is two’s complement number.914 */915 if (!(ctl & PLL_ALPHA_MODE))916 return alpha_huayra_pll_calc_rate(rate, l, alpha);917 918 alpha_m = alpha >> PLL_HUAYRA_M_SHIFT & PLL_HUAYRA_M_MASK;919 alpha_n = alpha >> PLL_HUAYRA_N_SHIFT & PLL_HUAYRA_N_MASK;920 921 rate *= l;922 tmp = parent_rate;923 if (alpha_m >= BIT(PLL_HUAYRA_M_WIDTH - 1)) {924 alpha_m = BIT(PLL_HUAYRA_M_WIDTH) - alpha_m;925 tmp *= alpha_m;926 do_div(tmp, alpha_n);927 rate -= tmp;928 } else {929 tmp *= alpha_m;930 do_div(tmp, alpha_n);931 rate += tmp;932 }933 934 return rate;935 }936 937 return alpha_huayra_pll_calc_rate(rate, l, alpha);938}939 940static int alpha_pll_huayra_set_rate(struct clk_hw *hw, unsigned long rate,941 unsigned long prate)942{943 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);944 u32 l, a, ctl, cur_alpha = 0;945 946 rate = alpha_huayra_pll_round_rate(rate, prate, &l, &a);947 948 regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);949 950 if (ctl & PLL_ALPHA_EN)951 regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &cur_alpha);952 953 /*954 * Huayra PLL supports PLL dynamic programming. User can change L_VAL,955 * without having to go through the power on sequence.956 */957 if (clk_alpha_pll_is_enabled(hw)) {958 if (cur_alpha != a) {959 pr_err("%s: clock needs to be gated\n",960 clk_hw_get_name(hw));961 return -EBUSY;962 }963 964 regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);965 /* Ensure that the write above goes to detect L val change. */966 mb();967 return wait_for_pll_enable_lock(pll);968 }969 970 regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);971 regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);972 973 if (a == 0)974 regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),975 PLL_ALPHA_EN, 0x0);976 else977 regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),978 PLL_ALPHA_EN | PLL_ALPHA_MODE, PLL_ALPHA_EN);979 980 return 0;981}982 983static long alpha_pll_huayra_round_rate(struct clk_hw *hw, unsigned long rate,984 unsigned long *prate)985{986 u32 l, a;987 988 return alpha_huayra_pll_round_rate(rate, *prate, &l, &a);989}990 991static int trion_pll_is_enabled(struct clk_alpha_pll *pll,992 struct regmap *regmap)993{994 u32 mode_val, opmode_val;995 int ret;996 997 ret = regmap_read(regmap, PLL_MODE(pll), &mode_val);998 ret |= regmap_read(regmap, PLL_OPMODE(pll), &opmode_val);999 if (ret)1000 return 0;1001 1002 return ((opmode_val & PLL_RUN) && (mode_val & PLL_OUTCTRL));1003}1004 1005static int clk_trion_pll_is_enabled(struct clk_hw *hw)1006{1007 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1008 1009 return trion_pll_is_enabled(pll, pll->clkr.regmap);1010}1011 1012static int clk_trion_pll_enable(struct clk_hw *hw)1013{1014 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1015 struct regmap *regmap = pll->clkr.regmap;1016 u32 val;1017 int ret;1018 1019 ret = regmap_read(regmap, PLL_MODE(pll), &val);1020 if (ret)1021 return ret;1022 1023 /* If in FSM mode, just vote for it */1024 if (val & PLL_VOTE_FSM_ENA) {1025 ret = clk_enable_regmap(hw);1026 if (ret)1027 return ret;1028 return wait_for_pll_enable_active(pll);1029 }1030 1031 /* Set operation mode to RUN */1032 regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN);1033 1034 ret = wait_for_pll_enable_lock(pll);1035 if (ret)1036 return ret;1037 1038 /* Enable the PLL outputs */1039 ret = regmap_update_bits(regmap, PLL_USER_CTL(pll),1040 PLL_OUT_MASK, PLL_OUT_MASK);1041 if (ret)1042 return ret;1043 1044 /* Enable the global PLL outputs */1045 return regmap_update_bits(regmap, PLL_MODE(pll),1046 PLL_OUTCTRL, PLL_OUTCTRL);1047}1048 1049static void clk_trion_pll_disable(struct clk_hw *hw)1050{1051 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1052 struct regmap *regmap = pll->clkr.regmap;1053 u32 val;1054 int ret;1055 1056 ret = regmap_read(regmap, PLL_MODE(pll), &val);1057 if (ret)1058 return;1059 1060 /* If in FSM mode, just unvote it */1061 if (val & PLL_VOTE_FSM_ENA) {1062 clk_disable_regmap(hw);1063 return;1064 }1065 1066 /* Disable the global PLL output */1067 ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);1068 if (ret)1069 return;1070 1071 /* Disable the PLL outputs */1072 ret = regmap_update_bits(regmap, PLL_USER_CTL(pll),1073 PLL_OUT_MASK, 0);1074 if (ret)1075 return;1076 1077 /* Place the PLL mode in STANDBY */1078 regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);1079 regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);1080}1081 1082static unsigned long1083clk_trion_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)1084{1085 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1086 u32 l, frac, alpha_width = pll_alpha_width(pll);1087 1088 regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);1089 regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &frac);1090 1091 return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width);1092}1093 1094const struct clk_ops clk_alpha_pll_fixed_ops = {1095 .enable = clk_alpha_pll_enable,1096 .disable = clk_alpha_pll_disable,1097 .is_enabled = clk_alpha_pll_is_enabled,1098 .recalc_rate = clk_alpha_pll_recalc_rate,1099};1100EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_ops);1101 1102const struct clk_ops clk_alpha_pll_ops = {1103 .enable = clk_alpha_pll_enable,1104 .disable = clk_alpha_pll_disable,1105 .is_enabled = clk_alpha_pll_is_enabled,1106 .recalc_rate = clk_alpha_pll_recalc_rate,1107 .round_rate = clk_alpha_pll_round_rate,1108 .set_rate = clk_alpha_pll_set_rate,1109};1110EXPORT_SYMBOL_GPL(clk_alpha_pll_ops);1111 1112const struct clk_ops clk_alpha_pll_huayra_ops = {1113 .enable = clk_alpha_pll_enable,1114 .disable = clk_alpha_pll_disable,1115 .is_enabled = clk_alpha_pll_is_enabled,1116 .recalc_rate = alpha_pll_huayra_recalc_rate,1117 .round_rate = alpha_pll_huayra_round_rate,1118 .set_rate = alpha_pll_huayra_set_rate,1119};1120EXPORT_SYMBOL_GPL(clk_alpha_pll_huayra_ops);1121 1122const struct clk_ops clk_alpha_pll_hwfsm_ops = {1123 .enable = clk_alpha_pll_hwfsm_enable,1124 .disable = clk_alpha_pll_hwfsm_disable,1125 .is_enabled = clk_alpha_pll_hwfsm_is_enabled,1126 .recalc_rate = clk_alpha_pll_recalc_rate,1127 .round_rate = clk_alpha_pll_round_rate,1128 .set_rate = clk_alpha_pll_hwfsm_set_rate,1129};1130EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops);1131 1132const struct clk_ops clk_alpha_pll_fixed_trion_ops = {1133 .enable = clk_trion_pll_enable,1134 .disable = clk_trion_pll_disable,1135 .is_enabled = clk_trion_pll_is_enabled,1136 .recalc_rate = clk_trion_pll_recalc_rate,1137 .round_rate = clk_alpha_pll_round_rate,1138};1139EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_trion_ops);1140 1141static unsigned long1142clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)1143{1144 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);1145 u32 ctl;1146 1147 regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);1148 1149 ctl >>= PLL_POST_DIV_SHIFT;1150 ctl &= PLL_POST_DIV_MASK(pll);1151 1152 return parent_rate >> fls(ctl);1153}1154 1155static const struct clk_div_table clk_alpha_div_table[] = {1156 { 0x0, 1 },1157 { 0x1, 2 },1158 { 0x3, 4 },1159 { 0x7, 8 },1160 { 0xf, 16 },1161 { }1162};1163 1164static const struct clk_div_table clk_alpha_2bit_div_table[] = {1165 { 0x0, 1 },1166 { 0x1, 2 },1167 { 0x3, 4 },1168 { }1169};1170 1171static long1172clk_alpha_pll_postdiv_round_rate(struct clk_hw *hw, unsigned long rate,1173 unsigned long *prate)1174{1175 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);1176 const struct clk_div_table *table;1177 1178 if (pll->width == 2)1179 table = clk_alpha_2bit_div_table;1180 else1181 table = clk_alpha_div_table;1182 1183 return divider_round_rate(hw, rate, prate, table,1184 pll->width, CLK_DIVIDER_POWER_OF_TWO);1185}1186 1187static long1188clk_alpha_pll_postdiv_round_ro_rate(struct clk_hw *hw, unsigned long rate,1189 unsigned long *prate)1190{1191 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);1192 u32 ctl, div;1193 1194 regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl);1195 1196 ctl >>= PLL_POST_DIV_SHIFT;1197 ctl &= BIT(pll->width) - 1;1198 div = 1 << fls(ctl);1199 1200 if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)1201 *prate = clk_hw_round_rate(clk_hw_get_parent(hw), div * rate);1202 1203 return DIV_ROUND_UP_ULL((u64)*prate, div);1204}1205 1206static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,1207 unsigned long parent_rate)1208{1209 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);1210 int div;1211 1212 /* 16 -> 0xf, 8 -> 0x7, 4 -> 0x3, 2 -> 0x1, 1 -> 0x0 */1213 div = DIV_ROUND_UP_ULL(parent_rate, rate) - 1;1214 1215 return regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),1216 PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT,1217 div << PLL_POST_DIV_SHIFT);1218}1219 1220const struct clk_ops clk_alpha_pll_postdiv_ops = {1221 .recalc_rate = clk_alpha_pll_postdiv_recalc_rate,1222 .round_rate = clk_alpha_pll_postdiv_round_rate,1223 .set_rate = clk_alpha_pll_postdiv_set_rate,1224};1225EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_ops);1226 1227const struct clk_ops clk_alpha_pll_postdiv_ro_ops = {1228 .round_rate = clk_alpha_pll_postdiv_round_ro_rate,1229 .recalc_rate = clk_alpha_pll_postdiv_recalc_rate,1230};1231EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_ro_ops);1232 1233void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,1234 const struct alpha_pll_config *config)1235{1236 u32 val, mask;1237 1238 clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l);1239 clk_alpha_pll_write_config(regmap, PLL_FRAC(pll), config->alpha);1240 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll),1241 config->config_ctl_val);1242 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll),1243 config->config_ctl_hi_val);1244 clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll),1245 config->user_ctl_val);1246 clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll),1247 config->user_ctl_hi_val);1248 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll),1249 config->test_ctl_val);1250 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll),1251 config->test_ctl_hi_val);1252 1253 if (config->post_div_mask) {1254 mask = config->post_div_mask;1255 val = config->post_div_val;1256 regmap_update_bits(regmap, PLL_USER_CTL(pll), mask, val);1257 }1258 1259 if (pll->flags & SUPPORTS_FSM_LEGACY_MODE)1260 regmap_update_bits(regmap, PLL_MODE(pll), PLL_FSM_LEGACY_MODE,1261 PLL_FSM_LEGACY_MODE);1262 1263 regmap_update_bits(regmap, PLL_MODE(pll), PLL_UPDATE_BYPASS,1264 PLL_UPDATE_BYPASS);1265 1266 regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);1267}1268EXPORT_SYMBOL_GPL(clk_fabia_pll_configure);1269 1270static int alpha_pll_fabia_enable(struct clk_hw *hw)1271{1272 int ret;1273 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1274 u32 val, opmode_val;1275 struct regmap *regmap = pll->clkr.regmap;1276 1277 ret = regmap_read(regmap, PLL_MODE(pll), &val);1278 if (ret)1279 return ret;1280 1281 /* If in FSM mode, just vote for it */1282 if (val & PLL_VOTE_FSM_ENA) {1283 ret = clk_enable_regmap(hw);1284 if (ret)1285 return ret;1286 return wait_for_pll_enable_active(pll);1287 }1288 1289 ret = regmap_read(regmap, PLL_OPMODE(pll), &opmode_val);1290 if (ret)1291 return ret;1292 1293 /* Skip If PLL is already running */1294 if ((opmode_val & PLL_RUN) && (val & PLL_OUTCTRL))1295 return 0;1296 1297 ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);1298 if (ret)1299 return ret;1300 1301 ret = regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);1302 if (ret)1303 return ret;1304 1305 ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N,1306 PLL_RESET_N);1307 if (ret)1308 return ret;1309 1310 ret = regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN);1311 if (ret)1312 return ret;1313 1314 ret = wait_for_pll_enable_lock(pll);1315 if (ret)1316 return ret;1317 1318 ret = regmap_update_bits(regmap, PLL_USER_CTL(pll),1319 PLL_OUT_MASK, PLL_OUT_MASK);1320 if (ret)1321 return ret;1322 1323 return regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL,1324 PLL_OUTCTRL);1325}1326 1327static void alpha_pll_fabia_disable(struct clk_hw *hw)1328{1329 int ret;1330 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1331 u32 val;1332 struct regmap *regmap = pll->clkr.regmap;1333 1334 ret = regmap_read(regmap, PLL_MODE(pll), &val);1335 if (ret)1336 return;1337 1338 /* If in FSM mode, just unvote it */1339 if (val & PLL_FSM_ENA) {1340 clk_disable_regmap(hw);1341 return;1342 }1343 1344 ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);1345 if (ret)1346 return;1347 1348 /* Disable main outputs */1349 ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, 0);1350 if (ret)1351 return;1352 1353 /* Place the PLL in STANDBY */1354 regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);1355}1356 1357static unsigned long alpha_pll_fabia_recalc_rate(struct clk_hw *hw,1358 unsigned long parent_rate)1359{1360 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1361 u32 l, frac, alpha_width = pll_alpha_width(pll);1362 1363 regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);1364 regmap_read(pll->clkr.regmap, PLL_FRAC(pll), &frac);1365 1366 return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width);1367}1368 1369/*1370 * Due to limited number of bits for fractional rate programming, the1371 * rounded up rate could be marginally higher than the requested rate.1372 */1373static int alpha_pll_check_rate_margin(struct clk_hw *hw,1374 unsigned long rrate, unsigned long rate)1375{1376 unsigned long rate_margin = rate + PLL_RATE_MARGIN;1377 1378 if (rrate > rate_margin || rrate < rate) {1379 pr_err("%s: Rounded rate %lu not within range [%lu, %lu)\n",1380 clk_hw_get_name(hw), rrate, rate, rate_margin);1381 return -EINVAL;1382 }1383 1384 return 0;1385}1386 1387static int alpha_pll_fabia_set_rate(struct clk_hw *hw, unsigned long rate,1388 unsigned long prate)1389{1390 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1391 u32 l, alpha_width = pll_alpha_width(pll);1392 unsigned long rrate;1393 int ret;1394 u64 a;1395 1396 rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);1397 1398 ret = alpha_pll_check_rate_margin(hw, rrate, rate);1399 if (ret < 0)1400 return ret;1401 1402 regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);1403 regmap_write(pll->clkr.regmap, PLL_FRAC(pll), a);1404 1405 return __clk_alpha_pll_update_latch(pll);1406}1407 1408static int alpha_pll_fabia_prepare(struct clk_hw *hw)1409{1410 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1411 const struct pll_vco *vco;1412 struct clk_hw *parent_hw;1413 unsigned long cal_freq, rrate;1414 u32 cal_l, val, alpha_width = pll_alpha_width(pll);1415 const char *name = clk_hw_get_name(hw);1416 u64 a;1417 int ret;1418 1419 /* Check if calibration needs to be done i.e. PLL is in reset */1420 ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);1421 if (ret)1422 return ret;1423 1424 /* Return early if calibration is not needed. */1425 if (val & PLL_RESET_N)1426 return 0;1427 1428 vco = alpha_pll_find_vco(pll, clk_hw_get_rate(hw));1429 if (!vco) {1430 pr_err("%s: alpha pll not in a valid vco range\n", name);1431 return -EINVAL;1432 }1433 1434 cal_freq = DIV_ROUND_CLOSEST((pll->vco_table[0].min_freq +1435 pll->vco_table[0].max_freq) * 54, 100);1436 1437 parent_hw = clk_hw_get_parent(hw);1438 if (!parent_hw)1439 return -EINVAL;1440 1441 rrate = alpha_pll_round_rate(cal_freq, clk_hw_get_rate(parent_hw),1442 &cal_l, &a, alpha_width);1443 1444 ret = alpha_pll_check_rate_margin(hw, rrate, cal_freq);1445 if (ret < 0)1446 return ret;1447 1448 /* Setup PLL for calibration frequency */1449 regmap_write(pll->clkr.regmap, PLL_CAL_L_VAL(pll), cal_l);1450 1451 /* Bringup the PLL at calibration frequency */1452 ret = clk_alpha_pll_enable(hw);1453 if (ret) {1454 pr_err("%s: alpha pll calibration failed\n", name);1455 return ret;1456 }1457 1458 clk_alpha_pll_disable(hw);1459 1460 return 0;1461}1462 1463const struct clk_ops clk_alpha_pll_fabia_ops = {1464 .prepare = alpha_pll_fabia_prepare,1465 .enable = alpha_pll_fabia_enable,1466 .disable = alpha_pll_fabia_disable,1467 .is_enabled = clk_alpha_pll_is_enabled,1468 .set_rate = alpha_pll_fabia_set_rate,1469 .recalc_rate = alpha_pll_fabia_recalc_rate,1470 .round_rate = clk_alpha_pll_round_rate,1471};1472EXPORT_SYMBOL_GPL(clk_alpha_pll_fabia_ops);1473 1474const struct clk_ops clk_alpha_pll_fixed_fabia_ops = {1475 .enable = alpha_pll_fabia_enable,1476 .disable = alpha_pll_fabia_disable,1477 .is_enabled = clk_alpha_pll_is_enabled,1478 .recalc_rate = alpha_pll_fabia_recalc_rate,1479 .round_rate = clk_alpha_pll_round_rate,1480};1481EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_fabia_ops);1482 1483static unsigned long clk_alpha_pll_postdiv_fabia_recalc_rate(struct clk_hw *hw,1484 unsigned long parent_rate)1485{1486 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);1487 u32 i, div = 1, val;1488 int ret;1489 1490 ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);1491 if (ret)1492 return ret;1493 1494 val >>= pll->post_div_shift;1495 val &= BIT(pll->width) - 1;1496 1497 for (i = 0; i < pll->num_post_div; i++) {1498 if (pll->post_div_table[i].val == val) {1499 div = pll->post_div_table[i].div;1500 break;1501 }1502 }1503 1504 return (parent_rate / div);1505}1506 1507static unsigned long1508clk_trion_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)1509{1510 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);1511 struct regmap *regmap = pll->clkr.regmap;1512 u32 i, div = 1, val;1513 1514 regmap_read(regmap, PLL_USER_CTL(pll), &val);1515 1516 val >>= pll->post_div_shift;1517 val &= PLL_POST_DIV_MASK(pll);1518 1519 for (i = 0; i < pll->num_post_div; i++) {1520 if (pll->post_div_table[i].val == val) {1521 div = pll->post_div_table[i].div;1522 break;1523 }1524 }1525 1526 return (parent_rate / div);1527}1528 1529static long1530clk_trion_pll_postdiv_round_rate(struct clk_hw *hw, unsigned long rate,1531 unsigned long *prate)1532{1533 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);1534 1535 return divider_round_rate(hw, rate, prate, pll->post_div_table,1536 pll->width, CLK_DIVIDER_ROUND_CLOSEST);1537};1538 1539static int1540clk_trion_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,1541 unsigned long parent_rate)1542{1543 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);1544 struct regmap *regmap = pll->clkr.regmap;1545 int i, val = 0, div;1546 1547 div = DIV_ROUND_UP_ULL(parent_rate, rate);1548 for (i = 0; i < pll->num_post_div; i++) {1549 if (pll->post_div_table[i].div == div) {1550 val = pll->post_div_table[i].val;1551 break;1552 }1553 }1554 1555 return regmap_update_bits(regmap, PLL_USER_CTL(pll),1556 PLL_POST_DIV_MASK(pll) << pll->post_div_shift,1557 val << pll->post_div_shift);1558}1559 1560const struct clk_ops clk_alpha_pll_postdiv_trion_ops = {1561 .recalc_rate = clk_trion_pll_postdiv_recalc_rate,1562 .round_rate = clk_trion_pll_postdiv_round_rate,1563 .set_rate = clk_trion_pll_postdiv_set_rate,1564};1565EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_trion_ops);1566 1567static long clk_alpha_pll_postdiv_fabia_round_rate(struct clk_hw *hw,1568 unsigned long rate, unsigned long *prate)1569{1570 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);1571 1572 return divider_round_rate(hw, rate, prate, pll->post_div_table,1573 pll->width, CLK_DIVIDER_ROUND_CLOSEST);1574}1575 1576static int clk_alpha_pll_postdiv_fabia_set_rate(struct clk_hw *hw,1577 unsigned long rate, unsigned long parent_rate)1578{1579 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);1580 int i, val = 0, div, ret;1581 1582 /*1583 * If the PLL is in FSM mode, then treat set_rate callback as a1584 * no-operation.1585 */1586 ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);1587 if (ret)1588 return ret;1589 1590 if (val & PLL_VOTE_FSM_ENA)1591 return 0;1592 1593 div = DIV_ROUND_UP_ULL(parent_rate, rate);1594 for (i = 0; i < pll->num_post_div; i++) {1595 if (pll->post_div_table[i].div == div) {1596 val = pll->post_div_table[i].val;1597 break;1598 }1599 }1600 1601 return regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),1602 (BIT(pll->width) - 1) << pll->post_div_shift,1603 val << pll->post_div_shift);1604}1605 1606const struct clk_ops clk_alpha_pll_postdiv_fabia_ops = {1607 .recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate,1608 .round_rate = clk_alpha_pll_postdiv_fabia_round_rate,1609 .set_rate = clk_alpha_pll_postdiv_fabia_set_rate,1610};1611EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_fabia_ops);1612 1613/**1614 * clk_trion_pll_configure - configure the trion pll1615 *1616 * @pll: clk alpha pll1617 * @regmap: register map1618 * @config: configuration to apply for pll1619 */1620void clk_trion_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,1621 const struct alpha_pll_config *config)1622{1623 /*1624 * If the bootloader left the PLL enabled it's likely that there are1625 * RCGs that will lock up if we disable the PLL below.1626 */1627 if (trion_pll_is_enabled(pll, regmap)) {1628 pr_debug("Trion PLL is already enabled, skipping configuration\n");1629 return;1630 }1631 1632 clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l);1633 regmap_write(regmap, PLL_CAL_L_VAL(pll), TRION_PLL_CAL_VAL);1634 clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha);1635 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll),1636 config->config_ctl_val);1637 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll),1638 config->config_ctl_hi_val);1639 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll),1640 config->config_ctl_hi1_val);1641 clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll),1642 config->user_ctl_val);1643 clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll),1644 config->user_ctl_hi_val);1645 clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U1(pll),1646 config->user_ctl_hi1_val);1647 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll),1648 config->test_ctl_val);1649 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll),1650 config->test_ctl_hi_val);1651 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll),1652 config->test_ctl_hi1_val);1653 1654 regmap_update_bits(regmap, PLL_MODE(pll), PLL_UPDATE_BYPASS,1655 PLL_UPDATE_BYPASS);1656 1657 /* Disable PLL output */1658 regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);1659 1660 /* Set operation mode to OFF */1661 regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);1662 1663 /* Place the PLL in STANDBY mode */1664 regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);1665}1666EXPORT_SYMBOL_GPL(clk_trion_pll_configure);1667 1668/*1669 * The TRION PLL requires a power-on self-calibration which happens when the1670 * PLL comes out of reset. Calibrate in case it is not completed.1671 */1672static int __alpha_pll_trion_prepare(struct clk_hw *hw, u32 pcal_done)1673{1674 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1675 u32 val;1676 int ret;1677 1678 /* Return early if calibration is not needed. */1679 regmap_read(pll->clkr.regmap, PLL_STATUS(pll), &val);1680 if (val & pcal_done)1681 return 0;1682 1683 /* On/off to calibrate */1684 ret = clk_trion_pll_enable(hw);1685 if (!ret)1686 clk_trion_pll_disable(hw);1687 1688 return ret;1689}1690 1691static int alpha_pll_trion_prepare(struct clk_hw *hw)1692{1693 return __alpha_pll_trion_prepare(hw, TRION_PCAL_DONE);1694}1695 1696static int alpha_pll_lucid_prepare(struct clk_hw *hw)1697{1698 return __alpha_pll_trion_prepare(hw, LUCID_PCAL_DONE);1699}1700 1701static int __alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate,1702 unsigned long prate, u32 latch_bit, u32 latch_ack)1703{1704 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1705 unsigned long rrate;1706 u32 val, l, alpha_width = pll_alpha_width(pll);1707 u64 a;1708 int ret;1709 1710 rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);1711 1712 ret = alpha_pll_check_rate_margin(hw, rrate, rate);1713 if (ret < 0)1714 return ret;1715 1716 regmap_update_bits(pll->clkr.regmap, PLL_L_VAL(pll), LUCID_EVO_PLL_L_VAL_MASK, l);1717 regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);1718 1719 /* Latch the PLL input */1720 ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), latch_bit, latch_bit);1721 if (ret)1722 return ret;1723 1724 /* Wait for 2 reference cycles before checking the ACK bit. */1725 udelay(1);1726 regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);1727 if (!(val & latch_ack)) {1728 pr_err("Lucid PLL latch failed. Output may be unstable!\n");1729 return -EINVAL;1730 }1731 1732 /* Return the latch input to 0 */1733 ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), latch_bit, 0);1734 if (ret)1735 return ret;1736 1737 if (clk_hw_is_enabled(hw)) {1738 ret = wait_for_pll_enable_lock(pll);1739 if (ret)1740 return ret;1741 }1742 1743 /* Wait for PLL output to stabilize */1744 udelay(100);1745 return 0;1746}1747 1748static int alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate,1749 unsigned long prate)1750{1751 return __alpha_pll_trion_set_rate(hw, rate, prate, PLL_UPDATE, ALPHA_PLL_ACK_LATCH);1752}1753 1754const struct clk_ops clk_alpha_pll_trion_ops = {1755 .prepare = alpha_pll_trion_prepare,1756 .enable = clk_trion_pll_enable,1757 .disable = clk_trion_pll_disable,1758 .is_enabled = clk_trion_pll_is_enabled,1759 .recalc_rate = clk_trion_pll_recalc_rate,1760 .round_rate = clk_alpha_pll_round_rate,1761 .set_rate = alpha_pll_trion_set_rate,1762};1763EXPORT_SYMBOL_GPL(clk_alpha_pll_trion_ops);1764 1765const struct clk_ops clk_alpha_pll_lucid_ops = {1766 .prepare = alpha_pll_lucid_prepare,1767 .enable = clk_trion_pll_enable,1768 .disable = clk_trion_pll_disable,1769 .is_enabled = clk_trion_pll_is_enabled,1770 .recalc_rate = clk_trion_pll_recalc_rate,1771 .round_rate = clk_alpha_pll_round_rate,1772 .set_rate = alpha_pll_trion_set_rate,1773};1774EXPORT_SYMBOL_GPL(clk_alpha_pll_lucid_ops);1775 1776const struct clk_ops clk_alpha_pll_postdiv_lucid_ops = {1777 .recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate,1778 .round_rate = clk_alpha_pll_postdiv_fabia_round_rate,1779 .set_rate = clk_alpha_pll_postdiv_fabia_set_rate,1780};1781EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_lucid_ops);1782 1783void clk_agera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,1784 const struct alpha_pll_config *config)1785{1786 clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l);1787 clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha);1788 clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll),1789 config->user_ctl_val);1790 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll),1791 config->config_ctl_val);1792 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll),1793 config->config_ctl_hi_val);1794 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll),1795 config->test_ctl_val);1796 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll),1797 config->test_ctl_hi_val);1798}1799EXPORT_SYMBOL_GPL(clk_agera_pll_configure);1800 1801static int clk_alpha_pll_agera_set_rate(struct clk_hw *hw, unsigned long rate,1802 unsigned long prate)1803{1804 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1805 u32 l, alpha_width = pll_alpha_width(pll);1806 int ret;1807 unsigned long rrate;1808 u64 a;1809 1810 rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);1811 ret = alpha_pll_check_rate_margin(hw, rrate, rate);1812 if (ret < 0)1813 return ret;1814 1815 /* change L_VAL without having to go through the power on sequence */1816 regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);1817 regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);1818 1819 if (clk_hw_is_enabled(hw))1820 return wait_for_pll_enable_lock(pll);1821 1822 return 0;1823}1824 1825const struct clk_ops clk_alpha_pll_agera_ops = {1826 .enable = clk_alpha_pll_enable,1827 .disable = clk_alpha_pll_disable,1828 .is_enabled = clk_alpha_pll_is_enabled,1829 .recalc_rate = alpha_pll_fabia_recalc_rate,1830 .round_rate = clk_alpha_pll_round_rate,1831 .set_rate = clk_alpha_pll_agera_set_rate,1832};1833EXPORT_SYMBOL_GPL(clk_alpha_pll_agera_ops);1834 1835/**1836 * clk_lucid_5lpe_pll_configure - configure the lucid 5lpe pll1837 *1838 * @pll: clk alpha pll1839 * @regmap: register map1840 * @config: configuration to apply for pll1841 */1842void clk_lucid_5lpe_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,1843 const struct alpha_pll_config *config)1844{1845 /*1846 * If the bootloader left the PLL enabled it's likely that there are1847 * RCGs that will lock up if we disable the PLL below.1848 */1849 if (trion_pll_is_enabled(pll, regmap)) {1850 pr_debug("Lucid 5LPE PLL is already enabled, skipping configuration\n");1851 return;1852 }1853 1854 clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l);1855 regmap_write(regmap, PLL_CAL_L_VAL(pll), TRION_PLL_CAL_VAL);1856 clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha);1857 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll),1858 config->config_ctl_val);1859 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll),1860 config->config_ctl_hi_val);1861 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll),1862 config->config_ctl_hi1_val);1863 clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll),1864 config->user_ctl_val);1865 clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll),1866 config->user_ctl_hi_val);1867 clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U1(pll),1868 config->user_ctl_hi1_val);1869 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll),1870 config->test_ctl_val);1871 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll),1872 config->test_ctl_hi_val);1873 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll),1874 config->test_ctl_hi1_val);1875 1876 /* Disable PLL output */1877 regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);1878 1879 /* Set operation mode to OFF */1880 regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);1881 1882 /* Place the PLL in STANDBY mode */1883 regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);1884}1885EXPORT_SYMBOL_GPL(clk_lucid_5lpe_pll_configure);1886 1887static int alpha_pll_lucid_5lpe_enable(struct clk_hw *hw)1888{1889 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1890 u32 val;1891 int ret;1892 1893 ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);1894 if (ret)1895 return ret;1896 1897 /* If in FSM mode, just vote for it */1898 if (val & LUCID_5LPE_ENABLE_VOTE_RUN) {1899 ret = clk_enable_regmap(hw);1900 if (ret)1901 return ret;1902 return wait_for_pll_enable_lock(pll);1903 }1904 1905 /* Check if PLL is already enabled, return if enabled */1906 ret = trion_pll_is_enabled(pll, pll->clkr.regmap);1907 if (ret < 0)1908 return ret;1909 1910 ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);1911 if (ret)1912 return ret;1913 1914 regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), PLL_RUN);1915 1916 ret = wait_for_pll_enable_lock(pll);1917 if (ret)1918 return ret;1919 1920 /* Enable the PLL outputs */1921 ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, PLL_OUT_MASK);1922 if (ret)1923 return ret;1924 1925 /* Enable the global PLL outputs */1926 return regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL);1927}1928 1929static void alpha_pll_lucid_5lpe_disable(struct clk_hw *hw)1930{1931 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1932 u32 val;1933 int ret;1934 1935 ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);1936 if (ret)1937 return;1938 1939 /* If in FSM mode, just unvote it */1940 if (val & LUCID_5LPE_ENABLE_VOTE_RUN) {1941 clk_disable_regmap(hw);1942 return;1943 }1944 1945 /* Disable the global PLL output */1946 ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);1947 if (ret)1948 return;1949 1950 /* Disable the PLL outputs */1951 ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, 0);1952 if (ret)1953 return;1954 1955 /* Place the PLL mode in STANDBY */1956 regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), PLL_STANDBY);1957}1958 1959/*1960 * The Lucid 5LPE PLL requires a power-on self-calibration which happens1961 * when the PLL comes out of reset. Calibrate in case it is not completed.1962 */1963static int alpha_pll_lucid_5lpe_prepare(struct clk_hw *hw)1964{1965 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);1966 struct clk_hw *p;1967 u32 val = 0;1968 int ret;1969 1970 /* Return early if calibration is not needed. */1971 regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);1972 if (val & LUCID_5LPE_PCAL_DONE)1973 return 0;1974 1975 p = clk_hw_get_parent(hw);1976 if (!p)1977 return -EINVAL;1978 1979 ret = alpha_pll_lucid_5lpe_enable(hw);1980 if (ret)1981 return ret;1982 1983 alpha_pll_lucid_5lpe_disable(hw);1984 1985 return 0;1986}1987 1988static int alpha_pll_lucid_5lpe_set_rate(struct clk_hw *hw, unsigned long rate,1989 unsigned long prate)1990{1991 return __alpha_pll_trion_set_rate(hw, rate, prate,1992 LUCID_5LPE_PLL_LATCH_INPUT,1993 LUCID_5LPE_ALPHA_PLL_ACK_LATCH);1994}1995 1996static int __clk_lucid_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,1997 unsigned long parent_rate,1998 unsigned long enable_vote_run)1999{2000 struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);2001 struct regmap *regmap = pll->clkr.regmap;2002 int i, val, div, ret;2003 u32 mask;2004 2005 /*2006 * If the PLL is in FSM mode, then treat set_rate callback as a2007 * no-operation.2008 */2009 ret = regmap_read(regmap, PLL_USER_CTL(pll), &val);2010 if (ret)2011 return ret;2012 2013 if (val & enable_vote_run)2014 return 0;2015 2016 if (!pll->post_div_table) {2017 pr_err("Missing the post_div_table for the %s PLL\n",2018 clk_hw_get_name(&pll->clkr.hw));2019 return -EINVAL;2020 }2021 2022 div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);2023 for (i = 0; i < pll->num_post_div; i++) {2024 if (pll->post_div_table[i].div == div) {2025 val = pll->post_div_table[i].val;2026 break;2027 }2028 }2029 2030 mask = GENMASK(pll->width + pll->post_div_shift - 1, pll->post_div_shift);2031 return regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),2032 mask, val << pll->post_div_shift);2033}2034 2035static int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,2036 unsigned long parent_rate)2037{2038 return __clk_lucid_pll_postdiv_set_rate(hw, rate, parent_rate, LUCID_5LPE_ENABLE_VOTE_RUN);2039}2040 2041const struct clk_ops clk_alpha_pll_lucid_5lpe_ops = {2042 .prepare = alpha_pll_lucid_5lpe_prepare,2043 .enable = alpha_pll_lucid_5lpe_enable,2044 .disable = alpha_pll_lucid_5lpe_disable,2045 .is_enabled = clk_trion_pll_is_enabled,2046 .recalc_rate = clk_trion_pll_recalc_rate,2047 .round_rate = clk_alpha_pll_round_rate,2048 .set_rate = alpha_pll_lucid_5lpe_set_rate,2049};2050EXPORT_SYMBOL_GPL(clk_alpha_pll_lucid_5lpe_ops);2051 2052const struct clk_ops clk_alpha_pll_fixed_lucid_5lpe_ops = {2053 .enable = alpha_pll_lucid_5lpe_enable,2054 .disable = alpha_pll_lucid_5lpe_disable,2055 .is_enabled = clk_trion_pll_is_enabled,2056 .recalc_rate = clk_trion_pll_recalc_rate,2057 .round_rate = clk_alpha_pll_round_rate,2058};2059EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_lucid_5lpe_ops);2060 2061const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops = {2062 .recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate,2063 .round_rate = clk_alpha_pll_postdiv_fabia_round_rate,2064 .set_rate = clk_lucid_5lpe_pll_postdiv_set_rate,2065};2066EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_lucid_5lpe_ops);2067 2068void clk_zonda_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,2069 const struct alpha_pll_config *config)2070{2071 clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l);2072 clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha);2073 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val);2074 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val);2075 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val);2076 clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), config->user_ctl_val);2077 clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val);2078 clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U1(pll), config->user_ctl_hi1_val);2079 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val);2080 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val);2081 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val);2082 2083 regmap_update_bits(regmap, PLL_MODE(pll), PLL_BYPASSNL, 0);2084 2085 /* Disable PLL output */2086 regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);2087 2088 /* Set operation mode to OFF */2089 regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);2090 2091 /* Place the PLL in STANDBY mode */2092 regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);2093}2094EXPORT_SYMBOL_GPL(clk_zonda_pll_configure);2095 2096static int clk_zonda_pll_enable(struct clk_hw *hw)2097{2098 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);2099 struct regmap *regmap = pll->clkr.regmap;2100 u32 val;2101 int ret;2102 2103 regmap_read(regmap, PLL_MODE(pll), &val);2104 2105 /* If in FSM mode, just vote for it */2106 if (val & PLL_VOTE_FSM_ENA) {2107 ret = clk_enable_regmap(hw);2108 if (ret)2109 return ret;2110 return wait_for_pll_enable_active(pll);2111 }2112 2113 /* Get the PLL out of bypass mode */2114 regmap_update_bits(regmap, PLL_MODE(pll), PLL_BYPASSNL, PLL_BYPASSNL);2115 2116 /*2117 * H/W requires a 1us delay between disabling the bypass and2118 * de-asserting the reset.2119 */2120 udelay(1);2121 2122 regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);2123 2124 /* Set operation mode to RUN */2125 regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN);2126 2127 regmap_read(regmap, PLL_TEST_CTL(pll), &val);2128 2129 /* If cfa mode then poll for freq lock */2130 if (val & ZONDA_STAY_IN_CFA)2131 ret = wait_for_zonda_pll_freq_lock(pll);2132 else2133 ret = wait_for_pll_enable_lock(pll);2134 if (ret)2135 return ret;2136 2137 /* Enable the PLL outputs */2138 regmap_update_bits(regmap, PLL_USER_CTL(pll), ZONDA_PLL_OUT_MASK, ZONDA_PLL_OUT_MASK);2139 2140 /* Enable the global PLL outputs */2141 regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL);2142 2143 return 0;2144}2145 2146static void clk_zonda_pll_disable(struct clk_hw *hw)2147{2148 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);2149 struct regmap *regmap = pll->clkr.regmap;2150 u32 val;2151 2152 regmap_read(regmap, PLL_MODE(pll), &val);2153 2154 /* If in FSM mode, just unvote it */2155 if (val & PLL_VOTE_FSM_ENA) {2156 clk_disable_regmap(hw);2157 return;2158 }2159 2160 /* Disable the global PLL output */2161 regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);2162 2163 /* Disable the PLL outputs */2164 regmap_update_bits(regmap, PLL_USER_CTL(pll), ZONDA_PLL_OUT_MASK, 0);2165 2166 /* Put the PLL in bypass and reset */2167 regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N | PLL_BYPASSNL, 0);2168 2169 /* Place the PLL mode in OFF state */2170 regmap_write(regmap, PLL_OPMODE(pll), 0x0);2171}2172 2173static void zonda_pll_adjust_l_val(unsigned long rate, unsigned long prate, u32 *l)2174{2175 u64 remainder, quotient;2176 2177 quotient = rate;2178 remainder = do_div(quotient, prate);2179 2180 *l = rate + (u32)(remainder * 2 >= prate);2181}2182 2183static int clk_zonda_pll_set_rate(struct clk_hw *hw, unsigned long rate,2184 unsigned long prate)2185{2186 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);2187 unsigned long rrate;2188 u32 test_ctl_val;2189 u32 l, alpha_width = pll_alpha_width(pll);2190 u64 a;2191 int ret;2192 2193 rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);2194 2195 ret = alpha_pll_check_rate_margin(hw, rrate, rate);2196 if (ret < 0)2197 return ret;2198 2199 if (a & PLL_ALPHA_MSB)2200 zonda_pll_adjust_l_val(rate, prate, &l);2201 2202 regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);2203 regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);2204 2205 if (!clk_hw_is_enabled(hw))2206 return 0;2207 2208 /* Wait before polling for the frequency latch */2209 udelay(5);2210 2211 /* Read stay in cfa mode */2212 regmap_read(pll->clkr.regmap, PLL_TEST_CTL(pll), &test_ctl_val);2213 2214 /* If cfa mode then poll for freq lock */2215 if (test_ctl_val & ZONDA_STAY_IN_CFA)2216 ret = wait_for_zonda_pll_freq_lock(pll);2217 else2218 ret = wait_for_pll_enable_lock(pll);2219 if (ret)2220 return ret;2221 2222 /* Wait for PLL output to stabilize */2223 udelay(100);2224 return 0;2225}2226 2227const struct clk_ops clk_alpha_pll_zonda_ops = {2228 .enable = clk_zonda_pll_enable,2229 .disable = clk_zonda_pll_disable,2230 .is_enabled = clk_trion_pll_is_enabled,2231 .recalc_rate = clk_trion_pll_recalc_rate,2232 .round_rate = clk_alpha_pll_round_rate,2233 .set_rate = clk_zonda_pll_set_rate,2234};2235EXPORT_SYMBOL_GPL(clk_alpha_pll_zonda_ops);2236 2237void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,2238 const struct alpha_pll_config *config)2239{2240 u32 lval = config->l;2241 2242 /*2243 * If the bootloader left the PLL enabled it's likely that there are2244 * RCGs that will lock up if we disable the PLL below.2245 */2246 if (trion_pll_is_enabled(pll, regmap)) {2247 pr_debug("Lucid Evo PLL is already enabled, skipping configuration\n");2248 return;2249 }2250 2251 lval |= TRION_PLL_CAL_VAL << LUCID_EVO_PLL_CAL_L_VAL_SHIFT;2252 clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), lval);2253 clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha);2254 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val);2255 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val);2256 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val);2257 clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), config->user_ctl_val);2258 clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val);2259 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val);2260 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val);2261 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val);2262 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U2(pll), config->test_ctl_hi2_val);2263 2264 /* Disable PLL output */2265 regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);2266 2267 /* Set operation mode to STANDBY and de-assert the reset */2268 regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);2269 regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);2270}2271EXPORT_SYMBOL_GPL(clk_lucid_evo_pll_configure);2272 2273void clk_lucid_ole_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,2274 const struct alpha_pll_config *config)2275{2276 u32 lval = config->l;2277 2278 lval |= TRION_PLL_CAL_VAL << LUCID_EVO_PLL_CAL_L_VAL_SHIFT;2279 lval |= TRION_PLL_CAL_VAL << LUCID_OLE_PLL_RINGOSC_CAL_L_VAL_SHIFT;2280 clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), lval);2281 clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha);2282 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val);2283 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val);2284 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val);2285 clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), config->user_ctl_val);2286 clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val);2287 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val);2288 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val);2289 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val);2290 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U2(pll), config->test_ctl_hi2_val);2291 2292 /* Disable PLL output */2293 regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);2294 2295 /* Set operation mode to STANDBY and de-assert the reset */2296 regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);2297 regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);2298}2299EXPORT_SYMBOL_GPL(clk_lucid_ole_pll_configure);2300 2301static int alpha_pll_lucid_evo_enable(struct clk_hw *hw)2302{2303 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);2304 struct regmap *regmap = pll->clkr.regmap;2305 u32 val;2306 int ret;2307 2308 ret = regmap_read(regmap, PLL_USER_CTL(pll), &val);2309 if (ret)2310 return ret;2311 2312 /* If in FSM mode, just vote for it */2313 if (val & LUCID_EVO_ENABLE_VOTE_RUN) {2314 ret = clk_enable_regmap(hw);2315 if (ret)2316 return ret;2317 return wait_for_pll_enable_lock(pll);2318 }2319 2320 /* Check if PLL is already enabled */2321 ret = trion_pll_is_enabled(pll, regmap);2322 if (ret < 0) {2323 return ret;2324 } else if (ret) {2325 pr_warn("%s PLL is already enabled\n", clk_hw_get_name(&pll->clkr.hw));2326 return 0;2327 }2328 2329 ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);2330 if (ret)2331 return ret;2332 2333 /* Set operation mode to RUN */2334 regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN);2335 2336 ret = wait_for_pll_enable_lock(pll);2337 if (ret)2338 return ret;2339 2340 /* Enable the PLL outputs */2341 ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, PLL_OUT_MASK);2342 if (ret)2343 return ret;2344 2345 /* Enable the global PLL outputs */2346 ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL);2347 if (ret)2348 return ret;2349 2350 /* Ensure that the write above goes through before returning. */2351 mb();2352 return ret;2353}2354 2355static void _alpha_pll_lucid_evo_disable(struct clk_hw *hw, bool reset)2356{2357 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);2358 struct regmap *regmap = pll->clkr.regmap;2359 u32 val;2360 int ret;2361 2362 ret = regmap_read(regmap, PLL_USER_CTL(pll), &val);2363 if (ret)2364 return;2365 2366 /* If in FSM mode, just unvote it */2367 if (val & LUCID_EVO_ENABLE_VOTE_RUN) {2368 clk_disable_regmap(hw);2369 return;2370 }2371 2372 /* Disable the global PLL output */2373 ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);2374 if (ret)2375 return;2376 2377 /* Disable the PLL outputs */2378 ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, 0);2379 if (ret)2380 return;2381 2382 /* Place the PLL mode in STANDBY */2383 regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);2384 2385 if (reset)2386 regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, 0);2387}2388 2389static int _alpha_pll_lucid_evo_prepare(struct clk_hw *hw, bool reset)2390{2391 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);2392 struct clk_hw *p;2393 u32 val = 0;2394 int ret;2395 2396 /* Return early if calibration is not needed. */2397 regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);2398 if (!(val & LUCID_EVO_PCAL_NOT_DONE))2399 return 0;2400 2401 p = clk_hw_get_parent(hw);2402 if (!p)2403 return -EINVAL;2404 2405 ret = alpha_pll_lucid_evo_enable(hw);2406 if (ret)2407 return ret;2408 2409 _alpha_pll_lucid_evo_disable(hw, reset);2410 2411 return 0;2412}2413 2414static void alpha_pll_lucid_evo_disable(struct clk_hw *hw)2415{2416 _alpha_pll_lucid_evo_disable(hw, false);2417}2418 2419static int alpha_pll_lucid_evo_prepare(struct clk_hw *hw)2420{2421 return _alpha_pll_lucid_evo_prepare(hw, false);2422}2423 2424static void alpha_pll_reset_lucid_evo_disable(struct clk_hw *hw)2425{2426 _alpha_pll_lucid_evo_disable(hw, true);2427}2428 2429static int alpha_pll_reset_lucid_evo_prepare(struct clk_hw *hw)2430{2431 return _alpha_pll_lucid_evo_prepare(hw, true);2432}2433 2434static unsigned long alpha_pll_lucid_evo_recalc_rate(struct clk_hw *hw,2435 unsigned long parent_rate)2436{2437 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);2438 struct regmap *regmap = pll->clkr.regmap;2439 u32 l, frac;2440 2441 regmap_read(regmap, PLL_L_VAL(pll), &l);2442 l &= LUCID_EVO_PLL_L_VAL_MASK;2443 regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac);2444 2445 return alpha_pll_calc_rate(parent_rate, l, frac, pll_alpha_width(pll));2446}2447 2448static int clk_lucid_evo_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,2449 unsigned long parent_rate)2450{2451 return __clk_lucid_pll_postdiv_set_rate(hw, rate, parent_rate, LUCID_EVO_ENABLE_VOTE_RUN);2452}2453 2454const struct clk_ops clk_alpha_pll_fixed_lucid_evo_ops = {2455 .enable = alpha_pll_lucid_evo_enable,2456 .disable = alpha_pll_lucid_evo_disable,2457 .is_enabled = clk_trion_pll_is_enabled,2458 .recalc_rate = alpha_pll_lucid_evo_recalc_rate,2459 .round_rate = clk_alpha_pll_round_rate,2460};2461EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_lucid_evo_ops);2462 2463const struct clk_ops clk_alpha_pll_postdiv_lucid_evo_ops = {2464 .recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate,2465 .round_rate = clk_alpha_pll_postdiv_fabia_round_rate,2466 .set_rate = clk_lucid_evo_pll_postdiv_set_rate,2467};2468EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_lucid_evo_ops);2469 2470const struct clk_ops clk_alpha_pll_lucid_evo_ops = {2471 .prepare = alpha_pll_lucid_evo_prepare,2472 .enable = alpha_pll_lucid_evo_enable,2473 .disable = alpha_pll_lucid_evo_disable,2474 .is_enabled = clk_trion_pll_is_enabled,2475 .recalc_rate = alpha_pll_lucid_evo_recalc_rate,2476 .round_rate = clk_alpha_pll_round_rate,2477 .set_rate = alpha_pll_lucid_5lpe_set_rate,2478};2479EXPORT_SYMBOL_GPL(clk_alpha_pll_lucid_evo_ops);2480 2481const struct clk_ops clk_alpha_pll_reset_lucid_evo_ops = {2482 .prepare = alpha_pll_reset_lucid_evo_prepare,2483 .enable = alpha_pll_lucid_evo_enable,2484 .disable = alpha_pll_reset_lucid_evo_disable,2485 .is_enabled = clk_trion_pll_is_enabled,2486 .recalc_rate = alpha_pll_lucid_evo_recalc_rate,2487 .round_rate = clk_alpha_pll_round_rate,2488 .set_rate = alpha_pll_lucid_5lpe_set_rate,2489};2490EXPORT_SYMBOL_GPL(clk_alpha_pll_reset_lucid_evo_ops);2491 2492void clk_rivian_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,2493 const struct alpha_pll_config *config)2494{2495 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val);2496 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val);2497 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val);2498 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val);2499 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val);2500 clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l);2501 clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), config->user_ctl_val);2502 clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val);2503 2504 regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);2505 2506 regmap_update_bits(regmap, PLL_MODE(pll),2507 PLL_RESET_N | PLL_BYPASSNL | PLL_OUTCTRL,2508 PLL_RESET_N | PLL_BYPASSNL);2509}2510EXPORT_SYMBOL_GPL(clk_rivian_evo_pll_configure);2511 2512static unsigned long clk_rivian_evo_pll_recalc_rate(struct clk_hw *hw,2513 unsigned long parent_rate)2514{2515 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);2516 u32 l;2517 2518 regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l);2519 2520 return parent_rate * l;2521}2522 2523static long clk_rivian_evo_pll_round_rate(struct clk_hw *hw, unsigned long rate,2524 unsigned long *prate)2525{2526 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);2527 unsigned long min_freq, max_freq;2528 u32 l;2529 u64 a;2530 2531 rate = alpha_pll_round_rate(rate, *prate, &l, &a, 0);2532 if (!pll->vco_table || alpha_pll_find_vco(pll, rate))2533 return rate;2534 2535 min_freq = pll->vco_table[0].min_freq;2536 max_freq = pll->vco_table[pll->num_vco - 1].max_freq;2537 2538 return clamp(rate, min_freq, max_freq);2539}2540 2541const struct clk_ops clk_alpha_pll_rivian_evo_ops = {2542 .enable = alpha_pll_lucid_5lpe_enable,2543 .disable = alpha_pll_lucid_5lpe_disable,2544 .is_enabled = clk_trion_pll_is_enabled,2545 .recalc_rate = clk_rivian_evo_pll_recalc_rate,2546 .round_rate = clk_rivian_evo_pll_round_rate,2547};2548EXPORT_SYMBOL_GPL(clk_alpha_pll_rivian_evo_ops);2549 2550void clk_stromer_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,2551 const struct alpha_pll_config *config)2552{2553 u32 val, val_u, mask, mask_u;2554 2555 regmap_write(regmap, PLL_L_VAL(pll), config->l);2556 regmap_write(regmap, PLL_ALPHA_VAL(pll), config->alpha);2557 regmap_write(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val);2558 2559 if (pll_has_64bit_config(pll))2560 regmap_write(regmap, PLL_CONFIG_CTL_U(pll),2561 config->config_ctl_hi_val);2562 2563 if (pll_alpha_width(pll) > 32)2564 regmap_write(regmap, PLL_ALPHA_VAL_U(pll), config->alpha_hi);2565 2566 val = config->main_output_mask;2567 val |= config->aux_output_mask;2568 val |= config->aux2_output_mask;2569 val |= config->early_output_mask;2570 val |= config->pre_div_val;2571 val |= config->post_div_val;2572 val |= config->vco_val;2573 val |= config->alpha_en_mask;2574 val |= config->alpha_mode_mask;2575 2576 mask = config->main_output_mask;2577 mask |= config->aux_output_mask;2578 mask |= config->aux2_output_mask;2579 mask |= config->early_output_mask;2580 mask |= config->pre_div_mask;2581 mask |= config->post_div_mask;2582 mask |= config->vco_mask;2583 mask |= config->alpha_en_mask;2584 mask |= config->alpha_mode_mask;2585 2586 regmap_update_bits(regmap, PLL_USER_CTL(pll), mask, val);2587 2588 /* Stromer APSS PLL does not enable LOCK_DET by default, so enable it */2589 val_u = config->status_val << ALPHA_PLL_STATUS_REG_SHIFT;2590 val_u |= config->lock_det;2591 2592 mask_u = config->status_mask;2593 mask_u |= config->lock_det;2594 2595 regmap_update_bits(regmap, PLL_USER_CTL_U(pll), mask_u, val_u);2596 regmap_write(regmap, PLL_TEST_CTL(pll), config->test_ctl_val);2597 regmap_write(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val);2598 2599 if (pll->flags & SUPPORTS_FSM_MODE)2600 qcom_pll_set_fsm_mode(regmap, PLL_MODE(pll), 6, 0);2601}2602EXPORT_SYMBOL_GPL(clk_stromer_pll_configure);2603 2604static int clk_alpha_pll_stromer_determine_rate(struct clk_hw *hw,2605 struct clk_rate_request *req)2606{2607 u32 l;2608 u64 a;2609 2610 req->rate = alpha_pll_round_rate(req->rate, req->best_parent_rate,2611 &l, &a, ALPHA_REG_BITWIDTH);2612 2613 return 0;2614}2615 2616static int clk_alpha_pll_stromer_set_rate(struct clk_hw *hw, unsigned long rate,2617 unsigned long prate)2618{2619 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);2620 int ret;2621 u32 l;2622 u64 a;2623 2624 rate = alpha_pll_round_rate(rate, prate, &l, &a, ALPHA_REG_BITWIDTH);2625 2626 regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);2627 2628 a <<= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH;2629 regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);2630 regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll),2631 a >> ALPHA_BITWIDTH);2632 2633 regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),2634 PLL_ALPHA_EN, PLL_ALPHA_EN);2635 2636 if (!clk_hw_is_enabled(hw))2637 return 0;2638 2639 /*2640 * Stromer PLL supports Dynamic programming.2641 * It allows the PLL frequency to be changed on-the-fly without first2642 * execution of a shutdown procedure followed by a bring up procedure.2643 */2644 regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_UPDATE,2645 PLL_UPDATE);2646 2647 ret = wait_for_pll_update(pll);2648 if (ret)2649 return ret;2650 2651 return wait_for_pll_enable_lock(pll);2652}2653 2654const struct clk_ops clk_alpha_pll_stromer_ops = {2655 .enable = clk_alpha_pll_enable,2656 .disable = clk_alpha_pll_disable,2657 .is_enabled = clk_alpha_pll_is_enabled,2658 .recalc_rate = clk_alpha_pll_recalc_rate,2659 .determine_rate = clk_alpha_pll_stromer_determine_rate,2660 .set_rate = clk_alpha_pll_stromer_set_rate,2661};2662EXPORT_SYMBOL_GPL(clk_alpha_pll_stromer_ops);2663 2664static int clk_alpha_pll_stromer_plus_set_rate(struct clk_hw *hw,2665 unsigned long rate,2666 unsigned long prate)2667{2668 struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);2669 u32 l, alpha_width = pll_alpha_width(pll);2670 int ret, pll_mode;2671 u64 a;2672 2673 rate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width);2674 2675 ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &pll_mode);2676 if (ret)2677 return ret;2678 2679 regmap_write(pll->clkr.regmap, PLL_MODE(pll), 0);2680 2681 /* Delay of 2 output clock ticks required until output is disabled */2682 udelay(1);2683 2684 regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l);2685 2686 if (alpha_width > ALPHA_BITWIDTH)2687 a <<= alpha_width - ALPHA_BITWIDTH;2688 2689 regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a);2690 regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll),2691 a >> ALPHA_BITWIDTH);2692 2693 regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),2694 PLL_ALPHA_EN, PLL_ALPHA_EN);2695 2696 regmap_write(pll->clkr.regmap, PLL_MODE(pll), PLL_BYPASSNL);2697 2698 /* Wait five micro seconds or more */2699 udelay(5);2700 regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_RESET_N,2701 PLL_RESET_N);2702 2703 /* The lock time should be less than 50 micro seconds worst case */2704 usleep_range(50, 60);2705 2706 ret = wait_for_pll_enable_lock(pll);2707 if (ret) {2708 pr_err("Wait for PLL enable lock failed [%s] %d\n",2709 clk_hw_get_name(hw), ret);2710 return ret;2711 }2712 2713 if (pll_mode & PLL_OUTCTRL)2714 regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL,2715 PLL_OUTCTRL);2716 2717 return 0;2718}2719 2720const struct clk_ops clk_alpha_pll_stromer_plus_ops = {2721 .prepare = clk_alpha_pll_enable,2722 .unprepare = clk_alpha_pll_disable,2723 .is_enabled = clk_alpha_pll_is_enabled,2724 .recalc_rate = clk_alpha_pll_recalc_rate,2725 .determine_rate = clk_alpha_pll_stromer_determine_rate,2726 .set_rate = clk_alpha_pll_stromer_plus_set_rate,2727};2728EXPORT_SYMBOL_GPL(clk_alpha_pll_stromer_plus_ops);2729 2730void clk_regera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,2731 const struct alpha_pll_config *config)2732{2733 clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l);2734 clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha);2735 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val);2736 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val);2737 clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val);2738 clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), config->user_ctl_val);2739 clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val);2740 clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U1(pll), config->user_ctl_hi1_val);2741 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val);2742 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val);2743 clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val);2744 2745 /* Set operation mode to STANDBY */2746 regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);2747}2748EXPORT_SYMBOL_GPL(clk_regera_pll_configure);2749 2750const struct clk_ops clk_alpha_pll_regera_ops = {2751 .enable = clk_zonda_pll_enable,2752 .disable = clk_zonda_pll_disable,2753 .is_enabled = clk_alpha_pll_is_enabled,2754 .recalc_rate = clk_trion_pll_recalc_rate,2755 .round_rate = clk_alpha_pll_round_rate,2756 .set_rate = clk_zonda_pll_set_rate,2757};2758EXPORT_SYMBOL_GPL(clk_alpha_pll_regera_ops);2759