/*
 * Copyright (c) 2019-2021, 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"

#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) &&
			    (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] = (uint8_t)(!ret);
			}
		}
	}
}

/**
 * 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;
}
