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