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