1c73a90e5STejas Patel /* 2c73a90e5STejas Patel * Copyright (c) 2019, Xilinx, Inc. All rights reserved. 3c73a90e5STejas Patel * 4c73a90e5STejas Patel * SPDX-License-Identifier: BSD-3-Clause 5c73a90e5STejas Patel */ 6c73a90e5STejas Patel 7c73a90e5STejas Patel /* 8c73a90e5STejas Patel * APU specific definition of processors in the subsystem as well as functions 9c73a90e5STejas Patel * for getting information about and changing state of the APU. 10c73a90e5STejas Patel */ 11c73a90e5STejas Patel 12c73a90e5STejas Patel #include <plat_ipi.h> 13c73a90e5STejas Patel #include <platform_def.h> 14c73a90e5STejas Patel #include <versal_def.h> 15c73a90e5STejas Patel #include <lib/bakery_lock.h> 16fbb32695STejas Patel #include <lib/mmio.h> 17fbb32695STejas Patel #include <drivers/arm/gicv3.h> 18fbb32695STejas Patel #include <plat/common/platform.h> 19c73a90e5STejas Patel #include "pm_client.h" 20c73a90e5STejas Patel 21*25b1a910STejas Patel #define UNDEFINED_CPUID (~0) 22*25b1a910STejas Patel 23c73a90e5STejas Patel DEFINE_BAKERY_LOCK(pm_client_secure_lock); 24c73a90e5STejas Patel 25c73a90e5STejas Patel static const struct pm_ipi apu_ipi = { 26c73a90e5STejas Patel .local_ipi_id = IPI_ID_APU, 27c73a90e5STejas Patel .remote_ipi_id = IPI_ID_PMC, 28c73a90e5STejas Patel .buffer_base = IPI_BUFFER_APU_BASE, 29c73a90e5STejas Patel }; 30c73a90e5STejas Patel 31c73a90e5STejas Patel /* Order in pm_procs_all array must match cpu ids */ 32c73a90e5STejas Patel static const struct pm_proc pm_procs_all[] = { 33c73a90e5STejas Patel { 34c73a90e5STejas Patel .node_id = XPM_DEVID_ACPU_0, 35c73a90e5STejas Patel .ipi = &apu_ipi, 36fbb32695STejas Patel .pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK, 37c73a90e5STejas Patel }, 38c73a90e5STejas Patel { 39c73a90e5STejas Patel .node_id = XPM_DEVID_ACPU_1, 40c73a90e5STejas Patel .ipi = &apu_ipi, 41fbb32695STejas Patel .pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK, 42c73a90e5STejas Patel } 43c73a90e5STejas Patel }; 44c73a90e5STejas Patel 45c73a90e5STejas Patel const struct pm_proc *primary_proc = &pm_procs_all[0]; 46fbb32695STejas Patel 47fbb32695STejas Patel /** 48fbb32695STejas Patel * pm_client_suspend() - Client-specific suspend actions 49fbb32695STejas Patel * 50fbb32695STejas Patel * This function should contain any PU-specific actions 51fbb32695STejas Patel * required prior to sending suspend request to PMU 52fbb32695STejas Patel * Actions taken depend on the state system is suspending to. 53fbb32695STejas Patel */ 54fbb32695STejas Patel void pm_client_suspend(const struct pm_proc *proc, unsigned int state) 55fbb32695STejas Patel { 56fbb32695STejas Patel bakery_lock_get(&pm_client_secure_lock); 57fbb32695STejas Patel 58fbb32695STejas Patel /* Set powerdown request */ 59fbb32695STejas Patel mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) | 60fbb32695STejas Patel proc->pwrdn_mask); 61fbb32695STejas Patel 62fbb32695STejas Patel bakery_lock_release(&pm_client_secure_lock); 63fbb32695STejas Patel } 64fbb32695STejas Patel 65fbb32695STejas Patel /** 66fbb32695STejas Patel * pm_client_abort_suspend() - Client-specific abort-suspend actions 67fbb32695STejas Patel * 68fbb32695STejas Patel * This function should contain any PU-specific actions 69fbb32695STejas Patel * required for aborting a prior suspend request 70fbb32695STejas Patel */ 71fbb32695STejas Patel void pm_client_abort_suspend(void) 72fbb32695STejas Patel { 73fbb32695STejas Patel /* Enable interrupts at processor level (for current cpu) */ 74fbb32695STejas Patel gicv3_cpuif_enable(plat_my_core_pos()); 75fbb32695STejas Patel 76fbb32695STejas Patel bakery_lock_get(&pm_client_secure_lock); 77fbb32695STejas Patel 78fbb32695STejas Patel /* Clear powerdown request */ 79fbb32695STejas Patel mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) & 80fbb32695STejas Patel ~primary_proc->pwrdn_mask); 81fbb32695STejas Patel 82fbb32695STejas Patel bakery_lock_release(&pm_client_secure_lock); 83fbb32695STejas Patel } 84fbb32695STejas Patel 85fbb32695STejas Patel /** 86*25b1a910STejas Patel * pm_get_cpuid() - get the local cpu ID for a global node ID 87*25b1a910STejas Patel * @nid: node id of the processor 88*25b1a910STejas Patel * 89*25b1a910STejas Patel * Return: the cpu ID (starting from 0) for the subsystem 90*25b1a910STejas Patel */ 91*25b1a910STejas Patel static unsigned int pm_get_cpuid(uint32_t nid) 92*25b1a910STejas Patel { 93*25b1a910STejas Patel for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) { 94*25b1a910STejas Patel if (pm_procs_all[i].node_id == nid) 95*25b1a910STejas Patel return i; 96*25b1a910STejas Patel } 97*25b1a910STejas Patel return UNDEFINED_CPUID; 98*25b1a910STejas Patel } 99*25b1a910STejas Patel 100*25b1a910STejas Patel /** 101*25b1a910STejas Patel * pm_client_wakeup() - Client-specific wakeup actions 102*25b1a910STejas Patel * 103*25b1a910STejas Patel * This function should contain any PU-specific actions 104*25b1a910STejas Patel * required for waking up another APU core 105*25b1a910STejas Patel */ 106*25b1a910STejas Patel void pm_client_wakeup(const struct pm_proc *proc) 107*25b1a910STejas Patel { 108*25b1a910STejas Patel unsigned int cpuid = pm_get_cpuid(proc->node_id); 109*25b1a910STejas Patel 110*25b1a910STejas Patel if (cpuid == UNDEFINED_CPUID) 111*25b1a910STejas Patel return; 112*25b1a910STejas Patel 113*25b1a910STejas Patel bakery_lock_get(&pm_client_secure_lock); 114*25b1a910STejas Patel 115*25b1a910STejas Patel /* clear powerdown bit for affected cpu */ 116*25b1a910STejas Patel uint32_t val = mmio_read_32(FPD_APU_PWRCTL); 117*25b1a910STejas Patel val &= ~(proc->pwrdn_mask); 118*25b1a910STejas Patel mmio_write_32(FPD_APU_PWRCTL, val); 119*25b1a910STejas Patel 120*25b1a910STejas Patel bakery_lock_release(&pm_client_secure_lock); 121*25b1a910STejas Patel } 122*25b1a910STejas Patel 123*25b1a910STejas Patel /** 124fbb32695STejas Patel * pm_get_proc() - returns pointer to the proc structure 125fbb32695STejas Patel * @cpuid: id of the cpu whose proc struct pointer should be returned 126fbb32695STejas Patel * 127fbb32695STejas Patel * Return: pointer to a proc structure if proc is found, otherwise NULL 128fbb32695STejas Patel */ 129fbb32695STejas Patel const struct pm_proc *pm_get_proc(unsigned int cpuid) 130fbb32695STejas Patel { 131fbb32695STejas Patel if (cpuid < ARRAY_SIZE(pm_procs_all)) 132fbb32695STejas Patel return &pm_procs_all[cpuid]; 133fbb32695STejas Patel 134fbb32695STejas Patel return NULL; 135fbb32695STejas Patel } 136