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