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 25 static inline bool vapss_gdscr_pwr_on(uint32_t val) 26 { 27 return val & VAPSS_GDSCR_PWR_ON_MASK; 28 } 29 30 static inline bool vapss_gdscr_pwr_off(uint32_t val) 31 { 32 return !vapss_gdscr_pwr_on(val); 33 } 34 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 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 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 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 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 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 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