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 = { 32c73a90e5STejas Patel .local_ipi_id = IPI_ID_APU, 33c73a90e5STejas Patel .remote_ipi_id = IPI_ID_PMC, 34*bfd06265SMichal 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 /** 546e82cd8cSTejas Patel * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number 556e82cd8cSTejas Patel * @irq: Interrupt number 566e82cd8cSTejas Patel * 576e82cd8cSTejas Patel * Return: PM node index corresponding to the specified interrupt 586e82cd8cSTejas Patel */ 593ae28aa4SJay Buddhabhatti enum pm_device_node_idx irq_to_pm_node_idx(uint32_t irq) 606e82cd8cSTejas Patel { 610ec6c313SJay Buddhabhatti enum pm_device_node_idx dev_idx = XPM_NODEIDX_DEV_MIN; 620ec6c313SJay Buddhabhatti 636e82cd8cSTejas Patel assert(irq <= IRQ_MAX); 640ec6c313SJay Buddhabhatti 650ec6c313SJay Buddhabhatti switch (irq) { 660ec6c313SJay Buddhabhatti case 13: 670ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_GPIO; 680ec6c313SJay Buddhabhatti break; 690ec6c313SJay Buddhabhatti case 14: 700ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_I2C_0; 710ec6c313SJay Buddhabhatti break; 720ec6c313SJay Buddhabhatti case 15: 730ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_I2C_1; 740ec6c313SJay Buddhabhatti break; 750ec6c313SJay Buddhabhatti case 16: 760ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_SPI_0; 770ec6c313SJay Buddhabhatti break; 780ec6c313SJay Buddhabhatti case 17: 790ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_SPI_1; 800ec6c313SJay Buddhabhatti break; 810ec6c313SJay Buddhabhatti case 18: 820ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_UART_0; 830ec6c313SJay Buddhabhatti break; 840ec6c313SJay Buddhabhatti case 19: 850ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_UART_1; 860ec6c313SJay Buddhabhatti break; 870ec6c313SJay Buddhabhatti case 20: 880ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_CAN_FD_0; 890ec6c313SJay Buddhabhatti break; 900ec6c313SJay Buddhabhatti case 21: 910ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_CAN_FD_1; 920ec6c313SJay Buddhabhatti break; 930ec6c313SJay Buddhabhatti case 22: 940ec6c313SJay Buddhabhatti case 23: 950ec6c313SJay Buddhabhatti case 24: 960ec6c313SJay Buddhabhatti case 25: 970ec6c313SJay Buddhabhatti case 26: 980ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_USB_0; 990ec6c313SJay Buddhabhatti break; 1000ec6c313SJay Buddhabhatti case 37: 1010ec6c313SJay Buddhabhatti case 38: 1020ec6c313SJay Buddhabhatti case 39: 1030ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_TTC_0; 1040ec6c313SJay Buddhabhatti break; 1050ec6c313SJay Buddhabhatti case 40: 1060ec6c313SJay Buddhabhatti case 41: 1070ec6c313SJay Buddhabhatti case 42: 1080ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_TTC_1; 1090ec6c313SJay Buddhabhatti break; 1100ec6c313SJay Buddhabhatti case 43: 1110ec6c313SJay Buddhabhatti case 44: 1120ec6c313SJay Buddhabhatti case 45: 1130ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_TTC_2; 1140ec6c313SJay Buddhabhatti break; 1150ec6c313SJay Buddhabhatti case 46: 1160ec6c313SJay Buddhabhatti case 47: 1170ec6c313SJay Buddhabhatti case 48: 1180ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_TTC_3; 1190ec6c313SJay Buddhabhatti break; 1200ec6c313SJay Buddhabhatti case 56: 1210ec6c313SJay Buddhabhatti case 57: 1220ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_GEM_0; 1230ec6c313SJay Buddhabhatti break; 1240ec6c313SJay Buddhabhatti default: 1250ec6c313SJay Buddhabhatti dev_idx = XPM_NODEIDX_DEV_MIN; 1260ec6c313SJay Buddhabhatti break; 1270ec6c313SJay Buddhabhatti } 1280ec6c313SJay Buddhabhatti 1290ec6c313SJay Buddhabhatti return dev_idx; 1306e82cd8cSTejas Patel } 1316e82cd8cSTejas Patel 1326e82cd8cSTejas Patel /** 133fbb32695STejas Patel * pm_client_suspend() - Client-specific suspend actions 134fbb32695STejas Patel * 135fbb32695STejas Patel * This function should contain any PU-specific actions 136fbb32695STejas Patel * required prior to sending suspend request to PMU 137fbb32695STejas Patel * Actions taken depend on the state system is suspending to. 138fbb32695STejas Patel */ 139912b7a6fSVenkatesh Yadav Abbarapu void pm_client_suspend(const struct pm_proc *proc, uint32_t state) 140fbb32695STejas Patel { 141fbb32695STejas Patel bakery_lock_get(&pm_client_secure_lock); 142fbb32695STejas Patel 14341567195SAbhyuday Godhasara if (state == PM_STATE_SUSPEND_TO_RAM) { 1445d1c211eSAbhyuday Godhasara pm_client_set_wakeup_sources((uint32_t)proc->node_id); 14541567195SAbhyuday Godhasara } 1466e82cd8cSTejas Patel 147fbb32695STejas Patel /* Set powerdown request */ 148fbb32695STejas Patel mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) | 149775bf1bbSAbhyuday Godhasara (uint32_t)proc->pwrdn_mask); 150fbb32695STejas Patel 151fbb32695STejas Patel bakery_lock_release(&pm_client_secure_lock); 152fbb32695STejas Patel } 153fbb32695STejas Patel 154fbb32695STejas Patel /** 155fbb32695STejas Patel * pm_client_abort_suspend() - Client-specific abort-suspend actions 156fbb32695STejas Patel * 157fbb32695STejas Patel * This function should contain any PU-specific actions 158fbb32695STejas Patel * required for aborting a prior suspend request 159fbb32695STejas Patel */ 160fbb32695STejas Patel void pm_client_abort_suspend(void) 161fbb32695STejas Patel { 162fbb32695STejas Patel /* Enable interrupts at processor level (for current cpu) */ 163fbb32695STejas Patel gicv3_cpuif_enable(plat_my_core_pos()); 164fbb32695STejas Patel 165fbb32695STejas Patel bakery_lock_get(&pm_client_secure_lock); 166fbb32695STejas Patel 167fbb32695STejas Patel /* Clear powerdown request */ 168fbb32695STejas Patel mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) & 169775bf1bbSAbhyuday Godhasara ~((uint32_t)primary_proc->pwrdn_mask)); 170fbb32695STejas Patel 171fbb32695STejas Patel bakery_lock_release(&pm_client_secure_lock); 172fbb32695STejas Patel } 173fbb32695STejas Patel 174fbb32695STejas Patel /** 17525b1a910STejas Patel * pm_get_cpuid() - get the local cpu ID for a global node ID 17625b1a910STejas Patel * @nid: node id of the processor 17725b1a910STejas Patel * 17825b1a910STejas Patel * Return: the cpu ID (starting from 0) for the subsystem 17925b1a910STejas Patel */ 180912b7a6fSVenkatesh Yadav Abbarapu static uint32_t pm_get_cpuid(uint32_t nid) 18125b1a910STejas Patel { 1825d1c211eSAbhyuday Godhasara for (size_t i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) { 18341567195SAbhyuday Godhasara if (pm_procs_all[i].node_id == nid) { 18425b1a910STejas Patel return i; 18525b1a910STejas Patel } 18641567195SAbhyuday Godhasara } 18725b1a910STejas Patel return UNDEFINED_CPUID; 18825b1a910STejas Patel } 18925b1a910STejas Patel 19025b1a910STejas Patel /** 19125b1a910STejas Patel * pm_client_wakeup() - Client-specific wakeup actions 19225b1a910STejas Patel * 19325b1a910STejas Patel * This function should contain any PU-specific actions 19425b1a910STejas Patel * required for waking up another APU core 19525b1a910STejas Patel */ 19625b1a910STejas Patel void pm_client_wakeup(const struct pm_proc *proc) 19725b1a910STejas Patel { 198912b7a6fSVenkatesh Yadav Abbarapu uint32_t cpuid = pm_get_cpuid(proc->node_id); 19925b1a910STejas Patel 20041567195SAbhyuday Godhasara if (cpuid == UNDEFINED_CPUID) { 20125b1a910STejas Patel return; 20241567195SAbhyuday Godhasara } 20325b1a910STejas Patel 20425b1a910STejas Patel bakery_lock_get(&pm_client_secure_lock); 20525b1a910STejas Patel 20625b1a910STejas Patel /* clear powerdown bit for affected cpu */ 20725b1a910STejas Patel uint32_t val = mmio_read_32(FPD_APU_PWRCTL); 20825b1a910STejas Patel val &= ~(proc->pwrdn_mask); 20925b1a910STejas Patel mmio_write_32(FPD_APU_PWRCTL, val); 21025b1a910STejas Patel 21125b1a910STejas Patel bakery_lock_release(&pm_client_secure_lock); 21225b1a910STejas Patel } 21325b1a910STejas Patel 21425b1a910STejas Patel /** 215fbb32695STejas Patel * pm_get_proc() - returns pointer to the proc structure 216fbb32695STejas Patel * @cpuid: id of the cpu whose proc struct pointer should be returned 217fbb32695STejas Patel * 218fbb32695STejas Patel * Return: pointer to a proc structure if proc is found, otherwise NULL 219fbb32695STejas Patel */ 220912b7a6fSVenkatesh Yadav Abbarapu const struct pm_proc *pm_get_proc(uint32_t cpuid) 221fbb32695STejas Patel { 22241567195SAbhyuday Godhasara if (cpuid < ARRAY_SIZE(pm_procs_all)) { 223fbb32695STejas Patel return &pm_procs_all[cpuid]; 22441567195SAbhyuday Godhasara } 225fbb32695STejas Patel 226fbb32695STejas Patel return NULL; 227fbb32695STejas Patel } 228