xref: /optee_os/core/drivers/clk/qcom/clock-qcom.c (revision fedadb6460b1ea7db709c6f5a0572f5a8cb8e5c9)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2025, Linaro Ltd
4  * Copyright (c) 2026, Qualcomm Technologies, Inc. and/or its subsidiaries.
5  */
6 
7 #include <drivers/clk.h>
8 #include <drivers/clk_qcom.h>
9 #include <malloc.h>
10 #include <stdint.h>
11 #include <io.h>
12 #include <mm/core_memprot.h>
13 #include <mm/core_mmu.h>
14 #include <trace.h>
15 #include <platform_config.h>
16 
17 #include "clock_group_qcom.h"
18 
19 /* CBCR register fields */
20 #define CBCR_BRANCH_ENABLE_BIT		BIT(0)
21 #define CBCR_HW_CTL_ENABLE_BIT		BIT(1)
22 #define CBCR_BRANCH_OFF_BIT		BIT(31)
23 
24 register_phys_mem(MEM_AREA_IO_NSEC, GCC_BASE, GCC_SIZE);
25 
26 #define REG_POLL_TIMEOUT(_addr, _timeout_us, _delay_us, _retp, _match)	\
27 	do {								\
28 		uint32_t __val;						\
29 		int __rc;						\
30 									\
31 		__rc = IO_READ32_POLL_TIMEOUT(_addr, __val,		\
32 					     (_match)(__val),		\
33 					     _delay_us, _timeout_us);	\
34 		*(_retp) = __rc ? -1 : 0;				\
35 	} while (0)
36 
37 static inline bool cbcr_branch_on(uint32_t val)
38 {
39 	return !(val & CBCR_BRANCH_OFF_BIT);
40 }
41 
42 /* Enable clock controlled by CBC soft macro */
43 static int clk_enable_cbc(vaddr_t cbcr)
44 {
45 	int ret = 0;
46 
47 	io_setbits32(cbcr, CBCR_BRANCH_ENABLE_BIT);
48 
49 	REG_POLL_TIMEOUT(cbcr, 10 * 1000, 10, &ret, cbcr_branch_on);
50 
51 	return ret;
52 }
53 
54 static inline bool vapss_gdscr_pwr_on(uint32_t val)
55 {
56 	return val & VAPSS_GDSCR_PWR_ON_MASK;
57 }
58 
59 static inline bool vapss_gdscr_pwr_off(uint32_t val)
60 {
61 	return !vapss_gdscr_pwr_on(val);
62 }
63 
64 static inline bool vapss_cfg_gdscr_pwr_up_complete(uint32_t val)
65 {
66 	return val & VAPSS_CFG_GDSCR_PWR_UP_COMPLETE_MASK;
67 }
68 
69 static inline bool vapss_gds_hw_state_idle(uint32_t val)
70 {
71 	uint32_t state = (val & VAPSS_GDS_HW_STATE_MASK) >>
72 			 VAPSS_GDS_HW_STATE_SHIFT;
73 
74 	return state == 0;
75 }
76 
77 static inline bool vapss_gds_hw_state_powerup_wait(uint32_t val)
78 {
79 	uint32_t state = (val & VAPSS_GDS_HW_STATE_MASK) >>
80 			 VAPSS_GDS_HW_STATE_SHIFT;
81 
82 	/* ready to power up */
83 	return state == 0xA;
84 }
85 
86 static int compute_cc_enable(void)
87 {
88 	struct io_pa_va turing_cc_io = { .pa = TURING_BASE + TURING_CC_OFFSET };
89 	vaddr_t cc_base = io_pa_or_va(&turing_cc_io, TURING_CC_SIZE);
90 	int res = 0;
91 
92 	io_clrbits32(cc_base + TURING_Q6SS_Q6_AXIM_CLK, CBCR_BRANCH_ENABLE_BIT);
93 	io_setbits32(cc_base + TURING_Q6SS_Q6_AXIM_CLK, CBCR_HW_CTL_ENABLE_BIT);
94 	io_setbits32(cc_base + TURING_CENG_CLK, CBCR_HW_CTL_ENABLE_BIT);
95 	io_clrbits32(cc_base + TURING_NSPNOC_CLK, CBCR_HW_CTL_ENABLE_BIT);
96 
97 	res = clk_enable_cbc(cc_base + TURING_Q6SS_AHBS_AON_CLK);
98 	if (res)
99 		return res;
100 
101 	/* Retention flop initialization sequence */
102 
103 	io_clrbits32(cc_base + TURING_VAPSS_GDSCR,
104 		     VAPSS_GDSCR_SW_COLLAPSE_MASK);
105 
106 	REG_POLL_TIMEOUT(cc_base + TURING_VAPSS_GDSCR,
107 			 10 * 1000, 10, &res, vapss_gdscr_pwr_on);
108 	if (res)
109 		return res;
110 
111 	REG_POLL_TIMEOUT(cc_base + TURING_VAPSS_CFG_GDSCR,
112 			 10 * 1000, 10, &res,
113 			 vapss_cfg_gdscr_pwr_up_complete);
114 	if (res)
115 		return res;
116 
117 	REG_POLL_TIMEOUT(cc_base + TURING_VAPSS_GDS_HW_CTRL,
118 			 10 * 1000, 10, &res, vapss_gds_hw_state_idle);
119 	if (res)
120 		return res;
121 
122 	io_setbits32(cc_base + TURING_VAPSS_GDSCR,
123 		     VAPSS_GDSCR_RETAIN_FF_ENABLE_MASK);
124 
125 	io_setbits32(cc_base + TURING_VAPSS_GDSCR,
126 		     VAPSS_GDSCR_SW_COLLAPSE_MASK);
127 
128 	REG_POLL_TIMEOUT(cc_base + TURING_VAPSS_GDSCR,
129 			 10 * 1000, 10, &res, vapss_gdscr_pwr_off);
130 	if (res)
131 		return res;
132 
133 	REG_POLL_TIMEOUT(cc_base + TURING_VAPSS_GDS_HW_CTRL,
134 			 10 * 1000, 10, &res, vapss_gds_hw_state_powerup_wait);
135 	if (res)
136 		return res;
137 
138 	return 0;
139 }
140 
141 static int lpass_gdsc_enable(void)
142 {
143 	struct io_pa_va gdsc_io = { .pa = LPASS_BASE + LPASS_GDSC_OFFSET };
144 	vaddr_t gdsc_base = io_pa_or_va(&gdsc_io, LPASS_GDSC_SIZE);
145 	int res = 0;
146 
147 	res = clk_enable_cbc(gdsc_base + TOP_CC_AGGNOC_MPU_LS_CLK);
148 	if (res)
149 		return res;
150 
151 	return clk_enable_cbc(gdsc_base + TOP_CC_LPI_Q6_AXIM_HS_CLK);
152 }
153 
154 TEE_Result qcom_clock_enable(enum qcom_clk_group group)
155 {
156 	struct io_pa_va base = { .pa = GCC_BASE };
157 	vaddr_t gcc_base = io_pa_or_va(&base, GCC_SIZE);
158 	int res = 0;
159 
160 	switch (group) {
161 	case QCOM_CLKS_WPSS:
162 		res = clk_enable_cbc(gcc_base + GCC_WPSS_AHB_CLK);
163 		if (res)
164 			goto timeout;
165 		res = clk_enable_cbc(gcc_base + GCC_WPSS_AHB_BDG_MST_CLK);
166 		if (res)
167 			goto timeout;
168 		res = clk_enable_cbc(gcc_base + GCC_WPSS_RSCP_CLK);
169 		if (res)
170 			goto timeout;
171 		break;
172 	case QCOM_CLKS_TURING:
173 		res = clk_enable_cbc(gcc_base + GCC_TURING_CFG_AHB_CLK);
174 		if (res)
175 			goto timeout;
176 		res = compute_cc_enable();
177 		if (res)
178 			goto timeout;
179 		break;
180 	case QCOM_CLKS_LPASS:
181 		res = clk_enable_cbc(gcc_base + GCC_CFG_NOC_LPASS_CLK);
182 		if (res)
183 			goto timeout;
184 		res = lpass_gdsc_enable();
185 		if (res)
186 			goto timeout;
187 		break;
188 	default:
189 		EMSG("Unsupported clock group %d\n", group);
190 		return TEE_ERROR_BAD_PARAMETERS;
191 	}
192 
193 	return TEE_SUCCESS;
194 
195 timeout:
196 	EMSG("Timeout trying to enable clock group %d\n", group);
197 	return TEE_ERROR_TIMEOUT;
198 }
199