1 /* 2 * Copyright (c) 2022, Xilinx, Inc. All rights reserved. 3 * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 /* 9 * APU specific definition of processors in the subsystem as well as functions 10 * for getting information about and changing state of the APU. 11 */ 12 13 #include <assert.h> 14 15 #include <drivers/arm/gic_common.h> 16 #include <drivers/arm/gicv3.h> 17 #include <lib/bakery_lock.h> 18 #include <lib/mmio.h> 19 #include <lib/spinlock.h> 20 #include <lib/utils.h> 21 #include <plat/common/platform.h> 22 23 #include <platform_def.h> 24 #include "def.h" 25 #include <plat_ipi.h> 26 #include <plat_pm_common.h> 27 #include "pm_api_sys.h" 28 #include "pm_client.h" 29 30 #define UNDEFINED_CPUID UINT32_MAX 31 32 DEFINE_RENAME_SYSREG_RW_FUNCS(cpu_pwrctrl_val, S3_0_C15_C2_7) 33 34 /* 35 * ARM v8.2, the cache will turn off automatically when cpu 36 * power down. Therefore, there is no doubt to use the spin_lock here. 37 */ 38 static spinlock_t pm_client_secure_lock; 39 static inline void pm_client_lock_get(void) 40 { 41 spin_lock(&pm_client_secure_lock); 42 } 43 44 static inline void pm_client_lock_release(void) 45 { 46 spin_unlock(&pm_client_secure_lock); 47 } 48 49 static const struct pm_ipi apu_ipi = { 50 .local_ipi_id = IPI_LOCAL_ID, 51 .remote_ipi_id = IPI_REMOTE_ID, 52 .buffer_base = IPI_BUFFER_LOCAL_BASE, 53 }; 54 55 /* Order in pm_procs_all array must match cpu ids */ 56 static const struct pm_proc pm_procs_all[] = { 57 { 58 .node_id = PM_DEV_CLUSTER0_ACPU_0, 59 .ipi = &apu_ipi, 60 }, 61 { 62 .node_id = PM_DEV_CLUSTER0_ACPU_1, 63 .ipi = &apu_ipi, 64 }, 65 { 66 .node_id = PM_DEV_CLUSTER1_ACPU_0, 67 .ipi = &apu_ipi, 68 }, 69 { 70 .node_id = PM_DEV_CLUSTER1_ACPU_1, 71 .ipi = &apu_ipi, 72 }, 73 { 74 .node_id = PM_DEV_CLUSTER2_ACPU_0, 75 .ipi = &apu_ipi, 76 }, 77 { 78 .node_id = PM_DEV_CLUSTER2_ACPU_1, 79 .ipi = &apu_ipi, 80 }, 81 { 82 .node_id = PM_DEV_CLUSTER3_ACPU_0, 83 .ipi = &apu_ipi, 84 }, 85 { 86 .node_id = PM_DEV_CLUSTER3_ACPU_1, 87 .ipi = &apu_ipi, 88 }, 89 }; 90 91 const struct pm_proc *primary_proc = &pm_procs_all[0]; 92 93 /** 94 * pm_get_proc() - returns pointer to the proc structure. 95 * @cpuid: id of the cpu whose proc struct pointer should be returned. 96 * 97 * Return: Pointer to a proc structure if proc is found, otherwise NULL. 98 */ 99 const struct pm_proc *pm_get_proc(uint32_t cpuid) 100 { 101 const struct pm_proc *proc = NULL; 102 103 if (cpuid < ARRAY_SIZE(pm_procs_all)) { 104 proc = &pm_procs_all[cpuid]; 105 } else { 106 ERROR("cpuid: %d proc NULL\n", cpuid); 107 } 108 109 return proc; 110 } 111 112 /** 113 * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number. 114 * @irq: Interrupt number. 115 * 116 * Return: PM node index corresponding to the specified interrupt. 117 */ 118 enum pm_device_node_idx irq_to_pm_node_idx(uint32_t irq) 119 { 120 enum pm_device_node_idx dev_idx = XPM_NODEIDX_DEV_MIN; 121 122 assert(irq <= IRQ_MAX); 123 124 switch (irq) { 125 case 11: 126 dev_idx = XPM_NODEIDX_DEV_I2C_2; 127 break; 128 case 12: 129 dev_idx = XPM_NODEIDX_DEV_I2C_3; 130 break; 131 case 13: 132 dev_idx = XPM_NODEIDX_DEV_I2C_4; 133 break; 134 case 20: 135 dev_idx = XPM_NODEIDX_DEV_GPIO; 136 break; 137 case 21: 138 dev_idx = XPM_NODEIDX_DEV_I2C_0; 139 break; 140 case 22: 141 dev_idx = XPM_NODEIDX_DEV_I2C_1; 142 break; 143 case 23: 144 dev_idx = XPM_NODEIDX_DEV_SPI_0; 145 break; 146 case 24: 147 dev_idx = XPM_NODEIDX_DEV_SPI_1; 148 break; 149 case 25: 150 dev_idx = XPM_NODEIDX_DEV_UART_0; 151 break; 152 case 26: 153 dev_idx = XPM_NODEIDX_DEV_UART_1; 154 break; 155 case 27: 156 dev_idx = XPM_NODEIDX_DEV_CAN_FD_0; 157 break; 158 case 28: 159 dev_idx = XPM_NODEIDX_DEV_CAN_FD_1; 160 break; 161 case 29: 162 case 30: 163 case 31: 164 case 32: 165 case 33: 166 case 98: 167 dev_idx = XPM_NODEIDX_DEV_USB_0; 168 break; 169 case 34: 170 case 35: 171 case 36: 172 case 37: 173 case 38: 174 case 99: 175 dev_idx = XPM_NODEIDX_DEV_USB_1; 176 break; 177 case 39: 178 case 40: 179 dev_idx = XPM_NODEIDX_DEV_GEM_0; 180 break; 181 case 41: 182 case 42: 183 dev_idx = XPM_NODEIDX_DEV_GEM_1; 184 break; 185 case 43: 186 dev_idx = XPM_NODEIDX_DEV_TTC_0; 187 break; 188 case 44: 189 dev_idx = XPM_NODEIDX_DEV_TTC_1; 190 break; 191 case 45: 192 dev_idx = XPM_NODEIDX_DEV_TTC_2; 193 break; 194 case 46: 195 dev_idx = XPM_NODEIDX_DEV_TTC_3; 196 break; 197 case 47: 198 dev_idx = XPM_NODEIDX_DEV_TTC_4; 199 break; 200 case 48: 201 dev_idx = XPM_NODEIDX_DEV_TTC_5; 202 break; 203 case 49: 204 dev_idx = XPM_NODEIDX_DEV_TTC_6; 205 break; 206 case 50: 207 dev_idx = XPM_NODEIDX_DEV_TTC_7; 208 break; 209 case 72: 210 dev_idx = XPM_NODEIDX_DEV_ADMA_0; 211 break; 212 case 73: 213 dev_idx = XPM_NODEIDX_DEV_ADMA_1; 214 break; 215 case 74: 216 dev_idx = XPM_NODEIDX_DEV_ADMA_2; 217 break; 218 case 75: 219 dev_idx = XPM_NODEIDX_DEV_ADMA_3; 220 break; 221 case 76: 222 dev_idx = XPM_NODEIDX_DEV_ADMA_4; 223 break; 224 case 77: 225 dev_idx = XPM_NODEIDX_DEV_ADMA_5; 226 break; 227 case 78: 228 dev_idx = XPM_NODEIDX_DEV_ADMA_6; 229 break; 230 case 79: 231 dev_idx = XPM_NODEIDX_DEV_ADMA_7; 232 break; 233 case 95: 234 dev_idx = XPM_NODEIDX_DEV_CAN_FD_2; 235 break; 236 case 96: 237 dev_idx = XPM_NODEIDX_DEV_CAN_FD_3; 238 break; 239 case 100: 240 dev_idx = XPM_NODEIDX_DEV_I2C_5; 241 break; 242 case 101: 243 dev_idx = XPM_NODEIDX_DEV_I2C_6; 244 break; 245 case 102: 246 dev_idx = XPM_NODEIDX_DEV_I2C_7; 247 break; 248 case 164: 249 dev_idx = XPM_NODEIDX_DEV_MMI_GEM; 250 break; 251 case 200: 252 dev_idx = XPM_NODEIDX_DEV_RTC; 253 break; 254 case 218: 255 dev_idx = XPM_NODEIDX_DEV_SDIO_0; 256 break; 257 case 220: 258 dev_idx = XPM_NODEIDX_DEV_SDIO_1; 259 break; 260 default: 261 dev_idx = XPM_NODEIDX_DEV_MIN; 262 break; 263 } 264 265 return dev_idx; 266 } 267 268 /** 269 * pm_client_suspend() - Client-specific suspend actions. This function 270 * perform actions required prior to sending suspend 271 * request. 272 * Actions taken depend on the state system is 273 * suspending to. 274 * @proc: processor which need to suspend. 275 * @state: desired suspend state. 276 * @flag: 0 - Call from secure source. 277 * 1 - Call from non-secure source. 278 */ 279 void pm_client_suspend(const struct pm_proc *proc, uint32_t state, uint32_t flag) 280 { 281 uint32_t cpu_id = plat_my_core_pos(); 282 uintptr_t val; 283 /* 284 * Get the core index, use it calculate offset for secondary cores 285 * to match with register database 286 */ 287 uint32_t core_index = cpu_id + ((cpu_id / 2U) * 2U); 288 289 pm_client_lock_get(); 290 291 if (state == PM_STATE_SUSPEND_TO_RAM) { 292 pm_client_set_wakeup_sources((uint32_t)proc->node_id, flag); 293 } 294 295 val = read_cpu_pwrctrl_val(); 296 val |= CORE_PWRDN_EN_BIT_MASK; 297 write_cpu_pwrctrl_val(val); 298 299 isb(); 300 301 /* Enable power down interrupt */ 302 mmio_write_32(APU_PCIL_CORE_X_IEN_POWER_REG(core_index), 303 APU_PCIL_CORE_X_IEN_POWER_MASK); 304 /* Enable wake interrupt */ 305 mmio_write_32(APU_PCIL_CORE_X_IEN_WAKE_REG(core_index), 306 APU_PCIL_CORE_X_IEN_WAKE_MASK); 307 308 pm_client_lock_release(); 309 } 310 311 /** 312 * pm_get_cpuid() - get the local cpu ID for a global node ID. 313 * @nid: node id of the processor. 314 * 315 * Return: the cpu ID (starting from 0) for the subsystem. 316 */ 317 static uint32_t pm_get_cpuid(uint32_t nid) 318 { 319 uint32_t ret = (uint32_t) UNDEFINED_CPUID; 320 size_t i; 321 322 for (i = 0; i < ARRAY_SIZE(pm_procs_all); i++) { 323 if (pm_procs_all[i].node_id == nid) { 324 ret = (uint32_t)i; 325 break; 326 } 327 } 328 329 return ret; 330 } 331 332 /** 333 * pm_client_wakeup() - Client-specific wakeup actions. 334 * @proc: Processor which need to wakeup. 335 * 336 * This function should contain any PU-specific actions 337 * required for waking up another APU core. 338 */ 339 void pm_client_wakeup(const struct pm_proc *proc) 340 { 341 uint32_t cpuid = pm_get_cpuid(proc->node_id); 342 uintptr_t val; 343 344 if (cpuid != (uint32_t) UNDEFINED_CPUID) { 345 /* 346 * Get the core index and use it to calculate offset for 347 * disabling power down and wakeup interrupts. 348 * i.e., Convert cpu-id to core_index with the following mapping: 349 * cpu-id -> core_index 350 * 0 -> 0 351 * 1 -> 1 352 * 2 -> 4 353 * 3 -> 5 354 * 4 -> 8 355 * 5 -> 9 356 * 6 -> 12 357 * 7 -> 13 358 * to match with register database. 359 */ 360 uint32_t core_index = cpuid + ((cpuid / 2U) * 2U); 361 362 pm_client_lock_get(); 363 364 /* Clear powerdown request */ 365 val = read_cpu_pwrctrl_val(); 366 val &= ~CORE_PWRDN_EN_BIT_MASK; 367 write_cpu_pwrctrl_val(val); 368 369 isb(); 370 371 /* Disabled power down interrupt */ 372 mmio_write_32(APU_PCIL_CORE_X_IDS_POWER_REG(core_index), 373 APU_PCIL_CORE_X_IDS_POWER_MASK); 374 /* Disable wake interrupt */ 375 mmio_write_32(APU_PCIL_CORE_X_IDS_WAKE_REG(core_index), 376 APU_PCIL_CORE_X_IDS_WAKE_MASK); 377 378 pm_client_lock_release(); 379 } 380 } 381