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