xilinx: versal: Implement set wakeup source for client
Add support to set wakeup source for APU while suspending. Signed-off-by: Tejas Patel <tejas.patel@xilinx.com> Signed-off-by: Rajan Vaja <rajan.vaja@xilinx.com> Signed-off-by: Jolly Shah <jolly.shah@xilinx.com> Change-Id: I4809fd83a710def8144fdad74990c45e62b8fdf3
This commit is contained in:
parent
89224531b4
commit
6e82cd8c9b
|
@ -9,16 +9,22 @@
|
|||
* for getting information about and changing state of the APU.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <plat_ipi.h>
|
||||
#include <platform_def.h>
|
||||
#include <versal_def.h>
|
||||
#include <lib/bakery_lock.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/utils.h>
|
||||
#include <drivers/arm/gicv3.h>
|
||||
#include <drivers/arm/gic_common.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include "pm_api_sys.h"
|
||||
#include "pm_client.h"
|
||||
|
||||
#define UNDEFINED_CPUID (~0)
|
||||
#define IRQ_MAX 142
|
||||
#define NUM_GICD_ISENABLER ((IRQ_MAX >> 5) + 1)
|
||||
|
||||
DEFINE_BAKERY_LOCK(pm_client_secure_lock);
|
||||
|
||||
|
@ -44,6 +50,111 @@ static const struct pm_proc pm_procs_all[] = {
|
|||
|
||||
const struct pm_proc *primary_proc = &pm_procs_all[0];
|
||||
|
||||
/* Interrupt to PM node index map */
|
||||
static enum pm_device_node_idx irq_node_map[IRQ_MAX + 1] = {
|
||||
[13] = XPM_NODEIDX_DEV_GPIO,
|
||||
[14] = XPM_NODEIDX_DEV_I2C_0,
|
||||
[15] = XPM_NODEIDX_DEV_I2C_1,
|
||||
[16] = XPM_NODEIDX_DEV_SPI_0,
|
||||
[17] = XPM_NODEIDX_DEV_SPI_1,
|
||||
[18] = XPM_NODEIDX_DEV_UART_0,
|
||||
[19] = XPM_NODEIDX_DEV_UART_1,
|
||||
[20] = XPM_NODEIDX_DEV_CAN_FD_0,
|
||||
[21] = XPM_NODEIDX_DEV_CAN_FD_1,
|
||||
[22] = XPM_NODEIDX_DEV_USB_0,
|
||||
[23] = XPM_NODEIDX_DEV_USB_0,
|
||||
[24] = XPM_NODEIDX_DEV_USB_0,
|
||||
[25] = XPM_NODEIDX_DEV_USB_0,
|
||||
[26] = XPM_NODEIDX_DEV_USB_0,
|
||||
[37] = XPM_NODEIDX_DEV_TTC_0,
|
||||
[38] = XPM_NODEIDX_DEV_TTC_0,
|
||||
[39] = XPM_NODEIDX_DEV_TTC_0,
|
||||
[40] = XPM_NODEIDX_DEV_TTC_1,
|
||||
[41] = XPM_NODEIDX_DEV_TTC_1,
|
||||
[42] = XPM_NODEIDX_DEV_TTC_1,
|
||||
[43] = XPM_NODEIDX_DEV_TTC_2,
|
||||
[44] = XPM_NODEIDX_DEV_TTC_2,
|
||||
[45] = XPM_NODEIDX_DEV_TTC_2,
|
||||
[46] = XPM_NODEIDX_DEV_TTC_3,
|
||||
[47] = XPM_NODEIDX_DEV_TTC_3,
|
||||
[48] = XPM_NODEIDX_DEV_TTC_3,
|
||||
[56] = XPM_NODEIDX_DEV_GEM_0,
|
||||
[57] = XPM_NODEIDX_DEV_GEM_0,
|
||||
[58] = XPM_NODEIDX_DEV_GEM_1,
|
||||
[59] = XPM_NODEIDX_DEV_GEM_1,
|
||||
[60] = XPM_NODEIDX_DEV_ADMA_0,
|
||||
[61] = XPM_NODEIDX_DEV_ADMA_1,
|
||||
[62] = XPM_NODEIDX_DEV_ADMA_2,
|
||||
[63] = XPM_NODEIDX_DEV_ADMA_3,
|
||||
[64] = XPM_NODEIDX_DEV_ADMA_4,
|
||||
[65] = XPM_NODEIDX_DEV_ADMA_5,
|
||||
[66] = XPM_NODEIDX_DEV_ADMA_6,
|
||||
[67] = XPM_NODEIDX_DEV_ADMA_7,
|
||||
[74] = XPM_NODEIDX_DEV_USB_0,
|
||||
[126] = XPM_NODEIDX_DEV_SDIO_0,
|
||||
[127] = XPM_NODEIDX_DEV_SDIO_0,
|
||||
[128] = XPM_NODEIDX_DEV_SDIO_1,
|
||||
[129] = XPM_NODEIDX_DEV_SDIO_1,
|
||||
[142] = XPM_NODEIDX_DEV_RTC,
|
||||
};
|
||||
|
||||
/**
|
||||
* irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number
|
||||
* @irq: Interrupt number
|
||||
*
|
||||
* Return: PM node index corresponding to the specified interrupt
|
||||
*/
|
||||
static enum pm_device_node_idx irq_to_pm_node_idx(unsigned int irq)
|
||||
{
|
||||
assert(irq <= IRQ_MAX);
|
||||
return irq_node_map[irq];
|
||||
}
|
||||
|
||||
/**
|
||||
* pm_client_set_wakeup_sources - Set all devices with enabled interrupts as
|
||||
* wake sources in the LibPM.
|
||||
*/
|
||||
static void pm_client_set_wakeup_sources(void)
|
||||
{
|
||||
uint32_t reg_num;
|
||||
uint32_t device_id;
|
||||
uint8_t pm_wakeup_nodes_set[XPM_NODEIDX_DEV_MAX];
|
||||
uintptr_t isenabler1 = PLAT_VERSAL_GICD_BASE + GICD_ISENABLER + 4;
|
||||
|
||||
zeromem(&pm_wakeup_nodes_set, sizeof(pm_wakeup_nodes_set));
|
||||
|
||||
for (reg_num = 0; reg_num < NUM_GICD_ISENABLER; reg_num++) {
|
||||
uint32_t base_irq = reg_num << ISENABLER_SHIFT;
|
||||
uint32_t reg = mmio_read_32(isenabler1 + (reg_num << 2));
|
||||
|
||||
if (!reg)
|
||||
continue;
|
||||
|
||||
while (reg) {
|
||||
enum pm_device_node_idx node_idx;
|
||||
uint32_t idx, ret, irq, lowest_set = reg & (-reg);
|
||||
|
||||
idx = __builtin_ctz(lowest_set);
|
||||
irq = base_irq + idx;
|
||||
|
||||
if (irq > IRQ_MAX)
|
||||
break;
|
||||
|
||||
node_idx = irq_to_pm_node_idx(irq);
|
||||
reg &= ~lowest_set;
|
||||
|
||||
if ((node_idx != XPM_NODEIDX_DEV_MIN) &&
|
||||
(!pm_wakeup_nodes_set[node_idx])) {
|
||||
/* Get device ID from node index */
|
||||
device_id = PERIPH_DEVID(node_idx);
|
||||
ret = pm_set_wakeup_source(XPM_DEVID_ACPU_0,
|
||||
device_id, 1);
|
||||
pm_wakeup_nodes_set[node_idx] = !ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pm_client_suspend() - Client-specific suspend actions
|
||||
*
|
||||
|
@ -55,6 +166,9 @@ void pm_client_suspend(const struct pm_proc *proc, unsigned int state)
|
|||
{
|
||||
bakery_lock_get(&pm_client_secure_lock);
|
||||
|
||||
if (state == PM_STATE_SUSPEND_TO_RAM)
|
||||
pm_client_set_wakeup_sources();
|
||||
|
||||
/* Set powerdown request */
|
||||
mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) |
|
||||
proc->pwrdn_mask);
|
||||
|
|
|
@ -29,6 +29,10 @@
|
|||
#define XPM_DEVID_ACPU_0 APU_DEVID(XPM_NODEIDX_DEV_ACPU_0)
|
||||
#define XPM_DEVID_ACPU_1 APU_DEVID(XPM_NODEIDX_DEV_ACPU_1)
|
||||
|
||||
#define PERIPH_DEVID(IDX) NODEID(XPM_NODECLASS_DEVICE, \
|
||||
XPM_NODESUBCL_DEV_PERIPH, \
|
||||
XPM_NODETYPE_DEV_PERIPH, (IDX))
|
||||
|
||||
/* PM API ids */
|
||||
#define PM_GET_API_VERSION 1U
|
||||
#define PM_GET_DEVICE_STATUS 3U
|
||||
|
|
Loading…
Reference in New Issue