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