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