// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright 2020 NXP
 */

#include <console.h>
#include <errno.h>
#include <fuse.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/imx-regs.h>
#include <env.h>
#include <asm/mach-imx/ele_api.h>
#include <asm/global_data.h>
#include <env.h>

DECLARE_GLOBAL_DATA_PTR;

#define WORDS_PER_BANKS 8

struct fsb_map_entry {
	s32 fuse_bank;
	u32 fuse_words;
	bool redundancy;
};

struct ele_map_entry {
	s32 fuse_bank;
	u32 fuse_words;
	u32 fuse_offset;
	u32 ele_index;
};

#if defined(CONFIG_IMX8ULP)
#define FSB_OTP_SHADOW	0x800
#define IS_FSB_ALLOWED (true)

struct fsb_map_entry fsb_mapping_table[] = {
	{ 3, 8 },
	{ 4, 8 },
	{ -1, 48 }, /* Reserve 48 words */
	{ 5, 8 },
	{ 6, 8 },
	{ 8,  4, true },
	{ 24, 4, true },
	{ 26, 4, true },
	{ 27, 4, true },
	{ 28, 8 },
	{ 29, 8 },
	{ 30, 8 },
	{ 31, 8 },
	{ 37, 8 },
	{ 38, 8 },
	{ 39, 8 },
	{ 40, 8 },
	{ 41, 8 },
	{ 42, 8 },
	{ 43, 8 },
	{ 44, 8 },
	{ 45, 8 },
	{ 46, 8 },
};

/* None ECC banks such like Redundancy or Bit protect */
u32 nonecc_fuse_banks[] = {
	0, 1, 8, 12, 16, 22, 24, 25, 26, 27, 36, 41, 51, 56
};

struct ele_map_entry ele_api_mapping_table[] = {
	{ 1, 8 },	/* LOCK */
	{ 2, 8 },	/* ECID */
	{ 7, 4, 0, 1 },	/* OTP_UNIQ_ID */
	{ 15, 8 }, /* OEM SRK HASH */
	{ 23, 1, 4, 2 }, /* OTFAD */
	{ 25, 8 }, /* Test config2 */
	{ 26, 8 }, /* PMU */
	{ 27, 8 }, /* Test flow/USB */
	{ 32, 8 }, /* GP1 */
	{ 33, 8 }, /* GP2 */
	{ 34, 8 }, /* GP3 */
	{ 35, 8 }, /* GP4 */
	{ 36, 8 }, /* GP5 */
	{ 49, 8 }, /* GP8 */
	{ 50, 8 }, /* GP9 */
	{ 51, 8 }, /* GP10 */
};
#elif defined(CONFIG_ARCH_IMX9)
#define FSB_OTP_SHADOW	0x8000
#define IS_FSB_ALLOWED (!IS_ENABLED(CONFIG_SCMI_FIRMWARE) && \
	!(readl(BLK_CTRL_NS_ANOMIX_BASE_ADDR + 0x28) & BIT(0)))

struct fsb_map_entry fsb_mapping_table[] = {
	{ 0, 8 },
	{ 1, 8 },
	{ 2, 8 },
	{ 3, 8 },
	{ 4, 8 },
	{ 5, 8 },
	{ 6, 4 },
	{ -1, 260 },
	{ 39, 8 },
	{ 40, 8 },
	{ 41, 8 },
	{ 42, 8 },
	{ 43, 8 },
	{ 44, 8 },
	{ 45, 8 },
	{ 46, 8 },
	{ 47, 8 },
	{ 48, 8 },
	{ 49, 8 },
	{ 50, 8 },
	{ 51, 8 },
	{ 52, 8 },
	{ 53, 8 },
	{ 54, 8 },
	{ 55, 8 },
	{ 56, 8 },
	{ 57, 8 },
	{ 58, 8 },
	{ 59, 8 },
	{ 60, 8 },
	{ 61, 8 },
	{ 62, 8 },
	{ 63, 8 },
};

struct ele_map_entry ele_api_mapping_table[] = {
	{ 7, 1, 7, 63 },
	{ 16, 8, },
	{ 17, 8, },
	{ 22, 1, 6 },
	{ 23, 1, 4 },
};
#endif

static s32 map_fsb_fuse_index(u32 bank, u32 word, bool *redundancy)
{
	s32 size = ARRAY_SIZE(fsb_mapping_table);
	s32 i, word_pos = 0;

	/* map the fuse from ocotp fuse map to FSB*/
	for (i = 0; i < size; i++) {
		if (fsb_mapping_table[i].fuse_bank != -1 &&
		    fsb_mapping_table[i].fuse_bank == bank) {
			break;
		}

		word_pos += fsb_mapping_table[i].fuse_words;
	}

	if (i == size)
		return -1; /* Failed to find */

	if (fsb_mapping_table[i].redundancy) {
		if ((fsb_mapping_table[i].fuse_words << 1) <= word)
			return -2; /* Not valid word */

		*redundancy = true;
		return (word >> 1) + word_pos;
	} else if (fsb_mapping_table[i].fuse_words <= word) {
		return -2; /* Not valid word */
	}

	*redundancy = false;
	return word + word_pos;
}

static s32 map_ele_fuse_index(u32 bank, u32 word)
{
	s32 size = ARRAY_SIZE(ele_api_mapping_table);
	s32 i;

	/* map the fuse from ocotp fuse map to FSB*/
	for (i = 0; i < size; i++) {
		if (ele_api_mapping_table[i].fuse_bank != -1 &&
		    ele_api_mapping_table[i].fuse_bank == bank) {
			if (word >= ele_api_mapping_table[i].fuse_offset &&
			    word < (ele_api_mapping_table[i].fuse_offset +
			    ele_api_mapping_table[i].fuse_words))
				break;
		}
	}

	if (i == size)
		return -1; /* Failed to find */

	if (ele_api_mapping_table[i].ele_index != 0)
		return ele_api_mapping_table[i].ele_index;

	return ele_api_mapping_table[i].fuse_bank * 8 + word;
}

#if defined(CONFIG_IMX8ULP)
int fuse_sense(u32 bank, u32 word, u32 *val)
{
	s32 word_index;

	if (word >= WORDS_PER_BANKS || !val)
		return -EINVAL;

	word_index = map_ele_fuse_index(bank, word);
	if (word_index >= 0) {
		u32 data[4];
		u32 res = 0, size = 4;
		int ret;

		/* Only UID return 4 words */
		if (word_index != 1)
			size = 1;

		ret = ele_read_common_fuse(word_index, data, size, &res);
		if (ret) {
			printf("ahab read fuse failed %d, 0x%x\n", ret, res);
			return ret;
		}

		if (word_index == 1) {
			*val = data[word]; /* UID */
		} else if (word_index == 2) {
			/*
			 * OTFAD 3 bits as follow:
			 * bit 0: OTFAD_ENABLE
			 * bit 1: OTFAD_DISABLE_OVERRIDE
			 * bit 2: KEY_BLOB_EN
			 */
			*val = data[0] << 3;
		} else {
			*val = data[0];
		}

		return 0;
	}

	return -ENOENT;
}

#elif defined(CONFIG_ARCH_IMX9)
int fuse_sense(u32 bank, u32 word, u32 *val)
{
	s32 word_index;
	bool redundancy;

	if (word >= WORDS_PER_BANKS || !val)
		return -EINVAL;

	if (!IS_ENABLED(CONFIG_SCMI_FIRMWARE)) {
		word_index = map_fsb_fuse_index(bank, word, &redundancy);

		/* ELE read common fuse API supports all FSB fuse. */
		if (word_index < 0)
			word_index = map_ele_fuse_index(bank, word);
	} else {
		word_index = bank * 8 + word;
	}

	if (word_index >= 0) {
		u32 data;
		u32 res = 0, size = 1;
		int ret;

		ret = ele_read_common_fuse(word_index, &data, size, &res);
		if (ret) {
			printf("ahab read fuse failed %d, 0x%x\n", ret, res);
			return ret;
		}

		*val = data;

		return 0;
	}

	return -ENOENT;
}
#endif

static int fuse_read_default(u32 bank, u32 word, u32 *val)
{
	s32 word_index;
	bool redundancy;

	if (IS_FSB_ALLOWED) {
		word_index = map_fsb_fuse_index(bank, word, &redundancy);
		if (word_index >= 0) {
			*val = readl((ulong)FSB_BASE_ADDR + FSB_OTP_SHADOW + (word_index << 2));
			if (redundancy)
				*val = (*val >> ((word % 2) * 16)) & 0xFFFF;

			return 0;
		}
	}

	return fuse_sense(bank, word, val);
}

static int fuse_read_ele_shd(u32 bank, u32 word, u32 *val)
{
	u32 res = 0;
	int ret;
	struct udevice *dev = gd->arch.ele_dev;

	if (!dev)
		return -ENODEV;

	ret = ele_read_shadow_fuse((bank * 8 + word), val, &res);
	if (ret) {
		printf("ele read shadow fuse failed %d, 0x%x\n", ret, res);
		return ret;
	}

	return 0;
}

int fuse_read(u32 bank, u32 word, u32 *val)
{
	if (word >= WORDS_PER_BANKS || !val)
		return -EINVAL;

	if (!IS_ENABLED(CONFIG_SPL_BUILD) &&
	    env_get_yesno("enable_ele_shd") == 1)
		return fuse_read_ele_shd(bank, word, val);
	else
		return fuse_read_default(bank, word, val);
}

int fuse_prog(u32 bank, u32 word, u32 val)
{
	u32 res = 0;
	int ret;
	bool lock = false;

	if (word >= WORDS_PER_BANKS || !val)
		return -EINVAL;

	/* Lock 8ULP ECC fuse word, so second programming will return failure.
	 * iMX9 OTP can protect ECC fuse, so not need it
	 */
#if defined(CONFIG_IMX8ULP)
	u32 i;
	for (i = 0; i < ARRAY_SIZE(nonecc_fuse_banks); i++) {
		if (nonecc_fuse_banks[i] == bank)
			break;
	}

	if (i == ARRAY_SIZE(nonecc_fuse_banks))
		lock = true;
#endif

	ret = ele_write_fuse((bank * 8 + word), val, lock, &res);
	if (ret) {
		printf("ahab write fuse failed %d, 0x%x\n", ret, res);
		return ret;
	}

	return 0;
}

int fuse_override(u32 bank, u32 word, u32 val)
{
	u32 res = 0;
	int ret;

	if (word >= WORDS_PER_BANKS || !val)
		return -EINVAL;

	ret = ele_write_shadow_fuse((bank * 8 + word), val, &res);
	if (ret) {
		printf("ahab write shadow fuse failed %d, 0x%x\n", ret, res);
		return ret;
	}

	return 0;
}
