162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved. 462306a36Sopenharmony_ci * Copyright (c) 2021, 2023, Qualcomm Innovation Center, Inc. All rights reserved. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/kernel.h> 862306a36Sopenharmony_ci#include <linux/export.h> 962306a36Sopenharmony_ci#include <linux/clk-provider.h> 1062306a36Sopenharmony_ci#include <linux/regmap.h> 1162306a36Sopenharmony_ci#include <linux/delay.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include "clk-alpha-pll.h" 1462306a36Sopenharmony_ci#include "common.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define PLL_MODE(p) ((p)->offset + 0x0) 1762306a36Sopenharmony_ci# define PLL_OUTCTRL BIT(0) 1862306a36Sopenharmony_ci# define PLL_BYPASSNL BIT(1) 1962306a36Sopenharmony_ci# define PLL_RESET_N BIT(2) 2062306a36Sopenharmony_ci# define PLL_OFFLINE_REQ BIT(7) 2162306a36Sopenharmony_ci# define PLL_LOCK_COUNT_SHIFT 8 2262306a36Sopenharmony_ci# define PLL_LOCK_COUNT_MASK 0x3f 2362306a36Sopenharmony_ci# define PLL_BIAS_COUNT_SHIFT 14 2462306a36Sopenharmony_ci# define PLL_BIAS_COUNT_MASK 0x3f 2562306a36Sopenharmony_ci# define PLL_VOTE_FSM_ENA BIT(20) 2662306a36Sopenharmony_ci# define PLL_FSM_ENA BIT(20) 2762306a36Sopenharmony_ci# define PLL_VOTE_FSM_RESET BIT(21) 2862306a36Sopenharmony_ci# define PLL_UPDATE BIT(22) 2962306a36Sopenharmony_ci# define PLL_UPDATE_BYPASS BIT(23) 3062306a36Sopenharmony_ci# define PLL_FSM_LEGACY_MODE BIT(24) 3162306a36Sopenharmony_ci# define PLL_OFFLINE_ACK BIT(28) 3262306a36Sopenharmony_ci# define ALPHA_PLL_ACK_LATCH BIT(29) 3362306a36Sopenharmony_ci# define PLL_ACTIVE_FLAG BIT(30) 3462306a36Sopenharmony_ci# define PLL_LOCK_DET BIT(31) 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define PLL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_L_VAL]) 3762306a36Sopenharmony_ci#define PLL_CAL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_L_VAL]) 3862306a36Sopenharmony_ci#define PLL_ALPHA_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL]) 3962306a36Sopenharmony_ci#define PLL_ALPHA_VAL_U(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL_U]) 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#define PLL_USER_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL]) 4262306a36Sopenharmony_ci# define PLL_POST_DIV_SHIFT 8 4362306a36Sopenharmony_ci# define PLL_POST_DIV_MASK(p) GENMASK((p)->width, 0) 4462306a36Sopenharmony_ci# define PLL_ALPHA_EN BIT(24) 4562306a36Sopenharmony_ci# define PLL_ALPHA_MODE BIT(25) 4662306a36Sopenharmony_ci# define PLL_VCO_SHIFT 20 4762306a36Sopenharmony_ci# define PLL_VCO_MASK 0x3 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define PLL_USER_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U]) 5062306a36Sopenharmony_ci#define PLL_USER_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U1]) 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#define PLL_CONFIG_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL]) 5362306a36Sopenharmony_ci#define PLL_CONFIG_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U]) 5462306a36Sopenharmony_ci#define PLL_CONFIG_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U1]) 5562306a36Sopenharmony_ci#define PLL_TEST_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL]) 5662306a36Sopenharmony_ci#define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U]) 5762306a36Sopenharmony_ci#define PLL_TEST_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U1]) 5862306a36Sopenharmony_ci#define PLL_TEST_CTL_U2(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U2]) 5962306a36Sopenharmony_ci#define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS]) 6062306a36Sopenharmony_ci#define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE]) 6162306a36Sopenharmony_ci#define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC]) 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ciconst u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { 6462306a36Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_DEFAULT] = { 6562306a36Sopenharmony_ci [PLL_OFF_L_VAL] = 0x04, 6662306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL] = 0x08, 6762306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL_U] = 0x0c, 6862306a36Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x10, 6962306a36Sopenharmony_ci [PLL_OFF_USER_CTL_U] = 0x14, 7062306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x18, 7162306a36Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x1c, 7262306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U] = 0x20, 7362306a36Sopenharmony_ci [PLL_OFF_STATUS] = 0x24, 7462306a36Sopenharmony_ci }, 7562306a36Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_HUAYRA] = { 7662306a36Sopenharmony_ci [PLL_OFF_L_VAL] = 0x04, 7762306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL] = 0x08, 7862306a36Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x10, 7962306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x14, 8062306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U] = 0x18, 8162306a36Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x1c, 8262306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U] = 0x20, 8362306a36Sopenharmony_ci [PLL_OFF_STATUS] = 0x24, 8462306a36Sopenharmony_ci }, 8562306a36Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_BRAMMO] = { 8662306a36Sopenharmony_ci [PLL_OFF_L_VAL] = 0x04, 8762306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL] = 0x08, 8862306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL_U] = 0x0c, 8962306a36Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x10, 9062306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x18, 9162306a36Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x1c, 9262306a36Sopenharmony_ci [PLL_OFF_STATUS] = 0x24, 9362306a36Sopenharmony_ci }, 9462306a36Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_FABIA] = { 9562306a36Sopenharmony_ci [PLL_OFF_L_VAL] = 0x04, 9662306a36Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x0c, 9762306a36Sopenharmony_ci [PLL_OFF_USER_CTL_U] = 0x10, 9862306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x14, 9962306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U] = 0x18, 10062306a36Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x1c, 10162306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U] = 0x20, 10262306a36Sopenharmony_ci [PLL_OFF_STATUS] = 0x24, 10362306a36Sopenharmony_ci [PLL_OFF_OPMODE] = 0x2c, 10462306a36Sopenharmony_ci [PLL_OFF_FRAC] = 0x38, 10562306a36Sopenharmony_ci }, 10662306a36Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_TRION] = { 10762306a36Sopenharmony_ci [PLL_OFF_L_VAL] = 0x04, 10862306a36Sopenharmony_ci [PLL_OFF_CAL_L_VAL] = 0x08, 10962306a36Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x0c, 11062306a36Sopenharmony_ci [PLL_OFF_USER_CTL_U] = 0x10, 11162306a36Sopenharmony_ci [PLL_OFF_USER_CTL_U1] = 0x14, 11262306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x18, 11362306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U] = 0x1c, 11462306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U1] = 0x20, 11562306a36Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x24, 11662306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U] = 0x28, 11762306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U1] = 0x2c, 11862306a36Sopenharmony_ci [PLL_OFF_STATUS] = 0x30, 11962306a36Sopenharmony_ci [PLL_OFF_OPMODE] = 0x38, 12062306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL] = 0x40, 12162306a36Sopenharmony_ci }, 12262306a36Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_AGERA] = { 12362306a36Sopenharmony_ci [PLL_OFF_L_VAL] = 0x04, 12462306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL] = 0x08, 12562306a36Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x0c, 12662306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x10, 12762306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U] = 0x14, 12862306a36Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x18, 12962306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U] = 0x1c, 13062306a36Sopenharmony_ci [PLL_OFF_STATUS] = 0x2c, 13162306a36Sopenharmony_ci }, 13262306a36Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_ZONDA] = { 13362306a36Sopenharmony_ci [PLL_OFF_L_VAL] = 0x04, 13462306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL] = 0x08, 13562306a36Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x0c, 13662306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x10, 13762306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U] = 0x14, 13862306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U1] = 0x18, 13962306a36Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x1c, 14062306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U] = 0x20, 14162306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U1] = 0x24, 14262306a36Sopenharmony_ci [PLL_OFF_OPMODE] = 0x28, 14362306a36Sopenharmony_ci [PLL_OFF_STATUS] = 0x38, 14462306a36Sopenharmony_ci }, 14562306a36Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_LUCID_EVO] = { 14662306a36Sopenharmony_ci [PLL_OFF_OPMODE] = 0x04, 14762306a36Sopenharmony_ci [PLL_OFF_STATUS] = 0x0c, 14862306a36Sopenharmony_ci [PLL_OFF_L_VAL] = 0x10, 14962306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL] = 0x14, 15062306a36Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x18, 15162306a36Sopenharmony_ci [PLL_OFF_USER_CTL_U] = 0x1c, 15262306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x20, 15362306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U] = 0x24, 15462306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U1] = 0x28, 15562306a36Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x2c, 15662306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U] = 0x30, 15762306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U1] = 0x34, 15862306a36Sopenharmony_ci }, 15962306a36Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_LUCID_OLE] = { 16062306a36Sopenharmony_ci [PLL_OFF_OPMODE] = 0x04, 16162306a36Sopenharmony_ci [PLL_OFF_STATE] = 0x08, 16262306a36Sopenharmony_ci [PLL_OFF_STATUS] = 0x0c, 16362306a36Sopenharmony_ci [PLL_OFF_L_VAL] = 0x10, 16462306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL] = 0x14, 16562306a36Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x18, 16662306a36Sopenharmony_ci [PLL_OFF_USER_CTL_U] = 0x1c, 16762306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x20, 16862306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U] = 0x24, 16962306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U1] = 0x28, 17062306a36Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x2c, 17162306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U] = 0x30, 17262306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U1] = 0x34, 17362306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U2] = 0x38, 17462306a36Sopenharmony_ci }, 17562306a36Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_RIVIAN_EVO] = { 17662306a36Sopenharmony_ci [PLL_OFF_OPMODE] = 0x04, 17762306a36Sopenharmony_ci [PLL_OFF_STATUS] = 0x0c, 17862306a36Sopenharmony_ci [PLL_OFF_L_VAL] = 0x10, 17962306a36Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x14, 18062306a36Sopenharmony_ci [PLL_OFF_USER_CTL_U] = 0x18, 18162306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x1c, 18262306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U] = 0x20, 18362306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U1] = 0x24, 18462306a36Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x28, 18562306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U] = 0x2c, 18662306a36Sopenharmony_ci }, 18762306a36Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_DEFAULT_EVO] = { 18862306a36Sopenharmony_ci [PLL_OFF_L_VAL] = 0x04, 18962306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL] = 0x08, 19062306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL_U] = 0x0c, 19162306a36Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x10, 19262306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U] = 0x14, 19362306a36Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x18, 19462306a36Sopenharmony_ci [PLL_OFF_USER_CTL_U] = 0x1c, 19562306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x20, 19662306a36Sopenharmony_ci [PLL_OFF_STATUS] = 0x24, 19762306a36Sopenharmony_ci }, 19862306a36Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_BRAMMO_EVO] = { 19962306a36Sopenharmony_ci [PLL_OFF_L_VAL] = 0x04, 20062306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL] = 0x08, 20162306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL_U] = 0x0c, 20262306a36Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x10, 20362306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U] = 0x14, 20462306a36Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x18, 20562306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x1C, 20662306a36Sopenharmony_ci [PLL_OFF_STATUS] = 0x20, 20762306a36Sopenharmony_ci }, 20862306a36Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_STROMER] = { 20962306a36Sopenharmony_ci [PLL_OFF_L_VAL] = 0x08, 21062306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL] = 0x10, 21162306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL_U] = 0x14, 21262306a36Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x18, 21362306a36Sopenharmony_ci [PLL_OFF_USER_CTL_U] = 0x1c, 21462306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x20, 21562306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U] = 0xff, 21662306a36Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x30, 21762306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U] = 0x34, 21862306a36Sopenharmony_ci [PLL_OFF_STATUS] = 0x28, 21962306a36Sopenharmony_ci }, 22062306a36Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_STROMER_PLUS] = { 22162306a36Sopenharmony_ci [PLL_OFF_L_VAL] = 0x04, 22262306a36Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x08, 22362306a36Sopenharmony_ci [PLL_OFF_USER_CTL_U] = 0x0c, 22462306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x10, 22562306a36Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x14, 22662306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U] = 0x18, 22762306a36Sopenharmony_ci [PLL_OFF_STATUS] = 0x1c, 22862306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL] = 0x24, 22962306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL_U] = 0x28, 23062306a36Sopenharmony_ci }, 23162306a36Sopenharmony_ci}; 23262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_regs); 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci/* 23562306a36Sopenharmony_ci * Even though 40 bits are present, use only 32 for ease of calculation. 23662306a36Sopenharmony_ci */ 23762306a36Sopenharmony_ci#define ALPHA_REG_BITWIDTH 40 23862306a36Sopenharmony_ci#define ALPHA_REG_16BIT_WIDTH 16 23962306a36Sopenharmony_ci#define ALPHA_BITWIDTH 32U 24062306a36Sopenharmony_ci#define ALPHA_SHIFT(w) min(w, ALPHA_BITWIDTH) 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci#define ALPHA_PLL_STATUS_REG_SHIFT 8 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci#define PLL_HUAYRA_M_WIDTH 8 24562306a36Sopenharmony_ci#define PLL_HUAYRA_M_SHIFT 8 24662306a36Sopenharmony_ci#define PLL_HUAYRA_M_MASK 0xff 24762306a36Sopenharmony_ci#define PLL_HUAYRA_N_SHIFT 0 24862306a36Sopenharmony_ci#define PLL_HUAYRA_N_MASK 0xff 24962306a36Sopenharmony_ci#define PLL_HUAYRA_ALPHA_WIDTH 16 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci#define PLL_STANDBY 0x0 25262306a36Sopenharmony_ci#define PLL_RUN 0x1 25362306a36Sopenharmony_ci#define PLL_OUT_MASK 0x7 25462306a36Sopenharmony_ci#define PLL_RATE_MARGIN 500 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci/* TRION PLL specific settings and offsets */ 25762306a36Sopenharmony_ci#define TRION_PLL_CAL_VAL 0x44 25862306a36Sopenharmony_ci#define TRION_PCAL_DONE BIT(26) 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci/* LUCID PLL specific settings and offsets */ 26162306a36Sopenharmony_ci#define LUCID_PCAL_DONE BIT(27) 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci/* LUCID 5LPE PLL specific settings and offsets */ 26462306a36Sopenharmony_ci#define LUCID_5LPE_PCAL_DONE BIT(11) 26562306a36Sopenharmony_ci#define LUCID_5LPE_ALPHA_PLL_ACK_LATCH BIT(13) 26662306a36Sopenharmony_ci#define LUCID_5LPE_PLL_LATCH_INPUT BIT(14) 26762306a36Sopenharmony_ci#define LUCID_5LPE_ENABLE_VOTE_RUN BIT(21) 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci/* LUCID EVO PLL specific settings and offsets */ 27062306a36Sopenharmony_ci#define LUCID_EVO_PCAL_NOT_DONE BIT(8) 27162306a36Sopenharmony_ci#define LUCID_EVO_ENABLE_VOTE_RUN BIT(25) 27262306a36Sopenharmony_ci#define LUCID_EVO_PLL_L_VAL_MASK GENMASK(15, 0) 27362306a36Sopenharmony_ci#define LUCID_EVO_PLL_CAL_L_VAL_SHIFT 16 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci/* ZONDA PLL specific */ 27662306a36Sopenharmony_ci#define ZONDA_PLL_OUT_MASK 0xf 27762306a36Sopenharmony_ci#define ZONDA_STAY_IN_CFA BIT(16) 27862306a36Sopenharmony_ci#define ZONDA_PLL_FREQ_LOCK_DET BIT(29) 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci#define pll_alpha_width(p) \ 28162306a36Sopenharmony_ci ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \ 28262306a36Sopenharmony_ci ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH) 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci#define pll_has_64bit_config(p) ((PLL_CONFIG_CTL_U(p) - PLL_CONFIG_CTL(p)) == 4) 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci#define to_clk_alpha_pll(_hw) container_of(to_clk_regmap(_hw), \ 28762306a36Sopenharmony_ci struct clk_alpha_pll, clkr) 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci#define to_clk_alpha_pll_postdiv(_hw) container_of(to_clk_regmap(_hw), \ 29062306a36Sopenharmony_ci struct clk_alpha_pll_postdiv, clkr) 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cistatic int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse, 29362306a36Sopenharmony_ci const char *action) 29462306a36Sopenharmony_ci{ 29562306a36Sopenharmony_ci u32 val; 29662306a36Sopenharmony_ci int count; 29762306a36Sopenharmony_ci int ret; 29862306a36Sopenharmony_ci const char *name = clk_hw_get_name(&pll->clkr.hw); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); 30162306a36Sopenharmony_ci if (ret) 30262306a36Sopenharmony_ci return ret; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci for (count = 200; count > 0; count--) { 30562306a36Sopenharmony_ci ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); 30662306a36Sopenharmony_ci if (ret) 30762306a36Sopenharmony_ci return ret; 30862306a36Sopenharmony_ci if (inverse && !(val & mask)) 30962306a36Sopenharmony_ci return 0; 31062306a36Sopenharmony_ci else if ((val & mask) == mask) 31162306a36Sopenharmony_ci return 0; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci udelay(1); 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci WARN(1, "%s failed to %s!\n", name, action); 31762306a36Sopenharmony_ci return -ETIMEDOUT; 31862306a36Sopenharmony_ci} 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci#define wait_for_pll_enable_active(pll) \ 32162306a36Sopenharmony_ci wait_for_pll(pll, PLL_ACTIVE_FLAG, 0, "enable") 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci#define wait_for_pll_enable_lock(pll) \ 32462306a36Sopenharmony_ci wait_for_pll(pll, PLL_LOCK_DET, 0, "enable") 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci#define wait_for_zonda_pll_freq_lock(pll) \ 32762306a36Sopenharmony_ci wait_for_pll(pll, ZONDA_PLL_FREQ_LOCK_DET, 0, "freq enable") 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci#define wait_for_pll_disable(pll) \ 33062306a36Sopenharmony_ci wait_for_pll(pll, PLL_ACTIVE_FLAG, 1, "disable") 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci#define wait_for_pll_offline(pll) \ 33362306a36Sopenharmony_ci wait_for_pll(pll, PLL_OFFLINE_ACK, 0, "offline") 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci#define wait_for_pll_update(pll) \ 33662306a36Sopenharmony_ci wait_for_pll(pll, PLL_UPDATE, 1, "update") 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci#define wait_for_pll_update_ack_set(pll) \ 33962306a36Sopenharmony_ci wait_for_pll(pll, ALPHA_PLL_ACK_LATCH, 0, "update_ack_set") 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci#define wait_for_pll_update_ack_clear(pll) \ 34262306a36Sopenharmony_ci wait_for_pll(pll, ALPHA_PLL_ACK_LATCH, 1, "update_ack_clear") 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistatic void clk_alpha_pll_write_config(struct regmap *regmap, unsigned int reg, 34562306a36Sopenharmony_ci unsigned int val) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci if (val) 34862306a36Sopenharmony_ci regmap_write(regmap, reg, val); 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_civoid clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, 35262306a36Sopenharmony_ci const struct alpha_pll_config *config) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci u32 val, mask; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci regmap_write(regmap, PLL_L_VAL(pll), config->l); 35762306a36Sopenharmony_ci regmap_write(regmap, PLL_ALPHA_VAL(pll), config->alpha); 35862306a36Sopenharmony_ci regmap_write(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci if (pll_has_64bit_config(pll)) 36162306a36Sopenharmony_ci regmap_write(regmap, PLL_CONFIG_CTL_U(pll), 36262306a36Sopenharmony_ci config->config_ctl_hi_val); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci if (pll_alpha_width(pll) > 32) 36562306a36Sopenharmony_ci regmap_write(regmap, PLL_ALPHA_VAL_U(pll), config->alpha_hi); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci val = config->main_output_mask; 36862306a36Sopenharmony_ci val |= config->aux_output_mask; 36962306a36Sopenharmony_ci val |= config->aux2_output_mask; 37062306a36Sopenharmony_ci val |= config->early_output_mask; 37162306a36Sopenharmony_ci val |= config->pre_div_val; 37262306a36Sopenharmony_ci val |= config->post_div_val; 37362306a36Sopenharmony_ci val |= config->vco_val; 37462306a36Sopenharmony_ci val |= config->alpha_en_mask; 37562306a36Sopenharmony_ci val |= config->alpha_mode_mask; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci mask = config->main_output_mask; 37862306a36Sopenharmony_ci mask |= config->aux_output_mask; 37962306a36Sopenharmony_ci mask |= config->aux2_output_mask; 38062306a36Sopenharmony_ci mask |= config->early_output_mask; 38162306a36Sopenharmony_ci mask |= config->pre_div_mask; 38262306a36Sopenharmony_ci mask |= config->post_div_mask; 38362306a36Sopenharmony_ci mask |= config->vco_mask; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_USER_CTL(pll), mask, val); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci if (config->test_ctl_mask) 38862306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_TEST_CTL(pll), 38962306a36Sopenharmony_ci config->test_ctl_mask, 39062306a36Sopenharmony_ci config->test_ctl_val); 39162306a36Sopenharmony_ci else 39262306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), 39362306a36Sopenharmony_ci config->test_ctl_val); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci if (config->test_ctl_hi_mask) 39662306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_TEST_CTL_U(pll), 39762306a36Sopenharmony_ci config->test_ctl_hi_mask, 39862306a36Sopenharmony_ci config->test_ctl_hi_val); 39962306a36Sopenharmony_ci else 40062306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), 40162306a36Sopenharmony_ci config->test_ctl_hi_val); 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci if (pll->flags & SUPPORTS_FSM_MODE) 40462306a36Sopenharmony_ci qcom_pll_set_fsm_mode(regmap, PLL_MODE(pll), 6, 0); 40562306a36Sopenharmony_ci} 40662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_configure); 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cistatic int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw) 40962306a36Sopenharmony_ci{ 41062306a36Sopenharmony_ci int ret; 41162306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 41262306a36Sopenharmony_ci u32 val; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); 41562306a36Sopenharmony_ci if (ret) 41662306a36Sopenharmony_ci return ret; 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci val |= PLL_FSM_ENA; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci if (pll->flags & SUPPORTS_OFFLINE_REQ) 42162306a36Sopenharmony_ci val &= ~PLL_OFFLINE_REQ; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci ret = regmap_write(pll->clkr.regmap, PLL_MODE(pll), val); 42462306a36Sopenharmony_ci if (ret) 42562306a36Sopenharmony_ci return ret; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci /* Make sure enable request goes through before waiting for update */ 42862306a36Sopenharmony_ci mb(); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci return wait_for_pll_enable_active(pll); 43162306a36Sopenharmony_ci} 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_cistatic void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw) 43462306a36Sopenharmony_ci{ 43562306a36Sopenharmony_ci int ret; 43662306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 43762306a36Sopenharmony_ci u32 val; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); 44062306a36Sopenharmony_ci if (ret) 44162306a36Sopenharmony_ci return; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci if (pll->flags & SUPPORTS_OFFLINE_REQ) { 44462306a36Sopenharmony_ci ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), 44562306a36Sopenharmony_ci PLL_OFFLINE_REQ, PLL_OFFLINE_REQ); 44662306a36Sopenharmony_ci if (ret) 44762306a36Sopenharmony_ci return; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci ret = wait_for_pll_offline(pll); 45062306a36Sopenharmony_ci if (ret) 45162306a36Sopenharmony_ci return; 45262306a36Sopenharmony_ci } 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci /* Disable hwfsm */ 45562306a36Sopenharmony_ci ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), 45662306a36Sopenharmony_ci PLL_FSM_ENA, 0); 45762306a36Sopenharmony_ci if (ret) 45862306a36Sopenharmony_ci return; 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci wait_for_pll_disable(pll); 46162306a36Sopenharmony_ci} 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_cistatic int pll_is_enabled(struct clk_hw *hw, u32 mask) 46462306a36Sopenharmony_ci{ 46562306a36Sopenharmony_ci int ret; 46662306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 46762306a36Sopenharmony_ci u32 val; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); 47062306a36Sopenharmony_ci if (ret) 47162306a36Sopenharmony_ci return ret; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci return !!(val & mask); 47462306a36Sopenharmony_ci} 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_cistatic int clk_alpha_pll_hwfsm_is_enabled(struct clk_hw *hw) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci return pll_is_enabled(hw, PLL_ACTIVE_FLAG); 47962306a36Sopenharmony_ci} 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_cistatic int clk_alpha_pll_is_enabled(struct clk_hw *hw) 48262306a36Sopenharmony_ci{ 48362306a36Sopenharmony_ci return pll_is_enabled(hw, PLL_LOCK_DET); 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_cistatic int clk_alpha_pll_enable(struct clk_hw *hw) 48762306a36Sopenharmony_ci{ 48862306a36Sopenharmony_ci int ret; 48962306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 49062306a36Sopenharmony_ci u32 val, mask; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL; 49362306a36Sopenharmony_ci ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); 49462306a36Sopenharmony_ci if (ret) 49562306a36Sopenharmony_ci return ret; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci /* If in FSM mode, just vote for it */ 49862306a36Sopenharmony_ci if (val & PLL_VOTE_FSM_ENA) { 49962306a36Sopenharmony_ci ret = clk_enable_regmap(hw); 50062306a36Sopenharmony_ci if (ret) 50162306a36Sopenharmony_ci return ret; 50262306a36Sopenharmony_ci return wait_for_pll_enable_active(pll); 50362306a36Sopenharmony_ci } 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci /* Skip if already enabled */ 50662306a36Sopenharmony_ci if ((val & mask) == mask) 50762306a36Sopenharmony_ci return 0; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), 51062306a36Sopenharmony_ci PLL_BYPASSNL, PLL_BYPASSNL); 51162306a36Sopenharmony_ci if (ret) 51262306a36Sopenharmony_ci return ret; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci /* 51562306a36Sopenharmony_ci * H/W requires a 5us delay between disabling the bypass and 51662306a36Sopenharmony_ci * de-asserting the reset. 51762306a36Sopenharmony_ci */ 51862306a36Sopenharmony_ci mb(); 51962306a36Sopenharmony_ci udelay(5); 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), 52262306a36Sopenharmony_ci PLL_RESET_N, PLL_RESET_N); 52362306a36Sopenharmony_ci if (ret) 52462306a36Sopenharmony_ci return ret; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci ret = wait_for_pll_enable_lock(pll); 52762306a36Sopenharmony_ci if (ret) 52862306a36Sopenharmony_ci return ret; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), 53162306a36Sopenharmony_ci PLL_OUTCTRL, PLL_OUTCTRL); 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci /* Ensure that the write above goes through before returning. */ 53462306a36Sopenharmony_ci mb(); 53562306a36Sopenharmony_ci return ret; 53662306a36Sopenharmony_ci} 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_cistatic void clk_alpha_pll_disable(struct clk_hw *hw) 53962306a36Sopenharmony_ci{ 54062306a36Sopenharmony_ci int ret; 54162306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 54262306a36Sopenharmony_ci u32 val, mask; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); 54562306a36Sopenharmony_ci if (ret) 54662306a36Sopenharmony_ci return; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci /* If in FSM mode, just unvote it */ 54962306a36Sopenharmony_ci if (val & PLL_VOTE_FSM_ENA) { 55062306a36Sopenharmony_ci clk_disable_regmap(hw); 55162306a36Sopenharmony_ci return; 55262306a36Sopenharmony_ci } 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci mask = PLL_OUTCTRL; 55562306a36Sopenharmony_ci regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), mask, 0); 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci /* Delay of 2 output clock ticks required until output is disabled */ 55862306a36Sopenharmony_ci mb(); 55962306a36Sopenharmony_ci udelay(1); 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci mask = PLL_RESET_N | PLL_BYPASSNL; 56262306a36Sopenharmony_ci regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), mask, 0); 56362306a36Sopenharmony_ci} 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_cistatic unsigned long 56662306a36Sopenharmony_cialpha_pll_calc_rate(u64 prate, u32 l, u32 a, u32 alpha_width) 56762306a36Sopenharmony_ci{ 56862306a36Sopenharmony_ci return (prate * l) + ((prate * a) >> ALPHA_SHIFT(alpha_width)); 56962306a36Sopenharmony_ci} 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_cistatic unsigned long 57262306a36Sopenharmony_cialpha_pll_round_rate(unsigned long rate, unsigned long prate, u32 *l, u64 *a, 57362306a36Sopenharmony_ci u32 alpha_width) 57462306a36Sopenharmony_ci{ 57562306a36Sopenharmony_ci u64 remainder; 57662306a36Sopenharmony_ci u64 quotient; 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci quotient = rate; 57962306a36Sopenharmony_ci remainder = do_div(quotient, prate); 58062306a36Sopenharmony_ci *l = quotient; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci if (!remainder) { 58362306a36Sopenharmony_ci *a = 0; 58462306a36Sopenharmony_ci return rate; 58562306a36Sopenharmony_ci } 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci /* Upper ALPHA_BITWIDTH bits of Alpha */ 58862306a36Sopenharmony_ci quotient = remainder << ALPHA_SHIFT(alpha_width); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci remainder = do_div(quotient, prate); 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci if (remainder) 59362306a36Sopenharmony_ci quotient++; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci *a = quotient; 59662306a36Sopenharmony_ci return alpha_pll_calc_rate(prate, *l, *a, alpha_width); 59762306a36Sopenharmony_ci} 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_cistatic const struct pll_vco * 60062306a36Sopenharmony_cialpha_pll_find_vco(const struct clk_alpha_pll *pll, unsigned long rate) 60162306a36Sopenharmony_ci{ 60262306a36Sopenharmony_ci const struct pll_vco *v = pll->vco_table; 60362306a36Sopenharmony_ci const struct pll_vco *end = v + pll->num_vco; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci for (; v < end; v++) 60662306a36Sopenharmony_ci if (rate >= v->min_freq && rate <= v->max_freq) 60762306a36Sopenharmony_ci return v; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci return NULL; 61062306a36Sopenharmony_ci} 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_cistatic unsigned long 61362306a36Sopenharmony_ciclk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) 61462306a36Sopenharmony_ci{ 61562306a36Sopenharmony_ci u32 l, low, high, ctl; 61662306a36Sopenharmony_ci u64 a = 0, prate = parent_rate; 61762306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 61862306a36Sopenharmony_ci u32 alpha_width = pll_alpha_width(pll); 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); 62362306a36Sopenharmony_ci if (ctl & PLL_ALPHA_EN) { 62462306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &low); 62562306a36Sopenharmony_ci if (alpha_width > 32) { 62662306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), 62762306a36Sopenharmony_ci &high); 62862306a36Sopenharmony_ci a = (u64)high << 32 | low; 62962306a36Sopenharmony_ci } else { 63062306a36Sopenharmony_ci a = low & GENMASK(alpha_width - 1, 0); 63162306a36Sopenharmony_ci } 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci if (alpha_width > ALPHA_BITWIDTH) 63462306a36Sopenharmony_ci a >>= alpha_width - ALPHA_BITWIDTH; 63562306a36Sopenharmony_ci } 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci return alpha_pll_calc_rate(prate, l, a, alpha_width); 63862306a36Sopenharmony_ci} 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_cistatic int __clk_alpha_pll_update_latch(struct clk_alpha_pll *pll) 64262306a36Sopenharmony_ci{ 64362306a36Sopenharmony_ci int ret; 64462306a36Sopenharmony_ci u32 mode; 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_MODE(pll), &mode); 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci /* Latch the input to the PLL */ 64962306a36Sopenharmony_ci regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_UPDATE, 65062306a36Sopenharmony_ci PLL_UPDATE); 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci /* Wait for 2 reference cycle before checking ACK bit */ 65362306a36Sopenharmony_ci udelay(1); 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci /* 65662306a36Sopenharmony_ci * PLL will latch the new L, Alpha and freq control word. 65762306a36Sopenharmony_ci * PLL will respond by raising PLL_ACK_LATCH output when new programming 65862306a36Sopenharmony_ci * has been latched in and PLL is being updated. When 65962306a36Sopenharmony_ci * UPDATE_LOGIC_BYPASS bit is not set, PLL_UPDATE will be cleared 66062306a36Sopenharmony_ci * automatically by hardware when PLL_ACK_LATCH is asserted by PLL. 66162306a36Sopenharmony_ci */ 66262306a36Sopenharmony_ci if (mode & PLL_UPDATE_BYPASS) { 66362306a36Sopenharmony_ci ret = wait_for_pll_update_ack_set(pll); 66462306a36Sopenharmony_ci if (ret) 66562306a36Sopenharmony_ci return ret; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_UPDATE, 0); 66862306a36Sopenharmony_ci } else { 66962306a36Sopenharmony_ci ret = wait_for_pll_update(pll); 67062306a36Sopenharmony_ci if (ret) 67162306a36Sopenharmony_ci return ret; 67262306a36Sopenharmony_ci } 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci ret = wait_for_pll_update_ack_clear(pll); 67562306a36Sopenharmony_ci if (ret) 67662306a36Sopenharmony_ci return ret; 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci /* Wait for PLL output to stabilize */ 67962306a36Sopenharmony_ci udelay(10); 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci return 0; 68262306a36Sopenharmony_ci} 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_cistatic int clk_alpha_pll_update_latch(struct clk_alpha_pll *pll, 68562306a36Sopenharmony_ci int (*is_enabled)(struct clk_hw *)) 68662306a36Sopenharmony_ci{ 68762306a36Sopenharmony_ci if (!is_enabled(&pll->clkr.hw) || 68862306a36Sopenharmony_ci !(pll->flags & SUPPORTS_DYNAMIC_UPDATE)) 68962306a36Sopenharmony_ci return 0; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci return __clk_alpha_pll_update_latch(pll); 69262306a36Sopenharmony_ci} 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_cistatic int __clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate, 69562306a36Sopenharmony_ci unsigned long prate, 69662306a36Sopenharmony_ci int (*is_enabled)(struct clk_hw *)) 69762306a36Sopenharmony_ci{ 69862306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 69962306a36Sopenharmony_ci const struct pll_vco *vco; 70062306a36Sopenharmony_ci u32 l, alpha_width = pll_alpha_width(pll); 70162306a36Sopenharmony_ci u64 a; 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci rate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); 70462306a36Sopenharmony_ci vco = alpha_pll_find_vco(pll, rate); 70562306a36Sopenharmony_ci if (pll->vco_table && !vco) { 70662306a36Sopenharmony_ci pr_err("%s: alpha pll not in a valid vco range\n", 70762306a36Sopenharmony_ci clk_hw_get_name(hw)); 70862306a36Sopenharmony_ci return -EINVAL; 70962306a36Sopenharmony_ci } 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci if (alpha_width > ALPHA_BITWIDTH) 71462306a36Sopenharmony_ci a <<= alpha_width - ALPHA_BITWIDTH; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci if (alpha_width > 32) 71762306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> 32); 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci if (vco) { 72262306a36Sopenharmony_ci regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), 72362306a36Sopenharmony_ci PLL_VCO_MASK << PLL_VCO_SHIFT, 72462306a36Sopenharmony_ci vco->val << PLL_VCO_SHIFT); 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), 72862306a36Sopenharmony_ci PLL_ALPHA_EN, PLL_ALPHA_EN); 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci return clk_alpha_pll_update_latch(pll, is_enabled); 73162306a36Sopenharmony_ci} 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_cistatic int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate, 73462306a36Sopenharmony_ci unsigned long prate) 73562306a36Sopenharmony_ci{ 73662306a36Sopenharmony_ci return __clk_alpha_pll_set_rate(hw, rate, prate, 73762306a36Sopenharmony_ci clk_alpha_pll_is_enabled); 73862306a36Sopenharmony_ci} 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_cistatic int clk_alpha_pll_hwfsm_set_rate(struct clk_hw *hw, unsigned long rate, 74162306a36Sopenharmony_ci unsigned long prate) 74262306a36Sopenharmony_ci{ 74362306a36Sopenharmony_ci return __clk_alpha_pll_set_rate(hw, rate, prate, 74462306a36Sopenharmony_ci clk_alpha_pll_hwfsm_is_enabled); 74562306a36Sopenharmony_ci} 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_cistatic long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate, 74862306a36Sopenharmony_ci unsigned long *prate) 74962306a36Sopenharmony_ci{ 75062306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 75162306a36Sopenharmony_ci u32 l, alpha_width = pll_alpha_width(pll); 75262306a36Sopenharmony_ci u64 a; 75362306a36Sopenharmony_ci unsigned long min_freq, max_freq; 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci rate = alpha_pll_round_rate(rate, *prate, &l, &a, alpha_width); 75662306a36Sopenharmony_ci if (!pll->vco_table || alpha_pll_find_vco(pll, rate)) 75762306a36Sopenharmony_ci return rate; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci min_freq = pll->vco_table[0].min_freq; 76062306a36Sopenharmony_ci max_freq = pll->vco_table[pll->num_vco - 1].max_freq; 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci return clamp(rate, min_freq, max_freq); 76362306a36Sopenharmony_ci} 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_cistatic unsigned long 76662306a36Sopenharmony_cialpha_huayra_pll_calc_rate(u64 prate, u32 l, u32 a) 76762306a36Sopenharmony_ci{ 76862306a36Sopenharmony_ci /* 76962306a36Sopenharmony_ci * a contains 16 bit alpha_val in two’s complement number in the range 77062306a36Sopenharmony_ci * of [-0.5, 0.5). 77162306a36Sopenharmony_ci */ 77262306a36Sopenharmony_ci if (a >= BIT(PLL_HUAYRA_ALPHA_WIDTH - 1)) 77362306a36Sopenharmony_ci l -= 1; 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci return (prate * l) + (prate * a >> PLL_HUAYRA_ALPHA_WIDTH); 77662306a36Sopenharmony_ci} 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_cistatic unsigned long 77962306a36Sopenharmony_cialpha_huayra_pll_round_rate(unsigned long rate, unsigned long prate, 78062306a36Sopenharmony_ci u32 *l, u32 *a) 78162306a36Sopenharmony_ci{ 78262306a36Sopenharmony_ci u64 remainder; 78362306a36Sopenharmony_ci u64 quotient; 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci quotient = rate; 78662306a36Sopenharmony_ci remainder = do_div(quotient, prate); 78762306a36Sopenharmony_ci *l = quotient; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci if (!remainder) { 79062306a36Sopenharmony_ci *a = 0; 79162306a36Sopenharmony_ci return rate; 79262306a36Sopenharmony_ci } 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci quotient = remainder << PLL_HUAYRA_ALPHA_WIDTH; 79562306a36Sopenharmony_ci remainder = do_div(quotient, prate); 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci if (remainder) 79862306a36Sopenharmony_ci quotient++; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci /* 80162306a36Sopenharmony_ci * alpha_val should be in two’s complement number in the range 80262306a36Sopenharmony_ci * of [-0.5, 0.5) so if quotient >= 0.5 then increment the l value 80362306a36Sopenharmony_ci * since alpha value will be subtracted in this case. 80462306a36Sopenharmony_ci */ 80562306a36Sopenharmony_ci if (quotient >= BIT(PLL_HUAYRA_ALPHA_WIDTH - 1)) 80662306a36Sopenharmony_ci *l += 1; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci *a = quotient; 80962306a36Sopenharmony_ci return alpha_huayra_pll_calc_rate(prate, *l, *a); 81062306a36Sopenharmony_ci} 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_cistatic unsigned long 81362306a36Sopenharmony_cialpha_pll_huayra_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) 81462306a36Sopenharmony_ci{ 81562306a36Sopenharmony_ci u64 rate = parent_rate, tmp; 81662306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 81762306a36Sopenharmony_ci u32 l, alpha = 0, ctl, alpha_m, alpha_n; 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); 82062306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci if (ctl & PLL_ALPHA_EN) { 82362306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &alpha); 82462306a36Sopenharmony_ci /* 82562306a36Sopenharmony_ci * Depending upon alpha_mode, it can be treated as M/N value or 82662306a36Sopenharmony_ci * as a two’s complement number. When alpha_mode=1, 82762306a36Sopenharmony_ci * pll_alpha_val<15:8>=M and pll_apla_val<7:0>=N 82862306a36Sopenharmony_ci * 82962306a36Sopenharmony_ci * Fout=FIN*(L+(M/N)) 83062306a36Sopenharmony_ci * 83162306a36Sopenharmony_ci * M is a signed number (-128 to 127) and N is unsigned 83262306a36Sopenharmony_ci * (0 to 255). M/N has to be within +/-0.5. 83362306a36Sopenharmony_ci * 83462306a36Sopenharmony_ci * When alpha_mode=0, it is a two’s complement number in the 83562306a36Sopenharmony_ci * range [-0.5, 0.5). 83662306a36Sopenharmony_ci * 83762306a36Sopenharmony_ci * Fout=FIN*(L+(alpha_val)/2^16) 83862306a36Sopenharmony_ci * 83962306a36Sopenharmony_ci * where alpha_val is two’s complement number. 84062306a36Sopenharmony_ci */ 84162306a36Sopenharmony_ci if (!(ctl & PLL_ALPHA_MODE)) 84262306a36Sopenharmony_ci return alpha_huayra_pll_calc_rate(rate, l, alpha); 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci alpha_m = alpha >> PLL_HUAYRA_M_SHIFT & PLL_HUAYRA_M_MASK; 84562306a36Sopenharmony_ci alpha_n = alpha >> PLL_HUAYRA_N_SHIFT & PLL_HUAYRA_N_MASK; 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci rate *= l; 84862306a36Sopenharmony_ci tmp = parent_rate; 84962306a36Sopenharmony_ci if (alpha_m >= BIT(PLL_HUAYRA_M_WIDTH - 1)) { 85062306a36Sopenharmony_ci alpha_m = BIT(PLL_HUAYRA_M_WIDTH) - alpha_m; 85162306a36Sopenharmony_ci tmp *= alpha_m; 85262306a36Sopenharmony_ci do_div(tmp, alpha_n); 85362306a36Sopenharmony_ci rate -= tmp; 85462306a36Sopenharmony_ci } else { 85562306a36Sopenharmony_ci tmp *= alpha_m; 85662306a36Sopenharmony_ci do_div(tmp, alpha_n); 85762306a36Sopenharmony_ci rate += tmp; 85862306a36Sopenharmony_ci } 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci return rate; 86162306a36Sopenharmony_ci } 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci return alpha_huayra_pll_calc_rate(rate, l, alpha); 86462306a36Sopenharmony_ci} 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_cistatic int alpha_pll_huayra_set_rate(struct clk_hw *hw, unsigned long rate, 86762306a36Sopenharmony_ci unsigned long prate) 86862306a36Sopenharmony_ci{ 86962306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 87062306a36Sopenharmony_ci u32 l, a, ctl, cur_alpha = 0; 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci rate = alpha_huayra_pll_round_rate(rate, prate, &l, &a); 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci if (ctl & PLL_ALPHA_EN) 87762306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &cur_alpha); 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci /* 88062306a36Sopenharmony_ci * Huayra PLL supports PLL dynamic programming. User can change L_VAL, 88162306a36Sopenharmony_ci * without having to go through the power on sequence. 88262306a36Sopenharmony_ci */ 88362306a36Sopenharmony_ci if (clk_alpha_pll_is_enabled(hw)) { 88462306a36Sopenharmony_ci if (cur_alpha != a) { 88562306a36Sopenharmony_ci pr_err("%s: clock needs to be gated\n", 88662306a36Sopenharmony_ci clk_hw_get_name(hw)); 88762306a36Sopenharmony_ci return -EBUSY; 88862306a36Sopenharmony_ci } 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); 89162306a36Sopenharmony_ci /* Ensure that the write above goes to detect L val change. */ 89262306a36Sopenharmony_ci mb(); 89362306a36Sopenharmony_ci return wait_for_pll_enable_lock(pll); 89462306a36Sopenharmony_ci } 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); 89762306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci if (a == 0) 90062306a36Sopenharmony_ci regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), 90162306a36Sopenharmony_ci PLL_ALPHA_EN, 0x0); 90262306a36Sopenharmony_ci else 90362306a36Sopenharmony_ci regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), 90462306a36Sopenharmony_ci PLL_ALPHA_EN | PLL_ALPHA_MODE, PLL_ALPHA_EN); 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci return 0; 90762306a36Sopenharmony_ci} 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_cistatic long alpha_pll_huayra_round_rate(struct clk_hw *hw, unsigned long rate, 91062306a36Sopenharmony_ci unsigned long *prate) 91162306a36Sopenharmony_ci{ 91262306a36Sopenharmony_ci u32 l, a; 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci return alpha_huayra_pll_round_rate(rate, *prate, &l, &a); 91562306a36Sopenharmony_ci} 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_cistatic int trion_pll_is_enabled(struct clk_alpha_pll *pll, 91862306a36Sopenharmony_ci struct regmap *regmap) 91962306a36Sopenharmony_ci{ 92062306a36Sopenharmony_ci u32 mode_val, opmode_val; 92162306a36Sopenharmony_ci int ret; 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci ret = regmap_read(regmap, PLL_MODE(pll), &mode_val); 92462306a36Sopenharmony_ci ret |= regmap_read(regmap, PLL_OPMODE(pll), &opmode_val); 92562306a36Sopenharmony_ci if (ret) 92662306a36Sopenharmony_ci return 0; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci return ((opmode_val & PLL_RUN) && (mode_val & PLL_OUTCTRL)); 92962306a36Sopenharmony_ci} 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_cistatic int clk_trion_pll_is_enabled(struct clk_hw *hw) 93262306a36Sopenharmony_ci{ 93362306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci return trion_pll_is_enabled(pll, pll->clkr.regmap); 93662306a36Sopenharmony_ci} 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_cistatic int clk_trion_pll_enable(struct clk_hw *hw) 93962306a36Sopenharmony_ci{ 94062306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 94162306a36Sopenharmony_ci struct regmap *regmap = pll->clkr.regmap; 94262306a36Sopenharmony_ci u32 val; 94362306a36Sopenharmony_ci int ret; 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci ret = regmap_read(regmap, PLL_MODE(pll), &val); 94662306a36Sopenharmony_ci if (ret) 94762306a36Sopenharmony_ci return ret; 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci /* If in FSM mode, just vote for it */ 95062306a36Sopenharmony_ci if (val & PLL_VOTE_FSM_ENA) { 95162306a36Sopenharmony_ci ret = clk_enable_regmap(hw); 95262306a36Sopenharmony_ci if (ret) 95362306a36Sopenharmony_ci return ret; 95462306a36Sopenharmony_ci return wait_for_pll_enable_active(pll); 95562306a36Sopenharmony_ci } 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci /* Set operation mode to RUN */ 95862306a36Sopenharmony_ci regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN); 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci ret = wait_for_pll_enable_lock(pll); 96162306a36Sopenharmony_ci if (ret) 96262306a36Sopenharmony_ci return ret; 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci /* Enable the PLL outputs */ 96562306a36Sopenharmony_ci ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), 96662306a36Sopenharmony_ci PLL_OUT_MASK, PLL_OUT_MASK); 96762306a36Sopenharmony_ci if (ret) 96862306a36Sopenharmony_ci return ret; 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci /* Enable the global PLL outputs */ 97162306a36Sopenharmony_ci return regmap_update_bits(regmap, PLL_MODE(pll), 97262306a36Sopenharmony_ci PLL_OUTCTRL, PLL_OUTCTRL); 97362306a36Sopenharmony_ci} 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_cistatic void clk_trion_pll_disable(struct clk_hw *hw) 97662306a36Sopenharmony_ci{ 97762306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 97862306a36Sopenharmony_ci struct regmap *regmap = pll->clkr.regmap; 97962306a36Sopenharmony_ci u32 val; 98062306a36Sopenharmony_ci int ret; 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci ret = regmap_read(regmap, PLL_MODE(pll), &val); 98362306a36Sopenharmony_ci if (ret) 98462306a36Sopenharmony_ci return; 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci /* If in FSM mode, just unvote it */ 98762306a36Sopenharmony_ci if (val & PLL_VOTE_FSM_ENA) { 98862306a36Sopenharmony_ci clk_disable_regmap(hw); 98962306a36Sopenharmony_ci return; 99062306a36Sopenharmony_ci } 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci /* Disable the global PLL output */ 99362306a36Sopenharmony_ci ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); 99462306a36Sopenharmony_ci if (ret) 99562306a36Sopenharmony_ci return; 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci /* Disable the PLL outputs */ 99862306a36Sopenharmony_ci ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), 99962306a36Sopenharmony_ci PLL_OUT_MASK, 0); 100062306a36Sopenharmony_ci if (ret) 100162306a36Sopenharmony_ci return; 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_ci /* Place the PLL mode in STANDBY */ 100462306a36Sopenharmony_ci regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); 100562306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); 100662306a36Sopenharmony_ci} 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_cistatic unsigned long 100962306a36Sopenharmony_ciclk_trion_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) 101062306a36Sopenharmony_ci{ 101162306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 101262306a36Sopenharmony_ci u32 l, frac, alpha_width = pll_alpha_width(pll); 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); 101562306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &frac); 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width); 101862306a36Sopenharmony_ci} 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_fixed_ops = { 102162306a36Sopenharmony_ci .enable = clk_alpha_pll_enable, 102262306a36Sopenharmony_ci .disable = clk_alpha_pll_disable, 102362306a36Sopenharmony_ci .is_enabled = clk_alpha_pll_is_enabled, 102462306a36Sopenharmony_ci .recalc_rate = clk_alpha_pll_recalc_rate, 102562306a36Sopenharmony_ci}; 102662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_ops); 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_ops = { 102962306a36Sopenharmony_ci .enable = clk_alpha_pll_enable, 103062306a36Sopenharmony_ci .disable = clk_alpha_pll_disable, 103162306a36Sopenharmony_ci .is_enabled = clk_alpha_pll_is_enabled, 103262306a36Sopenharmony_ci .recalc_rate = clk_alpha_pll_recalc_rate, 103362306a36Sopenharmony_ci .round_rate = clk_alpha_pll_round_rate, 103462306a36Sopenharmony_ci .set_rate = clk_alpha_pll_set_rate, 103562306a36Sopenharmony_ci}; 103662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_ops); 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_huayra_ops = { 103962306a36Sopenharmony_ci .enable = clk_alpha_pll_enable, 104062306a36Sopenharmony_ci .disable = clk_alpha_pll_disable, 104162306a36Sopenharmony_ci .is_enabled = clk_alpha_pll_is_enabled, 104262306a36Sopenharmony_ci .recalc_rate = alpha_pll_huayra_recalc_rate, 104362306a36Sopenharmony_ci .round_rate = alpha_pll_huayra_round_rate, 104462306a36Sopenharmony_ci .set_rate = alpha_pll_huayra_set_rate, 104562306a36Sopenharmony_ci}; 104662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_huayra_ops); 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_hwfsm_ops = { 104962306a36Sopenharmony_ci .enable = clk_alpha_pll_hwfsm_enable, 105062306a36Sopenharmony_ci .disable = clk_alpha_pll_hwfsm_disable, 105162306a36Sopenharmony_ci .is_enabled = clk_alpha_pll_hwfsm_is_enabled, 105262306a36Sopenharmony_ci .recalc_rate = clk_alpha_pll_recalc_rate, 105362306a36Sopenharmony_ci .round_rate = clk_alpha_pll_round_rate, 105462306a36Sopenharmony_ci .set_rate = clk_alpha_pll_hwfsm_set_rate, 105562306a36Sopenharmony_ci}; 105662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops); 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_fixed_trion_ops = { 105962306a36Sopenharmony_ci .enable = clk_trion_pll_enable, 106062306a36Sopenharmony_ci .disable = clk_trion_pll_disable, 106162306a36Sopenharmony_ci .is_enabled = clk_trion_pll_is_enabled, 106262306a36Sopenharmony_ci .recalc_rate = clk_trion_pll_recalc_rate, 106362306a36Sopenharmony_ci .round_rate = clk_alpha_pll_round_rate, 106462306a36Sopenharmony_ci}; 106562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_trion_ops); 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_cistatic unsigned long 106862306a36Sopenharmony_ciclk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) 106962306a36Sopenharmony_ci{ 107062306a36Sopenharmony_ci struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); 107162306a36Sopenharmony_ci u32 ctl; 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci ctl >>= PLL_POST_DIV_SHIFT; 107662306a36Sopenharmony_ci ctl &= PLL_POST_DIV_MASK(pll); 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci return parent_rate >> fls(ctl); 107962306a36Sopenharmony_ci} 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_cistatic const struct clk_div_table clk_alpha_div_table[] = { 108262306a36Sopenharmony_ci { 0x0, 1 }, 108362306a36Sopenharmony_ci { 0x1, 2 }, 108462306a36Sopenharmony_ci { 0x3, 4 }, 108562306a36Sopenharmony_ci { 0x7, 8 }, 108662306a36Sopenharmony_ci { 0xf, 16 }, 108762306a36Sopenharmony_ci { } 108862306a36Sopenharmony_ci}; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_cistatic const struct clk_div_table clk_alpha_2bit_div_table[] = { 109162306a36Sopenharmony_ci { 0x0, 1 }, 109262306a36Sopenharmony_ci { 0x1, 2 }, 109362306a36Sopenharmony_ci { 0x3, 4 }, 109462306a36Sopenharmony_ci { } 109562306a36Sopenharmony_ci}; 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_cistatic long 109862306a36Sopenharmony_ciclk_alpha_pll_postdiv_round_rate(struct clk_hw *hw, unsigned long rate, 109962306a36Sopenharmony_ci unsigned long *prate) 110062306a36Sopenharmony_ci{ 110162306a36Sopenharmony_ci struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); 110262306a36Sopenharmony_ci const struct clk_div_table *table; 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci if (pll->width == 2) 110562306a36Sopenharmony_ci table = clk_alpha_2bit_div_table; 110662306a36Sopenharmony_ci else 110762306a36Sopenharmony_ci table = clk_alpha_div_table; 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci return divider_round_rate(hw, rate, prate, table, 111062306a36Sopenharmony_ci pll->width, CLK_DIVIDER_POWER_OF_TWO); 111162306a36Sopenharmony_ci} 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_cistatic long 111462306a36Sopenharmony_ciclk_alpha_pll_postdiv_round_ro_rate(struct clk_hw *hw, unsigned long rate, 111562306a36Sopenharmony_ci unsigned long *prate) 111662306a36Sopenharmony_ci{ 111762306a36Sopenharmony_ci struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); 111862306a36Sopenharmony_ci u32 ctl, div; 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &ctl); 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci ctl >>= PLL_POST_DIV_SHIFT; 112362306a36Sopenharmony_ci ctl &= BIT(pll->width) - 1; 112462306a36Sopenharmony_ci div = 1 << fls(ctl); 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) 112762306a36Sopenharmony_ci *prate = clk_hw_round_rate(clk_hw_get_parent(hw), div * rate); 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci return DIV_ROUND_UP_ULL((u64)*prate, div); 113062306a36Sopenharmony_ci} 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_cistatic int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, 113362306a36Sopenharmony_ci unsigned long parent_rate) 113462306a36Sopenharmony_ci{ 113562306a36Sopenharmony_ci struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); 113662306a36Sopenharmony_ci int div; 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci /* 16 -> 0xf, 8 -> 0x7, 4 -> 0x3, 2 -> 0x1, 1 -> 0x0 */ 113962306a36Sopenharmony_ci div = DIV_ROUND_UP_ULL(parent_rate, rate) - 1; 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci return regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), 114262306a36Sopenharmony_ci PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT, 114362306a36Sopenharmony_ci div << PLL_POST_DIV_SHIFT); 114462306a36Sopenharmony_ci} 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_postdiv_ops = { 114762306a36Sopenharmony_ci .recalc_rate = clk_alpha_pll_postdiv_recalc_rate, 114862306a36Sopenharmony_ci .round_rate = clk_alpha_pll_postdiv_round_rate, 114962306a36Sopenharmony_ci .set_rate = clk_alpha_pll_postdiv_set_rate, 115062306a36Sopenharmony_ci}; 115162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_ops); 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_postdiv_ro_ops = { 115462306a36Sopenharmony_ci .round_rate = clk_alpha_pll_postdiv_round_ro_rate, 115562306a36Sopenharmony_ci .recalc_rate = clk_alpha_pll_postdiv_recalc_rate, 115662306a36Sopenharmony_ci}; 115762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_ro_ops); 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_civoid clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, 116062306a36Sopenharmony_ci const struct alpha_pll_config *config) 116162306a36Sopenharmony_ci{ 116262306a36Sopenharmony_ci u32 val, mask; 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l); 116562306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_FRAC(pll), config->alpha); 116662306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), 116762306a36Sopenharmony_ci config->config_ctl_val); 116862306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), 116962306a36Sopenharmony_ci config->config_ctl_hi_val); 117062306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), 117162306a36Sopenharmony_ci config->user_ctl_val); 117262306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), 117362306a36Sopenharmony_ci config->user_ctl_hi_val); 117462306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), 117562306a36Sopenharmony_ci config->test_ctl_val); 117662306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), 117762306a36Sopenharmony_ci config->test_ctl_hi_val); 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci if (config->post_div_mask) { 118062306a36Sopenharmony_ci mask = config->post_div_mask; 118162306a36Sopenharmony_ci val = config->post_div_val; 118262306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_USER_CTL(pll), mask, val); 118362306a36Sopenharmony_ci } 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci if (pll->flags & SUPPORTS_FSM_LEGACY_MODE) 118662306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_FSM_LEGACY_MODE, 118762306a36Sopenharmony_ci PLL_FSM_LEGACY_MODE); 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_UPDATE_BYPASS, 119062306a36Sopenharmony_ci PLL_UPDATE_BYPASS); 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); 119362306a36Sopenharmony_ci} 119462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_fabia_pll_configure); 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_cistatic int alpha_pll_fabia_enable(struct clk_hw *hw) 119762306a36Sopenharmony_ci{ 119862306a36Sopenharmony_ci int ret; 119962306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 120062306a36Sopenharmony_ci u32 val, opmode_val; 120162306a36Sopenharmony_ci struct regmap *regmap = pll->clkr.regmap; 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci ret = regmap_read(regmap, PLL_MODE(pll), &val); 120462306a36Sopenharmony_ci if (ret) 120562306a36Sopenharmony_ci return ret; 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci /* If in FSM mode, just vote for it */ 120862306a36Sopenharmony_ci if (val & PLL_VOTE_FSM_ENA) { 120962306a36Sopenharmony_ci ret = clk_enable_regmap(hw); 121062306a36Sopenharmony_ci if (ret) 121162306a36Sopenharmony_ci return ret; 121262306a36Sopenharmony_ci return wait_for_pll_enable_active(pll); 121362306a36Sopenharmony_ci } 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci ret = regmap_read(regmap, PLL_OPMODE(pll), &opmode_val); 121662306a36Sopenharmony_ci if (ret) 121762306a36Sopenharmony_ci return ret; 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci /* Skip If PLL is already running */ 122062306a36Sopenharmony_ci if ((opmode_val & PLL_RUN) && (val & PLL_OUTCTRL)) 122162306a36Sopenharmony_ci return 0; 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); 122462306a36Sopenharmony_ci if (ret) 122562306a36Sopenharmony_ci return ret; 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci ret = regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); 122862306a36Sopenharmony_ci if (ret) 122962306a36Sopenharmony_ci return ret; 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, 123262306a36Sopenharmony_ci PLL_RESET_N); 123362306a36Sopenharmony_ci if (ret) 123462306a36Sopenharmony_ci return ret; 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci ret = regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN); 123762306a36Sopenharmony_ci if (ret) 123862306a36Sopenharmony_ci return ret; 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci ret = wait_for_pll_enable_lock(pll); 124162306a36Sopenharmony_ci if (ret) 124262306a36Sopenharmony_ci return ret; 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), 124562306a36Sopenharmony_ci PLL_OUT_MASK, PLL_OUT_MASK); 124662306a36Sopenharmony_ci if (ret) 124762306a36Sopenharmony_ci return ret; 124862306a36Sopenharmony_ci 124962306a36Sopenharmony_ci return regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 125062306a36Sopenharmony_ci PLL_OUTCTRL); 125162306a36Sopenharmony_ci} 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_cistatic void alpha_pll_fabia_disable(struct clk_hw *hw) 125462306a36Sopenharmony_ci{ 125562306a36Sopenharmony_ci int ret; 125662306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 125762306a36Sopenharmony_ci u32 val; 125862306a36Sopenharmony_ci struct regmap *regmap = pll->clkr.regmap; 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci ret = regmap_read(regmap, PLL_MODE(pll), &val); 126162306a36Sopenharmony_ci if (ret) 126262306a36Sopenharmony_ci return; 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci /* If in FSM mode, just unvote it */ 126562306a36Sopenharmony_ci if (val & PLL_FSM_ENA) { 126662306a36Sopenharmony_ci clk_disable_regmap(hw); 126762306a36Sopenharmony_ci return; 126862306a36Sopenharmony_ci } 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); 127162306a36Sopenharmony_ci if (ret) 127262306a36Sopenharmony_ci return; 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci /* Disable main outputs */ 127562306a36Sopenharmony_ci ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, 0); 127662306a36Sopenharmony_ci if (ret) 127762306a36Sopenharmony_ci return; 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci /* Place the PLL in STANDBY */ 128062306a36Sopenharmony_ci regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); 128162306a36Sopenharmony_ci} 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_cistatic unsigned long alpha_pll_fabia_recalc_rate(struct clk_hw *hw, 128462306a36Sopenharmony_ci unsigned long parent_rate) 128562306a36Sopenharmony_ci{ 128662306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 128762306a36Sopenharmony_ci u32 l, frac, alpha_width = pll_alpha_width(pll); 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); 129062306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_FRAC(pll), &frac); 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_ci return alpha_pll_calc_rate(parent_rate, l, frac, alpha_width); 129362306a36Sopenharmony_ci} 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci/* 129662306a36Sopenharmony_ci * Due to limited number of bits for fractional rate programming, the 129762306a36Sopenharmony_ci * rounded up rate could be marginally higher than the requested rate. 129862306a36Sopenharmony_ci */ 129962306a36Sopenharmony_cistatic int alpha_pll_check_rate_margin(struct clk_hw *hw, 130062306a36Sopenharmony_ci unsigned long rrate, unsigned long rate) 130162306a36Sopenharmony_ci{ 130262306a36Sopenharmony_ci unsigned long rate_margin = rate + PLL_RATE_MARGIN; 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci if (rrate > rate_margin || rrate < rate) { 130562306a36Sopenharmony_ci pr_err("%s: Rounded rate %lu not within range [%lu, %lu)\n", 130662306a36Sopenharmony_ci clk_hw_get_name(hw), rrate, rate, rate_margin); 130762306a36Sopenharmony_ci return -EINVAL; 130862306a36Sopenharmony_ci } 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_ci return 0; 131162306a36Sopenharmony_ci} 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_cistatic int alpha_pll_fabia_set_rate(struct clk_hw *hw, unsigned long rate, 131462306a36Sopenharmony_ci unsigned long prate) 131562306a36Sopenharmony_ci{ 131662306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 131762306a36Sopenharmony_ci u32 l, alpha_width = pll_alpha_width(pll); 131862306a36Sopenharmony_ci unsigned long rrate; 131962306a36Sopenharmony_ci int ret; 132062306a36Sopenharmony_ci u64 a; 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_ci ret = alpha_pll_check_rate_margin(hw, rrate, rate); 132562306a36Sopenharmony_ci if (ret < 0) 132662306a36Sopenharmony_ci return ret; 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); 132962306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_FRAC(pll), a); 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_ci return __clk_alpha_pll_update_latch(pll); 133262306a36Sopenharmony_ci} 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_cistatic int alpha_pll_fabia_prepare(struct clk_hw *hw) 133562306a36Sopenharmony_ci{ 133662306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 133762306a36Sopenharmony_ci const struct pll_vco *vco; 133862306a36Sopenharmony_ci struct clk_hw *parent_hw; 133962306a36Sopenharmony_ci unsigned long cal_freq, rrate; 134062306a36Sopenharmony_ci u32 cal_l, val, alpha_width = pll_alpha_width(pll); 134162306a36Sopenharmony_ci const char *name = clk_hw_get_name(hw); 134262306a36Sopenharmony_ci u64 a; 134362306a36Sopenharmony_ci int ret; 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci /* Check if calibration needs to be done i.e. PLL is in reset */ 134662306a36Sopenharmony_ci ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); 134762306a36Sopenharmony_ci if (ret) 134862306a36Sopenharmony_ci return ret; 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci /* Return early if calibration is not needed. */ 135162306a36Sopenharmony_ci if (val & PLL_RESET_N) 135262306a36Sopenharmony_ci return 0; 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_ci vco = alpha_pll_find_vco(pll, clk_hw_get_rate(hw)); 135562306a36Sopenharmony_ci if (!vco) { 135662306a36Sopenharmony_ci pr_err("%s: alpha pll not in a valid vco range\n", name); 135762306a36Sopenharmony_ci return -EINVAL; 135862306a36Sopenharmony_ci } 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci cal_freq = DIV_ROUND_CLOSEST((pll->vco_table[0].min_freq + 136162306a36Sopenharmony_ci pll->vco_table[0].max_freq) * 54, 100); 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci parent_hw = clk_hw_get_parent(hw); 136462306a36Sopenharmony_ci if (!parent_hw) 136562306a36Sopenharmony_ci return -EINVAL; 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_ci rrate = alpha_pll_round_rate(cal_freq, clk_hw_get_rate(parent_hw), 136862306a36Sopenharmony_ci &cal_l, &a, alpha_width); 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci ret = alpha_pll_check_rate_margin(hw, rrate, cal_freq); 137162306a36Sopenharmony_ci if (ret < 0) 137262306a36Sopenharmony_ci return ret; 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci /* Setup PLL for calibration frequency */ 137562306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_CAL_L_VAL(pll), cal_l); 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci /* Bringup the PLL at calibration frequency */ 137862306a36Sopenharmony_ci ret = clk_alpha_pll_enable(hw); 137962306a36Sopenharmony_ci if (ret) { 138062306a36Sopenharmony_ci pr_err("%s: alpha pll calibration failed\n", name); 138162306a36Sopenharmony_ci return ret; 138262306a36Sopenharmony_ci } 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci clk_alpha_pll_disable(hw); 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci return 0; 138762306a36Sopenharmony_ci} 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_fabia_ops = { 139062306a36Sopenharmony_ci .prepare = alpha_pll_fabia_prepare, 139162306a36Sopenharmony_ci .enable = alpha_pll_fabia_enable, 139262306a36Sopenharmony_ci .disable = alpha_pll_fabia_disable, 139362306a36Sopenharmony_ci .is_enabled = clk_alpha_pll_is_enabled, 139462306a36Sopenharmony_ci .set_rate = alpha_pll_fabia_set_rate, 139562306a36Sopenharmony_ci .recalc_rate = alpha_pll_fabia_recalc_rate, 139662306a36Sopenharmony_ci .round_rate = clk_alpha_pll_round_rate, 139762306a36Sopenharmony_ci}; 139862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_fabia_ops); 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_fixed_fabia_ops = { 140162306a36Sopenharmony_ci .enable = alpha_pll_fabia_enable, 140262306a36Sopenharmony_ci .disable = alpha_pll_fabia_disable, 140362306a36Sopenharmony_ci .is_enabled = clk_alpha_pll_is_enabled, 140462306a36Sopenharmony_ci .recalc_rate = alpha_pll_fabia_recalc_rate, 140562306a36Sopenharmony_ci .round_rate = clk_alpha_pll_round_rate, 140662306a36Sopenharmony_ci}; 140762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_fabia_ops); 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_cistatic unsigned long clk_alpha_pll_postdiv_fabia_recalc_rate(struct clk_hw *hw, 141062306a36Sopenharmony_ci unsigned long parent_rate) 141162306a36Sopenharmony_ci{ 141262306a36Sopenharmony_ci struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); 141362306a36Sopenharmony_ci u32 i, div = 1, val; 141462306a36Sopenharmony_ci int ret; 141562306a36Sopenharmony_ci 141662306a36Sopenharmony_ci ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val); 141762306a36Sopenharmony_ci if (ret) 141862306a36Sopenharmony_ci return ret; 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_ci val >>= pll->post_div_shift; 142162306a36Sopenharmony_ci val &= BIT(pll->width) - 1; 142262306a36Sopenharmony_ci 142362306a36Sopenharmony_ci for (i = 0; i < pll->num_post_div; i++) { 142462306a36Sopenharmony_ci if (pll->post_div_table[i].val == val) { 142562306a36Sopenharmony_ci div = pll->post_div_table[i].div; 142662306a36Sopenharmony_ci break; 142762306a36Sopenharmony_ci } 142862306a36Sopenharmony_ci } 142962306a36Sopenharmony_ci 143062306a36Sopenharmony_ci return (parent_rate / div); 143162306a36Sopenharmony_ci} 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_cistatic unsigned long 143462306a36Sopenharmony_ciclk_trion_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) 143562306a36Sopenharmony_ci{ 143662306a36Sopenharmony_ci struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); 143762306a36Sopenharmony_ci struct regmap *regmap = pll->clkr.regmap; 143862306a36Sopenharmony_ci u32 i, div = 1, val; 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci regmap_read(regmap, PLL_USER_CTL(pll), &val); 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_ci val >>= pll->post_div_shift; 144362306a36Sopenharmony_ci val &= PLL_POST_DIV_MASK(pll); 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_ci for (i = 0; i < pll->num_post_div; i++) { 144662306a36Sopenharmony_ci if (pll->post_div_table[i].val == val) { 144762306a36Sopenharmony_ci div = pll->post_div_table[i].div; 144862306a36Sopenharmony_ci break; 144962306a36Sopenharmony_ci } 145062306a36Sopenharmony_ci } 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ci return (parent_rate / div); 145362306a36Sopenharmony_ci} 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_cistatic long 145662306a36Sopenharmony_ciclk_trion_pll_postdiv_round_rate(struct clk_hw *hw, unsigned long rate, 145762306a36Sopenharmony_ci unsigned long *prate) 145862306a36Sopenharmony_ci{ 145962306a36Sopenharmony_ci struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci return divider_round_rate(hw, rate, prate, pll->post_div_table, 146262306a36Sopenharmony_ci pll->width, CLK_DIVIDER_ROUND_CLOSEST); 146362306a36Sopenharmony_ci}; 146462306a36Sopenharmony_ci 146562306a36Sopenharmony_cistatic int 146662306a36Sopenharmony_ciclk_trion_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, 146762306a36Sopenharmony_ci unsigned long parent_rate) 146862306a36Sopenharmony_ci{ 146962306a36Sopenharmony_ci struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); 147062306a36Sopenharmony_ci struct regmap *regmap = pll->clkr.regmap; 147162306a36Sopenharmony_ci int i, val = 0, div; 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci div = DIV_ROUND_UP_ULL(parent_rate, rate); 147462306a36Sopenharmony_ci for (i = 0; i < pll->num_post_div; i++) { 147562306a36Sopenharmony_ci if (pll->post_div_table[i].div == div) { 147662306a36Sopenharmony_ci val = pll->post_div_table[i].val; 147762306a36Sopenharmony_ci break; 147862306a36Sopenharmony_ci } 147962306a36Sopenharmony_ci } 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci return regmap_update_bits(regmap, PLL_USER_CTL(pll), 148262306a36Sopenharmony_ci PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT, 148362306a36Sopenharmony_ci val << PLL_POST_DIV_SHIFT); 148462306a36Sopenharmony_ci} 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_postdiv_trion_ops = { 148762306a36Sopenharmony_ci .recalc_rate = clk_trion_pll_postdiv_recalc_rate, 148862306a36Sopenharmony_ci .round_rate = clk_trion_pll_postdiv_round_rate, 148962306a36Sopenharmony_ci .set_rate = clk_trion_pll_postdiv_set_rate, 149062306a36Sopenharmony_ci}; 149162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_trion_ops); 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_cistatic long clk_alpha_pll_postdiv_fabia_round_rate(struct clk_hw *hw, 149462306a36Sopenharmony_ci unsigned long rate, unsigned long *prate) 149562306a36Sopenharmony_ci{ 149662306a36Sopenharmony_ci struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci return divider_round_rate(hw, rate, prate, pll->post_div_table, 149962306a36Sopenharmony_ci pll->width, CLK_DIVIDER_ROUND_CLOSEST); 150062306a36Sopenharmony_ci} 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_cistatic int clk_alpha_pll_postdiv_fabia_set_rate(struct clk_hw *hw, 150362306a36Sopenharmony_ci unsigned long rate, unsigned long parent_rate) 150462306a36Sopenharmony_ci{ 150562306a36Sopenharmony_ci struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); 150662306a36Sopenharmony_ci int i, val = 0, div, ret; 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci /* 150962306a36Sopenharmony_ci * If the PLL is in FSM mode, then treat set_rate callback as a 151062306a36Sopenharmony_ci * no-operation. 151162306a36Sopenharmony_ci */ 151262306a36Sopenharmony_ci ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); 151362306a36Sopenharmony_ci if (ret) 151462306a36Sopenharmony_ci return ret; 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci if (val & PLL_VOTE_FSM_ENA) 151762306a36Sopenharmony_ci return 0; 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci div = DIV_ROUND_UP_ULL(parent_rate, rate); 152062306a36Sopenharmony_ci for (i = 0; i < pll->num_post_div; i++) { 152162306a36Sopenharmony_ci if (pll->post_div_table[i].div == div) { 152262306a36Sopenharmony_ci val = pll->post_div_table[i].val; 152362306a36Sopenharmony_ci break; 152462306a36Sopenharmony_ci } 152562306a36Sopenharmony_ci } 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci return regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), 152862306a36Sopenharmony_ci (BIT(pll->width) - 1) << pll->post_div_shift, 152962306a36Sopenharmony_ci val << pll->post_div_shift); 153062306a36Sopenharmony_ci} 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_postdiv_fabia_ops = { 153362306a36Sopenharmony_ci .recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate, 153462306a36Sopenharmony_ci .round_rate = clk_alpha_pll_postdiv_fabia_round_rate, 153562306a36Sopenharmony_ci .set_rate = clk_alpha_pll_postdiv_fabia_set_rate, 153662306a36Sopenharmony_ci}; 153762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_fabia_ops); 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_ci/** 154062306a36Sopenharmony_ci * clk_trion_pll_configure - configure the trion pll 154162306a36Sopenharmony_ci * 154262306a36Sopenharmony_ci * @pll: clk alpha pll 154362306a36Sopenharmony_ci * @regmap: register map 154462306a36Sopenharmony_ci * @config: configuration to apply for pll 154562306a36Sopenharmony_ci */ 154662306a36Sopenharmony_civoid clk_trion_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, 154762306a36Sopenharmony_ci const struct alpha_pll_config *config) 154862306a36Sopenharmony_ci{ 154962306a36Sopenharmony_ci /* 155062306a36Sopenharmony_ci * If the bootloader left the PLL enabled it's likely that there are 155162306a36Sopenharmony_ci * RCGs that will lock up if we disable the PLL below. 155262306a36Sopenharmony_ci */ 155362306a36Sopenharmony_ci if (trion_pll_is_enabled(pll, regmap)) { 155462306a36Sopenharmony_ci pr_debug("Trion PLL is already enabled, skipping configuration\n"); 155562306a36Sopenharmony_ci return; 155662306a36Sopenharmony_ci } 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l); 155962306a36Sopenharmony_ci regmap_write(regmap, PLL_CAL_L_VAL(pll), TRION_PLL_CAL_VAL); 156062306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha); 156162306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), 156262306a36Sopenharmony_ci config->config_ctl_val); 156362306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), 156462306a36Sopenharmony_ci config->config_ctl_hi_val); 156562306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), 156662306a36Sopenharmony_ci config->config_ctl_hi1_val); 156762306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), 156862306a36Sopenharmony_ci config->user_ctl_val); 156962306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), 157062306a36Sopenharmony_ci config->user_ctl_hi_val); 157162306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U1(pll), 157262306a36Sopenharmony_ci config->user_ctl_hi1_val); 157362306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), 157462306a36Sopenharmony_ci config->test_ctl_val); 157562306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), 157662306a36Sopenharmony_ci config->test_ctl_hi_val); 157762306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), 157862306a36Sopenharmony_ci config->test_ctl_hi1_val); 157962306a36Sopenharmony_ci 158062306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_UPDATE_BYPASS, 158162306a36Sopenharmony_ci PLL_UPDATE_BYPASS); 158262306a36Sopenharmony_ci 158362306a36Sopenharmony_ci /* Disable PLL output */ 158462306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); 158562306a36Sopenharmony_ci 158662306a36Sopenharmony_ci /* Set operation mode to OFF */ 158762306a36Sopenharmony_ci regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_ci /* Place the PLL in STANDBY mode */ 159062306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); 159162306a36Sopenharmony_ci} 159262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_trion_pll_configure); 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci/* 159562306a36Sopenharmony_ci * The TRION PLL requires a power-on self-calibration which happens when the 159662306a36Sopenharmony_ci * PLL comes out of reset. Calibrate in case it is not completed. 159762306a36Sopenharmony_ci */ 159862306a36Sopenharmony_cistatic int __alpha_pll_trion_prepare(struct clk_hw *hw, u32 pcal_done) 159962306a36Sopenharmony_ci{ 160062306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 160162306a36Sopenharmony_ci u32 val; 160262306a36Sopenharmony_ci int ret; 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci /* Return early if calibration is not needed. */ 160562306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_STATUS(pll), &val); 160662306a36Sopenharmony_ci if (val & pcal_done) 160762306a36Sopenharmony_ci return 0; 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci /* On/off to calibrate */ 161062306a36Sopenharmony_ci ret = clk_trion_pll_enable(hw); 161162306a36Sopenharmony_ci if (!ret) 161262306a36Sopenharmony_ci clk_trion_pll_disable(hw); 161362306a36Sopenharmony_ci 161462306a36Sopenharmony_ci return ret; 161562306a36Sopenharmony_ci} 161662306a36Sopenharmony_ci 161762306a36Sopenharmony_cistatic int alpha_pll_trion_prepare(struct clk_hw *hw) 161862306a36Sopenharmony_ci{ 161962306a36Sopenharmony_ci return __alpha_pll_trion_prepare(hw, TRION_PCAL_DONE); 162062306a36Sopenharmony_ci} 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_cistatic int alpha_pll_lucid_prepare(struct clk_hw *hw) 162362306a36Sopenharmony_ci{ 162462306a36Sopenharmony_ci return __alpha_pll_trion_prepare(hw, LUCID_PCAL_DONE); 162562306a36Sopenharmony_ci} 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_cistatic int __alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate, 162862306a36Sopenharmony_ci unsigned long prate, u32 latch_bit, u32 latch_ack) 162962306a36Sopenharmony_ci{ 163062306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 163162306a36Sopenharmony_ci unsigned long rrate; 163262306a36Sopenharmony_ci u32 val, l, alpha_width = pll_alpha_width(pll); 163362306a36Sopenharmony_ci u64 a; 163462306a36Sopenharmony_ci int ret; 163562306a36Sopenharmony_ci 163662306a36Sopenharmony_ci rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); 163762306a36Sopenharmony_ci 163862306a36Sopenharmony_ci ret = alpha_pll_check_rate_margin(hw, rrate, rate); 163962306a36Sopenharmony_ci if (ret < 0) 164062306a36Sopenharmony_ci return ret; 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); 164362306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci /* Latch the PLL input */ 164662306a36Sopenharmony_ci ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), latch_bit, latch_bit); 164762306a36Sopenharmony_ci if (ret) 164862306a36Sopenharmony_ci return ret; 164962306a36Sopenharmony_ci 165062306a36Sopenharmony_ci /* Wait for 2 reference cycles before checking the ACK bit. */ 165162306a36Sopenharmony_ci udelay(1); 165262306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); 165362306a36Sopenharmony_ci if (!(val & latch_ack)) { 165462306a36Sopenharmony_ci pr_err("Lucid PLL latch failed. Output may be unstable!\n"); 165562306a36Sopenharmony_ci return -EINVAL; 165662306a36Sopenharmony_ci } 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci /* Return the latch input to 0 */ 165962306a36Sopenharmony_ci ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), latch_bit, 0); 166062306a36Sopenharmony_ci if (ret) 166162306a36Sopenharmony_ci return ret; 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ci if (clk_hw_is_enabled(hw)) { 166462306a36Sopenharmony_ci ret = wait_for_pll_enable_lock(pll); 166562306a36Sopenharmony_ci if (ret) 166662306a36Sopenharmony_ci return ret; 166762306a36Sopenharmony_ci } 166862306a36Sopenharmony_ci 166962306a36Sopenharmony_ci /* Wait for PLL output to stabilize */ 167062306a36Sopenharmony_ci udelay(100); 167162306a36Sopenharmony_ci return 0; 167262306a36Sopenharmony_ci} 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_cistatic int alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate, 167562306a36Sopenharmony_ci unsigned long prate) 167662306a36Sopenharmony_ci{ 167762306a36Sopenharmony_ci return __alpha_pll_trion_set_rate(hw, rate, prate, PLL_UPDATE, ALPHA_PLL_ACK_LATCH); 167862306a36Sopenharmony_ci} 167962306a36Sopenharmony_ci 168062306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_trion_ops = { 168162306a36Sopenharmony_ci .prepare = alpha_pll_trion_prepare, 168262306a36Sopenharmony_ci .enable = clk_trion_pll_enable, 168362306a36Sopenharmony_ci .disable = clk_trion_pll_disable, 168462306a36Sopenharmony_ci .is_enabled = clk_trion_pll_is_enabled, 168562306a36Sopenharmony_ci .recalc_rate = clk_trion_pll_recalc_rate, 168662306a36Sopenharmony_ci .round_rate = clk_alpha_pll_round_rate, 168762306a36Sopenharmony_ci .set_rate = alpha_pll_trion_set_rate, 168862306a36Sopenharmony_ci}; 168962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_trion_ops); 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_lucid_ops = { 169262306a36Sopenharmony_ci .prepare = alpha_pll_lucid_prepare, 169362306a36Sopenharmony_ci .enable = clk_trion_pll_enable, 169462306a36Sopenharmony_ci .disable = clk_trion_pll_disable, 169562306a36Sopenharmony_ci .is_enabled = clk_trion_pll_is_enabled, 169662306a36Sopenharmony_ci .recalc_rate = clk_trion_pll_recalc_rate, 169762306a36Sopenharmony_ci .round_rate = clk_alpha_pll_round_rate, 169862306a36Sopenharmony_ci .set_rate = alpha_pll_trion_set_rate, 169962306a36Sopenharmony_ci}; 170062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_lucid_ops); 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_postdiv_lucid_ops = { 170362306a36Sopenharmony_ci .recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate, 170462306a36Sopenharmony_ci .round_rate = clk_alpha_pll_postdiv_fabia_round_rate, 170562306a36Sopenharmony_ci .set_rate = clk_alpha_pll_postdiv_fabia_set_rate, 170662306a36Sopenharmony_ci}; 170762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_lucid_ops); 170862306a36Sopenharmony_ci 170962306a36Sopenharmony_civoid clk_agera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, 171062306a36Sopenharmony_ci const struct alpha_pll_config *config) 171162306a36Sopenharmony_ci{ 171262306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l); 171362306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha); 171462306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), 171562306a36Sopenharmony_ci config->user_ctl_val); 171662306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), 171762306a36Sopenharmony_ci config->config_ctl_val); 171862306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), 171962306a36Sopenharmony_ci config->config_ctl_hi_val); 172062306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), 172162306a36Sopenharmony_ci config->test_ctl_val); 172262306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), 172362306a36Sopenharmony_ci config->test_ctl_hi_val); 172462306a36Sopenharmony_ci} 172562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_agera_pll_configure); 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_cistatic int clk_alpha_pll_agera_set_rate(struct clk_hw *hw, unsigned long rate, 172862306a36Sopenharmony_ci unsigned long prate) 172962306a36Sopenharmony_ci{ 173062306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 173162306a36Sopenharmony_ci u32 l, alpha_width = pll_alpha_width(pll); 173262306a36Sopenharmony_ci int ret; 173362306a36Sopenharmony_ci unsigned long rrate; 173462306a36Sopenharmony_ci u64 a; 173562306a36Sopenharmony_ci 173662306a36Sopenharmony_ci rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); 173762306a36Sopenharmony_ci ret = alpha_pll_check_rate_margin(hw, rrate, rate); 173862306a36Sopenharmony_ci if (ret < 0) 173962306a36Sopenharmony_ci return ret; 174062306a36Sopenharmony_ci 174162306a36Sopenharmony_ci /* change L_VAL without having to go through the power on sequence */ 174262306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); 174362306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); 174462306a36Sopenharmony_ci 174562306a36Sopenharmony_ci if (clk_hw_is_enabled(hw)) 174662306a36Sopenharmony_ci return wait_for_pll_enable_lock(pll); 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_ci return 0; 174962306a36Sopenharmony_ci} 175062306a36Sopenharmony_ci 175162306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_agera_ops = { 175262306a36Sopenharmony_ci .enable = clk_alpha_pll_enable, 175362306a36Sopenharmony_ci .disable = clk_alpha_pll_disable, 175462306a36Sopenharmony_ci .is_enabled = clk_alpha_pll_is_enabled, 175562306a36Sopenharmony_ci .recalc_rate = alpha_pll_fabia_recalc_rate, 175662306a36Sopenharmony_ci .round_rate = clk_alpha_pll_round_rate, 175762306a36Sopenharmony_ci .set_rate = clk_alpha_pll_agera_set_rate, 175862306a36Sopenharmony_ci}; 175962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_agera_ops); 176062306a36Sopenharmony_ci 176162306a36Sopenharmony_cistatic int alpha_pll_lucid_5lpe_enable(struct clk_hw *hw) 176262306a36Sopenharmony_ci{ 176362306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 176462306a36Sopenharmony_ci u32 val; 176562306a36Sopenharmony_ci int ret; 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_ci ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val); 176862306a36Sopenharmony_ci if (ret) 176962306a36Sopenharmony_ci return ret; 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_ci /* If in FSM mode, just vote for it */ 177262306a36Sopenharmony_ci if (val & LUCID_5LPE_ENABLE_VOTE_RUN) { 177362306a36Sopenharmony_ci ret = clk_enable_regmap(hw); 177462306a36Sopenharmony_ci if (ret) 177562306a36Sopenharmony_ci return ret; 177662306a36Sopenharmony_ci return wait_for_pll_enable_lock(pll); 177762306a36Sopenharmony_ci } 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci /* Check if PLL is already enabled, return if enabled */ 178062306a36Sopenharmony_ci ret = trion_pll_is_enabled(pll, pll->clkr.regmap); 178162306a36Sopenharmony_ci if (ret < 0) 178262306a36Sopenharmony_ci return ret; 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); 178562306a36Sopenharmony_ci if (ret) 178662306a36Sopenharmony_ci return ret; 178762306a36Sopenharmony_ci 178862306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), PLL_RUN); 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci ret = wait_for_pll_enable_lock(pll); 179162306a36Sopenharmony_ci if (ret) 179262306a36Sopenharmony_ci return ret; 179362306a36Sopenharmony_ci 179462306a36Sopenharmony_ci /* Enable the PLL outputs */ 179562306a36Sopenharmony_ci ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, PLL_OUT_MASK); 179662306a36Sopenharmony_ci if (ret) 179762306a36Sopenharmony_ci return ret; 179862306a36Sopenharmony_ci 179962306a36Sopenharmony_ci /* Enable the global PLL outputs */ 180062306a36Sopenharmony_ci return regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL); 180162306a36Sopenharmony_ci} 180262306a36Sopenharmony_ci 180362306a36Sopenharmony_cistatic void alpha_pll_lucid_5lpe_disable(struct clk_hw *hw) 180462306a36Sopenharmony_ci{ 180562306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 180662306a36Sopenharmony_ci u32 val; 180762306a36Sopenharmony_ci int ret; 180862306a36Sopenharmony_ci 180962306a36Sopenharmony_ci ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val); 181062306a36Sopenharmony_ci if (ret) 181162306a36Sopenharmony_ci return; 181262306a36Sopenharmony_ci 181362306a36Sopenharmony_ci /* If in FSM mode, just unvote it */ 181462306a36Sopenharmony_ci if (val & LUCID_5LPE_ENABLE_VOTE_RUN) { 181562306a36Sopenharmony_ci clk_disable_regmap(hw); 181662306a36Sopenharmony_ci return; 181762306a36Sopenharmony_ci } 181862306a36Sopenharmony_ci 181962306a36Sopenharmony_ci /* Disable the global PLL output */ 182062306a36Sopenharmony_ci ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); 182162306a36Sopenharmony_ci if (ret) 182262306a36Sopenharmony_ci return; 182362306a36Sopenharmony_ci 182462306a36Sopenharmony_ci /* Disable the PLL outputs */ 182562306a36Sopenharmony_ci ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, 0); 182662306a36Sopenharmony_ci if (ret) 182762306a36Sopenharmony_ci return; 182862306a36Sopenharmony_ci 182962306a36Sopenharmony_ci /* Place the PLL mode in STANDBY */ 183062306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), PLL_STANDBY); 183162306a36Sopenharmony_ci} 183262306a36Sopenharmony_ci 183362306a36Sopenharmony_ci/* 183462306a36Sopenharmony_ci * The Lucid 5LPE PLL requires a power-on self-calibration which happens 183562306a36Sopenharmony_ci * when the PLL comes out of reset. Calibrate in case it is not completed. 183662306a36Sopenharmony_ci */ 183762306a36Sopenharmony_cistatic int alpha_pll_lucid_5lpe_prepare(struct clk_hw *hw) 183862306a36Sopenharmony_ci{ 183962306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 184062306a36Sopenharmony_ci struct clk_hw *p; 184162306a36Sopenharmony_ci u32 val = 0; 184262306a36Sopenharmony_ci int ret; 184362306a36Sopenharmony_ci 184462306a36Sopenharmony_ci /* Return early if calibration is not needed. */ 184562306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); 184662306a36Sopenharmony_ci if (val & LUCID_5LPE_PCAL_DONE) 184762306a36Sopenharmony_ci return 0; 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci p = clk_hw_get_parent(hw); 185062306a36Sopenharmony_ci if (!p) 185162306a36Sopenharmony_ci return -EINVAL; 185262306a36Sopenharmony_ci 185362306a36Sopenharmony_ci ret = alpha_pll_lucid_5lpe_enable(hw); 185462306a36Sopenharmony_ci if (ret) 185562306a36Sopenharmony_ci return ret; 185662306a36Sopenharmony_ci 185762306a36Sopenharmony_ci alpha_pll_lucid_5lpe_disable(hw); 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_ci return 0; 186062306a36Sopenharmony_ci} 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_cistatic int alpha_pll_lucid_5lpe_set_rate(struct clk_hw *hw, unsigned long rate, 186362306a36Sopenharmony_ci unsigned long prate) 186462306a36Sopenharmony_ci{ 186562306a36Sopenharmony_ci return __alpha_pll_trion_set_rate(hw, rate, prate, 186662306a36Sopenharmony_ci LUCID_5LPE_PLL_LATCH_INPUT, 186762306a36Sopenharmony_ci LUCID_5LPE_ALPHA_PLL_ACK_LATCH); 186862306a36Sopenharmony_ci} 186962306a36Sopenharmony_ci 187062306a36Sopenharmony_cistatic int __clk_lucid_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, 187162306a36Sopenharmony_ci unsigned long parent_rate, 187262306a36Sopenharmony_ci unsigned long enable_vote_run) 187362306a36Sopenharmony_ci{ 187462306a36Sopenharmony_ci struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw); 187562306a36Sopenharmony_ci struct regmap *regmap = pll->clkr.regmap; 187662306a36Sopenharmony_ci int i, val, div, ret; 187762306a36Sopenharmony_ci u32 mask; 187862306a36Sopenharmony_ci 187962306a36Sopenharmony_ci /* 188062306a36Sopenharmony_ci * If the PLL is in FSM mode, then treat set_rate callback as a 188162306a36Sopenharmony_ci * no-operation. 188262306a36Sopenharmony_ci */ 188362306a36Sopenharmony_ci ret = regmap_read(regmap, PLL_USER_CTL(pll), &val); 188462306a36Sopenharmony_ci if (ret) 188562306a36Sopenharmony_ci return ret; 188662306a36Sopenharmony_ci 188762306a36Sopenharmony_ci if (val & enable_vote_run) 188862306a36Sopenharmony_ci return 0; 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_ci if (!pll->post_div_table) { 189162306a36Sopenharmony_ci pr_err("Missing the post_div_table for the %s PLL\n", 189262306a36Sopenharmony_ci clk_hw_get_name(&pll->clkr.hw)); 189362306a36Sopenharmony_ci return -EINVAL; 189462306a36Sopenharmony_ci } 189562306a36Sopenharmony_ci 189662306a36Sopenharmony_ci div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); 189762306a36Sopenharmony_ci for (i = 0; i < pll->num_post_div; i++) { 189862306a36Sopenharmony_ci if (pll->post_div_table[i].div == div) { 189962306a36Sopenharmony_ci val = pll->post_div_table[i].val; 190062306a36Sopenharmony_ci break; 190162306a36Sopenharmony_ci } 190262306a36Sopenharmony_ci } 190362306a36Sopenharmony_ci 190462306a36Sopenharmony_ci mask = GENMASK(pll->width + pll->post_div_shift - 1, pll->post_div_shift); 190562306a36Sopenharmony_ci return regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), 190662306a36Sopenharmony_ci mask, val << pll->post_div_shift); 190762306a36Sopenharmony_ci} 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_cistatic int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, 191062306a36Sopenharmony_ci unsigned long parent_rate) 191162306a36Sopenharmony_ci{ 191262306a36Sopenharmony_ci return __clk_lucid_pll_postdiv_set_rate(hw, rate, parent_rate, LUCID_5LPE_ENABLE_VOTE_RUN); 191362306a36Sopenharmony_ci} 191462306a36Sopenharmony_ci 191562306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_lucid_5lpe_ops = { 191662306a36Sopenharmony_ci .prepare = alpha_pll_lucid_5lpe_prepare, 191762306a36Sopenharmony_ci .enable = alpha_pll_lucid_5lpe_enable, 191862306a36Sopenharmony_ci .disable = alpha_pll_lucid_5lpe_disable, 191962306a36Sopenharmony_ci .is_enabled = clk_trion_pll_is_enabled, 192062306a36Sopenharmony_ci .recalc_rate = clk_trion_pll_recalc_rate, 192162306a36Sopenharmony_ci .round_rate = clk_alpha_pll_round_rate, 192262306a36Sopenharmony_ci .set_rate = alpha_pll_lucid_5lpe_set_rate, 192362306a36Sopenharmony_ci}; 192462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_lucid_5lpe_ops); 192562306a36Sopenharmony_ci 192662306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_fixed_lucid_5lpe_ops = { 192762306a36Sopenharmony_ci .enable = alpha_pll_lucid_5lpe_enable, 192862306a36Sopenharmony_ci .disable = alpha_pll_lucid_5lpe_disable, 192962306a36Sopenharmony_ci .is_enabled = clk_trion_pll_is_enabled, 193062306a36Sopenharmony_ci .recalc_rate = clk_trion_pll_recalc_rate, 193162306a36Sopenharmony_ci .round_rate = clk_alpha_pll_round_rate, 193262306a36Sopenharmony_ci}; 193362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_lucid_5lpe_ops); 193462306a36Sopenharmony_ci 193562306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops = { 193662306a36Sopenharmony_ci .recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate, 193762306a36Sopenharmony_ci .round_rate = clk_alpha_pll_postdiv_fabia_round_rate, 193862306a36Sopenharmony_ci .set_rate = clk_lucid_5lpe_pll_postdiv_set_rate, 193962306a36Sopenharmony_ci}; 194062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_lucid_5lpe_ops); 194162306a36Sopenharmony_ci 194262306a36Sopenharmony_civoid clk_zonda_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, 194362306a36Sopenharmony_ci const struct alpha_pll_config *config) 194462306a36Sopenharmony_ci{ 194562306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l); 194662306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha); 194762306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val); 194862306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val); 194962306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val); 195062306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), config->user_ctl_val); 195162306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val); 195262306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U1(pll), config->user_ctl_hi1_val); 195362306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val); 195462306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val); 195562306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val); 195662306a36Sopenharmony_ci 195762306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_BYPASSNL, 0); 195862306a36Sopenharmony_ci 195962306a36Sopenharmony_ci /* Disable PLL output */ 196062306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); 196162306a36Sopenharmony_ci 196262306a36Sopenharmony_ci /* Set operation mode to OFF */ 196362306a36Sopenharmony_ci regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); 196462306a36Sopenharmony_ci 196562306a36Sopenharmony_ci /* Place the PLL in STANDBY mode */ 196662306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); 196762306a36Sopenharmony_ci} 196862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_zonda_pll_configure); 196962306a36Sopenharmony_ci 197062306a36Sopenharmony_cistatic int clk_zonda_pll_enable(struct clk_hw *hw) 197162306a36Sopenharmony_ci{ 197262306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 197362306a36Sopenharmony_ci struct regmap *regmap = pll->clkr.regmap; 197462306a36Sopenharmony_ci u32 val; 197562306a36Sopenharmony_ci int ret; 197662306a36Sopenharmony_ci 197762306a36Sopenharmony_ci regmap_read(regmap, PLL_MODE(pll), &val); 197862306a36Sopenharmony_ci 197962306a36Sopenharmony_ci /* If in FSM mode, just vote for it */ 198062306a36Sopenharmony_ci if (val & PLL_VOTE_FSM_ENA) { 198162306a36Sopenharmony_ci ret = clk_enable_regmap(hw); 198262306a36Sopenharmony_ci if (ret) 198362306a36Sopenharmony_ci return ret; 198462306a36Sopenharmony_ci return wait_for_pll_enable_active(pll); 198562306a36Sopenharmony_ci } 198662306a36Sopenharmony_ci 198762306a36Sopenharmony_ci /* Get the PLL out of bypass mode */ 198862306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_BYPASSNL, PLL_BYPASSNL); 198962306a36Sopenharmony_ci 199062306a36Sopenharmony_ci /* 199162306a36Sopenharmony_ci * H/W requires a 1us delay between disabling the bypass and 199262306a36Sopenharmony_ci * de-asserting the reset. 199362306a36Sopenharmony_ci */ 199462306a36Sopenharmony_ci udelay(1); 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); 199762306a36Sopenharmony_ci 199862306a36Sopenharmony_ci /* Set operation mode to RUN */ 199962306a36Sopenharmony_ci regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN); 200062306a36Sopenharmony_ci 200162306a36Sopenharmony_ci regmap_read(regmap, PLL_TEST_CTL(pll), &val); 200262306a36Sopenharmony_ci 200362306a36Sopenharmony_ci /* If cfa mode then poll for freq lock */ 200462306a36Sopenharmony_ci if (val & ZONDA_STAY_IN_CFA) 200562306a36Sopenharmony_ci ret = wait_for_zonda_pll_freq_lock(pll); 200662306a36Sopenharmony_ci else 200762306a36Sopenharmony_ci ret = wait_for_pll_enable_lock(pll); 200862306a36Sopenharmony_ci if (ret) 200962306a36Sopenharmony_ci return ret; 201062306a36Sopenharmony_ci 201162306a36Sopenharmony_ci /* Enable the PLL outputs */ 201262306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_USER_CTL(pll), ZONDA_PLL_OUT_MASK, ZONDA_PLL_OUT_MASK); 201362306a36Sopenharmony_ci 201462306a36Sopenharmony_ci /* Enable the global PLL outputs */ 201562306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL); 201662306a36Sopenharmony_ci 201762306a36Sopenharmony_ci return 0; 201862306a36Sopenharmony_ci} 201962306a36Sopenharmony_ci 202062306a36Sopenharmony_cistatic void clk_zonda_pll_disable(struct clk_hw *hw) 202162306a36Sopenharmony_ci{ 202262306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 202362306a36Sopenharmony_ci struct regmap *regmap = pll->clkr.regmap; 202462306a36Sopenharmony_ci u32 val; 202562306a36Sopenharmony_ci 202662306a36Sopenharmony_ci regmap_read(regmap, PLL_MODE(pll), &val); 202762306a36Sopenharmony_ci 202862306a36Sopenharmony_ci /* If in FSM mode, just unvote it */ 202962306a36Sopenharmony_ci if (val & PLL_VOTE_FSM_ENA) { 203062306a36Sopenharmony_ci clk_disable_regmap(hw); 203162306a36Sopenharmony_ci return; 203262306a36Sopenharmony_ci } 203362306a36Sopenharmony_ci 203462306a36Sopenharmony_ci /* Disable the global PLL output */ 203562306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); 203662306a36Sopenharmony_ci 203762306a36Sopenharmony_ci /* Disable the PLL outputs */ 203862306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_USER_CTL(pll), ZONDA_PLL_OUT_MASK, 0); 203962306a36Sopenharmony_ci 204062306a36Sopenharmony_ci /* Put the PLL in bypass and reset */ 204162306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N | PLL_BYPASSNL, 0); 204262306a36Sopenharmony_ci 204362306a36Sopenharmony_ci /* Place the PLL mode in OFF state */ 204462306a36Sopenharmony_ci regmap_write(regmap, PLL_OPMODE(pll), 0x0); 204562306a36Sopenharmony_ci} 204662306a36Sopenharmony_ci 204762306a36Sopenharmony_cistatic int clk_zonda_pll_set_rate(struct clk_hw *hw, unsigned long rate, 204862306a36Sopenharmony_ci unsigned long prate) 204962306a36Sopenharmony_ci{ 205062306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 205162306a36Sopenharmony_ci unsigned long rrate; 205262306a36Sopenharmony_ci u32 test_ctl_val; 205362306a36Sopenharmony_ci u32 l, alpha_width = pll_alpha_width(pll); 205462306a36Sopenharmony_ci u64 a; 205562306a36Sopenharmony_ci int ret; 205662306a36Sopenharmony_ci 205762306a36Sopenharmony_ci rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); 205862306a36Sopenharmony_ci 205962306a36Sopenharmony_ci ret = alpha_pll_check_rate_margin(hw, rrate, rate); 206062306a36Sopenharmony_ci if (ret < 0) 206162306a36Sopenharmony_ci return ret; 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); 206462306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_ci /* Wait before polling for the frequency latch */ 206762306a36Sopenharmony_ci udelay(5); 206862306a36Sopenharmony_ci 206962306a36Sopenharmony_ci /* Read stay in cfa mode */ 207062306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_TEST_CTL(pll), &test_ctl_val); 207162306a36Sopenharmony_ci 207262306a36Sopenharmony_ci /* If cfa mode then poll for freq lock */ 207362306a36Sopenharmony_ci if (test_ctl_val & ZONDA_STAY_IN_CFA) 207462306a36Sopenharmony_ci ret = wait_for_zonda_pll_freq_lock(pll); 207562306a36Sopenharmony_ci else 207662306a36Sopenharmony_ci ret = wait_for_pll_enable_lock(pll); 207762306a36Sopenharmony_ci if (ret) 207862306a36Sopenharmony_ci return ret; 207962306a36Sopenharmony_ci 208062306a36Sopenharmony_ci /* Wait for PLL output to stabilize */ 208162306a36Sopenharmony_ci udelay(100); 208262306a36Sopenharmony_ci return 0; 208362306a36Sopenharmony_ci} 208462306a36Sopenharmony_ci 208562306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_zonda_ops = { 208662306a36Sopenharmony_ci .enable = clk_zonda_pll_enable, 208762306a36Sopenharmony_ci .disable = clk_zonda_pll_disable, 208862306a36Sopenharmony_ci .is_enabled = clk_trion_pll_is_enabled, 208962306a36Sopenharmony_ci .recalc_rate = clk_trion_pll_recalc_rate, 209062306a36Sopenharmony_ci .round_rate = clk_alpha_pll_round_rate, 209162306a36Sopenharmony_ci .set_rate = clk_zonda_pll_set_rate, 209262306a36Sopenharmony_ci}; 209362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_zonda_ops); 209462306a36Sopenharmony_ci 209562306a36Sopenharmony_civoid clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, 209662306a36Sopenharmony_ci const struct alpha_pll_config *config) 209762306a36Sopenharmony_ci{ 209862306a36Sopenharmony_ci u32 lval = config->l; 209962306a36Sopenharmony_ci 210062306a36Sopenharmony_ci lval |= TRION_PLL_CAL_VAL << LUCID_EVO_PLL_CAL_L_VAL_SHIFT; 210162306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), lval); 210262306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha); 210362306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val); 210462306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val); 210562306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val); 210662306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), config->user_ctl_val); 210762306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val); 210862306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val); 210962306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val); 211062306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val); 211162306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U2(pll), config->test_ctl_hi2_val); 211262306a36Sopenharmony_ci 211362306a36Sopenharmony_ci /* Disable PLL output */ 211462306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); 211562306a36Sopenharmony_ci 211662306a36Sopenharmony_ci /* Set operation mode to STANDBY and de-assert the reset */ 211762306a36Sopenharmony_ci regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); 211862306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); 211962306a36Sopenharmony_ci} 212062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_lucid_evo_pll_configure); 212162306a36Sopenharmony_ci 212262306a36Sopenharmony_cistatic int alpha_pll_lucid_evo_enable(struct clk_hw *hw) 212362306a36Sopenharmony_ci{ 212462306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 212562306a36Sopenharmony_ci struct regmap *regmap = pll->clkr.regmap; 212662306a36Sopenharmony_ci u32 val; 212762306a36Sopenharmony_ci int ret; 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci ret = regmap_read(regmap, PLL_USER_CTL(pll), &val); 213062306a36Sopenharmony_ci if (ret) 213162306a36Sopenharmony_ci return ret; 213262306a36Sopenharmony_ci 213362306a36Sopenharmony_ci /* If in FSM mode, just vote for it */ 213462306a36Sopenharmony_ci if (val & LUCID_EVO_ENABLE_VOTE_RUN) { 213562306a36Sopenharmony_ci ret = clk_enable_regmap(hw); 213662306a36Sopenharmony_ci if (ret) 213762306a36Sopenharmony_ci return ret; 213862306a36Sopenharmony_ci return wait_for_pll_enable_lock(pll); 213962306a36Sopenharmony_ci } 214062306a36Sopenharmony_ci 214162306a36Sopenharmony_ci /* Check if PLL is already enabled */ 214262306a36Sopenharmony_ci ret = trion_pll_is_enabled(pll, regmap); 214362306a36Sopenharmony_ci if (ret < 0) { 214462306a36Sopenharmony_ci return ret; 214562306a36Sopenharmony_ci } else if (ret) { 214662306a36Sopenharmony_ci pr_warn("%s PLL is already enabled\n", clk_hw_get_name(&pll->clkr.hw)); 214762306a36Sopenharmony_ci return 0; 214862306a36Sopenharmony_ci } 214962306a36Sopenharmony_ci 215062306a36Sopenharmony_ci ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); 215162306a36Sopenharmony_ci if (ret) 215262306a36Sopenharmony_ci return ret; 215362306a36Sopenharmony_ci 215462306a36Sopenharmony_ci /* Set operation mode to RUN */ 215562306a36Sopenharmony_ci regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN); 215662306a36Sopenharmony_ci 215762306a36Sopenharmony_ci ret = wait_for_pll_enable_lock(pll); 215862306a36Sopenharmony_ci if (ret) 215962306a36Sopenharmony_ci return ret; 216062306a36Sopenharmony_ci 216162306a36Sopenharmony_ci /* Enable the PLL outputs */ 216262306a36Sopenharmony_ci ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, PLL_OUT_MASK); 216362306a36Sopenharmony_ci if (ret) 216462306a36Sopenharmony_ci return ret; 216562306a36Sopenharmony_ci 216662306a36Sopenharmony_ci /* Enable the global PLL outputs */ 216762306a36Sopenharmony_ci ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL); 216862306a36Sopenharmony_ci if (ret) 216962306a36Sopenharmony_ci return ret; 217062306a36Sopenharmony_ci 217162306a36Sopenharmony_ci /* Ensure that the write above goes through before returning. */ 217262306a36Sopenharmony_ci mb(); 217362306a36Sopenharmony_ci return ret; 217462306a36Sopenharmony_ci} 217562306a36Sopenharmony_ci 217662306a36Sopenharmony_cistatic void _alpha_pll_lucid_evo_disable(struct clk_hw *hw, bool reset) 217762306a36Sopenharmony_ci{ 217862306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 217962306a36Sopenharmony_ci struct regmap *regmap = pll->clkr.regmap; 218062306a36Sopenharmony_ci u32 val; 218162306a36Sopenharmony_ci int ret; 218262306a36Sopenharmony_ci 218362306a36Sopenharmony_ci ret = regmap_read(regmap, PLL_USER_CTL(pll), &val); 218462306a36Sopenharmony_ci if (ret) 218562306a36Sopenharmony_ci return; 218662306a36Sopenharmony_ci 218762306a36Sopenharmony_ci /* If in FSM mode, just unvote it */ 218862306a36Sopenharmony_ci if (val & LUCID_EVO_ENABLE_VOTE_RUN) { 218962306a36Sopenharmony_ci clk_disable_regmap(hw); 219062306a36Sopenharmony_ci return; 219162306a36Sopenharmony_ci } 219262306a36Sopenharmony_ci 219362306a36Sopenharmony_ci /* Disable the global PLL output */ 219462306a36Sopenharmony_ci ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); 219562306a36Sopenharmony_ci if (ret) 219662306a36Sopenharmony_ci return; 219762306a36Sopenharmony_ci 219862306a36Sopenharmony_ci /* Disable the PLL outputs */ 219962306a36Sopenharmony_ci ret = regmap_update_bits(regmap, PLL_USER_CTL(pll), PLL_OUT_MASK, 0); 220062306a36Sopenharmony_ci if (ret) 220162306a36Sopenharmony_ci return; 220262306a36Sopenharmony_ci 220362306a36Sopenharmony_ci /* Place the PLL mode in STANDBY */ 220462306a36Sopenharmony_ci regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); 220562306a36Sopenharmony_ci 220662306a36Sopenharmony_ci if (reset) 220762306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, 0); 220862306a36Sopenharmony_ci} 220962306a36Sopenharmony_ci 221062306a36Sopenharmony_cistatic int _alpha_pll_lucid_evo_prepare(struct clk_hw *hw, bool reset) 221162306a36Sopenharmony_ci{ 221262306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 221362306a36Sopenharmony_ci struct clk_hw *p; 221462306a36Sopenharmony_ci u32 val = 0; 221562306a36Sopenharmony_ci int ret; 221662306a36Sopenharmony_ci 221762306a36Sopenharmony_ci /* Return early if calibration is not needed. */ 221862306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); 221962306a36Sopenharmony_ci if (!(val & LUCID_EVO_PCAL_NOT_DONE)) 222062306a36Sopenharmony_ci return 0; 222162306a36Sopenharmony_ci 222262306a36Sopenharmony_ci p = clk_hw_get_parent(hw); 222362306a36Sopenharmony_ci if (!p) 222462306a36Sopenharmony_ci return -EINVAL; 222562306a36Sopenharmony_ci 222662306a36Sopenharmony_ci ret = alpha_pll_lucid_evo_enable(hw); 222762306a36Sopenharmony_ci if (ret) 222862306a36Sopenharmony_ci return ret; 222962306a36Sopenharmony_ci 223062306a36Sopenharmony_ci _alpha_pll_lucid_evo_disable(hw, reset); 223162306a36Sopenharmony_ci 223262306a36Sopenharmony_ci return 0; 223362306a36Sopenharmony_ci} 223462306a36Sopenharmony_ci 223562306a36Sopenharmony_cistatic void alpha_pll_lucid_evo_disable(struct clk_hw *hw) 223662306a36Sopenharmony_ci{ 223762306a36Sopenharmony_ci _alpha_pll_lucid_evo_disable(hw, false); 223862306a36Sopenharmony_ci} 223962306a36Sopenharmony_ci 224062306a36Sopenharmony_cistatic int alpha_pll_lucid_evo_prepare(struct clk_hw *hw) 224162306a36Sopenharmony_ci{ 224262306a36Sopenharmony_ci return _alpha_pll_lucid_evo_prepare(hw, false); 224362306a36Sopenharmony_ci} 224462306a36Sopenharmony_ci 224562306a36Sopenharmony_cistatic void alpha_pll_reset_lucid_evo_disable(struct clk_hw *hw) 224662306a36Sopenharmony_ci{ 224762306a36Sopenharmony_ci _alpha_pll_lucid_evo_disable(hw, true); 224862306a36Sopenharmony_ci} 224962306a36Sopenharmony_ci 225062306a36Sopenharmony_cistatic int alpha_pll_reset_lucid_evo_prepare(struct clk_hw *hw) 225162306a36Sopenharmony_ci{ 225262306a36Sopenharmony_ci return _alpha_pll_lucid_evo_prepare(hw, true); 225362306a36Sopenharmony_ci} 225462306a36Sopenharmony_ci 225562306a36Sopenharmony_cistatic unsigned long alpha_pll_lucid_evo_recalc_rate(struct clk_hw *hw, 225662306a36Sopenharmony_ci unsigned long parent_rate) 225762306a36Sopenharmony_ci{ 225862306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 225962306a36Sopenharmony_ci struct regmap *regmap = pll->clkr.regmap; 226062306a36Sopenharmony_ci u32 l, frac; 226162306a36Sopenharmony_ci 226262306a36Sopenharmony_ci regmap_read(regmap, PLL_L_VAL(pll), &l); 226362306a36Sopenharmony_ci l &= LUCID_EVO_PLL_L_VAL_MASK; 226462306a36Sopenharmony_ci regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac); 226562306a36Sopenharmony_ci 226662306a36Sopenharmony_ci return alpha_pll_calc_rate(parent_rate, l, frac, pll_alpha_width(pll)); 226762306a36Sopenharmony_ci} 226862306a36Sopenharmony_ci 226962306a36Sopenharmony_cistatic int clk_lucid_evo_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, 227062306a36Sopenharmony_ci unsigned long parent_rate) 227162306a36Sopenharmony_ci{ 227262306a36Sopenharmony_ci return __clk_lucid_pll_postdiv_set_rate(hw, rate, parent_rate, LUCID_EVO_ENABLE_VOTE_RUN); 227362306a36Sopenharmony_ci} 227462306a36Sopenharmony_ci 227562306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_fixed_lucid_evo_ops = { 227662306a36Sopenharmony_ci .enable = alpha_pll_lucid_evo_enable, 227762306a36Sopenharmony_ci .disable = alpha_pll_lucid_evo_disable, 227862306a36Sopenharmony_ci .is_enabled = clk_trion_pll_is_enabled, 227962306a36Sopenharmony_ci .recalc_rate = alpha_pll_lucid_evo_recalc_rate, 228062306a36Sopenharmony_ci .round_rate = clk_alpha_pll_round_rate, 228162306a36Sopenharmony_ci}; 228262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_lucid_evo_ops); 228362306a36Sopenharmony_ci 228462306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_postdiv_lucid_evo_ops = { 228562306a36Sopenharmony_ci .recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate, 228662306a36Sopenharmony_ci .round_rate = clk_alpha_pll_postdiv_fabia_round_rate, 228762306a36Sopenharmony_ci .set_rate = clk_lucid_evo_pll_postdiv_set_rate, 228862306a36Sopenharmony_ci}; 228962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_lucid_evo_ops); 229062306a36Sopenharmony_ci 229162306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_lucid_evo_ops = { 229262306a36Sopenharmony_ci .prepare = alpha_pll_lucid_evo_prepare, 229362306a36Sopenharmony_ci .enable = alpha_pll_lucid_evo_enable, 229462306a36Sopenharmony_ci .disable = alpha_pll_lucid_evo_disable, 229562306a36Sopenharmony_ci .is_enabled = clk_trion_pll_is_enabled, 229662306a36Sopenharmony_ci .recalc_rate = alpha_pll_lucid_evo_recalc_rate, 229762306a36Sopenharmony_ci .round_rate = clk_alpha_pll_round_rate, 229862306a36Sopenharmony_ci .set_rate = alpha_pll_lucid_5lpe_set_rate, 229962306a36Sopenharmony_ci}; 230062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_lucid_evo_ops); 230162306a36Sopenharmony_ci 230262306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_reset_lucid_evo_ops = { 230362306a36Sopenharmony_ci .prepare = alpha_pll_reset_lucid_evo_prepare, 230462306a36Sopenharmony_ci .enable = alpha_pll_lucid_evo_enable, 230562306a36Sopenharmony_ci .disable = alpha_pll_reset_lucid_evo_disable, 230662306a36Sopenharmony_ci .is_enabled = clk_trion_pll_is_enabled, 230762306a36Sopenharmony_ci .recalc_rate = alpha_pll_lucid_evo_recalc_rate, 230862306a36Sopenharmony_ci .round_rate = clk_alpha_pll_round_rate, 230962306a36Sopenharmony_ci .set_rate = alpha_pll_lucid_5lpe_set_rate, 231062306a36Sopenharmony_ci}; 231162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_reset_lucid_evo_ops); 231262306a36Sopenharmony_ci 231362306a36Sopenharmony_civoid clk_rivian_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, 231462306a36Sopenharmony_ci const struct alpha_pll_config *config) 231562306a36Sopenharmony_ci{ 231662306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val); 231762306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val); 231862306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val); 231962306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val); 232062306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val); 232162306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l); 232262306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), config->user_ctl_val); 232362306a36Sopenharmony_ci clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val); 232462306a36Sopenharmony_ci 232562306a36Sopenharmony_ci regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); 232662306a36Sopenharmony_ci 232762306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_MODE(pll), 232862306a36Sopenharmony_ci PLL_RESET_N | PLL_BYPASSNL | PLL_OUTCTRL, 232962306a36Sopenharmony_ci PLL_RESET_N | PLL_BYPASSNL); 233062306a36Sopenharmony_ci} 233162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_rivian_evo_pll_configure); 233262306a36Sopenharmony_ci 233362306a36Sopenharmony_cistatic unsigned long clk_rivian_evo_pll_recalc_rate(struct clk_hw *hw, 233462306a36Sopenharmony_ci unsigned long parent_rate) 233562306a36Sopenharmony_ci{ 233662306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 233762306a36Sopenharmony_ci u32 l; 233862306a36Sopenharmony_ci 233962306a36Sopenharmony_ci regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); 234062306a36Sopenharmony_ci 234162306a36Sopenharmony_ci return parent_rate * l; 234262306a36Sopenharmony_ci} 234362306a36Sopenharmony_ci 234462306a36Sopenharmony_cistatic long clk_rivian_evo_pll_round_rate(struct clk_hw *hw, unsigned long rate, 234562306a36Sopenharmony_ci unsigned long *prate) 234662306a36Sopenharmony_ci{ 234762306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 234862306a36Sopenharmony_ci unsigned long min_freq, max_freq; 234962306a36Sopenharmony_ci u32 l; 235062306a36Sopenharmony_ci u64 a; 235162306a36Sopenharmony_ci 235262306a36Sopenharmony_ci rate = alpha_pll_round_rate(rate, *prate, &l, &a, 0); 235362306a36Sopenharmony_ci if (!pll->vco_table || alpha_pll_find_vco(pll, rate)) 235462306a36Sopenharmony_ci return rate; 235562306a36Sopenharmony_ci 235662306a36Sopenharmony_ci min_freq = pll->vco_table[0].min_freq; 235762306a36Sopenharmony_ci max_freq = pll->vco_table[pll->num_vco - 1].max_freq; 235862306a36Sopenharmony_ci 235962306a36Sopenharmony_ci return clamp(rate, min_freq, max_freq); 236062306a36Sopenharmony_ci} 236162306a36Sopenharmony_ci 236262306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_rivian_evo_ops = { 236362306a36Sopenharmony_ci .enable = alpha_pll_lucid_5lpe_enable, 236462306a36Sopenharmony_ci .disable = alpha_pll_lucid_5lpe_disable, 236562306a36Sopenharmony_ci .is_enabled = clk_trion_pll_is_enabled, 236662306a36Sopenharmony_ci .recalc_rate = clk_rivian_evo_pll_recalc_rate, 236762306a36Sopenharmony_ci .round_rate = clk_rivian_evo_pll_round_rate, 236862306a36Sopenharmony_ci}; 236962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_rivian_evo_ops); 237062306a36Sopenharmony_ci 237162306a36Sopenharmony_civoid clk_stromer_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, 237262306a36Sopenharmony_ci const struct alpha_pll_config *config) 237362306a36Sopenharmony_ci{ 237462306a36Sopenharmony_ci u32 val, val_u, mask, mask_u; 237562306a36Sopenharmony_ci 237662306a36Sopenharmony_ci regmap_write(regmap, PLL_L_VAL(pll), config->l); 237762306a36Sopenharmony_ci regmap_write(regmap, PLL_ALPHA_VAL(pll), config->alpha); 237862306a36Sopenharmony_ci regmap_write(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val); 237962306a36Sopenharmony_ci 238062306a36Sopenharmony_ci if (pll_has_64bit_config(pll)) 238162306a36Sopenharmony_ci regmap_write(regmap, PLL_CONFIG_CTL_U(pll), 238262306a36Sopenharmony_ci config->config_ctl_hi_val); 238362306a36Sopenharmony_ci 238462306a36Sopenharmony_ci if (pll_alpha_width(pll) > 32) 238562306a36Sopenharmony_ci regmap_write(regmap, PLL_ALPHA_VAL_U(pll), config->alpha_hi); 238662306a36Sopenharmony_ci 238762306a36Sopenharmony_ci val = config->main_output_mask; 238862306a36Sopenharmony_ci val |= config->aux_output_mask; 238962306a36Sopenharmony_ci val |= config->aux2_output_mask; 239062306a36Sopenharmony_ci val |= config->early_output_mask; 239162306a36Sopenharmony_ci val |= config->pre_div_val; 239262306a36Sopenharmony_ci val |= config->post_div_val; 239362306a36Sopenharmony_ci val |= config->vco_val; 239462306a36Sopenharmony_ci val |= config->alpha_en_mask; 239562306a36Sopenharmony_ci val |= config->alpha_mode_mask; 239662306a36Sopenharmony_ci 239762306a36Sopenharmony_ci mask = config->main_output_mask; 239862306a36Sopenharmony_ci mask |= config->aux_output_mask; 239962306a36Sopenharmony_ci mask |= config->aux2_output_mask; 240062306a36Sopenharmony_ci mask |= config->early_output_mask; 240162306a36Sopenharmony_ci mask |= config->pre_div_mask; 240262306a36Sopenharmony_ci mask |= config->post_div_mask; 240362306a36Sopenharmony_ci mask |= config->vco_mask; 240462306a36Sopenharmony_ci mask |= config->alpha_en_mask; 240562306a36Sopenharmony_ci mask |= config->alpha_mode_mask; 240662306a36Sopenharmony_ci 240762306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_USER_CTL(pll), mask, val); 240862306a36Sopenharmony_ci 240962306a36Sopenharmony_ci /* Stromer APSS PLL does not enable LOCK_DET by default, so enable it */ 241062306a36Sopenharmony_ci val_u = config->status_val << ALPHA_PLL_STATUS_REG_SHIFT; 241162306a36Sopenharmony_ci val_u |= config->lock_det; 241262306a36Sopenharmony_ci 241362306a36Sopenharmony_ci mask_u = config->status_mask; 241462306a36Sopenharmony_ci mask_u |= config->lock_det; 241562306a36Sopenharmony_ci 241662306a36Sopenharmony_ci regmap_update_bits(regmap, PLL_USER_CTL_U(pll), mask_u, val_u); 241762306a36Sopenharmony_ci regmap_write(regmap, PLL_TEST_CTL(pll), config->test_ctl_val); 241862306a36Sopenharmony_ci regmap_write(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val); 241962306a36Sopenharmony_ci 242062306a36Sopenharmony_ci if (pll->flags & SUPPORTS_FSM_MODE) 242162306a36Sopenharmony_ci qcom_pll_set_fsm_mode(regmap, PLL_MODE(pll), 6, 0); 242262306a36Sopenharmony_ci} 242362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_stromer_pll_configure); 242462306a36Sopenharmony_ci 242562306a36Sopenharmony_cistatic int clk_alpha_pll_stromer_determine_rate(struct clk_hw *hw, 242662306a36Sopenharmony_ci struct clk_rate_request *req) 242762306a36Sopenharmony_ci{ 242862306a36Sopenharmony_ci u32 l; 242962306a36Sopenharmony_ci u64 a; 243062306a36Sopenharmony_ci 243162306a36Sopenharmony_ci req->rate = alpha_pll_round_rate(req->rate, req->best_parent_rate, 243262306a36Sopenharmony_ci &l, &a, ALPHA_REG_BITWIDTH); 243362306a36Sopenharmony_ci 243462306a36Sopenharmony_ci return 0; 243562306a36Sopenharmony_ci} 243662306a36Sopenharmony_ci 243762306a36Sopenharmony_cistatic int clk_alpha_pll_stromer_set_rate(struct clk_hw *hw, unsigned long rate, 243862306a36Sopenharmony_ci unsigned long prate) 243962306a36Sopenharmony_ci{ 244062306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 244162306a36Sopenharmony_ci int ret; 244262306a36Sopenharmony_ci u32 l; 244362306a36Sopenharmony_ci u64 a; 244462306a36Sopenharmony_ci 244562306a36Sopenharmony_ci rate = alpha_pll_round_rate(rate, prate, &l, &a, ALPHA_REG_BITWIDTH); 244662306a36Sopenharmony_ci 244762306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); 244862306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); 244962306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), 245062306a36Sopenharmony_ci a >> ALPHA_BITWIDTH); 245162306a36Sopenharmony_ci 245262306a36Sopenharmony_ci regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), 245362306a36Sopenharmony_ci PLL_ALPHA_EN, PLL_ALPHA_EN); 245462306a36Sopenharmony_ci 245562306a36Sopenharmony_ci if (!clk_hw_is_enabled(hw)) 245662306a36Sopenharmony_ci return 0; 245762306a36Sopenharmony_ci 245862306a36Sopenharmony_ci /* 245962306a36Sopenharmony_ci * Stromer PLL supports Dynamic programming. 246062306a36Sopenharmony_ci * It allows the PLL frequency to be changed on-the-fly without first 246162306a36Sopenharmony_ci * execution of a shutdown procedure followed by a bring up procedure. 246262306a36Sopenharmony_ci */ 246362306a36Sopenharmony_ci regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_UPDATE, 246462306a36Sopenharmony_ci PLL_UPDATE); 246562306a36Sopenharmony_ci 246662306a36Sopenharmony_ci ret = wait_for_pll_update(pll); 246762306a36Sopenharmony_ci if (ret) 246862306a36Sopenharmony_ci return ret; 246962306a36Sopenharmony_ci 247062306a36Sopenharmony_ci return wait_for_pll_enable_lock(pll); 247162306a36Sopenharmony_ci} 247262306a36Sopenharmony_ci 247362306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_stromer_ops = { 247462306a36Sopenharmony_ci .enable = clk_alpha_pll_enable, 247562306a36Sopenharmony_ci .disable = clk_alpha_pll_disable, 247662306a36Sopenharmony_ci .is_enabled = clk_alpha_pll_is_enabled, 247762306a36Sopenharmony_ci .recalc_rate = clk_alpha_pll_recalc_rate, 247862306a36Sopenharmony_ci .determine_rate = clk_alpha_pll_stromer_determine_rate, 247962306a36Sopenharmony_ci .set_rate = clk_alpha_pll_stromer_set_rate, 248062306a36Sopenharmony_ci}; 248162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_stromer_ops); 248262306a36Sopenharmony_ci 248362306a36Sopenharmony_cistatic int clk_alpha_pll_stromer_plus_set_rate(struct clk_hw *hw, 248462306a36Sopenharmony_ci unsigned long rate, 248562306a36Sopenharmony_ci unsigned long prate) 248662306a36Sopenharmony_ci{ 248762306a36Sopenharmony_ci struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 248862306a36Sopenharmony_ci u32 l, alpha_width = pll_alpha_width(pll); 248962306a36Sopenharmony_ci int ret, pll_mode; 249062306a36Sopenharmony_ci u64 a; 249162306a36Sopenharmony_ci 249262306a36Sopenharmony_ci rate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); 249362306a36Sopenharmony_ci 249462306a36Sopenharmony_ci ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &pll_mode); 249562306a36Sopenharmony_ci if (ret) 249662306a36Sopenharmony_ci return ret; 249762306a36Sopenharmony_ci 249862306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_MODE(pll), 0); 249962306a36Sopenharmony_ci 250062306a36Sopenharmony_ci /* Delay of 2 output clock ticks required until output is disabled */ 250162306a36Sopenharmony_ci udelay(1); 250262306a36Sopenharmony_ci 250362306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); 250462306a36Sopenharmony_ci 250562306a36Sopenharmony_ci if (alpha_width > ALPHA_BITWIDTH) 250662306a36Sopenharmony_ci a <<= alpha_width - ALPHA_BITWIDTH; 250762306a36Sopenharmony_ci 250862306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); 250962306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), 251062306a36Sopenharmony_ci a >> ALPHA_BITWIDTH); 251162306a36Sopenharmony_ci 251262306a36Sopenharmony_ci regmap_write(pll->clkr.regmap, PLL_MODE(pll), PLL_BYPASSNL); 251362306a36Sopenharmony_ci 251462306a36Sopenharmony_ci /* Wait five micro seconds or more */ 251562306a36Sopenharmony_ci udelay(5); 251662306a36Sopenharmony_ci regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_RESET_N, 251762306a36Sopenharmony_ci PLL_RESET_N); 251862306a36Sopenharmony_ci 251962306a36Sopenharmony_ci /* The lock time should be less than 50 micro seconds worst case */ 252062306a36Sopenharmony_ci usleep_range(50, 60); 252162306a36Sopenharmony_ci 252262306a36Sopenharmony_ci ret = wait_for_pll_enable_lock(pll); 252362306a36Sopenharmony_ci if (ret) { 252462306a36Sopenharmony_ci pr_err("Wait for PLL enable lock failed [%s] %d\n", 252562306a36Sopenharmony_ci clk_hw_get_name(hw), ret); 252662306a36Sopenharmony_ci return ret; 252762306a36Sopenharmony_ci } 252862306a36Sopenharmony_ci 252962306a36Sopenharmony_ci if (pll_mode & PLL_OUTCTRL) 253062306a36Sopenharmony_ci regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, 253162306a36Sopenharmony_ci PLL_OUTCTRL); 253262306a36Sopenharmony_ci 253362306a36Sopenharmony_ci return 0; 253462306a36Sopenharmony_ci} 253562306a36Sopenharmony_ci 253662306a36Sopenharmony_ciconst struct clk_ops clk_alpha_pll_stromer_plus_ops = { 253762306a36Sopenharmony_ci .prepare = clk_alpha_pll_enable, 253862306a36Sopenharmony_ci .unprepare = clk_alpha_pll_disable, 253962306a36Sopenharmony_ci .is_enabled = clk_alpha_pll_is_enabled, 254062306a36Sopenharmony_ci .recalc_rate = clk_alpha_pll_recalc_rate, 254162306a36Sopenharmony_ci .determine_rate = clk_alpha_pll_stromer_determine_rate, 254262306a36Sopenharmony_ci .set_rate = clk_alpha_pll_stromer_plus_set_rate, 254362306a36Sopenharmony_ci}; 254462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(clk_alpha_pll_stromer_plus_ops); 2545