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

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

#include <inttypes.h>
#include <stdint.h>

#include <common/debug.h>
#include <drivers/marvell/io_win.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 = {Addr[19:0],20`h0} */
#define ADDRESS_SHIFT			(20 - 4)
#define ADDRESS_MASK			(0xFFFFFFF0)
#define IO_WIN_ALIGNMENT_1M		(0x100000)
#define IO_WIN_ALIGNMENT_64K		(0x10000)

/* AP registers */
#define IO_WIN_ALR_OFFSET(ap, win)	(MVEBU_IO_WIN_BASE(ap) + 0x0 + \
						(0x10 * win))
#define IO_WIN_AHR_OFFSET(ap, win)	(MVEBU_IO_WIN_BASE(ap) + 0x8 + \
						(0x10 * win))
#define IO_WIN_CR_OFFSET(ap, win)	(MVEBU_IO_WIN_BASE(ap) + 0xC + \
						(0x10 * win))

/* For storage of CR, ALR, AHR abd GCR */
static uint32_t io_win_regs_save[MVEBU_IO_WIN_MAX_WINS * 3 + 1];

static void io_win_check(struct addr_map_win *win)
{
	/* for IO The base is always 1M aligned */
	/* check if address is aligned to 1M */
	if (IS_NOT_ALIGN(win->base_addr, IO_WIN_ALIGNMENT_1M)) {
		win->base_addr = ALIGN_UP(win->base_addr, IO_WIN_ALIGNMENT_1M);
		NOTICE("%s: Align up the base address to 0x%" PRIx64 "\n",
		       __func__, win->base_addr);
	}

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

static void io_win_enable_window(int ap_index, struct addr_map_win *win,
				 uint32_t win_num)
{
	uint32_t alr, ahr;
	uint64_t end_addr;

	if (win->target_id < 0 || win->target_id >= MVEBU_IO_WIN_MAX_WINS) {
		ERROR("target ID = %d, is invalid\n", win->target_id);
		return;
	}

	if ((win_num == 0) || (win_num > MVEBU_IO_WIN_MAX_WINS)) {
		ERROR("Enabling wrong IOW window %d!\n", win_num);
		return;
	}

	/* calculate the end-address */
	end_addr = (win->base_addr + win->win_size - 1);

	alr = (uint32_t)((win->base_addr >> ADDRESS_SHIFT) & ADDRESS_MASK);
	alr |= WIN_ENABLE_BIT;
	ahr = (uint32_t)((end_addr >> ADDRESS_SHIFT) & ADDRESS_MASK);

	/* write start address and end address for IO window */
	mmio_write_32(IO_WIN_ALR_OFFSET(ap_index, win_num), alr);
	mmio_write_32(IO_WIN_AHR_OFFSET(ap_index, win_num), ahr);

	/* write window target */
	mmio_write_32(IO_WIN_CR_OFFSET(ap_index, win_num), win->target_id);
}

static void io_win_disable_window(int ap_index, uint32_t win_num)
{
	uint32_t win_reg;

	if ((win_num == 0) || (win_num > MVEBU_IO_WIN_MAX_WINS)) {
		ERROR("Disabling wrong IOW window %d!\n", win_num);
		return;
	}

	win_reg = mmio_read_32(IO_WIN_ALR_OFFSET(ap_index, win_num));
	win_reg &= ~WIN_ENABLE_BIT;
	mmio_write_32(IO_WIN_ALR_OFFSET(ap_index, win_num), 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 iow_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_IO_WIN_MAX_WINS - i - 1;
		io_win_check(win);
		io_win_enable_window(ap_index, win, win_id);
		win++;
	}
}

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

	/* Start from the last window and do not touch Win0 */
	for (int i = 0; i < size; i++) {
		uint64_t base;
		uint32_t target;

		win_id = MVEBU_IO_WIN_MAX_WINS - i - 1;

		target = mmio_read_32(IO_WIN_CR_OFFSET(ap_index, win_id));
		base = mmio_read_32(IO_WIN_ALR_OFFSET(ap_index, win_id));
		base &= ~WIN_ENABLE_BIT;
		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;
		}
		io_win_disable_window(ap_index, win_id);
		win++;
	}
}

#ifdef DEBUG_ADDR_MAP
static void dump_io_win(int ap_index)
{
	uint32_t trgt_id, win_id;
	uint32_t alr, ahr;
	uint64_t start, end;

	/* Dump all IO windows */
	printf("\tbank  target     start              end\n");
	printf("\t----------------------------------------------------\n");
	for (win_id = 0; win_id < MVEBU_IO_WIN_MAX_WINS; win_id++) {
		alr = mmio_read_32(IO_WIN_ALR_OFFSET(ap_index, win_id));
		if (alr & WIN_ENABLE_BIT) {
			alr &= ~WIN_ENABLE_BIT;
			ahr = mmio_read_32(IO_WIN_AHR_OFFSET(ap_index, win_id));
			trgt_id = mmio_read_32(IO_WIN_CR_OFFSET(ap_index,
								win_id));
			start = ((uint64_t)alr << ADDRESS_SHIFT);
			end = (((uint64_t)ahr + 0x10) << ADDRESS_SHIFT);
			printf("\tio-win %d     0x%016" PRIx64 " 0x%016" PRIx64 "\n",
			       trgt_id, start, end);
		}
	}
	printf("\tio-win gcr is %x\n",
	       mmio_read_32(MVEBU_IO_WIN_BASE(ap_index) +
	       MVEBU_IO_WIN_GCR_OFFSET));
}
#endif

static void iow_save_win_range(int ap_id, int win_first, int win_last,
			       uint32_t *buffer)
{
	int win_id, idx;

	/* Save IOW */
	for (idx = 0, win_id = win_first; win_id <= win_last; win_id++) {
		buffer[idx++] = mmio_read_32(IO_WIN_CR_OFFSET(ap_id, win_id));
		buffer[idx++] = mmio_read_32(IO_WIN_ALR_OFFSET(ap_id, win_id));
		buffer[idx++] = mmio_read_32(IO_WIN_AHR_OFFSET(ap_id, win_id));
	}
	buffer[idx] = mmio_read_32(MVEBU_IO_WIN_BASE(ap_id) +
				   MVEBU_IO_WIN_GCR_OFFSET);
}

static void iow_restore_win_range(int ap_id, int win_first, int win_last,
				  uint32_t *buffer)
{
	int win_id, idx;

	/* Restore IOW */
	for (idx = 0, win_id = win_first; win_id <= win_last; win_id++) {
		mmio_write_32(IO_WIN_CR_OFFSET(ap_id, win_id), buffer[idx++]);
		mmio_write_32(IO_WIN_ALR_OFFSET(ap_id, win_id), buffer[idx++]);
		mmio_write_32(IO_WIN_AHR_OFFSET(ap_id, win_id), buffer[idx++]);
	}
	mmio_write_32(MVEBU_IO_WIN_BASE(ap_id) + MVEBU_IO_WIN_GCR_OFFSET,
		      buffer[idx++]);
}

void iow_save_win_all(int ap_id)
{
	iow_save_win_range(ap_id, 0, MVEBU_IO_WIN_MAX_WINS - 1,
			   io_win_regs_save);
}

void iow_restore_win_all(int ap_id)
{
	iow_restore_win_range(ap_id, 0, MVEBU_IO_WIN_MAX_WINS - 1,
			      io_win_regs_save);
}

int init_io_win(int ap_index)
{
	struct addr_map_win *win;
	uint32_t win_id, win_reg;
	uint32_t win_count;

	INFO("Initializing IO WIN Address decoding\n");

	/* Get the array of the windows and its size */
	marvell_get_io_win_memory_map(ap_index, &win, &win_count);
	if (win_count <= 0)
		INFO("no windows configurations found\n");

	if (win_count > MVEBU_IO_WIN_MAX_WINS) {
		INFO("number of windows is bigger than %d\n",
		     MVEBU_IO_WIN_MAX_WINS);
		return 0;
	}

	/* Get the default target id to set the GCR */
	win_reg = marvell_get_io_win_gcr_target(ap_index);
	mmio_write_32(MVEBU_IO_WIN_BASE(ap_index) + MVEBU_IO_WIN_GCR_OFFSET,
		      win_reg);

	/* disable all IO windows */
	for (win_id = 1; win_id < MVEBU_IO_WIN_MAX_WINS; win_id++)
		io_win_disable_window(ap_index, win_id);

	/* enable relevant windows, starting from win_id = 1 because
	 * index 0 dedicated for BootROM
	 */
	for (win_id = 1; win_id <= win_count; win_id++, win++) {
		io_win_check(win);
		io_win_enable_window(ap_index, win, win_id);
	}

#ifdef DEBUG_ADDR_MAP
	dump_io_win(ap_index);
#endif

	INFO("Done IO WIN Address decoding Initializing\n");

	return 0;
}
