/*
 * Copyright (c) 2013-2018, ARM Limited and Contributors. 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 <string.h>

#include <common/bl_common.h>
#include <drivers/arm/gic_common.h>
#include <drivers/arm/gicv2.h>
#include <lib/bakery_lock.h>
#include <lib/mmio.h>
#include <lib/utils.h>

#include <plat_ipi.h>
#include <zynqmp_def.h>
#include "pm_api_sys.h"
#include "pm_client.h"
#include "pm_ipi.h"

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

#define PM_SUSPEND_MODE_STD		0U
#define PM_SUSPEND_MODE_POWER_OFF	1U

DEFINE_BAKERY_LOCK(pm_client_secure_lock);

extern const struct pm_ipi apu_ipi;

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

static uint32_t suspend_mode = PM_SUSPEND_MODE_STD;

/* Order in pm_procs_all array must match cpu ids */
static const struct pm_proc pm_procs_all[] = {
	{
		.node_id = NODE_APU_0,
		.pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK,
		.ipi = &apu_ipi,
	},
	{
		.node_id = NODE_APU_1,
		.pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK,
		.ipi = &apu_ipi,
	},
	{
		.node_id = NODE_APU_2,
		.pwrdn_mask = APU_2_PWRCTL_CPUPWRDWNREQ_MASK,
		.ipi = &apu_ipi,
	},
	{
		.node_id = NODE_APU_3,
		.pwrdn_mask = APU_3_PWRCTL_CPUPWRDWNREQ_MASK,
		.ipi = &apu_ipi,
	},
};

/* Interrupt to PM node ID map */
static enum pm_node_id irq_node_map[IRQ_MAX + 1U] = {
	NODE_UNKNOWN,
	NODE_UNKNOWN,
	NODE_UNKNOWN,
	NODE_UNKNOWN,	/* 3 */
	NODE_UNKNOWN,
	NODE_UNKNOWN,
	NODE_UNKNOWN,
	NODE_UNKNOWN,	/* 7 */
	NODE_UNKNOWN,
	NODE_UNKNOWN,
	NODE_UNKNOWN,
	NODE_UNKNOWN,	/* 11 */
	NODE_UNKNOWN,
	NODE_UNKNOWN,
	NODE_NAND,
	NODE_QSPI,	/* 15 */
	NODE_GPIO,
	NODE_I2C_0,
	NODE_I2C_1,
	NODE_SPI_0,	/* 19 */
	NODE_SPI_1,
	NODE_UART_0,
	NODE_UART_1,
	NODE_CAN_0,	/* 23 */
	NODE_CAN_1,
	NODE_UNKNOWN,
	NODE_RTC,
	NODE_RTC,	/* 27 */
	NODE_UNKNOWN,
	NODE_UNKNOWN,
	NODE_UNKNOWN,
	NODE_UNKNOWN,	/* 31 */
	NODE_UNKNOWN,
	NODE_UNKNOWN,
	NODE_UNKNOWN,
	NODE_UNKNOWN,	/* 35, NODE_IPI_APU */
	NODE_TTC_0,
	NODE_TTC_0,
	NODE_TTC_0,
	NODE_TTC_1,	/* 39 */
	NODE_TTC_1,
	NODE_TTC_1,
	NODE_TTC_2,
	NODE_TTC_2,	/* 43 */
	NODE_TTC_2,
	NODE_TTC_3,
	NODE_TTC_3,
	NODE_TTC_3,	/* 47 */
	NODE_SD_0,
	NODE_SD_1,
	NODE_SD_0,
	NODE_SD_1,	/* 51 */
	NODE_UNKNOWN,
	NODE_UNKNOWN,
	NODE_UNKNOWN,
	NODE_UNKNOWN,	/* 55 */
	NODE_UNKNOWN,
	NODE_ETH_0,
	NODE_ETH_0,
	NODE_ETH_1,	/* 59 */
	NODE_ETH_1,
	NODE_ETH_2,
	NODE_ETH_2,
	NODE_ETH_3,	/* 63 */
	NODE_ETH_3,
	NODE_USB_0,
	NODE_USB_0,
	NODE_USB_0,	/* 67 */
	NODE_USB_0,
	NODE_USB_0,
	NODE_USB_1,
	NODE_USB_1,	/* 71 */
	NODE_USB_1,
	NODE_USB_1,
	NODE_USB_1,
	NODE_USB_0,	/* 75 */
	NODE_USB_0,
	NODE_ADMA,
	NODE_ADMA,
	NODE_ADMA,	/* 79 */
	NODE_ADMA,
	NODE_ADMA,
	NODE_ADMA,
	NODE_ADMA,	/* 83 */
	NODE_ADMA,
};

/**
 * irq_to_pm_node - Get PM node ID corresponding to the interrupt number
 * @irq:	Interrupt number
 *
 * Return:	PM node ID corresponding to the specified interrupt
 */
static enum pm_node_id irq_to_pm_node(uint32_t irq)
{
	assert(irq <= IRQ_MAX);
	return irq_node_map[irq];
}

/**
 * pm_client_set_wakeup_sources - Set all slaves with enabled interrupts as wake
 *				sources in the PMU firmware
 */
static void pm_client_set_wakeup_sources(void)
{
	uint32_t reg_num;
	uint8_t pm_wakeup_nodes_set[NODE_MAX] = { 0 };
	uintptr_t isenabler1 = BASE_GICD_BASE + GICD_ISENABLER + 4U;

	/* In case of power-off suspend, only NODE_EXTERN must be set */
	if (suspend_mode == PM_SUSPEND_MODE_POWER_OFF) {
		enum pm_ret_status ret;

		ret = pm_set_wakeup_source(NODE_APU, NODE_EXTERN, 1U);
		/**
		 * If NODE_EXTERN could not be set as wake source, proceed with
		 * standard suspend (no one will wake the system otherwise)
		 */
		if (ret == PM_RET_SUCCESS) {
			return;
		}
	}

	zeromem(&pm_wakeup_nodes_set, 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 << 2U));

		if (reg == 0) {
			continue;
		}

		while (reg) {
			enum pm_node_id node;
			uint32_t idx, ret, irq, lowest_set = reg & (-reg);

			idx = __builtin_ctz(lowest_set);
			irq = base_irq + idx;

			if (irq > IRQ_MAX) {
				break;
			}

			node = irq_to_pm_node(irq);
			reg &= ~lowest_set;

			if (node > NODE_UNKNOWN && node < NODE_MAX) {
				if (pm_wakeup_nodes_set[node] == 0U) {
					ret = pm_set_wakeup_source(NODE_APU, node, 1U);
					pm_wakeup_nodes_set[node] = (ret == PM_RET_SUCCESS) ? 1U : 0U;
				}
			}
		}
	}
}

/**
 * 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(uint32_t cpuid)
{
	if (cpuid < ARRAY_SIZE(pm_procs_all)) {
		return &pm_procs_all[cpuid];
	}

	return NULL;
}

/**
 * pm_get_proc_by_node() - returns pointer to the proc structure
 * @nid:	node id of the processor
 *
 * Return: pointer to a proc structure if proc is found, otherwise NULL
 */
const struct pm_proc *pm_get_proc_by_node(enum pm_node_id nid)
{
	for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) {
		if (nid == pm_procs_all[i].node_id) {
			return &pm_procs_all[i];
		}
	}
	return NULL;
}

/**
 * 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 uint32_t pm_get_cpuid(enum pm_node_id nid)
{
	for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) {
		if (pm_procs_all[i].node_id == nid) {
			return i;
		}
	}
	return UNDEFINED_CPUID;
}

const struct pm_proc *primary_proc = &pm_procs_all[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, uint32_t 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(APU_PWRCTL, mmio_read_32(APU_PWRCTL) | 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) */
	gicv2_cpuif_enable();

	bakery_lock_get(&pm_client_secure_lock);

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

	bakery_lock_release(&pm_client_secure_lock);
}

/**
 * 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)
{
	uint32_t 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(APU_PWRCTL);
	val &= ~(proc->pwrdn_mask);
	mmio_write_32(APU_PWRCTL, val);

	bakery_lock_release(&pm_client_secure_lock);
}

enum pm_ret_status pm_set_suspend_mode(uint32_t mode)
{
	if ((mode != PM_SUSPEND_MODE_STD) &&
	    (mode != PM_SUSPEND_MODE_POWER_OFF)) {
		return PM_RET_ERROR_ARGS;
	}

	suspend_mode = mode;
	return PM_RET_SUCCESS;
}
