1c73a90e5STejas Patel /* 20b151872STanmay Shah * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved. 331b68489SJay Buddhabhatti * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. 4c73a90e5STejas Patel * 5c73a90e5STejas Patel * SPDX-License-Identifier: BSD-3-Clause 6c73a90e5STejas Patel */ 7c73a90e5STejas Patel 8c73a90e5STejas Patel /* 9c73a90e5STejas Patel * APU specific definition of processors in the subsystem as well as functions 10c73a90e5STejas Patel * for getting information about and changing state of the APU. 11c73a90e5STejas Patel */ 12c73a90e5STejas Patel 136e82cd8cSTejas Patel #include <assert.h> 14c73a90e5STejas Patel #include <plat_ipi.h> 15c73a90e5STejas Patel #include <platform_def.h> 16c73a90e5STejas Patel #include <versal_def.h> 17c73a90e5STejas Patel #include <lib/bakery_lock.h> 18fbb32695STejas Patel #include <lib/mmio.h> 196e82cd8cSTejas Patel #include <lib/utils.h> 20fbb32695STejas Patel #include <drivers/arm/gicv3.h> 216e82cd8cSTejas Patel #include <drivers/arm/gic_common.h> 22fbb32695STejas Patel #include <plat/common/platform.h> 236e82cd8cSTejas Patel #include "pm_api_sys.h" 24c73a90e5STejas Patel #include "pm_client.h" 250b151872STanmay Shah #include "pm_defs.h" 26c73a90e5STejas Patel 2725b1a910STejas Patel #define UNDEFINED_CPUID (~0) 2825b1a910STejas Patel 29c73a90e5STejas Patel DEFINE_BAKERY_LOCK(pm_client_secure_lock); 30c73a90e5STejas Patel 31c73a90e5STejas Patel static const struct pm_ipi apu_ipi = { 32068b0bc6SMichal Simek .local_ipi_id = IPI_LOCAL_ID, 33068b0bc6SMichal Simek .remote_ipi_id = IPI_REMOTE_ID, 34bfd06265SMichal Simek .buffer_base = IPI_BUFFER_LOCAL_BASE, 35c73a90e5STejas Patel }; 36c73a90e5STejas Patel 37c73a90e5STejas Patel /* Order in pm_procs_all array must match cpu ids */ 38c73a90e5STejas Patel static const struct pm_proc pm_procs_all[] = { 39c73a90e5STejas Patel { 40c73a90e5STejas Patel .node_id = XPM_DEVID_ACPU_0, 41c73a90e5STejas Patel .ipi = &apu_ipi, 42fbb32695STejas Patel .pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK, 43c73a90e5STejas Patel }, 44c73a90e5STejas Patel { 45c73a90e5STejas Patel .node_id = XPM_DEVID_ACPU_1, 46c73a90e5STejas Patel .ipi = &apu_ipi, 47fbb32695STejas Patel .pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK, 48c73a90e5STejas Patel } 49c73a90e5STejas Patel }; 50c73a90e5STejas Patel 51c73a90e5STejas Patel const struct pm_proc *primary_proc = &pm_procs_all[0]; 52fbb32695STejas Patel 536e82cd8cSTejas Patel /** 54*de7ed953SPrasad Kummari * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number. 556e82cd8cSTejas Patel * @irq: Interrupt number 566e82cd8cSTejas Patel * 57*de7ed953SPrasad Kummari * Return: PM node index corresponding to the specified interrupt. 58*de7ed953SPrasad Kummari * 596e82cd8cSTejas Patel */ 603ae28aa4SJay Buddhabhatti enum pm_device_node_idx irq_to_pm_node_idx(uint32_t irq) 616e82cd8cSTejas Patel { 620ec6c313SJay Buddhabhatti enum pm_device_node_idx dev_idx = XPM_NODEIDX_DEV_MIN; 630ec6c313SJay Buddhabhatti 646e82cd8cSTejas Patel assert(irq <= IRQ_MAX); 650ec6c313SJay Buddhabhatti 660ec6c313SJay Buddhabhatti switch (irq) { 670ec6c313SJay Buddhabhatti case 13: 680ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_GPIO; 690ec6c313SJay Buddhabhatti break; 700ec6c313SJay Buddhabhatti case 14: 710ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_I2C_0; 720ec6c313SJay Buddhabhatti break; 730ec6c313SJay Buddhabhatti case 15: 740ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_I2C_1; 750ec6c313SJay Buddhabhatti break; 760ec6c313SJay Buddhabhatti case 16: 770ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_SPI_0; 780ec6c313SJay Buddhabhatti break; 790ec6c313SJay Buddhabhatti case 17: 800ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_SPI_1; 810ec6c313SJay Buddhabhatti break; 820ec6c313SJay Buddhabhatti case 18: 830ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_UART_0; 840ec6c313SJay Buddhabhatti break; 850ec6c313SJay Buddhabhatti case 19: 860ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_UART_1; 870ec6c313SJay Buddhabhatti break; 880ec6c313SJay Buddhabhatti case 20: 890ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_CAN_FD_0; 900ec6c313SJay Buddhabhatti break; 910ec6c313SJay Buddhabhatti case 21: 920ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_CAN_FD_1; 930ec6c313SJay Buddhabhatti break; 940ec6c313SJay Buddhabhatti case 22: 950ec6c313SJay Buddhabhatti case 23: 960ec6c313SJay Buddhabhatti case 24: 970ec6c313SJay Buddhabhatti case 25: 980ec6c313SJay Buddhabhatti case 26: 990ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_USB_0; 1000ec6c313SJay Buddhabhatti break; 1010ec6c313SJay Buddhabhatti case 37: 1020ec6c313SJay Buddhabhatti case 38: 1030ec6c313SJay Buddhabhatti case 39: 1040ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_TTC_0; 1050ec6c313SJay Buddhabhatti break; 1060ec6c313SJay Buddhabhatti case 40: 1070ec6c313SJay Buddhabhatti case 41: 1080ec6c313SJay Buddhabhatti case 42: 1090ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_TTC_1; 1100ec6c313SJay Buddhabhatti break; 1110ec6c313SJay Buddhabhatti case 43: 1120ec6c313SJay Buddhabhatti case 44: 1130ec6c313SJay Buddhabhatti case 45: 1140ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_TTC_2; 1150ec6c313SJay Buddhabhatti break; 1160ec6c313SJay Buddhabhatti case 46: 1170ec6c313SJay Buddhabhatti case 47: 1180ec6c313SJay Buddhabhatti case 48: 1190ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_TTC_3; 1200ec6c313SJay Buddhabhatti break; 1210ec6c313SJay Buddhabhatti case 56: 1220ec6c313SJay Buddhabhatti case 57: 1230ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_GEM_0; 1240ec6c313SJay Buddhabhatti break; 12506b9c4c8SJay Buddhabhatti case 58: 12606b9c4c8SJay Buddhabhatti case 59: 12706b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_GEM_1; 12806b9c4c8SJay Buddhabhatti break; 12906b9c4c8SJay Buddhabhatti case 60: 13006b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_ADMA_0; 13106b9c4c8SJay Buddhabhatti break; 13206b9c4c8SJay Buddhabhatti case 61: 13306b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_ADMA_1; 13406b9c4c8SJay Buddhabhatti break; 13506b9c4c8SJay Buddhabhatti case 62: 13606b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_ADMA_2; 13706b9c4c8SJay Buddhabhatti break; 13806b9c4c8SJay Buddhabhatti case 63: 13906b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_ADMA_3; 14006b9c4c8SJay Buddhabhatti break; 14106b9c4c8SJay Buddhabhatti case 64: 14206b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_ADMA_4; 14306b9c4c8SJay Buddhabhatti break; 14406b9c4c8SJay Buddhabhatti case 65: 14506b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_ADMA_5; 14606b9c4c8SJay Buddhabhatti break; 14706b9c4c8SJay Buddhabhatti case 66: 14806b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_ADMA_6; 14906b9c4c8SJay Buddhabhatti break; 15006b9c4c8SJay Buddhabhatti case 67: 15106b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_ADMA_7; 15206b9c4c8SJay Buddhabhatti break; 15306b9c4c8SJay Buddhabhatti case 74: 15406b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_USB_0; 15506b9c4c8SJay Buddhabhatti break; 15606b9c4c8SJay Buddhabhatti case 126: 15706b9c4c8SJay Buddhabhatti case 127: 15806b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_SDIO_0; 15906b9c4c8SJay Buddhabhatti break; 16006b9c4c8SJay Buddhabhatti case 128: 16106b9c4c8SJay Buddhabhatti case 129: 16206b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_SDIO_1; 16306b9c4c8SJay Buddhabhatti break; 16406b9c4c8SJay Buddhabhatti case 142: 16506b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_RTC; 16606b9c4c8SJay Buddhabhatti break; 1670ec6c313SJay Buddhabhatti default: 1680ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_MIN; 1690ec6c313SJay Buddhabhatti break; 1700ec6c313SJay Buddhabhatti } 1710ec6c313SJay Buddhabhatti 1720ec6c313SJay Buddhabhatti return dev_idx; 1736e82cd8cSTejas Patel } 1746e82cd8cSTejas Patel 1756e82cd8cSTejas Patel /** 176*de7ed953SPrasad Kummari * pm_client_suspend() - Client-specific suspend actions. 177*de7ed953SPrasad Kummari * @proc: processor which need to suspend. 178*de7ed953SPrasad Kummari * @state: desired suspend state. 179fbb32695STejas Patel * 180fbb32695STejas Patel * This function should contain any PU-specific actions 181fbb32695STejas Patel * required prior to sending suspend request to PMU 182fbb32695STejas Patel * Actions taken depend on the state system is suspending to. 183*de7ed953SPrasad Kummari * 184fbb32695STejas Patel */ 185912b7a6fSVenkatesh Yadav Abbarapu void pm_client_suspend(const struct pm_proc *proc, uint32_t state) 186fbb32695STejas Patel { 187fbb32695STejas Patel bakery_lock_get(&pm_client_secure_lock); 188fbb32695STejas Patel 18941567195SAbhyuday Godhasara if (state == PM_STATE_SUSPEND_TO_RAM) { 1905d1c211eSAbhyuday Godhasara pm_client_set_wakeup_sources((uint32_t)proc->node_id); 19141567195SAbhyuday Godhasara } 1926e82cd8cSTejas Patel 193fbb32695STejas Patel /* Set powerdown request */ 194fbb32695STejas Patel mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) | 195775bf1bbSAbhyuday Godhasara (uint32_t)proc->pwrdn_mask); 196fbb32695STejas Patel 197fbb32695STejas Patel bakery_lock_release(&pm_client_secure_lock); 198fbb32695STejas Patel } 199fbb32695STejas Patel 200fbb32695STejas Patel /** 201*de7ed953SPrasad Kummari * pm_client_abort_suspend() - Client-specific abort-suspend actions. 202fbb32695STejas Patel * 203fbb32695STejas Patel * This function should contain any PU-specific actions 204*de7ed953SPrasad Kummari * required for aborting a prior suspend request. 205*de7ed953SPrasad Kummari * 206fbb32695STejas Patel */ 207fbb32695STejas Patel void pm_client_abort_suspend(void) 208fbb32695STejas Patel { 209fbb32695STejas Patel /* Enable interrupts at processor level (for current cpu) */ 210fbb32695STejas Patel gicv3_cpuif_enable(plat_my_core_pos()); 211fbb32695STejas Patel 212fbb32695STejas Patel bakery_lock_get(&pm_client_secure_lock); 213fbb32695STejas Patel 214fbb32695STejas Patel /* Clear powerdown request */ 215fbb32695STejas Patel mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) & 216775bf1bbSAbhyuday Godhasara ~((uint32_t)primary_proc->pwrdn_mask)); 217fbb32695STejas Patel 218fbb32695STejas Patel bakery_lock_release(&pm_client_secure_lock); 219fbb32695STejas Patel } 220fbb32695STejas Patel 221fbb32695STejas Patel /** 222*de7ed953SPrasad Kummari * pm_get_cpuid() - get the local cpu ID for a global node ID. 223*de7ed953SPrasad Kummari * @nid: node id of the processor. 22425b1a910STejas Patel * 225*de7ed953SPrasad Kummari * Return: the cpu ID (starting from 0) for the subsystem. 226*de7ed953SPrasad Kummari * 22725b1a910STejas Patel */ 228912b7a6fSVenkatesh Yadav Abbarapu static uint32_t pm_get_cpuid(uint32_t nid) 22925b1a910STejas Patel { 2305d1c211eSAbhyuday Godhasara for (size_t i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) { 23141567195SAbhyuday Godhasara if (pm_procs_all[i].node_id == nid) { 23225b1a910STejas Patel return i; 23325b1a910STejas Patel } 23441567195SAbhyuday Godhasara } 23525b1a910STejas Patel return UNDEFINED_CPUID; 23625b1a910STejas Patel } 23725b1a910STejas Patel 23825b1a910STejas Patel /** 239*de7ed953SPrasad Kummari * pm_client_wakeup() - Client-specific wakeup actions. 240*de7ed953SPrasad Kummari * @proc: Processor which need to wakeup. 24125b1a910STejas Patel * 24225b1a910STejas Patel * This function should contain any PU-specific actions 243*de7ed953SPrasad Kummari * required for waking up another APU core. 244*de7ed953SPrasad Kummari * 24525b1a910STejas Patel */ 24625b1a910STejas Patel void pm_client_wakeup(const struct pm_proc *proc) 24725b1a910STejas Patel { 248912b7a6fSVenkatesh Yadav Abbarapu uint32_t cpuid = pm_get_cpuid(proc->node_id); 24925b1a910STejas Patel 25041567195SAbhyuday Godhasara if (cpuid == UNDEFINED_CPUID) { 25125b1a910STejas Patel return; 25241567195SAbhyuday Godhasara } 25325b1a910STejas Patel 25425b1a910STejas Patel bakery_lock_get(&pm_client_secure_lock); 25525b1a910STejas Patel 25625b1a910STejas Patel /* clear powerdown bit for affected cpu */ 25725b1a910STejas Patel uint32_t val = mmio_read_32(FPD_APU_PWRCTL); 25825b1a910STejas Patel val &= ~(proc->pwrdn_mask); 25925b1a910STejas Patel mmio_write_32(FPD_APU_PWRCTL, val); 26025b1a910STejas Patel 26125b1a910STejas Patel bakery_lock_release(&pm_client_secure_lock); 26225b1a910STejas Patel } 26325b1a910STejas Patel 26425b1a910STejas Patel /** 265*de7ed953SPrasad Kummari * pm_get_proc() - returns pointer to the proc structure. 266*de7ed953SPrasad Kummari * @cpuid: id of the cpu whose proc struct pointer should be returned. 267fbb32695STejas Patel * 268*de7ed953SPrasad Kummari * Return: pointer to a proc structure if proc is found, otherwise NULL. 269*de7ed953SPrasad Kummari * 270fbb32695STejas Patel */ 271912b7a6fSVenkatesh Yadav Abbarapu const struct pm_proc *pm_get_proc(uint32_t cpuid) 272fbb32695STejas Patel { 27341567195SAbhyuday Godhasara if (cpuid < ARRAY_SIZE(pm_procs_all)) { 274fbb32695STejas Patel return &pm_procs_all[cpuid]; 27541567195SAbhyuday Godhasara } 276fbb32695STejas Patel 277fbb32695STejas Patel return NULL; 278fbb32695STejas Patel } 279