xref: /rk3399_ARM-atf/plat/rockchip/rk3576/scmi/rk3576_clk.c (revision 04b2fb42b171e3fbf2ef823558ac5b0119663dc7)
1*036935a8SXiaoDong Huang // SPDX-License-Identifier: BSD-3-Clause
2*036935a8SXiaoDong Huang /*
3*036935a8SXiaoDong Huang  * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
4*036935a8SXiaoDong Huang  */
5*036935a8SXiaoDong Huang 
6*036935a8SXiaoDong Huang #include <assert.h>
7*036935a8SXiaoDong Huang #include <errno.h>
8*036935a8SXiaoDong Huang 
9*036935a8SXiaoDong Huang #include <drivers/delay_timer.h>
10*036935a8SXiaoDong Huang #include <drivers/scmi.h>
11*036935a8SXiaoDong Huang #include <lib/mmio.h>
12*036935a8SXiaoDong Huang #include <lib/spinlock.h>
13*036935a8SXiaoDong Huang #include <platform_def.h>
14*036935a8SXiaoDong Huang 
15*036935a8SXiaoDong Huang #include <plat_private.h>
16*036935a8SXiaoDong Huang #include <rk3576_clk.h>
17*036935a8SXiaoDong Huang #include <rockchip_sip_svc.h>
18*036935a8SXiaoDong Huang #include <scmi_clock.h>
19*036935a8SXiaoDong Huang #include <soc.h>
20*036935a8SXiaoDong Huang 
21*036935a8SXiaoDong Huang enum pll_type_sel {
22*036935a8SXiaoDong Huang 	PLL_SEL_AUTO, /* all plls (normal pll or pvtpll) */
23*036935a8SXiaoDong Huang 	PLL_SEL_PVT,
24*036935a8SXiaoDong Huang 	PLL_SEL_NOR,
25*036935a8SXiaoDong Huang 	PLL_SEL_AUTO_NOR /* all normal plls (apll/gpll/npll) */
26*036935a8SXiaoDong Huang };
27*036935a8SXiaoDong Huang 
28*036935a8SXiaoDong Huang #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
29*036935a8SXiaoDong Huang 
30*036935a8SXiaoDong Huang #define RK3576_PVTPLL_RING_EN		0x00
31*036935a8SXiaoDong Huang #define RK3576_PVTPLL_RING0_LENGTH	0x04
32*036935a8SXiaoDong Huang #define RK3576_PVTPLL_RING1_LENGTH	0x08
33*036935a8SXiaoDong Huang #define RK3576_PVTPLL_RING2_LENGTH	0x0c
34*036935a8SXiaoDong Huang #define RK3576_PVTPLL_RING3_LENGTH	0x10
35*036935a8SXiaoDong Huang #define RK3576_PVTPLL_GCK_CFG		0x20
36*036935a8SXiaoDong Huang #define RK3576_PVTPLL_GCK_LEN		0x24
37*036935a8SXiaoDong Huang #define RK3576_PVTPLL_GCK_DIV		0x28
38*036935a8SXiaoDong Huang #define RK3576_PVTPLL_GCK_CAL_CNT	0x2c
39*036935a8SXiaoDong Huang #define RK3576_PVTPLL_GCK_REF_VAL	0x30
40*036935a8SXiaoDong Huang #define RK3576_PVTPLL_GCK_CFG_VAL	0x34
41*036935a8SXiaoDong Huang #define RK3576_PVTPLL_GCK_THR		0x38
42*036935a8SXiaoDong Huang #define RK3576_PVTPLL_GFREE_CON		0x3c
43*036935a8SXiaoDong Huang #define RK3576_PVTPLL_ADC_CFG		0x40
44*036935a8SXiaoDong Huang #define RK3576_PVTPLL_ADC_CAL_CNT	0x48
45*036935a8SXiaoDong Huang #define RK3576_PVTPLL_GCK_CNT		0x50
46*036935a8SXiaoDong Huang #define RK3576_PVTPLL_GCK_CNT_AVG	0x54
47*036935a8SXiaoDong Huang #define RK3576_PVTPLL_GCK_STATE		0x5c
48*036935a8SXiaoDong Huang #define RK3576_PVTPLL_ADC_CNT		0x60
49*036935a8SXiaoDong Huang #define RK3576_PVTPLL_ADC_CNT_AVG	0x68
50*036935a8SXiaoDong Huang #define RK3576_PVTPLL_VERSION		0x70
51*036935a8SXiaoDong Huang #define RK3576_PVTPLL_MAX_LENGTH	0x3f
52*036935a8SXiaoDong Huang 
53*036935a8SXiaoDong Huang #define GPLL_RATE			1188000000
54*036935a8SXiaoDong Huang #define CPLL_RATE			1000000000
55*036935a8SXiaoDong Huang #define SPLL_RATE			702000000
56*036935a8SXiaoDong Huang #define AUPLL_RATE			786431952
57*036935a8SXiaoDong Huang 
58*036935a8SXiaoDong Huang #define MAX_RATE_TABLE			16
59*036935a8SXiaoDong Huang 
60*036935a8SXiaoDong Huang #define CLKDIV_6BITS_SHF(div, shift)	BITS_WITH_WMASK(div, 0x3fU, shift)
61*036935a8SXiaoDong Huang #define CLKDIV_5BITS_SHF(div, shift)	BITS_WITH_WMASK(div, 0x1fU, shift)
62*036935a8SXiaoDong Huang #define CLKDIV_4BITS_SHF(div, shift)	BITS_WITH_WMASK(div, 0xfU, shift)
63*036935a8SXiaoDong Huang #define CLKDIV_3BITS_SHF(div, shift)	BITS_WITH_WMASK(div, 0x7U, shift)
64*036935a8SXiaoDong Huang #define CLKDIV_2BITS_SHF(div, shift)	BITS_WITH_WMASK(div, 0x3U, shift)
65*036935a8SXiaoDong Huang #define CLKDIV_1BITS_SHF(div, shift)	BITS_WITH_WMASK(div, 0x1U, shift)
66*036935a8SXiaoDong Huang 
67*036935a8SXiaoDong Huang #define CPU_PLL_PATH_SLOWMODE		BITS_WITH_WMASK(0U, 0x3U, 0)
68*036935a8SXiaoDong Huang #define CPU_PLL_PATH_NORMAL		BITS_WITH_WMASK(1U, 0x3U, 0)
69*036935a8SXiaoDong Huang #define CPU_PLL_PATH_DEEP_SLOW		BITS_WITH_WMASK(2U, 0x3U, 0)
70*036935a8SXiaoDong Huang 
71*036935a8SXiaoDong Huang #define CRU_PLL_POWER_DOWN		BIT_WITH_WMSK(13)
72*036935a8SXiaoDong Huang #define CRU_PLL_POWER_UP		WMSK_BIT(13)
73*036935a8SXiaoDong Huang 
74*036935a8SXiaoDong Huang /* clk_core:
75*036935a8SXiaoDong Huang  * from normal pll(core_i: gpll or apll) path or direct pass from apll
76*036935a8SXiaoDong Huang  */
77*036935a8SXiaoDong Huang 
78*036935a8SXiaoDong Huang /* cpul clk path */
79*036935a8SXiaoDong Huang #define CPUL_CLK_PATH_NOR_GPLL		BITS_WITH_WMASK(1U, 0x3U, 12)
80*036935a8SXiaoDong Huang #define CPUL_CLK_PATH_NOR_LPLL		BITS_WITH_WMASK(0U, 0x3U, 12)
81*036935a8SXiaoDong Huang #define CPUL_CLK_PATH_NOR_PVTPLL	BITS_WITH_WMASK(2U, 0x3U, 12)
82*036935a8SXiaoDong Huang 
83*036935a8SXiaoDong Huang #define CPUL_CLK_PATH_LPLL		BITS_WITH_WMASK(0U, 0x3U, 6)
84*036935a8SXiaoDong Huang #define CPUL_CLK_PATH_DIR_LPLL		BITS_WITH_WMASK(2U, 0x3U, 6)
85*036935a8SXiaoDong Huang #define CPUL_CLK_PATH_PVTPLL		BITS_WITH_WMASK(1U, 0x3U, 6)
86*036935a8SXiaoDong Huang 
87*036935a8SXiaoDong Huang #define CPUL_PVTPLL_PATH_DEEP_SLOW	BITS_WITH_WMASK(0U, 0x1U, 13)
88*036935a8SXiaoDong Huang #define CPUL_PVTPLL_PATH_PVTPLL		BITS_WITH_WMASK(0x1, 0x1U, 13)
89*036935a8SXiaoDong Huang 
90*036935a8SXiaoDong Huang /* cpub clk path */
91*036935a8SXiaoDong Huang #define CPUB_CLK_PATH_NOR_GPLL		BITS_WITH_WMASK(1U, 0x3U, 12)
92*036935a8SXiaoDong Huang #define CPUB_CLK_PATH_NOR_BPLL		BITS_WITH_WMASK(0U, 0x3U, 12)
93*036935a8SXiaoDong Huang #define CPUB_CLK_PATH_NOR_PVTPLL	BITS_WITH_WMASK(2U, 0x3U, 12)
94*036935a8SXiaoDong Huang 
95*036935a8SXiaoDong Huang #define CPUB_CLK_PATH_BPLL		BITS_WITH_WMASK(0U, 0x3U, 14)
96*036935a8SXiaoDong Huang #define CPUB_CLK_PATH_DIR_BPLL		BITS_WITH_WMASK(2U, 0x3U, 14)
97*036935a8SXiaoDong Huang #define CPUB_CLK_PATH_PVTPLL		BITS_WITH_WMASK(1U, 0x3U, 14)
98*036935a8SXiaoDong Huang 
99*036935a8SXiaoDong Huang #define CPUB_PVTPLL_PATH_DEEP_SLOW	BITS_WITH_WMASK(0U, 0x1U, 5)
100*036935a8SXiaoDong Huang #define CPUB_PVTPLL_PATH_PVTPLL		BITS_WITH_WMASK(0x1, 0x1U, 5)
101*036935a8SXiaoDong Huang 
102*036935a8SXiaoDong Huang #define CPUB_PCLK_PATH_100M		BITS_WITH_WMASK(0U, 0x3U, 0)
103*036935a8SXiaoDong Huang #define CPUB_PCLK_PATH_50M		BITS_WITH_WMASK(1U, 0x3U, 0)
104*036935a8SXiaoDong Huang #define CPUB_PCLK_PATH_24M		BITS_WITH_WMASK(2U, 0x3U, 0)
105*036935a8SXiaoDong Huang 
106*036935a8SXiaoDong Huang /* cci clk path */
107*036935a8SXiaoDong Huang #define SCLK_CCI_PATH_XIN		BITS_WITH_WMASK(0U, 0x3U, 12)
108*036935a8SXiaoDong Huang #define SCLK_CCI_PATH_PVTPLL		BITS_WITH_WMASK(1U, 0x3U, 12)
109*036935a8SXiaoDong Huang #define SCLK_CCI_PATH_NOR_LPLL		BITS_WITH_WMASK(3U, 0x3U, 12)
110*036935a8SXiaoDong Huang #define SCLK_CCI_PATH_NOR_GPLL		BITS_WITH_WMASK(2U, 0x3U, 12)
111*036935a8SXiaoDong Huang 
112*036935a8SXiaoDong Huang #define CCI_PVTPLL_PATH_DEEP_SLOW	BITS_WITH_WMASK(0U, 0x1U, 14)
113*036935a8SXiaoDong Huang #define CCI_PVTPLL_PATH_PVTPLL		BITS_WITH_WMASK(1U, 0x1U, 14)
114*036935a8SXiaoDong Huang 
115*036935a8SXiaoDong Huang /* npu clk path */
116*036935a8SXiaoDong Huang #define NPU_CLK_PATH_NOR_GPLL		BITS_WITH_WMASK(0U, 0x7U, 7)
117*036935a8SXiaoDong Huang #define NPU_CLK_PATH_NOR_CPLL		BITS_WITH_WMASK(1U, 0x7U, 7)
118*036935a8SXiaoDong Huang #define NPU_CLK_PATH_NOR_AUPLL		BITS_WITH_WMASK(2U, 0x7U, 7)
119*036935a8SXiaoDong Huang #define NPU_CLK_PATH_NOR_SPLL		BITS_WITH_WMASK(3U, 0x7U, 7)
120*036935a8SXiaoDong Huang 
121*036935a8SXiaoDong Huang #define NPU_CLK_PATH_NOR_PLL		WMSK_BIT(15)
122*036935a8SXiaoDong Huang #define NPU_CLK_PATH_PVTPLL		BIT_WITH_WMSK(15)
123*036935a8SXiaoDong Huang #define NPU_PVTPLL_PATH_DEEP_SLOW	BITS_WITH_WMASK(0U, 0x1U, 9)
124*036935a8SXiaoDong Huang #define NPU_PVTPLL_PATH_PVTPLL		BITS_WITH_WMASK(1U, 0x1U, 9)
125*036935a8SXiaoDong Huang 
126*036935a8SXiaoDong Huang /* gpu clk path */
127*036935a8SXiaoDong Huang #define GPU_CLK_PATH_NOR_GPLL		BITS_WITH_WMASK(0U, 0x7U, 5)
128*036935a8SXiaoDong Huang #define GPU_CLK_PATH_NOR_CPLL		BITS_WITH_WMASK(1U, 0x7U, 5)
129*036935a8SXiaoDong Huang #define GPU_CLK_PATH_NOR_AUPLL		BITS_WITH_WMASK(2U, 0x7U, 5)
130*036935a8SXiaoDong Huang #define GPU_CLK_PATH_NOR_SPLL		BITS_WITH_WMASK(3U, 0x7U, 5)
131*036935a8SXiaoDong Huang #define GPU_CLK_PATH_NOR_LPLL		BITS_WITH_WMASK(4U, 0x7U, 5)
132*036935a8SXiaoDong Huang #define GPU_CLK_PATH_NOR_PLL		WMSK_BIT(8)
133*036935a8SXiaoDong Huang #define GPU_CLK_PATH_PVTPLL		BIT_WITH_WMSK(8)
134*036935a8SXiaoDong Huang #define GPU_PVTPLL_PATH_DEEP_SLOW	BITS_WITH_WMASK(0U, 0x1U, 9)
135*036935a8SXiaoDong Huang #define GPU_PVTPLL_PATH_PVTPLL		BITS_WITH_WMASK(1U, 0x1U, 9)
136*036935a8SXiaoDong Huang 
137*036935a8SXiaoDong Huang #define PVTPLL_NEED(type, length)	(((type) == PLL_SEL_PVT || \
138*036935a8SXiaoDong Huang 					  (type) == PLL_SEL_AUTO) && \
139*036935a8SXiaoDong Huang 					 (length))
140*036935a8SXiaoDong Huang /*
141*036935a8SXiaoDong Huang  * [0]:      set intermediate rate
142*036935a8SXiaoDong Huang  *           [1]: scaling up rate or scaling down rate
143*036935a8SXiaoDong Huang  * [1]:      add length for pvtpll
144*036935a8SXiaoDong Huang  *           [2:5]: length
145*036935a8SXiaoDong Huang  * [2]:      use low length for pvtpll
146*036935a8SXiaoDong Huang  * [3:5]:    reserved
147*036935a8SXiaoDong Huang  */
148*036935a8SXiaoDong Huang #define OPP_RATE_MASK			0x3f
149*036935a8SXiaoDong Huang #define OPP_INTERMEDIATE_RATE		BIT(0)
150*036935a8SXiaoDong Huang #define OPP_SCALING_UP_RATE		BIT(1)
151*036935a8SXiaoDong Huang #define OPP_ADD_LENGTH			BIT(1)
152*036935a8SXiaoDong Huang #define OPP_LENGTH_MASK			GENMASK_32(5, 2)
153*036935a8SXiaoDong Huang #define OPP_LENGTH_SHIFT		2
154*036935a8SXiaoDong Huang #define OPP_LENGTH_LOW			BIT(2)
155*036935a8SXiaoDong Huang 
156*036935a8SXiaoDong Huang #define PRATE(x) static const unsigned long const x[]
157*036935a8SXiaoDong Huang #define PINFO(x) static const uint32_t const x[]
158*036935a8SXiaoDong Huang 
159*036935a8SXiaoDong Huang PRATE(p_24m)			= { OSC_HZ };
160*036935a8SXiaoDong Huang PRATE(p_100m_24m)		= { 100 * MHz, OSC_HZ };
161*036935a8SXiaoDong Huang PRATE(p_350m_175m_116m_24m)	= { 350 * MHz, 175 * MHz, 116 * MHz, OSC_HZ };
162*036935a8SXiaoDong Huang PRATE(p_175m_116m_58m_24m)	= { 175 * MHz, 116 * MHz, 58 * MHz, OSC_HZ };
163*036935a8SXiaoDong Huang PRATE(p_116m_58m_24m)		= { 116 * MHz, 58 * MHz, OSC_HZ };
164*036935a8SXiaoDong Huang PRATE(p_pclk_secure_s)		= { PCLK_SECURE_S };
165*036935a8SXiaoDong Huang PRATE(p_hclk_secure_s)		= { HCLK_SECURE_S };
166*036935a8SXiaoDong Huang PRATE(p_aclk_secure_s)		= { ACLK_SECURE_S };
167*036935a8SXiaoDong Huang PRATE(p_hclk_vo0_s)		= { HCLK_VO0_S };
168*036935a8SXiaoDong Huang PRATE(p_pclk_vo0_s)		= { PCLK_VO0_S };
169*036935a8SXiaoDong Huang PRATE(p_hclk_vo1_s)		= { HCLK_VO1_S };
170*036935a8SXiaoDong Huang PRATE(p_pclk_vo1_s)		= { PCLK_VO1_S };
171*036935a8SXiaoDong Huang 
172*036935a8SXiaoDong Huang PINFO(clk_stimer0_root_info)	= { 0x27214004, 6, 1, 0, 0, 0, 0x27214028, 9 };
173*036935a8SXiaoDong Huang PINFO(clk_stimer1_root_info)	= { 0x27214004, 7, 1, 0, 0, 0, 0x2721402c, 1 };
174*036935a8SXiaoDong Huang PINFO(pclk_secure_s_info)	= { 0x27214004, 4, 2, 0, 0, 0, 0x27214028, 2 };
175*036935a8SXiaoDong Huang PINFO(hclk_secure_s_info)	= { 0x27214004, 2, 2, 0, 0, 0, 0x27214028, 1 };
176*036935a8SXiaoDong Huang PINFO(aclk_secure_s_info)	= { 0x27214004, 0, 2, 0, 0, 0, 0x27214028, 0 };
177*036935a8SXiaoDong Huang PINFO(clk_pka_crypto_s_info)	= { 0x27214004, 11, 2, 0, 0, 0, 0x27214030, 11 };
178*036935a8SXiaoDong Huang PINFO(hclk_vo1_s_info)		= { 0x27214010, 0, 2, 0, 0, 0, 0x27214038, 1 };
179*036935a8SXiaoDong Huang PINFO(pclk_vo1_s_info)		= { 0x27214010, 2, 2, 0, 0, 0, 0x27214038, 4 };
180*036935a8SXiaoDong Huang PINFO(hclk_vo0_s_info)		= { 0x27214018, 0, 2, 0, 0, 0, 0x2721403c, 1 };
181*036935a8SXiaoDong Huang PINFO(pclk_vo0_s_info)		= { 0x27214018, 2, 2, 0, 0, 0, 0x2721403c, 4 };
182*036935a8SXiaoDong Huang PINFO(pclk_klad_info)		= { 0, 0, 0, 0, 0, 0, 0x27214030, 7 };
183*036935a8SXiaoDong Huang PINFO(hclk_crypto_s_info)	= { 0, 0, 0, 0, 0, 0, 0x27214030, 8 };
184*036935a8SXiaoDong Huang PINFO(hclk_klad_info)		= { 0, 0, 0, 0, 0, 0, 0x27214030, 9 };
185*036935a8SXiaoDong Huang PINFO(aclk_crypto_s_info)	= { 0, 0, 0, 0, 0, 0, 0x27214030, 12 };
186*036935a8SXiaoDong Huang PINFO(hclk_trng_s_info)		= { 0, 0, 0, 0, 0, 0, 0x27214034, 0 };
187*036935a8SXiaoDong Huang PINFO(pclk_otpc_s_info)		= { 0, 0, 0, 0, 0, 0, 0x27214034, 3 };
188*036935a8SXiaoDong Huang PINFO(clk_otpc_s_info)		= { 0, 0, 0, 0, 0, 0, 0x27214034, 4 };
189*036935a8SXiaoDong Huang PINFO(pclk_wdt_s_info)		= { 0, 0, 0, 0, 0, 0, 0x27214034, 9 };
190*036935a8SXiaoDong Huang PINFO(tclk_wdt_s_info)		= { 0, 0, 0, 0, 0, 0, 0x27214034, 10 };
191*036935a8SXiaoDong Huang PINFO(pclk_hdcp1_trng_info)	= { 0, 0, 0, 0, 0, 0, 0x27214038, 0 };
192*036935a8SXiaoDong Huang PINFO(hclk_hdcp_key1_info)	= { 0, 0, 0, 0, 0, 0, 0x27214038, 3 };
193*036935a8SXiaoDong Huang PINFO(pclk_hdcp0_trng_info)	= { 0, 0, 0, 0, 0, 0, 0x2721403c, 0 };
194*036935a8SXiaoDong Huang PINFO(hclk_hdcp_key0_info)	= { 0, 0, 0, 0, 0, 0, 0x2721403c, 3 };
195*036935a8SXiaoDong Huang PINFO(pclk_edp_s_info)		= { 0, 0, 0, 0, 0, 0, 0x2721403c, 5 };
196*036935a8SXiaoDong Huang 
197*036935a8SXiaoDong Huang struct pvtpll_table {
198*036935a8SXiaoDong Huang 	unsigned int rate;
199*036935a8SXiaoDong Huang 	uint32_t length;
200*036935a8SXiaoDong Huang 	uint32_t length_frac;
201*036935a8SXiaoDong Huang 	uint32_t length_low;
202*036935a8SXiaoDong Huang 	uint32_t length_low_frac;
203*036935a8SXiaoDong Huang 	uint32_t ring_sel;
204*036935a8SXiaoDong Huang 	uint32_t volt_sel_thr;
205*036935a8SXiaoDong Huang };
206*036935a8SXiaoDong Huang 
207*036935a8SXiaoDong Huang struct sys_clk_info_t {
208*036935a8SXiaoDong Huang 	struct pvtpll_table *cpul_table;
209*036935a8SXiaoDong Huang 	struct pvtpll_table *cci_table;
210*036935a8SXiaoDong Huang 	struct pvtpll_table *cpub_table;
211*036935a8SXiaoDong Huang 	struct pvtpll_table *gpu_table;
212*036935a8SXiaoDong Huang 	struct pvtpll_table *npu_table;
213*036935a8SXiaoDong Huang 	unsigned int cpul_rate_count;
214*036935a8SXiaoDong Huang 	unsigned int cci_rate_count;
215*036935a8SXiaoDong Huang 	unsigned int cpub_rate_count;
216*036935a8SXiaoDong Huang 	unsigned int gpu_rate_count;
217*036935a8SXiaoDong Huang 	unsigned int npu_rate_count;
218*036935a8SXiaoDong Huang 	unsigned long cpul_rate;
219*036935a8SXiaoDong Huang 	unsigned long cci_rate;
220*036935a8SXiaoDong Huang 	unsigned long cpub_rate;
221*036935a8SXiaoDong Huang 	unsigned long gpu_rate;
222*036935a8SXiaoDong Huang 	unsigned long npu_rate;
223*036935a8SXiaoDong Huang };
224*036935a8SXiaoDong Huang 
225*036935a8SXiaoDong Huang struct otp_opp_info {
226*036935a8SXiaoDong Huang 	uint16_t min_freq;
227*036935a8SXiaoDong Huang 	uint16_t max_freq;
228*036935a8SXiaoDong Huang 	uint8_t volt;
229*036935a8SXiaoDong Huang 	uint8_t length;
230*036935a8SXiaoDong Huang } __packed;
231*036935a8SXiaoDong Huang 
232*036935a8SXiaoDong Huang #define RK3576_SCMI_CLOCK(_id, _name, _data, _table, _cnt, _is_s)	\
233*036935a8SXiaoDong Huang rk_scmi_clock_t _name = {						\
234*036935a8SXiaoDong Huang 	.id	= _id,							\
235*036935a8SXiaoDong Huang 	.name = #_name,							\
236*036935a8SXiaoDong Huang 	.clk_ops = _data,						\
237*036935a8SXiaoDong Huang 	.rate_table = _table,						\
238*036935a8SXiaoDong Huang 	.rate_cnt = _cnt,						\
239*036935a8SXiaoDong Huang 	.is_security = _is_s,						\
240*036935a8SXiaoDong Huang }
241*036935a8SXiaoDong Huang 
242*036935a8SXiaoDong Huang #define RK3576_SCMI_CLOCK_COM(_id, _name,  _parent_table, _info, _data,	\
243*036935a8SXiaoDong Huang 			     _table, is_d, _is_s)			\
244*036935a8SXiaoDong Huang rk_scmi_clock_t _name = {						\
245*036935a8SXiaoDong Huang 	.id	= _id,							\
246*036935a8SXiaoDong Huang 	.name = #_name,							\
247*036935a8SXiaoDong Huang 	.parent_table = _parent_table,					\
248*036935a8SXiaoDong Huang 	.info = _info,							\
249*036935a8SXiaoDong Huang 	.clk_ops = _data,						\
250*036935a8SXiaoDong Huang 	.rate_table = _table,						\
251*036935a8SXiaoDong Huang 	.rate_cnt = ARRAY_SIZE(_table),					\
252*036935a8SXiaoDong Huang 	.is_dynamic_prate = is_d,					\
253*036935a8SXiaoDong Huang 	.is_security = _is_s,						\
254*036935a8SXiaoDong Huang }
255*036935a8SXiaoDong Huang 
256*036935a8SXiaoDong Huang #define ROCKCHIP_PVTPLL(_rate, _sel, _len, _len_frac)			\
257*036935a8SXiaoDong Huang {									\
258*036935a8SXiaoDong Huang 	.rate = _rate##U,						\
259*036935a8SXiaoDong Huang 	.ring_sel = _sel,						\
260*036935a8SXiaoDong Huang 	.length = _len,							\
261*036935a8SXiaoDong Huang 	.length_frac = _len_frac,					\
262*036935a8SXiaoDong Huang }
263*036935a8SXiaoDong Huang 
264*036935a8SXiaoDong Huang static struct pvtpll_table rk3576_cpul_pvtpll_table[] = {
265*036935a8SXiaoDong Huang 	/* rate_hz, ring_sel, length, length_frac */
266*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(2016000000, 0, 6, 0),
267*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(1920000000, 0, 6, 1),
268*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(1800000000, 0, 6, 1),
269*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(1608000000, 0, 6, 1),
270*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(1416000000, 0, 8, 0),
271*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(1200000000, 0, 11, 0),
272*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(1008000000, 0, 17, 0),
273*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(816000000, 0, 26, 0),
274*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(600000000, 0, 0, 0),
275*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(408000000, 0, 0, 0),
276*036935a8SXiaoDong Huang 	{ /* sentinel */ },
277*036935a8SXiaoDong Huang };
278*036935a8SXiaoDong Huang 
279*036935a8SXiaoDong Huang static struct pvtpll_table rk3576_cci_pvtpll_table[] = {
280*036935a8SXiaoDong Huang 	/* cpul_rate_hz, ring_sel, length, length_frac */
281*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(2016000000 / 2, 0, 27, 0),
282*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(1920000000 / 2, 0, 28, 0),
283*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(1800000000 / 2, 0, 28, 0),
284*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(1608000000 / 2, 0, 30, 0),
285*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(1416000000 / 2, 0, 34, 0),
286*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(1200000000 / 2, 0, 34, 0),
287*036935a8SXiaoDong Huang 	{ /* sentinel */ },
288*036935a8SXiaoDong Huang };
289*036935a8SXiaoDong Huang 
290*036935a8SXiaoDong Huang static struct pvtpll_table rk3576_cpub_pvtpll_table[] = {
291*036935a8SXiaoDong Huang 	/* rate_hz, ring_sel, length, length_frac, length_low, length_low_frac */
292*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(2208000000, 0, 4, 3),
293*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(2112000000, 0, 5, 0),
294*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(2016000000, 0, 5, 0),
295*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(1800000000, 0, 5, 0),
296*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(1608000000, 0, 5, 0),
297*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(1416000000, 0, 7, 0),
298*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(1200000000, 0, 11, 0),
299*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(1008000000, 0, 17, 0),
300*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(816000000, 0, 26, 0),
301*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(600000000, 0, 0, 0),
302*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(408000000, 0, 0, 0),
303*036935a8SXiaoDong Huang 	{ /* sentinel */ },
304*036935a8SXiaoDong Huang };
305*036935a8SXiaoDong Huang 
306*036935a8SXiaoDong Huang static struct pvtpll_table rk3576_gpu_pvtpll_table[] = {
307*036935a8SXiaoDong Huang 	/* rate_hz, ring_sel, length, length_frac, length_low, length_low_frac */
308*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(900000000, 0, 20, 0),
309*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(800000000, 0, 21, 0),
310*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(700000000, 0, 21, 0),
311*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(600000000, 0, 23, 0),
312*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(500000000, 0, 32, 0),
313*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(400000000, 0, 48, 0),
314*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(300000000, 0, 63, 0),
315*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(200000000, 0, 0, 0),
316*036935a8SXiaoDong Huang 	{ /* sentinel */ },
317*036935a8SXiaoDong Huang };
318*036935a8SXiaoDong Huang 
319*036935a8SXiaoDong Huang static struct pvtpll_table rk3576_npu_pvtpll_table[] = {
320*036935a8SXiaoDong Huang 	/* rate_hz, ring_sel, length, length_frac, length_low, length_low_frac */
321*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(950000000, 0, 16, 0),
322*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(900000000, 0, 17, 0),
323*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(800000000, 0, 18, 0),
324*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(700000000, 0, 22, 0),
325*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(600000000, 0, 25, 0),
326*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(500000000, 0, 35, 0),
327*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(400000000, 0, 46, 0),
328*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(300000000, 0, 63, 0),
329*036935a8SXiaoDong Huang 	ROCKCHIP_PVTPLL(200000000, 0, 0, 0),
330*036935a8SXiaoDong Huang 	{ /* sentinel */ },
331*036935a8SXiaoDong Huang };
332*036935a8SXiaoDong Huang 
333*036935a8SXiaoDong Huang static unsigned long rk3576_cpul_rates[] = {
334*036935a8SXiaoDong Huang 	408000000, 600000000, 816000000, 1008000000,
335*036935a8SXiaoDong Huang 	1200000000, 1416000000, 1608000000, 1800000000,
336*036935a8SXiaoDong Huang 	2016000000, 2208000000, 2304000063
337*036935a8SXiaoDong Huang };
338*036935a8SXiaoDong Huang 
339*036935a8SXiaoDong Huang static unsigned long rk3576_cpub_rates[] = {
340*036935a8SXiaoDong Huang 	408000000, 600000000, 816000000, 1008000000,
341*036935a8SXiaoDong Huang 	1200000000, 1416000000, 1608000000, 1800000000,
342*036935a8SXiaoDong Huang 	2016000000, 2208000000, 2304000000, 2400000063
343*036935a8SXiaoDong Huang };
344*036935a8SXiaoDong Huang 
345*036935a8SXiaoDong Huang static unsigned long rk3576_gpu_rates[] = {
346*036935a8SXiaoDong Huang 	200000000, 300000000, 400000000, 500000000,
347*036935a8SXiaoDong Huang 	600000000, 700000000, 800000000, 900000000,
348*036935a8SXiaoDong Huang 	1000000063
349*036935a8SXiaoDong Huang };
350*036935a8SXiaoDong Huang 
351*036935a8SXiaoDong Huang static unsigned long rk3576_npu_rates[] = {
352*036935a8SXiaoDong Huang 	200000000, 300000000, 400000000, 500000000,
353*036935a8SXiaoDong Huang 	600000000, 700000000, 800000000, 900000000,
354*036935a8SXiaoDong Huang 	1000000063
355*036935a8SXiaoDong Huang };
356*036935a8SXiaoDong Huang 
357*036935a8SXiaoDong Huang static unsigned long rk3576_common_rates[] = {
358*036935a8SXiaoDong Huang 	400000, 24000000, 58000000, 100000000, 116000000, 175000000, 350000000,
359*036935a8SXiaoDong Huang };
360*036935a8SXiaoDong Huang 
361*036935a8SXiaoDong Huang static unsigned long rk3576_aclk_secure_s_rates[] = {
362*036935a8SXiaoDong Huang 	116000000, 175000000, 350000000,
363*036935a8SXiaoDong Huang };
364*036935a8SXiaoDong Huang 
365*036935a8SXiaoDong Huang static int aclk_crypto_s_enable;
366*036935a8SXiaoDong Huang static int aclk_klad_enable;
367*036935a8SXiaoDong Huang static spinlock_t crypto_lock;
368*036935a8SXiaoDong Huang static bool cpub_suspended;
369*036935a8SXiaoDong Huang 
370*036935a8SXiaoDong Huang static struct sys_clk_info_t sys_clk_info;
371*036935a8SXiaoDong Huang static int clk_scmi_cci_set_rate(rk_scmi_clock_t *clock, unsigned long rate);
372*036935a8SXiaoDong Huang 
rkclk_get_pvtpll_config(struct pvtpll_table * table,unsigned int count,unsigned int freq_hz)373*036935a8SXiaoDong Huang static struct pvtpll_table *rkclk_get_pvtpll_config(struct pvtpll_table *table,
374*036935a8SXiaoDong Huang 						    unsigned int count,
375*036935a8SXiaoDong Huang 						    unsigned int freq_hz)
376*036935a8SXiaoDong Huang {
377*036935a8SXiaoDong Huang 	int i;
378*036935a8SXiaoDong Huang 
379*036935a8SXiaoDong Huang 	for (i = 0; i < count; i++) {
380*036935a8SXiaoDong Huang 		if (freq_hz == table[i].rate)
381*036935a8SXiaoDong Huang 			return &table[i];
382*036935a8SXiaoDong Huang 	}
383*036935a8SXiaoDong Huang 	return NULL;
384*036935a8SXiaoDong Huang }
385*036935a8SXiaoDong Huang 
clk_scmi_set_low_length(struct pvtpll_table * pvtpll,unsigned int count)386*036935a8SXiaoDong Huang static int clk_scmi_set_low_length(struct pvtpll_table *pvtpll, unsigned int count)
387*036935a8SXiaoDong Huang {
388*036935a8SXiaoDong Huang 	int i;
389*036935a8SXiaoDong Huang 
390*036935a8SXiaoDong Huang 	for (i = 0; i < count; i++) {
391*036935a8SXiaoDong Huang 		if (pvtpll[i].length_low) {
392*036935a8SXiaoDong Huang 			pvtpll[i].length = pvtpll[i].length_low;
393*036935a8SXiaoDong Huang 			pvtpll[i].length_frac = pvtpll[i].length_low_frac;
394*036935a8SXiaoDong Huang 		}
395*036935a8SXiaoDong Huang 	}
396*036935a8SXiaoDong Huang 
397*036935a8SXiaoDong Huang 	return 0;
398*036935a8SXiaoDong Huang }
399*036935a8SXiaoDong Huang 
clk_cpul_set_rate(unsigned long rate,enum pll_type_sel type)400*036935a8SXiaoDong Huang static int clk_cpul_set_rate(unsigned long rate, enum pll_type_sel type)
401*036935a8SXiaoDong Huang {
402*036935a8SXiaoDong Huang 	struct pvtpll_table *pvtpll;
403*036935a8SXiaoDong Huang 	int div;
404*036935a8SXiaoDong Huang 
405*036935a8SXiaoDong Huang 	if (rate == 0)
406*036935a8SXiaoDong Huang 		return SCMI_INVALID_PARAMETERS;
407*036935a8SXiaoDong Huang 
408*036935a8SXiaoDong Huang 	pvtpll = rkclk_get_pvtpll_config(sys_clk_info.cpul_table,
409*036935a8SXiaoDong Huang 					 sys_clk_info.cpul_rate_count, rate);
410*036935a8SXiaoDong Huang 	if (pvtpll == NULL)
411*036935a8SXiaoDong Huang 		return SCMI_INVALID_PARAMETERS;
412*036935a8SXiaoDong Huang 
413*036935a8SXiaoDong Huang 	/*
414*036935a8SXiaoDong Huang 	 *               |-\
415*036935a8SXiaoDong Huang 	 * -----lpll-----|  \
416*036935a8SXiaoDong Huang 	 *               |   \                                        |-\
417*036935a8SXiaoDong Huang 	 * -----gpll-----|mux|--litcore unclean src--[div]--[autocs]--|  \
418*036935a8SXiaoDong Huang 	 *               |   /                                        |   \
419*036935a8SXiaoDong Huang 	 * --pvtpll src--|  /                           --pvtpll src--|mux|--litcore--
420*036935a8SXiaoDong Huang 	 *               |-/                                          |   /
421*036935a8SXiaoDong Huang 	 *                                       --litcore clean src--|  /
422*036935a8SXiaoDong Huang 	 *                                                            |-/
423*036935a8SXiaoDong Huang 	 */
424*036935a8SXiaoDong Huang 	if (PVTPLL_NEED(type, pvtpll->length)) {
425*036935a8SXiaoDong Huang 		/* set ring sel and length */
426*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_LITCORE_BASE + RK3576_PVTPLL_GCK_LEN,
427*036935a8SXiaoDong Huang 			      0x1dff0000 |
428*036935a8SXiaoDong Huang 			      (pvtpll->ring_sel << 10) |
429*036935a8SXiaoDong Huang 			      (pvtpll->length << 2) |
430*036935a8SXiaoDong Huang 			      (pvtpll->length_frac));
431*036935a8SXiaoDong Huang 		/* set cal cnt = 24, T = 1us */
432*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_LITCORE_BASE + RK3576_PVTPLL_GCK_CAL_CNT, 0x18);
433*036935a8SXiaoDong Huang 		/* enable pvtpll */
434*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_LITCORE_BASE + RK3576_PVTPLL_GCK_CFG, 0x00220022);
435*036935a8SXiaoDong Huang 		/* start pvtpll */
436*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_LITCORE_BASE + RK3576_PVTPLL_GCK_CFG,  0x00230023);
437*036935a8SXiaoDong Huang 
438*036935a8SXiaoDong Huang 		/* set pvtpll_src parent from 24MHz/32KHz to pvtpll */
439*036935a8SXiaoDong Huang 		mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(1),
440*036935a8SXiaoDong Huang 			      CPUL_PVTPLL_PATH_PVTPLL);
441*036935a8SXiaoDong Huang 
442*036935a8SXiaoDong Huang 		/* set litcore unclean_src parent to pvtpll_src */
443*036935a8SXiaoDong Huang 		mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(0),
444*036935a8SXiaoDong Huang 			      CPUL_CLK_PATH_NOR_PVTPLL);
445*036935a8SXiaoDong Huang 		/*
446*036935a8SXiaoDong Huang 		 * set litcore parent from pvtpll_src to unclean_src,
447*036935a8SXiaoDong Huang 		 * because autocs is on litcore unclean_src.
448*036935a8SXiaoDong Huang 		 */
449*036935a8SXiaoDong Huang 		mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(1),
450*036935a8SXiaoDong Huang 			      CPUL_CLK_PATH_LPLL);
451*036935a8SXiaoDong Huang 		/* set litcore unclean_src div to 0 */
452*036935a8SXiaoDong Huang 		mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(0),
453*036935a8SXiaoDong Huang 			      CLKDIV_5BITS_SHF(0, 7));
454*036935a8SXiaoDong Huang 
455*036935a8SXiaoDong Huang 		return 0;
456*036935a8SXiaoDong Huang 	}
457*036935a8SXiaoDong Huang 	/* set litcore unclean_src div */
458*036935a8SXiaoDong Huang 	div = DIV_ROUND_UP(GPLL_RATE, rate) - 1;
459*036935a8SXiaoDong Huang 	mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(0),
460*036935a8SXiaoDong Huang 		      CLKDIV_5BITS_SHF(div, 7));
461*036935a8SXiaoDong Huang 	/* set litcore unclean_src parent to gpll */
462*036935a8SXiaoDong Huang 	mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(0),
463*036935a8SXiaoDong Huang 		      CPUL_CLK_PATH_NOR_GPLL);
464*036935a8SXiaoDong Huang 	/* set litcore parent to unclean_src */
465*036935a8SXiaoDong Huang 	mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(1),
466*036935a8SXiaoDong Huang 		      CPUL_CLK_PATH_LPLL);
467*036935a8SXiaoDong Huang 
468*036935a8SXiaoDong Huang 	return 0;
469*036935a8SXiaoDong Huang }
470*036935a8SXiaoDong Huang 
clk_scmi_cpul_set_rate(rk_scmi_clock_t * clock,unsigned long rate)471*036935a8SXiaoDong Huang static int clk_scmi_cpul_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
472*036935a8SXiaoDong Huang {
473*036935a8SXiaoDong Huang 	int ret;
474*036935a8SXiaoDong Huang 
475*036935a8SXiaoDong Huang 	if (rate == 0)
476*036935a8SXiaoDong Huang 		return SCMI_INVALID_PARAMETERS;
477*036935a8SXiaoDong Huang 
478*036935a8SXiaoDong Huang 	ret = clk_cpul_set_rate(rate, PLL_SEL_AUTO);
479*036935a8SXiaoDong Huang 	if (ret == 0) {
480*036935a8SXiaoDong Huang 		sys_clk_info.cpul_rate = rate;
481*036935a8SXiaoDong Huang 		ret = clk_scmi_cci_set_rate(clock, rate / 2);
482*036935a8SXiaoDong Huang 	}
483*036935a8SXiaoDong Huang 
484*036935a8SXiaoDong Huang 	return ret;
485*036935a8SXiaoDong Huang }
486*036935a8SXiaoDong Huang 
rk3576_lpll_get_rate(void)487*036935a8SXiaoDong Huang static unsigned long rk3576_lpll_get_rate(void)
488*036935a8SXiaoDong Huang {
489*036935a8SXiaoDong Huang 	unsigned int m, p, s, k;
490*036935a8SXiaoDong Huang 	uint64_t rate64 = 24000000, postdiv;
491*036935a8SXiaoDong Huang 	int mode;
492*036935a8SXiaoDong Huang 
493*036935a8SXiaoDong Huang 	mode = mmio_read_32(LITTLE_CRU_BASE + CRU_MODE_CON) &
494*036935a8SXiaoDong Huang 	       0x3;
495*036935a8SXiaoDong Huang 
496*036935a8SXiaoDong Huang 	if (mode == 0)
497*036935a8SXiaoDong Huang 		return rate64;
498*036935a8SXiaoDong Huang 
499*036935a8SXiaoDong Huang 	m = (mmio_read_32(CCI_CRU_BASE + CRU_PLL_CON(16)) >>
500*036935a8SXiaoDong Huang 		 CRU_PLLCON0_M_SHIFT) &
501*036935a8SXiaoDong Huang 		CRU_PLLCON0_M_MASK;
502*036935a8SXiaoDong Huang 	p = (mmio_read_32(CCI_CRU_BASE + CRU_PLL_CON(17)) >>
503*036935a8SXiaoDong Huang 		    CRU_PLLCON1_P_SHIFT) &
504*036935a8SXiaoDong Huang 		   CRU_PLLCON1_P_MASK;
505*036935a8SXiaoDong Huang 	s = (mmio_read_32(CCI_CRU_BASE + CRU_PLL_CON(17)) >>
506*036935a8SXiaoDong Huang 		  CRU_PLLCON1_S_SHIFT) &
507*036935a8SXiaoDong Huang 		 CRU_PLLCON1_S_MASK;
508*036935a8SXiaoDong Huang 	k = (mmio_read_32(CCI_CRU_BASE + CRU_PLL_CON(18)) >>
509*036935a8SXiaoDong Huang 		    CRU_PLLCON2_K_SHIFT) &
510*036935a8SXiaoDong Huang 		   CRU_PLLCON2_K_MASK;
511*036935a8SXiaoDong Huang 
512*036935a8SXiaoDong Huang 	rate64 *= m;
513*036935a8SXiaoDong Huang 	rate64 = rate64 / p;
514*036935a8SXiaoDong Huang 
515*036935a8SXiaoDong Huang 	if (k != 0) {
516*036935a8SXiaoDong Huang 		/* fractional mode */
517*036935a8SXiaoDong Huang 		uint64_t frac_rate64 = 24000000 * k;
518*036935a8SXiaoDong Huang 
519*036935a8SXiaoDong Huang 		postdiv = p * 65536;
520*036935a8SXiaoDong Huang 		frac_rate64 = frac_rate64 / postdiv;
521*036935a8SXiaoDong Huang 		rate64 += frac_rate64;
522*036935a8SXiaoDong Huang 	}
523*036935a8SXiaoDong Huang 	rate64 = rate64 >> s;
524*036935a8SXiaoDong Huang 
525*036935a8SXiaoDong Huang 	return (unsigned long)rate64;
526*036935a8SXiaoDong Huang }
527*036935a8SXiaoDong Huang 
clk_scmi_cpul_get_rate(rk_scmi_clock_t * clock)528*036935a8SXiaoDong Huang static unsigned long clk_scmi_cpul_get_rate(rk_scmi_clock_t *clock)
529*036935a8SXiaoDong Huang {
530*036935a8SXiaoDong Huang 	int src, div;
531*036935a8SXiaoDong Huang 
532*036935a8SXiaoDong Huang 	src = mmio_read_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(1)) & 0x00c0;
533*036935a8SXiaoDong Huang 	src = src >> 6;
534*036935a8SXiaoDong Huang 	if (src == 1)
535*036935a8SXiaoDong Huang 		return sys_clk_info.cpul_rate;
536*036935a8SXiaoDong Huang 
537*036935a8SXiaoDong Huang 	src = mmio_read_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(0)) & 0x3000;
538*036935a8SXiaoDong Huang 	src = src >> 12;
539*036935a8SXiaoDong Huang 	div = mmio_read_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(6)) & 0x0f80;
540*036935a8SXiaoDong Huang 	div = div >> 7;
541*036935a8SXiaoDong Huang 	switch (src) {
542*036935a8SXiaoDong Huang 	case 0:
543*036935a8SXiaoDong Huang 		return rk3576_lpll_get_rate();
544*036935a8SXiaoDong Huang 	case 1:
545*036935a8SXiaoDong Huang 		/* Make the return rate is equal to the set rate */
546*036935a8SXiaoDong Huang 		if (sys_clk_info.cpul_rate != 0)
547*036935a8SXiaoDong Huang 			return sys_clk_info.cpul_rate;
548*036935a8SXiaoDong Huang 		else
549*036935a8SXiaoDong Huang 			return GPLL_RATE / (div + 1);
550*036935a8SXiaoDong Huang 	case 2:
551*036935a8SXiaoDong Huang 		return sys_clk_info.cpul_rate;
552*036935a8SXiaoDong Huang 	default:
553*036935a8SXiaoDong Huang 		return 0;
554*036935a8SXiaoDong Huang 	}
555*036935a8SXiaoDong Huang }
556*036935a8SXiaoDong Huang 
clk_scmi_cpul_set_status(rk_scmi_clock_t * clock,bool status)557*036935a8SXiaoDong Huang static int clk_scmi_cpul_set_status(rk_scmi_clock_t *clock, bool status)
558*036935a8SXiaoDong Huang {
559*036935a8SXiaoDong Huang 	return 0;
560*036935a8SXiaoDong Huang }
561*036935a8SXiaoDong Huang 
clk_cpub_set_rate(unsigned long rate,enum pll_type_sel type)562*036935a8SXiaoDong Huang static int clk_cpub_set_rate(unsigned long rate, enum pll_type_sel type)
563*036935a8SXiaoDong Huang {
564*036935a8SXiaoDong Huang 	struct pvtpll_table *pvtpll;
565*036935a8SXiaoDong Huang 	int div;
566*036935a8SXiaoDong Huang 
567*036935a8SXiaoDong Huang 	if (rate == 0)
568*036935a8SXiaoDong Huang 		return SCMI_INVALID_PARAMETERS;
569*036935a8SXiaoDong Huang 
570*036935a8SXiaoDong Huang 	pvtpll = rkclk_get_pvtpll_config(sys_clk_info.cpub_table,
571*036935a8SXiaoDong Huang 					 sys_clk_info.cpub_rate_count, rate);
572*036935a8SXiaoDong Huang 	if (pvtpll == NULL)
573*036935a8SXiaoDong Huang 		return SCMI_INVALID_PARAMETERS;
574*036935a8SXiaoDong Huang 
575*036935a8SXiaoDong Huang 	/*
576*036935a8SXiaoDong Huang 	 *               |-\
577*036935a8SXiaoDong Huang 	 * -----bpll-----|  \
578*036935a8SXiaoDong Huang 	 *               |   \                                        |-\
579*036935a8SXiaoDong Huang 	 * -----gpll-----|mux|--bigcore unclean src--[div]--[autocs]--|  \
580*036935a8SXiaoDong Huang 	 *               |   /                                        |   \
581*036935a8SXiaoDong Huang 	 * --pvtpll src--|  /                           --pvtpll src--|mux|--bigcore--
582*036935a8SXiaoDong Huang 	 *               |-/                                          |   /
583*036935a8SXiaoDong Huang 	 *                                       --bigcore clean src--|  /
584*036935a8SXiaoDong Huang 	 *                                                            |-/
585*036935a8SXiaoDong Huang 	 */
586*036935a8SXiaoDong Huang 	if (PVTPLL_NEED(type, pvtpll->length) != 0) {
587*036935a8SXiaoDong Huang 		/* set ring sel and length */
588*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_BIGCORE_BASE + RK3576_PVTPLL_GCK_LEN,
589*036935a8SXiaoDong Huang 			      0x1dff0000 |
590*036935a8SXiaoDong Huang 			      (pvtpll->ring_sel << 10) |
591*036935a8SXiaoDong Huang 			      (pvtpll->length << 2) |
592*036935a8SXiaoDong Huang 			      (pvtpll->length_frac));
593*036935a8SXiaoDong Huang 		/* set cal cnt = 24, T = 1us */
594*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_BIGCORE_BASE + RK3576_PVTPLL_GCK_CAL_CNT, 0x18);
595*036935a8SXiaoDong Huang 		/* enable pvtpll */
596*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_BIGCORE_BASE + RK3576_PVTPLL_GCK_CFG, 0x00220022);
597*036935a8SXiaoDong Huang 		/* start pvtpll */
598*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_BIGCORE_BASE + RK3576_PVTPLL_GCK_CFG, 0x00230023);
599*036935a8SXiaoDong Huang 
600*036935a8SXiaoDong Huang 		/* set pvtpll_src parent from 24MHz/32KHz to pvtpll */
601*036935a8SXiaoDong Huang 		mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(2),
602*036935a8SXiaoDong Huang 			      CPUB_PVTPLL_PATH_PVTPLL);
603*036935a8SXiaoDong Huang 
604*036935a8SXiaoDong Huang 		/* set bigcore unclean_src parent to pvtpll_src */
605*036935a8SXiaoDong Huang 		mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
606*036935a8SXiaoDong Huang 			      CPUB_CLK_PATH_NOR_PVTPLL);
607*036935a8SXiaoDong Huang 		/*
608*036935a8SXiaoDong Huang 		 * set bigcore parent from pvtpll_src to unclean_src,
609*036935a8SXiaoDong Huang 		 * because autocs is on bigcore unclean_src.
610*036935a8SXiaoDong Huang 		 */
611*036935a8SXiaoDong Huang 		mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
612*036935a8SXiaoDong Huang 			      CPUB_CLK_PATH_BPLL);
613*036935a8SXiaoDong Huang 
614*036935a8SXiaoDong Huang 		/* set bigcore unclean_src div to 0 */
615*036935a8SXiaoDong Huang 		mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
616*036935a8SXiaoDong Huang 			      CLKDIV_5BITS_SHF(0, 7));
617*036935a8SXiaoDong Huang 
618*036935a8SXiaoDong Huang 		return 0;
619*036935a8SXiaoDong Huang 	}
620*036935a8SXiaoDong Huang 
621*036935a8SXiaoDong Huang 	/* set bigcore unclean_src div */
622*036935a8SXiaoDong Huang 	div = DIV_ROUND_UP(GPLL_RATE, rate) - 1;
623*036935a8SXiaoDong Huang 	mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
624*036935a8SXiaoDong Huang 		      CLKDIV_5BITS_SHF(div, 7));
625*036935a8SXiaoDong Huang 	/* set bigcore unclean_src parent to gpll */
626*036935a8SXiaoDong Huang 	mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
627*036935a8SXiaoDong Huang 		      CPUB_CLK_PATH_NOR_GPLL);
628*036935a8SXiaoDong Huang 	/* set bigcore parent to unclean_src */
629*036935a8SXiaoDong Huang 	mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
630*036935a8SXiaoDong Huang 		      CPUB_CLK_PATH_BPLL);
631*036935a8SXiaoDong Huang 
632*036935a8SXiaoDong Huang 	return 0;
633*036935a8SXiaoDong Huang }
634*036935a8SXiaoDong Huang 
clk_scmi_cpub_set_rate(rk_scmi_clock_t * clock,unsigned long rate)635*036935a8SXiaoDong Huang static int clk_scmi_cpub_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
636*036935a8SXiaoDong Huang {
637*036935a8SXiaoDong Huang 	int ret;
638*036935a8SXiaoDong Huang 
639*036935a8SXiaoDong Huang 	if (rate == 0)
640*036935a8SXiaoDong Huang 		return SCMI_INVALID_PARAMETERS;
641*036935a8SXiaoDong Huang 
642*036935a8SXiaoDong Huang 	if ((rate & OPP_LENGTH_LOW) != 0) {
643*036935a8SXiaoDong Huang 		clk_scmi_set_low_length(sys_clk_info.cpub_table,
644*036935a8SXiaoDong Huang 					sys_clk_info.cpub_rate_count);
645*036935a8SXiaoDong Huang 		return 0;
646*036935a8SXiaoDong Huang 	}
647*036935a8SXiaoDong Huang 
648*036935a8SXiaoDong Huang 	ret = clk_cpub_set_rate(rate, PLL_SEL_AUTO);
649*036935a8SXiaoDong Huang 	if (ret == 0)
650*036935a8SXiaoDong Huang 		sys_clk_info.cpub_rate = rate;
651*036935a8SXiaoDong Huang 
652*036935a8SXiaoDong Huang 	return ret;
653*036935a8SXiaoDong Huang }
654*036935a8SXiaoDong Huang 
rk3576_bpll_get_rate(void)655*036935a8SXiaoDong Huang static unsigned long rk3576_bpll_get_rate(void)
656*036935a8SXiaoDong Huang {
657*036935a8SXiaoDong Huang 	unsigned int m, p, s, k;
658*036935a8SXiaoDong Huang 	uint64_t rate64 = 24000000, postdiv;
659*036935a8SXiaoDong Huang 	int mode;
660*036935a8SXiaoDong Huang 
661*036935a8SXiaoDong Huang 	mode = mmio_read_32(CRU_BASE + CRU_MODE_CON) &
662*036935a8SXiaoDong Huang 	       0x3;
663*036935a8SXiaoDong Huang 
664*036935a8SXiaoDong Huang 	if (mode == 0)
665*036935a8SXiaoDong Huang 		return rate64;
666*036935a8SXiaoDong Huang 
667*036935a8SXiaoDong Huang 	m = (mmio_read_32(CRU_BASE + CRU_PLL_CON(0)) >>
668*036935a8SXiaoDong Huang 		 CRU_PLLCON0_M_SHIFT) &
669*036935a8SXiaoDong Huang 		CRU_PLLCON0_M_MASK;
670*036935a8SXiaoDong Huang 	p = (mmio_read_32(CRU_BASE + CRU_PLL_CON(1)) >>
671*036935a8SXiaoDong Huang 		    CRU_PLLCON1_P_SHIFT) &
672*036935a8SXiaoDong Huang 		   CRU_PLLCON1_P_MASK;
673*036935a8SXiaoDong Huang 	s = (mmio_read_32(CRU_BASE + CRU_PLL_CON(1)) >>
674*036935a8SXiaoDong Huang 		  CRU_PLLCON1_S_SHIFT) &
675*036935a8SXiaoDong Huang 		 CRU_PLLCON1_S_MASK;
676*036935a8SXiaoDong Huang 	k = (mmio_read_32(CRU_BASE + CRU_PLL_CON(2)) >>
677*036935a8SXiaoDong Huang 		    CRU_PLLCON2_K_SHIFT) &
678*036935a8SXiaoDong Huang 		   CRU_PLLCON2_K_MASK;
679*036935a8SXiaoDong Huang 
680*036935a8SXiaoDong Huang 	rate64 *= m;
681*036935a8SXiaoDong Huang 	rate64 = rate64 / p;
682*036935a8SXiaoDong Huang 
683*036935a8SXiaoDong Huang 	if (k != 0) {
684*036935a8SXiaoDong Huang 		/* fractional mode */
685*036935a8SXiaoDong Huang 		uint64_t frac_rate64 = 24000000 * k;
686*036935a8SXiaoDong Huang 
687*036935a8SXiaoDong Huang 		postdiv = p * 65536;
688*036935a8SXiaoDong Huang 		frac_rate64 = frac_rate64 / postdiv;
689*036935a8SXiaoDong Huang 		rate64 += frac_rate64;
690*036935a8SXiaoDong Huang 	}
691*036935a8SXiaoDong Huang 	rate64 = rate64 >> s;
692*036935a8SXiaoDong Huang 
693*036935a8SXiaoDong Huang 	return (unsigned long)rate64;
694*036935a8SXiaoDong Huang }
695*036935a8SXiaoDong Huang 
clk_scmi_cpub_get_rate(rk_scmi_clock_t * clock)696*036935a8SXiaoDong Huang static unsigned long clk_scmi_cpub_get_rate(rk_scmi_clock_t *clock)
697*036935a8SXiaoDong Huang {
698*036935a8SXiaoDong Huang 	int value, src, div;
699*036935a8SXiaoDong Huang 
700*036935a8SXiaoDong Huang 	if (cpub_suspended != 0)
701*036935a8SXiaoDong Huang 		return sys_clk_info.cpub_rate;
702*036935a8SXiaoDong Huang 
703*036935a8SXiaoDong Huang 	value = mmio_read_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1));
704*036935a8SXiaoDong Huang 	src = (value & 0xc000) >> 14;
705*036935a8SXiaoDong Huang 	if (src == 1)
706*036935a8SXiaoDong Huang 		return sys_clk_info.cpub_rate;
707*036935a8SXiaoDong Huang 
708*036935a8SXiaoDong Huang 	value = mmio_read_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1));
709*036935a8SXiaoDong Huang 	src = (value & 0x3000) >> 12;
710*036935a8SXiaoDong Huang 	div = (value & 0x0f80) >> 7;
711*036935a8SXiaoDong Huang 	switch (src) {
712*036935a8SXiaoDong Huang 	case 0:
713*036935a8SXiaoDong Huang 		return rk3576_bpll_get_rate();
714*036935a8SXiaoDong Huang 	case 1:
715*036935a8SXiaoDong Huang 		/* Make the return rate is equal to the set rate */
716*036935a8SXiaoDong Huang 		if (sys_clk_info.cpub_rate != 0)
717*036935a8SXiaoDong Huang 			return sys_clk_info.cpub_rate;
718*036935a8SXiaoDong Huang 		else
719*036935a8SXiaoDong Huang 			return GPLL_RATE / (div + 1);
720*036935a8SXiaoDong Huang 	case 2:
721*036935a8SXiaoDong Huang 		return sys_clk_info.cpub_rate;
722*036935a8SXiaoDong Huang 	default:
723*036935a8SXiaoDong Huang 		return 0;
724*036935a8SXiaoDong Huang 	}
725*036935a8SXiaoDong Huang }
726*036935a8SXiaoDong Huang 
clk_scmi_cpub_set_status(rk_scmi_clock_t * clock,bool status)727*036935a8SXiaoDong Huang static int clk_scmi_cpub_set_status(rk_scmi_clock_t *clock, bool status)
728*036935a8SXiaoDong Huang {
729*036935a8SXiaoDong Huang 	return 0;
730*036935a8SXiaoDong Huang }
731*036935a8SXiaoDong Huang 
clk_scmi_cci_get_rate(rk_scmi_clock_t * clock)732*036935a8SXiaoDong Huang static unsigned long clk_scmi_cci_get_rate(rk_scmi_clock_t *clock)
733*036935a8SXiaoDong Huang {
734*036935a8SXiaoDong Huang 	int src, div;
735*036935a8SXiaoDong Huang 
736*036935a8SXiaoDong Huang 	src = mmio_read_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4)) & 0x3000;
737*036935a8SXiaoDong Huang 	src = src >> 12;
738*036935a8SXiaoDong Huang 	if (src == 1)
739*036935a8SXiaoDong Huang 		return sys_clk_info.cci_rate;
740*036935a8SXiaoDong Huang 
741*036935a8SXiaoDong Huang 	div = mmio_read_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4)) & 0xf80;
742*036935a8SXiaoDong Huang 	div = div >> 7;
743*036935a8SXiaoDong Huang 	switch (src) {
744*036935a8SXiaoDong Huang 	case 0:
745*036935a8SXiaoDong Huang 		return OSC_HZ;
746*036935a8SXiaoDong Huang 	case 1:
747*036935a8SXiaoDong Huang 		return sys_clk_info.cci_rate;
748*036935a8SXiaoDong Huang 	case 2:
749*036935a8SXiaoDong Huang 		return GPLL_RATE / (div + 1);
750*036935a8SXiaoDong Huang 	case 3:
751*036935a8SXiaoDong Huang 		return rk3576_lpll_get_rate() / (div + 1);
752*036935a8SXiaoDong Huang 	default:
753*036935a8SXiaoDong Huang 		return 0;
754*036935a8SXiaoDong Huang 	}
755*036935a8SXiaoDong Huang }
756*036935a8SXiaoDong Huang 
clk_cci_set_rate(unsigned long rate,enum pll_type_sel type)757*036935a8SXiaoDong Huang static int clk_cci_set_rate(unsigned long rate, enum pll_type_sel type)
758*036935a8SXiaoDong Huang {
759*036935a8SXiaoDong Huang 	struct pvtpll_table *pvtpll;
760*036935a8SXiaoDong Huang 	uint32_t pvtpll_en = 0;
761*036935a8SXiaoDong Huang 
762*036935a8SXiaoDong Huang 	if (rate == 0)
763*036935a8SXiaoDong Huang 		return SCMI_INVALID_PARAMETERS;
764*036935a8SXiaoDong Huang 
765*036935a8SXiaoDong Huang 	pvtpll = rkclk_get_pvtpll_config(sys_clk_info.cci_table,
766*036935a8SXiaoDong Huang 					 sys_clk_info.cci_rate_count, rate);
767*036935a8SXiaoDong Huang 
768*036935a8SXiaoDong Huang 	/* set pvtpll */
769*036935a8SXiaoDong Huang 	if ((pvtpll != 0) && (PVTPLL_NEED(type, pvtpll->length) != 0)) {
770*036935a8SXiaoDong Huang 		/* set ring sel and length */
771*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_CCI_BASE + RK3576_PVTPLL_GCK_LEN,
772*036935a8SXiaoDong Huang 			      0x1dff0000 |
773*036935a8SXiaoDong Huang 			      (pvtpll->ring_sel << 10) |
774*036935a8SXiaoDong Huang 			      (pvtpll->length << 2) |
775*036935a8SXiaoDong Huang 			      (pvtpll->length_frac));
776*036935a8SXiaoDong Huang 		/* set cal cnt = 24, T = 1us */
777*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_CCI_BASE + RK3576_PVTPLL_GCK_CAL_CNT, 0x18);
778*036935a8SXiaoDong Huang 		/* enable pvtpll */
779*036935a8SXiaoDong Huang 		pvtpll_en = mmio_read_32(PVTPLL_CCI_BASE + RK3576_PVTPLL_GCK_CFG);
780*036935a8SXiaoDong Huang 		if (pvtpll_en && 0x22 != 0x22)
781*036935a8SXiaoDong Huang 			mmio_write_32(PVTPLL_CCI_BASE + RK3576_PVTPLL_GCK_CFG, 0x00220022);
782*036935a8SXiaoDong Huang 		/* start pvtpll */
783*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_CCI_BASE + RK3576_PVTPLL_GCK_CFG, 0x00230023);
784*036935a8SXiaoDong Huang 
785*036935a8SXiaoDong Huang 		/* set cci mux pvtpll */
786*036935a8SXiaoDong Huang 		mmio_write_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4),
787*036935a8SXiaoDong Huang 			      CCI_PVTPLL_PATH_PVTPLL);
788*036935a8SXiaoDong Huang 		mmio_write_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4),
789*036935a8SXiaoDong Huang 			      SCLK_CCI_PATH_PVTPLL);
790*036935a8SXiaoDong Huang 		mmio_write_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4),
791*036935a8SXiaoDong Huang 			      CLKDIV_5BITS_SHF(0, 7));
792*036935a8SXiaoDong Huang 		sys_clk_info.cci_rate = rate;
793*036935a8SXiaoDong Huang 		return 0;
794*036935a8SXiaoDong Huang 	}
795*036935a8SXiaoDong Huang 	sys_clk_info.cci_rate = 594000000;
796*036935a8SXiaoDong Huang 	/* set cci div */
797*036935a8SXiaoDong Huang 	mmio_write_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4),
798*036935a8SXiaoDong Huang 		      CLKDIV_5BITS_SHF(1, 7));
799*036935a8SXiaoDong Huang 	/* set cci mux gpll */
800*036935a8SXiaoDong Huang 	mmio_write_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4),
801*036935a8SXiaoDong Huang 		      SCLK_CCI_PATH_NOR_GPLL);
802*036935a8SXiaoDong Huang 
803*036935a8SXiaoDong Huang 	return 0;
804*036935a8SXiaoDong Huang }
805*036935a8SXiaoDong Huang 
clk_scmi_cci_set_rate(rk_scmi_clock_t * clock,unsigned long rate)806*036935a8SXiaoDong Huang static int clk_scmi_cci_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
807*036935a8SXiaoDong Huang {
808*036935a8SXiaoDong Huang 	if (rate == 0)
809*036935a8SXiaoDong Huang 		return SCMI_INVALID_PARAMETERS;
810*036935a8SXiaoDong Huang 
811*036935a8SXiaoDong Huang 	return clk_cci_set_rate(rate, PLL_SEL_AUTO);
812*036935a8SXiaoDong Huang }
813*036935a8SXiaoDong Huang 
clk_scmi_cci_set_status(rk_scmi_clock_t * clock,bool status)814*036935a8SXiaoDong Huang static int clk_scmi_cci_set_status(rk_scmi_clock_t *clock, bool status)
815*036935a8SXiaoDong Huang {
816*036935a8SXiaoDong Huang 	return 0;
817*036935a8SXiaoDong Huang }
818*036935a8SXiaoDong Huang 
clk_scmi_gpu_get_rate(rk_scmi_clock_t * clock)819*036935a8SXiaoDong Huang static unsigned long clk_scmi_gpu_get_rate(rk_scmi_clock_t *clock)
820*036935a8SXiaoDong Huang {
821*036935a8SXiaoDong Huang 	int div, src;
822*036935a8SXiaoDong Huang 
823*036935a8SXiaoDong Huang 	if ((mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(165)) & 0x100) != 0)
824*036935a8SXiaoDong Huang 		return sys_clk_info.gpu_rate;
825*036935a8SXiaoDong Huang 
826*036935a8SXiaoDong Huang 	div = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(165)) & 0x1f;
827*036935a8SXiaoDong Huang 	src = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(165)) & 0x00e0;
828*036935a8SXiaoDong Huang 	src = src >> 5;
829*036935a8SXiaoDong Huang 	switch (src) {
830*036935a8SXiaoDong Huang 	case 0:
831*036935a8SXiaoDong Huang 		/* Make the return rate is equal to the set rate */
832*036935a8SXiaoDong Huang 		if (sys_clk_info.gpu_rate != 0)
833*036935a8SXiaoDong Huang 			return sys_clk_info.gpu_rate;
834*036935a8SXiaoDong Huang 		else
835*036935a8SXiaoDong Huang 			return GPLL_RATE / (div + 1);
836*036935a8SXiaoDong Huang 	case 1:
837*036935a8SXiaoDong Huang 		return CPLL_RATE / (div + 1);
838*036935a8SXiaoDong Huang 	case 2:
839*036935a8SXiaoDong Huang 		return AUPLL_RATE / (div + 1);
840*036935a8SXiaoDong Huang 	case 3:
841*036935a8SXiaoDong Huang 		return SPLL_RATE / (div + 1);
842*036935a8SXiaoDong Huang 	case 4:
843*036935a8SXiaoDong Huang 		return rk3576_lpll_get_rate() / (div + 1);
844*036935a8SXiaoDong Huang 	default:
845*036935a8SXiaoDong Huang 		return 0;
846*036935a8SXiaoDong Huang 	}
847*036935a8SXiaoDong Huang }
848*036935a8SXiaoDong Huang 
clk_gpu_set_rate(unsigned long rate,enum pll_type_sel type)849*036935a8SXiaoDong Huang static int clk_gpu_set_rate(unsigned long rate, enum pll_type_sel type)
850*036935a8SXiaoDong Huang {
851*036935a8SXiaoDong Huang 	struct pvtpll_table *pvtpll;
852*036935a8SXiaoDong Huang 	int div;
853*036935a8SXiaoDong Huang 
854*036935a8SXiaoDong Huang 	pvtpll = rkclk_get_pvtpll_config(sys_clk_info.gpu_table,
855*036935a8SXiaoDong Huang 					 sys_clk_info.gpu_rate_count, rate);
856*036935a8SXiaoDong Huang 	if (pvtpll == NULL)
857*036935a8SXiaoDong Huang 		return SCMI_INVALID_PARAMETERS;
858*036935a8SXiaoDong Huang 
859*036935a8SXiaoDong Huang 	if (PVTPLL_NEED(type, pvtpll->length) != 0) {
860*036935a8SXiaoDong Huang 		/* set ring sel and length */
861*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_GPU_BASE + RK3576_PVTPLL_GCK_LEN,
862*036935a8SXiaoDong Huang 			      0x1dff0000 |
863*036935a8SXiaoDong Huang 			      (pvtpll->ring_sel << 10) |
864*036935a8SXiaoDong Huang 			      (pvtpll->length << 2) |
865*036935a8SXiaoDong Huang 			      (pvtpll->length_frac));
866*036935a8SXiaoDong Huang 		/* set cal cnt = 24, T = 1us */
867*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_GPU_BASE + RK3576_PVTPLL_GCK_CAL_CNT, 0x18);
868*036935a8SXiaoDong Huang 		/* enable pvtpll */
869*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_GPU_BASE + RK3576_PVTPLL_GCK_CFG, 0x00220022);
870*036935a8SXiaoDong Huang 		/* start pvtpll */
871*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_GPU_BASE + RK3576_PVTPLL_GCK_CFG, 0x00230023);
872*036935a8SXiaoDong Huang 		/* set gpu mux pvtpll */
873*036935a8SXiaoDong Huang 		mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(165),
874*036935a8SXiaoDong Huang 			      GPU_PVTPLL_PATH_PVTPLL);
875*036935a8SXiaoDong Huang 		mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(165),
876*036935a8SXiaoDong Huang 			      GPU_CLK_PATH_PVTPLL);
877*036935a8SXiaoDong Huang 		return 0;
878*036935a8SXiaoDong Huang 	}
879*036935a8SXiaoDong Huang 
880*036935a8SXiaoDong Huang 	/* set gpu div */
881*036935a8SXiaoDong Huang 	div = DIV_ROUND_UP(GPLL_RATE, rate);
882*036935a8SXiaoDong Huang 	mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(165),
883*036935a8SXiaoDong Huang 		      CLKDIV_5BITS_SHF(div - 1, 0));
884*036935a8SXiaoDong Huang 	/* set gpu mux gpll */
885*036935a8SXiaoDong Huang 	mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(165),
886*036935a8SXiaoDong Huang 		      GPU_CLK_PATH_NOR_GPLL);
887*036935a8SXiaoDong Huang 	mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(165),
888*036935a8SXiaoDong Huang 		      GPU_CLK_PATH_NOR_PLL);
889*036935a8SXiaoDong Huang 
890*036935a8SXiaoDong Huang 	return 0;
891*036935a8SXiaoDong Huang }
892*036935a8SXiaoDong Huang 
clk_scmi_gpu_set_rate(rk_scmi_clock_t * clock,unsigned long rate)893*036935a8SXiaoDong Huang static int clk_scmi_gpu_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
894*036935a8SXiaoDong Huang {
895*036935a8SXiaoDong Huang 	int ret;
896*036935a8SXiaoDong Huang 
897*036935a8SXiaoDong Huang 	if (rate == 0)
898*036935a8SXiaoDong Huang 		return SCMI_INVALID_PARAMETERS;
899*036935a8SXiaoDong Huang 
900*036935a8SXiaoDong Huang 	if ((rate & OPP_LENGTH_LOW) != 0) {
901*036935a8SXiaoDong Huang 		clk_scmi_set_low_length(sys_clk_info.gpu_table,
902*036935a8SXiaoDong Huang 					sys_clk_info.gpu_rate_count);
903*036935a8SXiaoDong Huang 		return 0;
904*036935a8SXiaoDong Huang 	}
905*036935a8SXiaoDong Huang 
906*036935a8SXiaoDong Huang 	ret = clk_gpu_set_rate(rate, PLL_SEL_AUTO);
907*036935a8SXiaoDong Huang 	if (ret == 0)
908*036935a8SXiaoDong Huang 		sys_clk_info.gpu_rate = rate;
909*036935a8SXiaoDong Huang 
910*036935a8SXiaoDong Huang 	return ret;
911*036935a8SXiaoDong Huang }
912*036935a8SXiaoDong Huang 
clk_scmi_gpu_set_status(rk_scmi_clock_t * clock,bool status)913*036935a8SXiaoDong Huang static int clk_scmi_gpu_set_status(rk_scmi_clock_t *clock, bool status)
914*036935a8SXiaoDong Huang {
915*036935a8SXiaoDong Huang 	return 0;
916*036935a8SXiaoDong Huang }
917*036935a8SXiaoDong Huang 
clk_scmi_npu_get_rate(rk_scmi_clock_t * clock)918*036935a8SXiaoDong Huang static unsigned long clk_scmi_npu_get_rate(rk_scmi_clock_t *clock)
919*036935a8SXiaoDong Huang {
920*036935a8SXiaoDong Huang 	int div, src, div_src;
921*036935a8SXiaoDong Huang 
922*036935a8SXiaoDong Huang 	if ((mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(86)) & 0x8000) != 0)
923*036935a8SXiaoDong Huang 		return sys_clk_info.npu_rate;
924*036935a8SXiaoDong Huang 
925*036935a8SXiaoDong Huang 	div_src = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(86)) & 0x07c;
926*036935a8SXiaoDong Huang 	div_src = div_src >> 2;
927*036935a8SXiaoDong Huang 	src = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(86)) & 0x0180;
928*036935a8SXiaoDong Huang 	src = src >> 7;
929*036935a8SXiaoDong Huang 	div = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(86)) & 0x7c00;
930*036935a8SXiaoDong Huang 	div = div >> 10;
931*036935a8SXiaoDong Huang 	switch (src) {
932*036935a8SXiaoDong Huang 	case 0:
933*036935a8SXiaoDong Huang 		/* Make the return rate is equal to the set rate */
934*036935a8SXiaoDong Huang 		if (sys_clk_info.npu_rate != 0)
935*036935a8SXiaoDong Huang 			return sys_clk_info.npu_rate;
936*036935a8SXiaoDong Huang 		else
937*036935a8SXiaoDong Huang 			return GPLL_RATE / (div_src + 1)  / (div + 1);
938*036935a8SXiaoDong Huang 	case 1:
939*036935a8SXiaoDong Huang 		return CPLL_RATE / (div_src + 1)  / (div + 1);
940*036935a8SXiaoDong Huang 	case 2:
941*036935a8SXiaoDong Huang 		return AUPLL_RATE / (div_src + 1)  / (div + 1);
942*036935a8SXiaoDong Huang 	case 3:
943*036935a8SXiaoDong Huang 		return SPLL_RATE / (div_src + 1)  / (div + 1);
944*036935a8SXiaoDong Huang 	default:
945*036935a8SXiaoDong Huang 		return 0;
946*036935a8SXiaoDong Huang 	}
947*036935a8SXiaoDong Huang }
948*036935a8SXiaoDong Huang 
clk_npu_set_rate(unsigned long rate,enum pll_type_sel type)949*036935a8SXiaoDong Huang static int clk_npu_set_rate(unsigned long rate, enum pll_type_sel type)
950*036935a8SXiaoDong Huang {
951*036935a8SXiaoDong Huang 	struct pvtpll_table *pvtpll;
952*036935a8SXiaoDong Huang 	int div;
953*036935a8SXiaoDong Huang 
954*036935a8SXiaoDong Huang 	pvtpll = rkclk_get_pvtpll_config(sys_clk_info.npu_table,
955*036935a8SXiaoDong Huang 					 sys_clk_info.npu_rate_count, rate);
956*036935a8SXiaoDong Huang 	if (pvtpll == NULL)
957*036935a8SXiaoDong Huang 		return SCMI_INVALID_PARAMETERS;
958*036935a8SXiaoDong Huang 
959*036935a8SXiaoDong Huang 	if (PVTPLL_NEED(type, pvtpll->length) != 0) {
960*036935a8SXiaoDong Huang 		/* set ring sel and length */
961*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_NPU_BASE + RK3576_PVTPLL_GCK_LEN,
962*036935a8SXiaoDong Huang 			      0x1dff0000 |
963*036935a8SXiaoDong Huang 			      (pvtpll->ring_sel << 10) |
964*036935a8SXiaoDong Huang 			      (pvtpll->length << 2) |
965*036935a8SXiaoDong Huang 			      (pvtpll->length_frac));
966*036935a8SXiaoDong Huang 		/* set cal cnt = 24, T = 1us */
967*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_NPU_BASE + RK3576_PVTPLL_GCK_CAL_CNT, 0x18);
968*036935a8SXiaoDong Huang 		/* enable pvtpll */
969*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_NPU_BASE + RK3576_PVTPLL_GCK_CFG, 0x00220022);
970*036935a8SXiaoDong Huang 		/* start pvtpll */
971*036935a8SXiaoDong Huang 		mmio_write_32(PVTPLL_NPU_BASE + RK3576_PVTPLL_GCK_CFG, 0x00230023);
972*036935a8SXiaoDong Huang 		/* set npu mux pvtpll */
973*036935a8SXiaoDong Huang 		mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
974*036935a8SXiaoDong Huang 			      NPU_PVTPLL_PATH_PVTPLL);
975*036935a8SXiaoDong Huang 		mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
976*036935a8SXiaoDong Huang 			      NPU_CLK_PATH_PVTPLL);
977*036935a8SXiaoDong Huang 		mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
978*036935a8SXiaoDong Huang 			      CLKDIV_5BITS_SHF(0, 10));
979*036935a8SXiaoDong Huang 		return 0;
980*036935a8SXiaoDong Huang 	}
981*036935a8SXiaoDong Huang 
982*036935a8SXiaoDong Huang 	/* set npu div */
983*036935a8SXiaoDong Huang 	div = DIV_ROUND_UP(GPLL_RATE, rate);
984*036935a8SXiaoDong Huang 	mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
985*036935a8SXiaoDong Huang 		      CLKDIV_5BITS_SHF(div - 1, 2));
986*036935a8SXiaoDong Huang 	mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
987*036935a8SXiaoDong Huang 		      CLKDIV_5BITS_SHF(0, 10));
988*036935a8SXiaoDong Huang 	/* set npu mux gpll */
989*036935a8SXiaoDong Huang 	mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
990*036935a8SXiaoDong Huang 		      NPU_CLK_PATH_NOR_GPLL);
991*036935a8SXiaoDong Huang 	mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
992*036935a8SXiaoDong Huang 		      NPU_CLK_PATH_NOR_PLL);
993*036935a8SXiaoDong Huang 
994*036935a8SXiaoDong Huang 	return 0;
995*036935a8SXiaoDong Huang }
996*036935a8SXiaoDong Huang 
clk_scmi_npu_set_rate(rk_scmi_clock_t * clock,unsigned long rate)997*036935a8SXiaoDong Huang static int clk_scmi_npu_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
998*036935a8SXiaoDong Huang {
999*036935a8SXiaoDong Huang 	int ret;
1000*036935a8SXiaoDong Huang 
1001*036935a8SXiaoDong Huang 	if (rate == 0)
1002*036935a8SXiaoDong Huang 		return SCMI_INVALID_PARAMETERS;
1003*036935a8SXiaoDong Huang 
1004*036935a8SXiaoDong Huang 	if ((rate & OPP_LENGTH_LOW) != 0) {
1005*036935a8SXiaoDong Huang 		clk_scmi_set_low_length(sys_clk_info.npu_table,
1006*036935a8SXiaoDong Huang 					sys_clk_info.npu_rate_count);
1007*036935a8SXiaoDong Huang 		return 0;
1008*036935a8SXiaoDong Huang 	}
1009*036935a8SXiaoDong Huang 
1010*036935a8SXiaoDong Huang 	ret = clk_npu_set_rate(rate, PLL_SEL_AUTO);
1011*036935a8SXiaoDong Huang 	if (ret == 0)
1012*036935a8SXiaoDong Huang 		sys_clk_info.npu_rate = rate;
1013*036935a8SXiaoDong Huang 
1014*036935a8SXiaoDong Huang 	return ret;
1015*036935a8SXiaoDong Huang }
1016*036935a8SXiaoDong Huang 
clk_scmi_npu_set_status(rk_scmi_clock_t * clock,bool status)1017*036935a8SXiaoDong Huang static int clk_scmi_npu_set_status(rk_scmi_clock_t *clock, bool status)
1018*036935a8SXiaoDong Huang {
1019*036935a8SXiaoDong Huang 	return 0;
1020*036935a8SXiaoDong Huang }
1021*036935a8SXiaoDong Huang 
clk_scmi_crypto_set_status(rk_scmi_clock_t * clock,bool status)1022*036935a8SXiaoDong Huang int clk_scmi_crypto_set_status(rk_scmi_clock_t *clock, bool status)
1023*036935a8SXiaoDong Huang {
1024*036935a8SXiaoDong Huang 	spin_lock(&crypto_lock);
1025*036935a8SXiaoDong Huang 
1026*036935a8SXiaoDong Huang 	if (clock->id == ACLK_CRYPTO_S)
1027*036935a8SXiaoDong Huang 		aclk_crypto_s_enable = status;
1028*036935a8SXiaoDong Huang 	else
1029*036935a8SXiaoDong Huang 		aclk_klad_enable = status;
1030*036935a8SXiaoDong Huang 
1031*036935a8SXiaoDong Huang 	if ((aclk_crypto_s_enable != 0) || (aclk_klad_enable != 0))
1032*036935a8SXiaoDong Huang 		clk_scmi_common_set_status(clock, 1);
1033*036935a8SXiaoDong Huang 	else
1034*036935a8SXiaoDong Huang 		clk_scmi_common_set_status(clock, 0);
1035*036935a8SXiaoDong Huang 
1036*036935a8SXiaoDong Huang 	spin_unlock(&crypto_lock);
1037*036935a8SXiaoDong Huang 	return 0;
1038*036935a8SXiaoDong Huang }
1039*036935a8SXiaoDong Huang 
clk_scmi_common_set_status_critical(rk_scmi_clock_t * clock,bool status)1040*036935a8SXiaoDong Huang static int clk_scmi_common_set_status_critical(rk_scmi_clock_t *clock, bool status)
1041*036935a8SXiaoDong Huang {
1042*036935a8SXiaoDong Huang 	return 0;
1043*036935a8SXiaoDong Huang }
1044*036935a8SXiaoDong Huang 
1045*036935a8SXiaoDong Huang static const struct rk_clk_ops clk_scmi_cpul_ops = {
1046*036935a8SXiaoDong Huang 	.get_rate = clk_scmi_cpul_get_rate,
1047*036935a8SXiaoDong Huang 	.set_rate = clk_scmi_cpul_set_rate,
1048*036935a8SXiaoDong Huang 	.set_status = clk_scmi_cpul_set_status,
1049*036935a8SXiaoDong Huang };
1050*036935a8SXiaoDong Huang 
1051*036935a8SXiaoDong Huang static const struct rk_clk_ops clk_scmi_cci_ops = {
1052*036935a8SXiaoDong Huang 	.get_rate = clk_scmi_cci_get_rate,
1053*036935a8SXiaoDong Huang 	.set_rate = clk_scmi_cci_set_rate,
1054*036935a8SXiaoDong Huang 	.set_status = clk_scmi_cci_set_status,
1055*036935a8SXiaoDong Huang };
1056*036935a8SXiaoDong Huang 
1057*036935a8SXiaoDong Huang static const struct rk_clk_ops clk_scmi_cpub_ops = {
1058*036935a8SXiaoDong Huang 	.get_rate = clk_scmi_cpub_get_rate,
1059*036935a8SXiaoDong Huang 	.set_rate = clk_scmi_cpub_set_rate,
1060*036935a8SXiaoDong Huang 	.set_status = clk_scmi_cpub_set_status,
1061*036935a8SXiaoDong Huang };
1062*036935a8SXiaoDong Huang 
1063*036935a8SXiaoDong Huang static const struct rk_clk_ops clk_scmi_gpu_ops = {
1064*036935a8SXiaoDong Huang 	.get_rate = clk_scmi_gpu_get_rate,
1065*036935a8SXiaoDong Huang 	.set_rate = clk_scmi_gpu_set_rate,
1066*036935a8SXiaoDong Huang 	.set_status = clk_scmi_gpu_set_status,
1067*036935a8SXiaoDong Huang };
1068*036935a8SXiaoDong Huang 
1069*036935a8SXiaoDong Huang static const struct rk_clk_ops clk_scmi_npu_ops = {
1070*036935a8SXiaoDong Huang 	.get_rate = clk_scmi_npu_get_rate,
1071*036935a8SXiaoDong Huang 	.set_rate = clk_scmi_npu_set_rate,
1072*036935a8SXiaoDong Huang 	.set_status = clk_scmi_npu_set_status,
1073*036935a8SXiaoDong Huang };
1074*036935a8SXiaoDong Huang 
1075*036935a8SXiaoDong Huang static const struct rk_clk_ops clk_scmi_ops_com_critical = {
1076*036935a8SXiaoDong Huang 	.get_rate = clk_scmi_common_get_rate,
1077*036935a8SXiaoDong Huang 	.set_rate = clk_scmi_common_set_rate,
1078*036935a8SXiaoDong Huang 	.set_status = clk_scmi_common_set_status_critical,
1079*036935a8SXiaoDong Huang };
1080*036935a8SXiaoDong Huang 
1081*036935a8SXiaoDong Huang static const struct rk_clk_ops clk_scmi_ops_com = {
1082*036935a8SXiaoDong Huang 	.get_rate = clk_scmi_common_get_rate,
1083*036935a8SXiaoDong Huang 	.set_rate = clk_scmi_common_set_rate,
1084*036935a8SXiaoDong Huang 	.set_status = clk_scmi_common_set_status,
1085*036935a8SXiaoDong Huang };
1086*036935a8SXiaoDong Huang 
1087*036935a8SXiaoDong Huang static const struct rk_clk_ops clk_scmi_ops_gate = {
1088*036935a8SXiaoDong Huang 	.get_rate = clk_scmi_common_get_rate,
1089*036935a8SXiaoDong Huang 	.set_status = clk_scmi_common_set_status,
1090*036935a8SXiaoDong Huang };
1091*036935a8SXiaoDong Huang 
1092*036935a8SXiaoDong Huang static const struct rk_clk_ops clk_scmi_ops_crypto = {
1093*036935a8SXiaoDong Huang 	.get_rate = clk_scmi_common_get_rate,
1094*036935a8SXiaoDong Huang 	.set_status = clk_scmi_crypto_set_status,
1095*036935a8SXiaoDong Huang };
1096*036935a8SXiaoDong Huang 
1097*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK(ARMCLK_L, scmi_armclkl, &clk_scmi_cpul_ops, rk3576_cpul_rates, ARRAY_SIZE(rk3576_cpul_rates), false);
1098*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK(ACLK_CCI_ROOT, scmi_aclk_cci, &clk_scmi_cci_ops, rk3576_cpul_rates, ARRAY_SIZE(rk3576_cpul_rates), false);
1099*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK(ARMCLK_B, scmi_armclkb, &clk_scmi_cpub_ops, rk3576_cpub_rates, ARRAY_SIZE(rk3576_cpub_rates), false);
1100*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK(CLK_GPU, scmi_clk_gpu, &clk_scmi_gpu_ops, rk3576_gpu_rates, ARRAY_SIZE(rk3576_gpu_rates), false);
1101*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK(CLK_RKNN_DSU0, scmi_clk_npu, &clk_scmi_npu_ops, rk3576_npu_rates, ARRAY_SIZE(rk3576_npu_rates), false);
1102*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(CLK_STIMER0_ROOT, clk_stimer0_root, p_100m_24m, clk_stimer0_root_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
1103*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(CLK_STIMER1_ROOT, clk_stimer1_root, p_100m_24m, clk_stimer1_root_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
1104*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(PCLK_SECURE_S, pclk_secure_s, p_116m_58m_24m, pclk_secure_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
1105*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(HCLK_SECURE_S, hclk_secure_s, p_175m_116m_58m_24m, hclk_secure_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
1106*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(ACLK_SECURE_S, aclk_secure_s, p_350m_175m_116m_24m, aclk_secure_s_info, &clk_scmi_ops_com_critical, rk3576_aclk_secure_s_rates, false, false);
1107*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(CLK_PKA_CRYPTO_S, clk_pka_crypto_s, p_350m_175m_116m_24m, clk_pka_crypto_s_info, &clk_scmi_ops_com, rk3576_common_rates, false, true);
1108*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(HCLK_VO1_S, hclk_vo1_s, p_175m_116m_58m_24m, hclk_vo1_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
1109*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(PCLK_VO1_S, pclk_vo1_s, p_116m_58m_24m, pclk_vo1_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
1110*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(HCLK_VO0_S, hclk_vo0_s, p_175m_116m_58m_24m, hclk_vo0_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
1111*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(PCLK_VO0_S, pclk_vo0_s, p_116m_58m_24m, pclk_vo0_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
1112*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(PCLK_KLAD, pclk_klad, p_pclk_secure_s, pclk_klad_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
1113*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(HCLK_CRYPTO_S, hclk_crypto_s, p_hclk_secure_s, hclk_crypto_s_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
1114*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(HCLK_KLAD, hclk_klad, p_hclk_secure_s, hclk_klad_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
1115*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(ACLK_CRYPTO_S, aclk_crypto_s, p_aclk_secure_s, aclk_crypto_s_info, &clk_scmi_ops_crypto, rk3576_common_rates, true, true);
1116*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(HCLK_TRNG_S, hclk_trng_s, p_hclk_secure_s, hclk_trng_s_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
1117*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(PCLK_OTPC_S, plk_otpc_s, p_pclk_secure_s, pclk_otpc_s_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
1118*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(CLK_OTPC_S, clk_otpc_s, p_24m, clk_otpc_s_info, &clk_scmi_ops_gate, rk3576_common_rates, false, true);
1119*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(PCLK_WDT_S, pclk_wdt_s, p_pclk_secure_s, pclk_wdt_s_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
1120*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(TCLK_WDT_S, tclk_wdt_s, p_24m, tclk_wdt_s_info, &clk_scmi_ops_gate, rk3576_common_rates, false, true);
1121*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(PCLK_HDCP0_TRNG, pclk_hdcp0_trng, p_pclk_vo0_s, pclk_hdcp0_trng_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
1122*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(PCLK_HDCP1_TRNG, pclk_hdcp1_trng, p_pclk_vo1_s, pclk_hdcp1_trng_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
1123*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(HCLK_HDCP_KEY0, hclk_hdcp_key0, p_hclk_vo0_s, hclk_hdcp_key0_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
1124*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(HCLK_HDCP_KEY1, hclk_hdcp_key1, p_hclk_vo1_s, hclk_hdcp_key1_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
1125*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(PCLK_EDP_S, pclk_edp_s, p_pclk_vo0_s, pclk_edp_s_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
1126*036935a8SXiaoDong Huang RK3576_SCMI_CLOCK_COM(ACLK_KLAD, aclk_klad, p_aclk_secure_s, aclk_crypto_s_info, &clk_scmi_ops_crypto, rk3576_common_rates, true, true);
1127*036935a8SXiaoDong Huang 
1128*036935a8SXiaoDong Huang rk_scmi_clock_t *clock_table[] = {
1129*036935a8SXiaoDong Huang 	[ARMCLK_L]		= &scmi_armclkl,
1130*036935a8SXiaoDong Huang 	[ACLK_CCI_ROOT]		= &scmi_aclk_cci,
1131*036935a8SXiaoDong Huang 	[ARMCLK_B]		= &scmi_armclkb,
1132*036935a8SXiaoDong Huang 	[CLK_GPU]		= &scmi_clk_gpu,
1133*036935a8SXiaoDong Huang 	[CLK_RKNN_DSU0]		= &scmi_clk_npu,
1134*036935a8SXiaoDong Huang 	[CLK_STIMER0_ROOT]	= &clk_stimer0_root,
1135*036935a8SXiaoDong Huang 	[CLK_STIMER1_ROOT]	= &clk_stimer1_root,
1136*036935a8SXiaoDong Huang 	[PCLK_SECURE_S]		= &pclk_secure_s,
1137*036935a8SXiaoDong Huang 	[HCLK_SECURE_S]		= &hclk_secure_s,
1138*036935a8SXiaoDong Huang 	[ACLK_SECURE_S]		= &aclk_secure_s,
1139*036935a8SXiaoDong Huang 	[CLK_PKA_CRYPTO_S]	= &clk_pka_crypto_s,
1140*036935a8SXiaoDong Huang 	[HCLK_VO1_S]		= &hclk_vo1_s,
1141*036935a8SXiaoDong Huang 	[PCLK_VO1_S]		= &pclk_vo1_s,
1142*036935a8SXiaoDong Huang 	[HCLK_VO0_S]		= &hclk_vo0_s,
1143*036935a8SXiaoDong Huang 	[PCLK_VO0_S]		= &pclk_vo0_s,
1144*036935a8SXiaoDong Huang 	[PCLK_KLAD]		= &pclk_klad,
1145*036935a8SXiaoDong Huang 	[HCLK_CRYPTO_S]		= &hclk_crypto_s,
1146*036935a8SXiaoDong Huang 	[HCLK_KLAD]		= &hclk_klad,
1147*036935a8SXiaoDong Huang 	[ACLK_CRYPTO_S]		= &aclk_crypto_s,
1148*036935a8SXiaoDong Huang 	[HCLK_TRNG_S]		= &hclk_trng_s,
1149*036935a8SXiaoDong Huang 	[PCLK_OTPC_S]		= &plk_otpc_s,
1150*036935a8SXiaoDong Huang 	[CLK_OTPC_S]		= &clk_otpc_s,
1151*036935a8SXiaoDong Huang 	[PCLK_WDT_S]		= &pclk_wdt_s,
1152*036935a8SXiaoDong Huang 	[TCLK_WDT_S]		= &tclk_wdt_s,
1153*036935a8SXiaoDong Huang 	[PCLK_HDCP0_TRNG]	= &pclk_hdcp0_trng,
1154*036935a8SXiaoDong Huang 	[PCLK_HDCP1_TRNG]	= &pclk_hdcp1_trng,
1155*036935a8SXiaoDong Huang 	[HCLK_HDCP_KEY0]	= &hclk_hdcp_key0,
1156*036935a8SXiaoDong Huang 	[HCLK_HDCP_KEY1]	= &hclk_hdcp_key1,
1157*036935a8SXiaoDong Huang 	[PCLK_EDP_S]		= &pclk_edp_s,
1158*036935a8SXiaoDong Huang 	[ACLK_KLAD]		= &aclk_klad,
1159*036935a8SXiaoDong Huang };
1160*036935a8SXiaoDong Huang 
rockchip_scmi_clock_count(unsigned int agent_id __unused)1161*036935a8SXiaoDong Huang size_t rockchip_scmi_clock_count(unsigned int agent_id __unused)
1162*036935a8SXiaoDong Huang {
1163*036935a8SXiaoDong Huang 	return CLK_NR_CLKS;
1164*036935a8SXiaoDong Huang }
1165*036935a8SXiaoDong Huang 
rockchip_scmi_get_clock(uint32_t agent_id __unused,uint32_t clock_id)1166*036935a8SXiaoDong Huang rk_scmi_clock_t *rockchip_scmi_get_clock(uint32_t agent_id __unused,
1167*036935a8SXiaoDong Huang 					 uint32_t clock_id)
1168*036935a8SXiaoDong Huang {
1169*036935a8SXiaoDong Huang 	rk_scmi_clock_t *table = NULL;
1170*036935a8SXiaoDong Huang 
1171*036935a8SXiaoDong Huang 	if (clock_id < ARRAY_SIZE(clock_table)) {
1172*036935a8SXiaoDong Huang 		table = clock_table[clock_id];
1173*036935a8SXiaoDong Huang 		if (table == NULL)
1174*036935a8SXiaoDong Huang 			return NULL;
1175*036935a8SXiaoDong Huang 	}
1176*036935a8SXiaoDong Huang 
1177*036935a8SXiaoDong Huang 	if ((table != NULL) && (table->is_security == 0))
1178*036935a8SXiaoDong Huang 		return table;
1179*036935a8SXiaoDong Huang 	else
1180*036935a8SXiaoDong Huang 		return NULL;
1181*036935a8SXiaoDong Huang 
1182*036935a8SXiaoDong Huang 	return NULL;
1183*036935a8SXiaoDong Huang }
1184*036935a8SXiaoDong Huang 
pvtplls_cpub_suspend(void)1185*036935a8SXiaoDong Huang void pvtplls_cpub_suspend(void)
1186*036935a8SXiaoDong Huang {
1187*036935a8SXiaoDong Huang 	clk_cpub_set_rate(408000000, PLL_SEL_NOR);
1188*036935a8SXiaoDong Huang 	cpub_suspended = true;
1189*036935a8SXiaoDong Huang }
1190*036935a8SXiaoDong Huang 
pvtplls_cpub_resume(void)1191*036935a8SXiaoDong Huang void pvtplls_cpub_resume(void)
1192*036935a8SXiaoDong Huang {
1193*036935a8SXiaoDong Huang 	cpub_suspended = false;
1194*036935a8SXiaoDong Huang 	clk_cpub_set_rate(sys_clk_info.cpub_rate, PLL_SEL_AUTO);
1195*036935a8SXiaoDong Huang }
1196*036935a8SXiaoDong Huang 
pvtplls_suspend(void)1197*036935a8SXiaoDong Huang void pvtplls_suspend(void)
1198*036935a8SXiaoDong Huang {
1199*036935a8SXiaoDong Huang 	clk_cpul_set_rate(408000000, PLL_SEL_NOR);
1200*036935a8SXiaoDong Huang 	clk_cci_set_rate(408000000, PLL_SEL_NOR);
1201*036935a8SXiaoDong Huang 	clk_cpub_set_rate(408000000, PLL_SEL_NOR);
1202*036935a8SXiaoDong Huang }
1203*036935a8SXiaoDong Huang 
pvtplls_resume(void)1204*036935a8SXiaoDong Huang void pvtplls_resume(void)
1205*036935a8SXiaoDong Huang {
1206*036935a8SXiaoDong Huang 	clk_cpul_set_rate(sys_clk_info.cpul_rate, PLL_SEL_AUTO);
1207*036935a8SXiaoDong Huang 	clk_cci_set_rate(sys_clk_info.cci_rate, PLL_SEL_AUTO);
1208*036935a8SXiaoDong Huang 	clk_cpub_set_rate(sys_clk_info.cpub_rate, PLL_SEL_AUTO);
1209*036935a8SXiaoDong Huang }
1210*036935a8SXiaoDong Huang 
sys_reset_pvtplls_prepare(void)1211*036935a8SXiaoDong Huang void sys_reset_pvtplls_prepare(void)
1212*036935a8SXiaoDong Huang {
1213*036935a8SXiaoDong Huang 	clk_gpu_set_rate(200000000, PLL_SEL_NOR);
1214*036935a8SXiaoDong Huang 	clk_npu_set_rate(200000000, PLL_SEL_NOR);
1215*036935a8SXiaoDong Huang 	clk_cpul_set_rate(408000000, PLL_SEL_NOR);
1216*036935a8SXiaoDong Huang 	clk_cci_set_rate(408000000, PLL_SEL_NOR);
1217*036935a8SXiaoDong Huang 	clk_cpub_set_rate(408000000, PLL_SEL_NOR);
1218*036935a8SXiaoDong Huang }
1219*036935a8SXiaoDong Huang 
rockchip_opteed_clk_set_rate(uint64_t clk_idx,uint64_t rate)1220*036935a8SXiaoDong Huang int rockchip_opteed_clk_set_rate(uint64_t clk_idx, uint64_t rate)
1221*036935a8SXiaoDong Huang {
1222*036935a8SXiaoDong Huang 	rk_scmi_clock_t *table;
1223*036935a8SXiaoDong Huang 
1224*036935a8SXiaoDong Huang 	if (clk_idx > CLK_NR_CLKS) {
1225*036935a8SXiaoDong Huang 		INFO("%s: clk-%ld, %ld not supported\n", __func__, clk_idx, rate);
1226*036935a8SXiaoDong Huang 		return SCMI_INVALID_PARAMETERS;
1227*036935a8SXiaoDong Huang 	}
1228*036935a8SXiaoDong Huang 
1229*036935a8SXiaoDong Huang 	table = rockchip_scmi_get_clock(0, clk_idx);
1230*036935a8SXiaoDong Huang 	if (table != NULL)
1231*036935a8SXiaoDong Huang 		table->clk_ops->set_rate(table, rate);
1232*036935a8SXiaoDong Huang 
1233*036935a8SXiaoDong Huang 	return 0;
1234*036935a8SXiaoDong Huang }
1235*036935a8SXiaoDong Huang 
rockchip_opteed_clk_get_rate(uint64_t clk_idx,uint64_t * rate)1236*036935a8SXiaoDong Huang int rockchip_opteed_clk_get_rate(uint64_t clk_idx, uint64_t *rate)
1237*036935a8SXiaoDong Huang {
1238*036935a8SXiaoDong Huang 	rk_scmi_clock_t *table;
1239*036935a8SXiaoDong Huang 
1240*036935a8SXiaoDong Huang 	if (clk_idx > CLK_NR_CLKS) {
1241*036935a8SXiaoDong Huang 		INFO("%s: clk-%ld not supported\n", __func__, clk_idx);
1242*036935a8SXiaoDong Huang 		return SCMI_INVALID_PARAMETERS;
1243*036935a8SXiaoDong Huang 	}
1244*036935a8SXiaoDong Huang 
1245*036935a8SXiaoDong Huang 	table = rockchip_scmi_get_clock(0, clk_idx);
1246*036935a8SXiaoDong Huang 	if (table != NULL)
1247*036935a8SXiaoDong Huang 		*rate = (uint64_t)table->clk_ops->get_rate(table);
1248*036935a8SXiaoDong Huang 	return 0;
1249*036935a8SXiaoDong Huang }
1250*036935a8SXiaoDong Huang 
rockchip_opteed_clk_enable(uint64_t clk_idx,uint64_t enable)1251*036935a8SXiaoDong Huang int rockchip_opteed_clk_enable(uint64_t clk_idx, uint64_t enable)
1252*036935a8SXiaoDong Huang {
1253*036935a8SXiaoDong Huang 	rk_scmi_clock_t *table;
1254*036935a8SXiaoDong Huang 
1255*036935a8SXiaoDong Huang 	if (clk_idx > CLK_NR_CLKS) {
1256*036935a8SXiaoDong Huang 		INFO("%s: clk-%ld, %ld not supported\n", __func__, clk_idx, enable);
1257*036935a8SXiaoDong Huang 		return SCMI_INVALID_PARAMETERS;
1258*036935a8SXiaoDong Huang 	}
1259*036935a8SXiaoDong Huang 
1260*036935a8SXiaoDong Huang 	table = rockchip_scmi_get_clock(0, clk_idx);
1261*036935a8SXiaoDong Huang 	if (table != NULL) {
1262*036935a8SXiaoDong Huang 		if (enable != 0) {
1263*036935a8SXiaoDong Huang 			table->clk_ops->set_status(table, enable);
1264*036935a8SXiaoDong Huang 			table->enable_count++;
1265*036935a8SXiaoDong Huang 		} else {
1266*036935a8SXiaoDong Huang 			if (table->enable_count == 0)
1267*036935a8SXiaoDong Huang 				return 0;
1268*036935a8SXiaoDong Huang 			if (--table->enable_count > 0)
1269*036935a8SXiaoDong Huang 				return 0;
1270*036935a8SXiaoDong Huang 			table->clk_ops->set_status(table, enable);
1271*036935a8SXiaoDong Huang 		}
1272*036935a8SXiaoDong Huang 	}
1273*036935a8SXiaoDong Huang 	return 0;
1274*036935a8SXiaoDong Huang }
1275*036935a8SXiaoDong Huang 
1276*036935a8SXiaoDong Huang #define RK3576_CPUB_OPP_INFO_OFFSET	48
1277*036935a8SXiaoDong Huang #define RK3576_CPUL_OPP_INFO_OFFSET	54
1278*036935a8SXiaoDong Huang #define RK3576_CCI_OPP_INFO_OFFSET	60
1279*036935a8SXiaoDong Huang #define RK3576_NPU_OPP_INFO_OFFSET	66
1280*036935a8SXiaoDong Huang #define RK3576_GPU_OPP_INFO_OFFSET	72
1281*036935a8SXiaoDong Huang 
rockchip_init_pvtpll_table(void)1282*036935a8SXiaoDong Huang static void rockchip_init_pvtpll_table(void)
1283*036935a8SXiaoDong Huang {
1284*036935a8SXiaoDong Huang 	sys_clk_info.cpul_table = rk3576_cpul_pvtpll_table;
1285*036935a8SXiaoDong Huang 	sys_clk_info.cpul_rate_count = ARRAY_SIZE(rk3576_cpul_pvtpll_table);
1286*036935a8SXiaoDong Huang 	sys_clk_info.cci_table = rk3576_cci_pvtpll_table;
1287*036935a8SXiaoDong Huang 	sys_clk_info.cci_rate_count = ARRAY_SIZE(rk3576_cci_pvtpll_table);
1288*036935a8SXiaoDong Huang 	sys_clk_info.cpub_table = rk3576_cpub_pvtpll_table;
1289*036935a8SXiaoDong Huang 	sys_clk_info.cpub_rate_count = ARRAY_SIZE(rk3576_cpub_pvtpll_table);
1290*036935a8SXiaoDong Huang 	sys_clk_info.gpu_table = rk3576_gpu_pvtpll_table;
1291*036935a8SXiaoDong Huang 	sys_clk_info.gpu_rate_count = ARRAY_SIZE(rk3576_gpu_pvtpll_table);
1292*036935a8SXiaoDong Huang 	sys_clk_info.npu_table = rk3576_npu_pvtpll_table;
1293*036935a8SXiaoDong Huang 	sys_clk_info.npu_rate_count = ARRAY_SIZE(rk3576_npu_pvtpll_table);
1294*036935a8SXiaoDong Huang }
1295*036935a8SXiaoDong Huang 
rockchip_clock_init(void)1296*036935a8SXiaoDong Huang void rockchip_clock_init(void)
1297*036935a8SXiaoDong Huang {
1298*036935a8SXiaoDong Huang 	rockchip_init_pvtpll_table();
1299*036935a8SXiaoDong Huang }
1300*036935a8SXiaoDong Huang 
pvtpll_get_clk(uint64_t clock_id,struct pvtpll_table ** table,unsigned int * count)1301*036935a8SXiaoDong Huang static int pvtpll_get_clk(uint64_t clock_id, struct pvtpll_table **table,
1302*036935a8SXiaoDong Huang 			  unsigned int *count)
1303*036935a8SXiaoDong Huang {
1304*036935a8SXiaoDong Huang 	switch (clock_id) {
1305*036935a8SXiaoDong Huang 	case ARMCLK_L:
1306*036935a8SXiaoDong Huang 		*table = sys_clk_info.cpul_table;
1307*036935a8SXiaoDong Huang 		*count = sys_clk_info.cpul_rate_count;
1308*036935a8SXiaoDong Huang 		break;
1309*036935a8SXiaoDong Huang 	case ARMCLK_B:
1310*036935a8SXiaoDong Huang 		*table = sys_clk_info.cpub_table;
1311*036935a8SXiaoDong Huang 		*count = sys_clk_info.cpub_rate_count;
1312*036935a8SXiaoDong Huang 		break;
1313*036935a8SXiaoDong Huang 	case CLK_GPU:
1314*036935a8SXiaoDong Huang 		*table = sys_clk_info.gpu_table;
1315*036935a8SXiaoDong Huang 		*count = sys_clk_info.gpu_rate_count;
1316*036935a8SXiaoDong Huang 		break;
1317*036935a8SXiaoDong Huang 	case CLK_RKNN_DSU0:
1318*036935a8SXiaoDong Huang 		*table = sys_clk_info.npu_table;
1319*036935a8SXiaoDong Huang 		*count = sys_clk_info.npu_rate_count;
1320*036935a8SXiaoDong Huang 		break;
1321*036935a8SXiaoDong Huang 	default:
1322*036935a8SXiaoDong Huang 		return -1;
1323*036935a8SXiaoDong Huang 	}
1324*036935a8SXiaoDong Huang 
1325*036935a8SXiaoDong Huang 	if ((*table == NULL) || (*count == 0))
1326*036935a8SXiaoDong Huang 		return -1;
1327*036935a8SXiaoDong Huang 
1328*036935a8SXiaoDong Huang 	return 0;
1329*036935a8SXiaoDong Huang }
1330*036935a8SXiaoDong Huang 
pvtpll_volt_sel_adjust(uint64_t clock_id,uint64_t volt_sel)1331*036935a8SXiaoDong Huang int pvtpll_volt_sel_adjust(uint64_t clock_id, uint64_t volt_sel)
1332*036935a8SXiaoDong Huang {
1333*036935a8SXiaoDong Huang 	struct pvtpll_table *table = NULL;
1334*036935a8SXiaoDong Huang 	uint32_t delta_len = 0;
1335*036935a8SXiaoDong Huang 	unsigned int count = 0;
1336*036935a8SXiaoDong Huang 	int i;
1337*036935a8SXiaoDong Huang 
1338*036935a8SXiaoDong Huang 	if (pvtpll_get_clk(clock_id, &table, &count) != 0)
1339*036935a8SXiaoDong Huang 		return -1;
1340*036935a8SXiaoDong Huang 
1341*036935a8SXiaoDong Huang 	for (i = 0; i < count; i++) {
1342*036935a8SXiaoDong Huang 		if (table[i].volt_sel_thr == 0)
1343*036935a8SXiaoDong Huang 			continue;
1344*036935a8SXiaoDong Huang 		if (volt_sel >= table[i].volt_sel_thr) {
1345*036935a8SXiaoDong Huang 			delta_len = volt_sel - table[i].volt_sel_thr + 1;
1346*036935a8SXiaoDong Huang 			table[i].length += delta_len;
1347*036935a8SXiaoDong Huang 			if (table[i].length > RK3576_PVTPLL_MAX_LENGTH)
1348*036935a8SXiaoDong Huang 				table[i].length = RK3576_PVTPLL_MAX_LENGTH;
1349*036935a8SXiaoDong Huang 		}
1350*036935a8SXiaoDong Huang 	}
1351*036935a8SXiaoDong Huang 
1352*036935a8SXiaoDong Huang 	return 0;
1353*036935a8SXiaoDong Huang }
1354