/*
 * Copyright (C) 2018 Marvell International Ltd.
 *
 * SPDX-License-Identifier:     BSD-3-Clause
 * https://spdx.org/licenses
 */

/* CCU unit device driver for Marvell AP807, AP807 and AP810 SoCs */

#include <common/debug.h>
#include <drivers/marvell/ccu.h>
#include <lib/mmio.h>

#include <armada_common.h>
#include <mvebu.h>
#include <mvebu_def.h>

#if LOG_LEVEL >= LOG_LEVEL_INFO
#define DEBUG_ADDR_MAP
#endif

/* common defines */
#define WIN_ENABLE_BIT			(0x1)
/* Physical address of the base of the window = {AddrLow[19:0],20'h0} */
#define ADDRESS_SHIFT			(20 - 4)
#define ADDRESS_MASK			(0xFFFFFFF0)
#define CCU_WIN_ALIGNMENT		(0x100000)

/*
 * Physical address of the highest address of window bits[31:19] = 0x6FF
 * Physical address of the lowest address of window bits[18:6] = 0x6E0
 * Unit Id bits [5:2] = 2
 * RGF Window Enable bit[0] = 1
 * 0x37f9b809 - 11011111111 0011011100000 0010 0 1
 */
#define ERRATA_WA_CCU_WIN4	0x37f9b809U

/*
 * Physical address of the highest address of window bits[31:19] = 0xFFF
 * Physical address of the lowest address of window bits[18:6] = 0x800
 * Unit Id bits [5:2] = 2
 * RGF Window Enable bit[0] = 1
 * 0x7ffa0009 - 111111111111 0100000000000 0010 0 1
 */
#define ERRATA_WA_CCU_WIN5	0x7ffa0009U

/*
 * Physical address of the highest address of window bits[31:19] = 0x1FFF
 * Physical address of the lowest address of window bits[18:6] = 0x1000
 * Unit Id bits [5:2] = 2
 * RGF Window Enable bit[0] = 1
 * 0xfffc000d - 1111111111111 1000000000000 0011 0 1
 */
#define ERRATA_WA_CCU_WIN6	0xfffc000dU

#define IS_DRAM_TARGET(tgt)		((((tgt) == DRAM_0_TID) || \
					((tgt) == DRAM_1_TID) || \
					((tgt) == RAR_TID)) ? 1 : 0)

#define CCU_RGF(win)			(MVEBU_CCU_BASE(MVEBU_AP0) + \
					 0x90 + 4 * (win))

/* For storage of CR, SCR, ALR, AHR abd GCR */
static uint32_t ccu_regs_save[MVEBU_CCU_MAX_WINS * 4 + 1];

#ifdef DEBUG_ADDR_MAP
static void dump_ccu(int ap_index)
{
	uint32_t win_id, win_cr, alr, ahr;
	uint8_t target_id;
	uint64_t start, end;

	/* Dump all AP windows */
	printf("\tbank  target     start              end\n");
	printf("\t----------------------------------------------------\n");
	for (win_id = 0; win_id < MVEBU_CCU_MAX_WINS; win_id++) {
		win_cr = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id));
		if (win_cr & WIN_ENABLE_BIT) {
			target_id = (win_cr >> CCU_TARGET_ID_OFFSET) &
				     CCU_TARGET_ID_MASK;
			alr = mmio_read_32(CCU_WIN_ALR_OFFSET(ap_index,
							      win_id));
			ahr = mmio_read_32(CCU_WIN_AHR_OFFSET(ap_index,
							      win_id));
			start = ((uint64_t)alr << ADDRESS_SHIFT);
			end = (((uint64_t)ahr + 0x10) << ADDRESS_SHIFT);
			printf("\tccu%d    %02x     0x%016llx 0x%016llx\n",
			       win_id, target_id, start, end);
		}
	}
	win_cr = mmio_read_32(CCU_WIN_GCR_OFFSET(ap_index));
	target_id = (win_cr >> CCU_GCR_TARGET_OFFSET) & CCU_GCR_TARGET_MASK;
	printf("\tccu   GCR %d - all other transactions\n", target_id);
}
#endif

void ccu_win_check(struct addr_map_win *win)
{
	/* check if address is aligned to 1M */
	if (IS_NOT_ALIGN(win->base_addr, CCU_WIN_ALIGNMENT)) {
		win->base_addr = ALIGN_UP(win->base_addr, CCU_WIN_ALIGNMENT);
		NOTICE("%s: Align up the base address to 0x%llx\n",
		       __func__, win->base_addr);
	}

	/* size parameter validity check */
	if (IS_NOT_ALIGN(win->win_size, CCU_WIN_ALIGNMENT)) {
		win->win_size = ALIGN_UP(win->win_size, CCU_WIN_ALIGNMENT);
		NOTICE("%s: Aligning size to 0x%llx\n",
		       __func__, win->win_size);
	}
}

int ccu_is_win_enabled(int ap_index, uint32_t win_id)
{
	return mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)) &
			    WIN_ENABLE_BIT;
}

void ccu_enable_win(int ap_index, struct addr_map_win *win, uint32_t win_id)
{
	uint32_t ccu_win_reg;
	uint32_t alr, ahr;
	uint64_t end_addr;

	if ((win_id == 0) || (win_id > MVEBU_CCU_MAX_WINS)) {
		ERROR("Enabling wrong CCU window %d!\n", win_id);
		return;
	}

	end_addr = (win->base_addr + win->win_size - 1);
	alr = (uint32_t)((win->base_addr >> ADDRESS_SHIFT) & ADDRESS_MASK);
	ahr = (uint32_t)((end_addr >> ADDRESS_SHIFT) & ADDRESS_MASK);

	mmio_write_32(CCU_WIN_ALR_OFFSET(ap_index, win_id), alr);
	mmio_write_32(CCU_WIN_AHR_OFFSET(ap_index, win_id), ahr);

	ccu_win_reg = WIN_ENABLE_BIT;
	ccu_win_reg |= (win->target_id & CCU_TARGET_ID_MASK)
			<< CCU_TARGET_ID_OFFSET;
	mmio_write_32(CCU_WIN_CR_OFFSET(ap_index, win_id), ccu_win_reg);
}

static void ccu_disable_win(int ap_index, uint32_t win_id)
{
	uint32_t win_reg;

	if ((win_id == 0) || (win_id > MVEBU_CCU_MAX_WINS)) {
		ERROR("Disabling wrong CCU window %d!\n", win_id);
		return;
	}

	win_reg = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id));
	win_reg &= ~WIN_ENABLE_BIT;
	mmio_write_32(CCU_WIN_CR_OFFSET(ap_index, win_id), win_reg);
}

/* Insert/Remove temporary window for using the out-of reset default
 * CPx base address to access the CP configuration space prior to
 * the further base address update in accordance with address mapping
 * design.
 *
 * NOTE: Use the same window array for insertion and removal of
 *       temporary windows.
 */
void ccu_temp_win_insert(int ap_index, struct addr_map_win *win, int size)
{
	uint32_t win_id;

	for (int i = 0; i < size; i++) {
		win_id = MVEBU_CCU_MAX_WINS - 1 - i;
		ccu_win_check(win);
		ccu_enable_win(ap_index, win, win_id);
		win++;
	}
}

/*
 * NOTE: Use the same window array for insertion and removal of
 *       temporary windows.
 */
void ccu_temp_win_remove(int ap_index, struct addr_map_win *win, int size)
{
	uint32_t win_id;

	for (int i = 0; i < size; i++) {
		uint64_t base;
		uint32_t target;

		win_id = MVEBU_CCU_MAX_WINS - 1 - i;

		target = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id));
		target >>= CCU_TARGET_ID_OFFSET;
		target &= CCU_TARGET_ID_MASK;

		base = mmio_read_32(CCU_WIN_ALR_OFFSET(ap_index, win_id));
		base <<= ADDRESS_SHIFT;

		if ((win->target_id != target) || (win->base_addr != base)) {
			ERROR("%s: Trying to remove bad window-%d!\n",
			      __func__, win_id);
			continue;
		}
		ccu_disable_win(ap_index, win_id);
		win++;
	}
}

/* Returns current DRAM window target (DRAM_0_TID, DRAM_1_TID, RAR_TID)
 * NOTE: Call only once for each AP.
 * The AP0 DRAM window is located at index 2 only at the BL31 execution start.
 * Then it relocated to index 1 for matching the rest of APs DRAM settings.
 * Calling this function after relocation will produce wrong results on AP0
 */
static uint32_t ccu_dram_target_get(int ap_index)
{
	/* On BLE stage the AP0 DRAM window is opened by the BootROM at index 2.
	 * All the rest of detected APs will use window at index 1.
	 * The AP0 DRAM window is moved from index 2 to 1 during
	 * init_ccu() execution.
	 */
	const uint32_t win_id = (ap_index == 0) ? 2 : 1;
	uint32_t target;

	target = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id));
	target >>= CCU_TARGET_ID_OFFSET;
	target &= CCU_TARGET_ID_MASK;

	return target;
}

void ccu_dram_target_set(int ap_index, uint32_t target)
{
	/* On BLE stage the AP0 DRAM window is opened by the BootROM at index 2.
	 * All the rest of detected APs will use window at index 1.
	 * The AP0 DRAM window is moved from index 2 to 1
	 * during init_ccu() execution.
	 */
	const uint32_t win_id = (ap_index == 0) ? 2 : 1;
	uint32_t dram_cr;

	dram_cr = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id));
	dram_cr &= ~(CCU_TARGET_ID_MASK << CCU_TARGET_ID_OFFSET);
	dram_cr |= (target & CCU_TARGET_ID_MASK) << CCU_TARGET_ID_OFFSET;
	mmio_write_32(CCU_WIN_CR_OFFSET(ap_index, win_id), dram_cr);
}

/* Setup CCU DRAM window and enable it */
void ccu_dram_win_config(int ap_index, struct addr_map_win *win)
{
#if IMAGE_BLE /* BLE */
	/* On BLE stage the AP0 DRAM window is opened by the BootROM at index 2.
	 * Since the BootROM is not accessing DRAM at BLE stage,
	 * the DRAM window can be temporarely disabled.
	 */
	const uint32_t win_id = (ap_index == 0) ? 2 : 1;
#else /* end of BLE */
	/* At the ccu_init() execution stage, DRAM windows of all APs
	 * are arranged at index 1.
	 * The AP0 still has the old window BootROM DRAM at index 2, so
	 * the window-1 can be safely disabled without breaking the DRAM access.
	 */
	const uint32_t win_id = 1;
#endif

	ccu_disable_win(ap_index, win_id);
	/* enable write secure (and clear read secure) */
	mmio_write_32(CCU_WIN_SCR_OFFSET(ap_index, win_id),
		      CCU_WIN_ENA_WRITE_SECURE);
	ccu_win_check(win);
	ccu_enable_win(ap_index, win, win_id);
}

/* Save content of CCU window + GCR */
static void ccu_save_win_range(int ap_id, int win_first,
			       int win_last, uint32_t *buffer)
{
	int win_id, idx;
	/* Save CCU */
	for (idx = 0, win_id = win_first; win_id <= win_last; win_id++) {
		buffer[idx++] = mmio_read_32(CCU_WIN_CR_OFFSET(ap_id, win_id));
		buffer[idx++] = mmio_read_32(CCU_WIN_SCR_OFFSET(ap_id, win_id));
		buffer[idx++] = mmio_read_32(CCU_WIN_ALR_OFFSET(ap_id, win_id));
		buffer[idx++] = mmio_read_32(CCU_WIN_AHR_OFFSET(ap_id, win_id));
	}
	buffer[idx] = mmio_read_32(CCU_WIN_GCR_OFFSET(ap_id));
}

/* Restore content of CCU window + GCR */
static void ccu_restore_win_range(int ap_id, int win_first,
				  int win_last, uint32_t *buffer)
{
	int win_id, idx;
	/* Restore CCU */
	for (idx = 0, win_id = win_first; win_id <= win_last; win_id++) {
		mmio_write_32(CCU_WIN_CR_OFFSET(ap_id, win_id),  buffer[idx++]);
		mmio_write_32(CCU_WIN_SCR_OFFSET(ap_id, win_id), buffer[idx++]);
		mmio_write_32(CCU_WIN_ALR_OFFSET(ap_id, win_id), buffer[idx++]);
		mmio_write_32(CCU_WIN_AHR_OFFSET(ap_id, win_id), buffer[idx++]);
	}
	mmio_write_32(CCU_WIN_GCR_OFFSET(ap_id), buffer[idx]);
}

void ccu_save_win_all(int ap_id)
{
	ccu_save_win_range(ap_id, 0, MVEBU_CCU_MAX_WINS - 1, ccu_regs_save);
}

void ccu_restore_win_all(int ap_id)
{
	ccu_restore_win_range(ap_id, 0, MVEBU_CCU_MAX_WINS - 1, ccu_regs_save);
}

int init_ccu(int ap_index)
{
	struct addr_map_win *win, *dram_win;
	uint32_t win_id, win_reg;
	uint32_t win_count, array_id;
	uint32_t dram_target;
#if IMAGE_BLE
	/* In BootROM context CCU Window-1
	 * has SRAM_TID target and should not be disabled
	 */
	const uint32_t win_start = 2;
#else
	const uint32_t win_start = 1;
#endif

	INFO("Initializing CCU Address decoding\n");

	/* Get the array of the windows and fill the map data */
	marvell_get_ccu_memory_map(ap_index, &win, &win_count);
	if (win_count <= 0) {
		INFO("No windows configurations found\n");
	} else if (win_count > (MVEBU_CCU_MAX_WINS - 1)) {
		ERROR("CCU mem map array > than max available windows (%d)\n",
		      MVEBU_CCU_MAX_WINS);
		win_count = MVEBU_CCU_MAX_WINS;
	}

	/* Need to set GCR to DRAM before all CCU windows are disabled for
	 * securing the normal access to DRAM location, which the ATF is running
	 * from. Once all CCU windows are set, which have to include the
	 * dedicated DRAM window as well, the GCR can be switched to the target
	 * defined by the platform configuration.
	 */
	dram_target = ccu_dram_target_get(ap_index);
	win_reg = (dram_target & CCU_GCR_TARGET_MASK) << CCU_GCR_TARGET_OFFSET;
	mmio_write_32(CCU_WIN_GCR_OFFSET(ap_index), win_reg);

	/* If the DRAM window was already configured at the BLE stage,
	 * only the window target considered valid, the address range should be
	 * updated according to the platform configuration.
	 */
	for (dram_win = win, array_id = 0; array_id < win_count;
	     array_id++, dram_win++) {
		if (IS_DRAM_TARGET(dram_win->target_id)) {
			dram_win->target_id = dram_target;
			break;
		}
	}

	/* Disable all AP CCU windows
	 * Window-0 is always bypassed since it already contains
	 * data allowing the internal configuration space access
	 */
	for (win_id = win_start; win_id < MVEBU_CCU_MAX_WINS; win_id++) {
		ccu_disable_win(ap_index, win_id);
		/* enable write secure (and clear read secure) */
		mmio_write_32(CCU_WIN_SCR_OFFSET(ap_index, win_id),
			      CCU_WIN_ENA_WRITE_SECURE);
	}

	/* win_id is the index of the current ccu window
	 * array_id is the index of the current memory map window entry
	 */
	for (win_id = win_start, array_id = 0;
	    ((win_id < MVEBU_CCU_MAX_WINS) && (array_id < win_count));
	    win_id++) {
		ccu_win_check(win);
		ccu_enable_win(ap_index, win, win_id);
		win++;
		array_id++;
	}

	/* Get & set the default target according to board topology */
	win_reg = (marvell_get_ccu_gcr_target(ap_index) & CCU_GCR_TARGET_MASK)
		   << CCU_GCR_TARGET_OFFSET;
	mmio_write_32(CCU_WIN_GCR_OFFSET(ap_index), win_reg);

#ifdef DEBUG_ADDR_MAP
	dump_ccu(ap_index);
#endif

	INFO("Done CCU Address decoding Initializing\n");

	return 0;
}

void errata_wa_init(void)
{
	/*
	 * EERATA ID: RES-3033912 - Internal Address Space Init state causes
	 * a hang upon accesses to [0xf070_0000, 0xf07f_ffff]
	 * Workaround: Boot Firmware (ATF) should configure CCU_RGF_WIN(4) to
	 * split [0x6e_0000, 0x1ff_ffff] to values [0x6e_0000, 0x6f_ffff] and
	 * [0x80_0000, 0xff_ffff] and [0x100_0000, 0x1ff_ffff],that cause
	 * accesses to the segment of [0xf070_0000, 0xf1ff_ffff]
	 * to act as RAZWI.
	 */
	mmio_write_32(CCU_RGF(4), ERRATA_WA_CCU_WIN4);
	mmio_write_32(CCU_RGF(5), ERRATA_WA_CCU_WIN5);
	mmio_write_32(CCU_RGF(6), ERRATA_WA_CCU_WIN6);
}
