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

/*
 * GIC-600 driver extension for multichip setup
 */

#include <assert.h>

#include <common/debug.h>
#include <drivers/arm/arm_gicv3_common.h>
#include <drivers/arm/gic600_multichip.h>
#include <drivers/arm/gicv3.h>

#include "../common/gic_common_private.h"
#include "gic600_multichip_private.h"

/*******************************************************************************
 * GIC-600 multichip operation related helper functions
 ******************************************************************************/
static void gicd_dchipr_wait_for_power_update_progress(uintptr_t base)
{
	unsigned int retry = GICD_PUP_UPDATE_RETRIES;

	while ((read_gicd_dchipr(base) & GICD_DCHIPR_PUP_BIT) != 0U) {
		if (retry-- == 0) {
			ERROR("GIC-600 connection to Routing Table Owner timed "
					 "out\n");
			panic();
		}
	}
}

/*******************************************************************************
 * Sets up the routing table owner.
 ******************************************************************************/
static void set_gicd_dchipr_rt_owner(uintptr_t base, unsigned int rt_owner)
{
	/*
	 * Ensure that Group enables in GICD_CTLR are disabled and no pending
	 * register writes to GICD_CTLR.
	 */
	if ((gicd_read_ctlr(base) &
			(CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
			 CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
		ERROR("GICD_CTLR group interrupts are either enabled or have "
				"pending writes. Cannot set RT owner.\n");
		panic();
	}

	/* Poll till PUP is zero before intiating write */
	gicd_dchipr_wait_for_power_update_progress(base);

	write_gicd_dchipr(base, read_gicd_dchipr(base) |
			(rt_owner << GICD_DCHIPR_RT_OWNER_SHIFT));

	/* Poll till PUP is zero to ensure write is complete */
	gicd_dchipr_wait_for_power_update_progress(base);
}

/*******************************************************************************
 * Configures the Chip Register to make connections to GICDs on
 * a multichip platform.
 ******************************************************************************/
static void set_gicd_chipr_n(uintptr_t base,
				unsigned int chip_id,
				uint64_t chip_addr,
				unsigned int spi_id_min,
				unsigned int spi_id_max)
{
	unsigned int spi_block_min, spi_blocks;
	unsigned int gicd_iidr_val = gicd_read_iidr(base);
	uint64_t chipr_n_val;

	/*
	 * Ensure that group enables in GICD_CTLR are disabled and no pending
	 * register writes to GICD_CTLR.
	 */
	if ((gicd_read_ctlr(base) &
			(CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
			 CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
		ERROR("GICD_CTLR group interrupts are either enabled or have "
				"pending writes. Cannot set CHIPR register.\n");
		panic();
	}

	/*
	 * spi_id_min and spi_id_max of value 0 is used to intidicate that the
	 * chip doesn't own any SPI block. Re-assign min and max values as SPI
	 * id starts from 32.
	 */
	if (spi_id_min == 0 && spi_id_max == 0) {
		spi_id_min = GIC600_SPI_ID_MIN;
		spi_id_max = GIC600_SPI_ID_MIN;
	}

	spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min);
	spi_blocks    = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max);

	switch ((gicd_iidr_val & IIDR_MODEL_MASK)) {
	case IIDR_MODEL_ARM_GIC_600:
		chipr_n_val = GICD_CHIPR_VALUE_GIC_600(chip_addr,
						       spi_block_min,
						       spi_blocks);
		break;
	case IIDR_MODEL_ARM_GIC_700:
		chipr_n_val = GICD_CHIPR_VALUE_GIC_700(chip_addr,
						       spi_block_min,
						       spi_blocks);
		break;
	default:
		ERROR("Unsupported GIC model 0x%x for multichip setup.\n",
		      gicd_iidr_val);
		panic();
		break;
	}
	chipr_n_val |= GICD_CHIPRx_SOCKET_STATE;

	/*
	 * Wait for DCHIPR.PUP to be zero before commencing writes to
	 * GICD_CHIPRx.
	 */
	gicd_dchipr_wait_for_power_update_progress(base);

	/*
	 * Assign chip addr, spi min block, number of spi blocks and bring chip
	 * online by setting SocketState.
	 */
	write_gicd_chipr_n(base, chip_id, chipr_n_val);

	/*
	 * Poll until DCHIP.PUP is zero to verify connection to rt_owner chip
	 * is complete.
	 */
	gicd_dchipr_wait_for_power_update_progress(base);

	/*
	 * Ensure that write to GICD_CHIPRx is successful and the chip_n came
	 * online.
	 */
	if (read_gicd_chipr_n(base, chip_id) != chipr_n_val) {
		ERROR("GICD_CHIPR%u write failed\n", chip_id);
		panic();
	}

	/* Ensure that chip is in consistent state */
	if (((read_gicd_chipsr(base) & GICD_CHIPSR_RTS_MASK) >>
				GICD_CHIPSR_RTS_SHIFT) !=
			GICD_CHIPSR_RTS_STATE_CONSISTENT) {
		ERROR("Chip %u routing table is not in consistent state\n",
				chip_id);
		panic();
	}
}

/*******************************************************************************
 * Validates the GIC-600 Multichip data structure passed by the platform.
 ******************************************************************************/
static void gic600_multichip_validate_data(
		struct gic600_multichip_data *multichip_data)
{
	unsigned int i, spi_id_min, spi_id_max, blocks_of_32;
	unsigned int multichip_spi_blocks = 0;

	assert(multichip_data != NULL);

	if (multichip_data->chip_count > GIC600_MAX_MULTICHIP) {
		ERROR("GIC-600 Multichip count should not exceed %d\n",
				GIC600_MAX_MULTICHIP);
		panic();
	}

	for (i = 0; i < multichip_data->chip_count; i++) {
		spi_id_min = multichip_data->spi_ids[i][SPI_MIN_INDEX];
		spi_id_max = multichip_data->spi_ids[i][SPI_MAX_INDEX];

		if ((spi_id_min != 0) || (spi_id_max != 0)) {

			/* SPI IDs range check */
			if (!(spi_id_min >= GIC600_SPI_ID_MIN) ||
			    !(spi_id_max < GIC600_SPI_ID_MAX) ||
			    !(spi_id_min <= spi_id_max) ||
			    !((spi_id_max - spi_id_min + 1) % 32 == 0)) {
				ERROR("Invalid SPI IDs {%u, %u} passed for "
						"Chip %u\n", spi_id_min,
						spi_id_max, i);
				panic();
			}

			/* SPI IDs overlap check */
			blocks_of_32 = BLOCKS_OF_32(spi_id_min, spi_id_max);
			if ((multichip_spi_blocks & blocks_of_32) != 0) {
				ERROR("SPI IDs of Chip %u overlapping\n", i);
				panic();
			}
			multichip_spi_blocks |= blocks_of_32;
		}
	}
}

/*******************************************************************************
 * Intialize GIC-600 Multichip operation.
 ******************************************************************************/
void gic600_multichip_init(struct gic600_multichip_data *multichip_data)
{
	unsigned int i;

	gic600_multichip_validate_data(multichip_data);

	/*
	 * Ensure that G0/G1S/G1NS interrupts are disabled. This also ensures
	 * that GIC-600 Multichip configuration is done first.
	 */
	if ((gicd_read_ctlr(multichip_data->rt_owner_base) &
			(CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
			 CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
		ERROR("GICD_CTLR group interrupts are either enabled or have "
				"pending writes.\n");
		panic();
	}

	/* Ensure that the routing table owner is in disconnected state */
	if (((read_gicd_chipsr(multichip_data->rt_owner_base) &
		GICD_CHIPSR_RTS_MASK) >> GICD_CHIPSR_RTS_SHIFT) !=
			GICD_CHIPSR_RTS_STATE_DISCONNECTED) {
		ERROR("GIC-600 routing table owner is not in disconnected "
				"state to begin multichip configuration\n");
		panic();
	}

	/* Initialize the GICD which is marked as routing table owner first */
	set_gicd_dchipr_rt_owner(multichip_data->rt_owner_base,
			multichip_data->rt_owner);

	set_gicd_chipr_n(multichip_data->rt_owner_base, multichip_data->rt_owner,
			multichip_data->chip_addrs[multichip_data->rt_owner],
			multichip_data->
			spi_ids[multichip_data->rt_owner][SPI_MIN_INDEX],
			multichip_data->
			spi_ids[multichip_data->rt_owner][SPI_MAX_INDEX]);

	for (i = 0; i < multichip_data->chip_count; i++) {
		if (i == multichip_data->rt_owner)
			continue;

		set_gicd_chipr_n(multichip_data->rt_owner_base, i,
				multichip_data->chip_addrs[i],
				multichip_data->spi_ids[i][SPI_MIN_INDEX],
				multichip_data->spi_ids[i][SPI_MAX_INDEX]);
	}
}
