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