/*
 * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

/*
 * APU specific definition of processors in the subsystem as well as functions
 * 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"
#include "pm_defs.h"

#define UNDEFINED_CPUID		(~0)
#define IRQ_MAX		142U
#define NUM_GICD_ISENABLER	((IRQ_MAX >> 5U) + 1U)

DEFINE_BAKERY_LOCK(pm_client_secure_lock);

static const struct pm_ipi apu_ipi = {
	.local_ipi_id = IPI_ID_APU,
	.remote_ipi_id = IPI_ID_PMC,
	.buffer_base = IPI_BUFFER_APU_BASE,
};

/* Order in pm_procs_all array must match cpu ids */
static const struct pm_proc pm_procs_all[] = {
	{
		.node_id = XPM_DEVID_ACPU_0,
		.ipi = &apu_ipi,
		.pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK,
	},
	{
		.node_id = XPM_DEVID_ACPU_1,
		.ipi = &apu_ipi,
		.pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK,
	}
};

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.
 * @node_id:	Node id of processor
 */
static void pm_client_set_wakeup_sources(uint32_t node_id)
{
	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, (u_register_t)sizeof(pm_wakeup_nodes_set));

	for (reg_num = 0U; 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 == 0U) {
			continue;
		}

		while (reg != 0U) {
			enum pm_device_node_idx node_idx;
			uint32_t idx, irq, lowest_set = reg & (-reg);
			enum pm_ret_status ret;

			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 && node_idx < XPM_NODEIDX_DEV_MAX) {
				if (pm_wakeup_nodes_set[node_idx] == 0U) {
					/* Get device ID from node index */
					device_id = PERIPH_DEVID(node_idx);
					ret = pm_set_wakeup_source(node_id,
								   device_id, 1,
								   SECURE_FLAG);
					pm_wakeup_nodes_set[node_idx] = (ret == PM_RET_SUCCESS) ?
											 1 : 0;
				}
			}
		}
	}
}

/**
 * pm_client_suspend() - Client-specific suspend actions
 *
 * This function should contain any PU-specific actions
 * required prior to sending suspend request to PMU
 * Actions taken depend on the state system is suspending to.
 */
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((uint32_t)proc->node_id);
	}

	/* Set powerdown request */
	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) |
		      (uint32_t)proc->pwrdn_mask);

	bakery_lock_release(&pm_client_secure_lock);
}

/**
 * pm_client_abort_suspend() - Client-specific abort-suspend actions
 *
 * This function should contain any PU-specific actions
 * required for aborting a prior suspend request
 */
void pm_client_abort_suspend(void)
{
	/* Enable interrupts at processor level (for current cpu) */
	gicv3_cpuif_enable(plat_my_core_pos());

	bakery_lock_get(&pm_client_secure_lock);

	/* Clear powerdown request */
	mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) &
		      ~((uint32_t)primary_proc->pwrdn_mask));

	bakery_lock_release(&pm_client_secure_lock);
}

/**
 * pm_get_cpuid() - get the local cpu ID for a global node ID
 * @nid:	node id of the processor
 *
 * Return: the cpu ID (starting from 0) for the subsystem
 */
static unsigned int pm_get_cpuid(uint32_t nid)
{
	for (size_t i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) {
		if (pm_procs_all[i].node_id == nid) {
			return i;
		}
	}
	return UNDEFINED_CPUID;
}

/**
 * pm_client_wakeup() - Client-specific wakeup actions
 *
 * This function should contain any PU-specific actions
 * required for waking up another APU core
 */
void pm_client_wakeup(const struct pm_proc *proc)
{
	unsigned int cpuid = pm_get_cpuid(proc->node_id);

	if (cpuid == UNDEFINED_CPUID) {
		return;
	}

	bakery_lock_get(&pm_client_secure_lock);

	/* clear powerdown bit for affected cpu */
	uint32_t val = mmio_read_32(FPD_APU_PWRCTL);
	val &= ~(proc->pwrdn_mask);
	mmio_write_32(FPD_APU_PWRCTL, val);

	bakery_lock_release(&pm_client_secure_lock);
}

/**
 * pm_get_proc() - returns pointer to the proc structure
 * @cpuid:	id of the cpu whose proc struct pointer should be returned
 *
 * Return: pointer to a proc structure if proc is found, otherwise NULL
 */
const struct pm_proc *pm_get_proc(unsigned int cpuid)
{
	if (cpuid < ARRAY_SIZE(pm_procs_all)) {
		return &pm_procs_all[cpuid];
	}

	return NULL;
}
