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> 14*01a326abSPrasad Kummari 15*01a326abSPrasad Kummari #include <drivers/arm/gic_common.h> 16*01a326abSPrasad Kummari #include <drivers/arm/gicv3.h> 17c73a90e5STejas Patel #include <lib/bakery_lock.h> 18fbb32695STejas Patel #include <lib/mmio.h> 196e82cd8cSTejas Patel #include <lib/utils.h> 20fbb32695STejas Patel #include <plat/common/platform.h> 21*01a326abSPrasad Kummari 22*01a326abSPrasad Kummari #include <plat_ipi.h> 23*01a326abSPrasad Kummari #include <platform_def.h> 246e82cd8cSTejas Patel #include "pm_api_sys.h" 25c73a90e5STejas Patel #include "pm_client.h" 260b151872STanmay Shah #include "pm_defs.h" 27*01a326abSPrasad Kummari #include <versal_def.h> 28c73a90e5STejas Patel 2925b1a910STejas Patel #define UNDEFINED_CPUID (~0) 3025b1a910STejas Patel 31c73a90e5STejas Patel DEFINE_BAKERY_LOCK(pm_client_secure_lock); 32c73a90e5STejas Patel 33c73a90e5STejas Patel static const struct pm_ipi apu_ipi = { 34068b0bc6SMichal Simek .local_ipi_id = IPI_LOCAL_ID, 35068b0bc6SMichal Simek .remote_ipi_id = IPI_REMOTE_ID, 36bfd06265SMichal Simek .buffer_base = IPI_BUFFER_LOCAL_BASE, 37c73a90e5STejas Patel }; 38c73a90e5STejas Patel 39c73a90e5STejas Patel /* Order in pm_procs_all array must match cpu ids */ 40c73a90e5STejas Patel static const struct pm_proc pm_procs_all[] = { 41c73a90e5STejas Patel { 42c73a90e5STejas Patel .node_id = XPM_DEVID_ACPU_0, 43c73a90e5STejas Patel .ipi = &apu_ipi, 44fbb32695STejas Patel .pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK, 45c73a90e5STejas Patel }, 46c73a90e5STejas Patel { 47c73a90e5STejas Patel .node_id = XPM_DEVID_ACPU_1, 48c73a90e5STejas Patel .ipi = &apu_ipi, 49fbb32695STejas Patel .pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK, 50c73a90e5STejas Patel } 51c73a90e5STejas Patel }; 52c73a90e5STejas Patel 53c73a90e5STejas Patel const struct pm_proc *primary_proc = &pm_procs_all[0]; 54fbb32695STejas Patel 556e82cd8cSTejas Patel /** 56de7ed953SPrasad Kummari * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number. 576e82cd8cSTejas Patel * @irq: Interrupt number 586e82cd8cSTejas Patel * 59de7ed953SPrasad Kummari * Return: PM node index corresponding to the specified interrupt. 60de7ed953SPrasad Kummari * 616e82cd8cSTejas Patel */ 623ae28aa4SJay Buddhabhatti enum pm_device_node_idx irq_to_pm_node_idx(uint32_t irq) 636e82cd8cSTejas Patel { 640ec6c313SJay Buddhabhatti enum pm_device_node_idx dev_idx = XPM_NODEIDX_DEV_MIN; 650ec6c313SJay Buddhabhatti 666e82cd8cSTejas Patel assert(irq <= IRQ_MAX); 670ec6c313SJay Buddhabhatti 680ec6c313SJay Buddhabhatti switch (irq) { 690ec6c313SJay Buddhabhatti case 13: 700ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_GPIO; 710ec6c313SJay Buddhabhatti break; 720ec6c313SJay Buddhabhatti case 14: 730ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_I2C_0; 740ec6c313SJay Buddhabhatti break; 750ec6c313SJay Buddhabhatti case 15: 760ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_I2C_1; 770ec6c313SJay Buddhabhatti break; 780ec6c313SJay Buddhabhatti case 16: 790ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_SPI_0; 800ec6c313SJay Buddhabhatti break; 810ec6c313SJay Buddhabhatti case 17: 820ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_SPI_1; 830ec6c313SJay Buddhabhatti break; 840ec6c313SJay Buddhabhatti case 18: 850ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_UART_0; 860ec6c313SJay Buddhabhatti break; 870ec6c313SJay Buddhabhatti case 19: 880ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_UART_1; 890ec6c313SJay Buddhabhatti break; 900ec6c313SJay Buddhabhatti case 20: 910ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_CAN_FD_0; 920ec6c313SJay Buddhabhatti break; 930ec6c313SJay Buddhabhatti case 21: 940ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_CAN_FD_1; 950ec6c313SJay Buddhabhatti break; 960ec6c313SJay Buddhabhatti case 22: 970ec6c313SJay Buddhabhatti case 23: 980ec6c313SJay Buddhabhatti case 24: 990ec6c313SJay Buddhabhatti case 25: 1000ec6c313SJay Buddhabhatti case 26: 1010ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_USB_0; 1020ec6c313SJay Buddhabhatti break; 1030ec6c313SJay Buddhabhatti case 37: 1040ec6c313SJay Buddhabhatti case 38: 1050ec6c313SJay Buddhabhatti case 39: 1060ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_TTC_0; 1070ec6c313SJay Buddhabhatti break; 1080ec6c313SJay Buddhabhatti case 40: 1090ec6c313SJay Buddhabhatti case 41: 1100ec6c313SJay Buddhabhatti case 42: 1110ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_TTC_1; 1120ec6c313SJay Buddhabhatti break; 1130ec6c313SJay Buddhabhatti case 43: 1140ec6c313SJay Buddhabhatti case 44: 1150ec6c313SJay Buddhabhatti case 45: 1160ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_TTC_2; 1170ec6c313SJay Buddhabhatti break; 1180ec6c313SJay Buddhabhatti case 46: 1190ec6c313SJay Buddhabhatti case 47: 1200ec6c313SJay Buddhabhatti case 48: 1210ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_TTC_3; 1220ec6c313SJay Buddhabhatti break; 1230ec6c313SJay Buddhabhatti case 56: 1240ec6c313SJay Buddhabhatti case 57: 1250ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_GEM_0; 1260ec6c313SJay Buddhabhatti break; 12706b9c4c8SJay Buddhabhatti case 58: 12806b9c4c8SJay Buddhabhatti case 59: 12906b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_GEM_1; 13006b9c4c8SJay Buddhabhatti break; 13106b9c4c8SJay Buddhabhatti case 60: 13206b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_ADMA_0; 13306b9c4c8SJay Buddhabhatti break; 13406b9c4c8SJay Buddhabhatti case 61: 13506b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_ADMA_1; 13606b9c4c8SJay Buddhabhatti break; 13706b9c4c8SJay Buddhabhatti case 62: 13806b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_ADMA_2; 13906b9c4c8SJay Buddhabhatti break; 14006b9c4c8SJay Buddhabhatti case 63: 14106b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_ADMA_3; 14206b9c4c8SJay Buddhabhatti break; 14306b9c4c8SJay Buddhabhatti case 64: 14406b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_ADMA_4; 14506b9c4c8SJay Buddhabhatti break; 14606b9c4c8SJay Buddhabhatti case 65: 14706b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_ADMA_5; 14806b9c4c8SJay Buddhabhatti break; 14906b9c4c8SJay Buddhabhatti case 66: 15006b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_ADMA_6; 15106b9c4c8SJay Buddhabhatti break; 15206b9c4c8SJay Buddhabhatti case 67: 15306b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_ADMA_7; 15406b9c4c8SJay Buddhabhatti break; 15506b9c4c8SJay Buddhabhatti case 74: 15606b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_USB_0; 15706b9c4c8SJay Buddhabhatti break; 15806b9c4c8SJay Buddhabhatti case 126: 15906b9c4c8SJay Buddhabhatti case 127: 16006b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_SDIO_0; 16106b9c4c8SJay Buddhabhatti break; 16206b9c4c8SJay Buddhabhatti case 128: 16306b9c4c8SJay Buddhabhatti case 129: 16406b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_SDIO_1; 16506b9c4c8SJay Buddhabhatti break; 16606b9c4c8SJay Buddhabhatti case 142: 16706b9c4c8SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_RTC; 16806b9c4c8SJay Buddhabhatti break; 1690ec6c313SJay Buddhabhatti default: 1700ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_MIN; 1710ec6c313SJay Buddhabhatti break; 1720ec6c313SJay Buddhabhatti } 1730ec6c313SJay Buddhabhatti 1740ec6c313SJay Buddhabhatti return dev_idx; 1756e82cd8cSTejas Patel } 1766e82cd8cSTejas Patel 1776e82cd8cSTejas Patel /** 178de7ed953SPrasad Kummari * pm_client_suspend() - Client-specific suspend actions. 179de7ed953SPrasad Kummari * @proc: processor which need to suspend. 180de7ed953SPrasad Kummari * @state: desired suspend state. 181fbb32695STejas Patel * 182fbb32695STejas Patel * This function should contain any PU-specific actions 183fbb32695STejas Patel * required prior to sending suspend request to PMU 184fbb32695STejas Patel * Actions taken depend on the state system is suspending to. 185de7ed953SPrasad Kummari * 186fbb32695STejas Patel */ 187912b7a6fSVenkatesh Yadav Abbarapu void pm_client_suspend(const struct pm_proc *proc, uint32_t state) 188fbb32695STejas Patel { 189fbb32695STejas Patel bakery_lock_get(&pm_client_secure_lock); 190fbb32695STejas Patel 19141567195SAbhyuday Godhasara if (state == PM_STATE_SUSPEND_TO_RAM) { 1925d1c211eSAbhyuday Godhasara pm_client_set_wakeup_sources((uint32_t)proc->node_id); 19341567195SAbhyuday Godhasara } 1946e82cd8cSTejas Patel 195fbb32695STejas Patel /* Set powerdown request */ 196fbb32695STejas Patel mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) | 197775bf1bbSAbhyuday Godhasara (uint32_t)proc->pwrdn_mask); 198fbb32695STejas Patel 199fbb32695STejas Patel bakery_lock_release(&pm_client_secure_lock); 200fbb32695STejas Patel } 201fbb32695STejas Patel 202fbb32695STejas Patel /** 203de7ed953SPrasad Kummari * pm_client_abort_suspend() - Client-specific abort-suspend actions. 204fbb32695STejas Patel * 205fbb32695STejas Patel * This function should contain any PU-specific actions 206de7ed953SPrasad Kummari * required for aborting a prior suspend request. 207de7ed953SPrasad Kummari * 208fbb32695STejas Patel */ 209fbb32695STejas Patel void pm_client_abort_suspend(void) 210fbb32695STejas Patel { 211fbb32695STejas Patel /* Enable interrupts at processor level (for current cpu) */ 212fbb32695STejas Patel gicv3_cpuif_enable(plat_my_core_pos()); 213fbb32695STejas Patel 214fbb32695STejas Patel bakery_lock_get(&pm_client_secure_lock); 215fbb32695STejas Patel 216fbb32695STejas Patel /* Clear powerdown request */ 217fbb32695STejas Patel mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) & 218775bf1bbSAbhyuday Godhasara ~((uint32_t)primary_proc->pwrdn_mask)); 219fbb32695STejas Patel 220fbb32695STejas Patel bakery_lock_release(&pm_client_secure_lock); 221fbb32695STejas Patel } 222fbb32695STejas Patel 223fbb32695STejas Patel /** 224de7ed953SPrasad Kummari * pm_get_cpuid() - get the local cpu ID for a global node ID. 225de7ed953SPrasad Kummari * @nid: node id of the processor. 22625b1a910STejas Patel * 227de7ed953SPrasad Kummari * Return: the cpu ID (starting from 0) for the subsystem. 228de7ed953SPrasad Kummari * 22925b1a910STejas Patel */ 230912b7a6fSVenkatesh Yadav Abbarapu static uint32_t pm_get_cpuid(uint32_t nid) 23125b1a910STejas Patel { 2325d1c211eSAbhyuday Godhasara for (size_t i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) { 23341567195SAbhyuday Godhasara if (pm_procs_all[i].node_id == nid) { 23425b1a910STejas Patel return i; 23525b1a910STejas Patel } 23641567195SAbhyuday Godhasara } 23725b1a910STejas Patel return UNDEFINED_CPUID; 23825b1a910STejas Patel } 23925b1a910STejas Patel 24025b1a910STejas Patel /** 241de7ed953SPrasad Kummari * pm_client_wakeup() - Client-specific wakeup actions. 242de7ed953SPrasad Kummari * @proc: Processor which need to wakeup. 24325b1a910STejas Patel * 24425b1a910STejas Patel * This function should contain any PU-specific actions 245de7ed953SPrasad Kummari * required for waking up another APU core. 246de7ed953SPrasad Kummari * 24725b1a910STejas Patel */ 24825b1a910STejas Patel void pm_client_wakeup(const struct pm_proc *proc) 24925b1a910STejas Patel { 250912b7a6fSVenkatesh Yadav Abbarapu uint32_t cpuid = pm_get_cpuid(proc->node_id); 25125b1a910STejas Patel 25241567195SAbhyuday Godhasara if (cpuid == UNDEFINED_CPUID) { 25325b1a910STejas Patel return; 25441567195SAbhyuday Godhasara } 25525b1a910STejas Patel 25625b1a910STejas Patel bakery_lock_get(&pm_client_secure_lock); 25725b1a910STejas Patel 25825b1a910STejas Patel /* clear powerdown bit for affected cpu */ 25925b1a910STejas Patel uint32_t val = mmio_read_32(FPD_APU_PWRCTL); 26025b1a910STejas Patel val &= ~(proc->pwrdn_mask); 26125b1a910STejas Patel mmio_write_32(FPD_APU_PWRCTL, val); 26225b1a910STejas Patel 26325b1a910STejas Patel bakery_lock_release(&pm_client_secure_lock); 26425b1a910STejas Patel } 26525b1a910STejas Patel 26625b1a910STejas Patel /** 267de7ed953SPrasad Kummari * pm_get_proc() - returns pointer to the proc structure. 268de7ed953SPrasad Kummari * @cpuid: id of the cpu whose proc struct pointer should be returned. 269fbb32695STejas Patel * 270de7ed953SPrasad Kummari * Return: pointer to a proc structure if proc is found, otherwise NULL. 271de7ed953SPrasad Kummari * 272fbb32695STejas Patel */ 273912b7a6fSVenkatesh Yadav Abbarapu const struct pm_proc *pm_get_proc(uint32_t cpuid) 274fbb32695STejas Patel { 27541567195SAbhyuday Godhasara if (cpuid < ARRAY_SIZE(pm_procs_all)) { 276fbb32695STejas Patel return &pm_procs_all[cpuid]; 27741567195SAbhyuday Godhasara } 278fbb32695STejas Patel 279fbb32695STejas Patel return NULL; 280fbb32695STejas Patel } 281