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