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

/* GWIN unit device driver for Marvell AP810 SoC */

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

#include <common/debug.h>
#include <drivers/marvell/gwin.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)
#define WIN_TARGET_MASK			(0xF)
#define WIN_TARGET_SHIFT		(0x8)
#define WIN_TARGET(tgt)			(((tgt) & WIN_TARGET_MASK) \
					<< WIN_TARGET_SHIFT)

/* Bits[43:26] of the physical address are the window base,
 * which is aligned to 64MB
 */
#define ADDRESS_RSHIFT			(26)
#define ADDRESS_LSHIFT			(10)
#define GWIN_ALIGNMENT_64M		(0x4000000)

/* AP registers */
#define GWIN_CR_OFFSET(ap, win)		(MVEBU_GWIN_BASE(ap) + 0x0 + \
						(0x10 * (win)))
#define GWIN_ALR_OFFSET(ap, win)	(MVEBU_GWIN_BASE(ap) + 0x8 + \
						(0x10 * (win)))
#define GWIN_AHR_OFFSET(ap, win)	(MVEBU_GWIN_BASE(ap) + 0xc + \
						(0x10 * (win)))

#define CCU_GRU_CR_OFFSET(ap)		(MVEBU_CCU_GRU_BASE(ap))
#define CCR_GRU_CR_GWIN_MBYPASS		(1 << 1)

static void gwin_check(struct addr_map_win *win)
{
	/* The base is always 64M aligned */
	if (IS_NOT_ALIGN(win->base_addr, GWIN_ALIGNMENT_64M)) {
		win->base_addr &= ~(GWIN_ALIGNMENT_64M - 1);
		NOTICE("%s: Align the base address to 0x%" PRIx64 "\n",
		       __func__, win->base_addr);
	}

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

static void gwin_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 & WIN_TARGET_MASK) != win->target_id) {
		ERROR("target ID = %d, is invalid\n", win->target_id);
		return;
	}

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

	alr = (uint32_t)((win->base_addr >> ADDRESS_RSHIFT) << ADDRESS_LSHIFT);
	ahr = (uint32_t)((end_addr >> ADDRESS_RSHIFT) << ADDRESS_LSHIFT);

	/* write start address and end address for GWIN */
	mmio_write_32(GWIN_ALR_OFFSET(ap_index, win_num), alr);
	mmio_write_32(GWIN_AHR_OFFSET(ap_index, win_num), ahr);

	/* write the target ID and enable the window */
	mmio_write_32(GWIN_CR_OFFSET(ap_index, win_num),
		      WIN_TARGET(win->target_id) | WIN_ENABLE_BIT);
}

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

	win_reg = mmio_read_32(GWIN_CR_OFFSET(ap_index, win_num));
	win_reg &= ~WIN_ENABLE_BIT;
	mmio_write_32(GWIN_CR_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 gwin_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_GWIN_MAX_WINS - i - 1;
		gwin_check(win);
		gwin_enable_window(ap_index, win, win_id);
		win++;
	}
}

/*
 * NOTE: Use the same window array for insertion and removal of
 *       temporary windows.
 */
void gwin_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_GWIN_MAX_WINS - i - 1;

		target = mmio_read_32(GWIN_CR_OFFSET(ap_index, win_id));
		target >>= WIN_TARGET_SHIFT;
		target &= WIN_TARGET_MASK;

		base = mmio_read_32(GWIN_ALR_OFFSET(ap_index, win_id));
		base >>= ADDRESS_LSHIFT;
		base <<= ADDRESS_RSHIFT;

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

#ifdef DEBUG_ADDR_MAP
static void dump_gwin(int ap_index)
{
	uint32_t win_num;

	/* Dump all GWIN windows */
	printf("\tbank  target     start              end\n");
	printf("\t----------------------------------------------------\n");
	for (win_num = 0; win_num < MVEBU_GWIN_MAX_WINS; win_num++) {
		uint32_t cr;
		uint64_t alr, ahr;

		cr  = mmio_read_32(GWIN_CR_OFFSET(ap_index, win_num));
		/* Window enabled */
		if (cr & WIN_ENABLE_BIT) {
			alr = mmio_read_32(GWIN_ALR_OFFSET(ap_index, win_num));
			alr = (alr >> ADDRESS_LSHIFT) << ADDRESS_RSHIFT;
			ahr = mmio_read_32(GWIN_AHR_OFFSET(ap_index, win_num));
			ahr = (ahr >> ADDRESS_LSHIFT) << ADDRESS_RSHIFT;
			printf("\tgwin   %d     0x%016" PRIx64 " 0x%016" PRIx64 "\n",
			       (cr >> 8) & 0xF, alr, ahr);
		}
	}
}
#endif

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

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

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

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

	/* disable all windows */
	for (win_id = 0; win_id < MVEBU_GWIN_MAX_WINS; win_id++)
		gwin_disable_window(ap_index, win_id);

	/* enable relevant windows */
	for (win_id = 0; win_id < win_count; win_id++, win++) {
		gwin_check(win);
		gwin_enable_window(ap_index, win, win_id);
	}

	/* GWIN Miss feature has not verified, therefore any access towards
	 * remote AP should be accompanied with proper configuration to
	 * GWIN registers group and therefore the GWIN Miss feature
	 * should be set into Bypass mode, need to make sure all GWIN regions
	 * are defined correctly that will assure no GWIN miss occurrance
	 * JIRA-AURORA2-1630
	 */
	INFO("Update GWIN miss bypass\n");
	win_reg = mmio_read_32(CCU_GRU_CR_OFFSET(ap_index));
	win_reg |= CCR_GRU_CR_GWIN_MBYPASS;
	mmio_write_32(CCU_GRU_CR_OFFSET(ap_index), win_reg);

#ifdef DEBUG_ADDR_MAP
	dump_gwin(ap_index);
#endif

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

	return 0;
}
