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