/* SPDX-License-Identifier: GPL-2.0-only */

#include <cbfs.h>
#include <console/console.h>
#include <memory_info.h>
#include <spd_bin.h>
#include <string.h>
#include <device/dram/ddr3.h>

void dump_spd_info(struct spd_block *blk)
{
	u8 i;

	for (i = 0; i < CONFIG_DIMM_MAX; i++)
		if (blk->spd_array[i] != NULL && blk->spd_array[i][0] != 0) {
			printk(BIOS_DEBUG, "SPD @ 0x%02X\n", blk->addr_map[i]);
			print_spd_info(blk->spd_array[i]);
		}
}

const char * __weak mainboard_get_dram_part_num(void)
{
	/* Default weak implementation, no need to override part number. */
	return NULL;
}

static bool use_ddr4_params(int dram_type)
{
	switch (dram_type) {
	case SPD_DRAM_DDR3:
	case SPD_DRAM_LPDDR3_INTEL:
		return false;
	/* Below DDR type share the same attributes */
	case SPD_DRAM_LPDDR3_JEDEC:
	case SPD_DRAM_DDR4:
	case SPD_DRAM_DDR5:
	case SPD_DRAM_LPDDR4:
	case SPD_DRAM_LPDDR4X:
		return true;
	default:
		printk(BIOS_ERR, "Defaulting to using DDR4 params. Please add dram_type check for %d to %s\n",
			dram_type, __func__);
		return true;
	}
}

static const char *spd_get_module_type_string(int dram_type)
{
	switch (dram_type) {
	case SPD_DRAM_DDR3:
		return "DDR3";
	case SPD_DRAM_LPDDR3_INTEL:
	case SPD_DRAM_LPDDR3_JEDEC:
		return "LPDDR3";
	case SPD_DRAM_DDR4:
		return "DDR4";
	case SPD_DRAM_LPDDR4:
		return "LPDDR4";
	case SPD_DRAM_LPDDR4X:
		return "LPDDR4X";
	case SPD_DRAM_DDR5:
		return "DDR5";
	case SPD_DRAM_LPDDR5:
		return "LPDDR5";
	}
	return "UNKNOWN";
}

static int spd_get_banks(const uint8_t spd[], int dram_type)
{
	static const int ddr3_banks[4] = { 8, 16, 32, 64 };
	static const int ddr4_banks[10] = { 4, 8, -1, -1, 8, 16, -1, -1, 16, 32 };
	int index = (spd[SPD_DENSITY_BANKS] >> 4) & 0xf;

	if (use_ddr4_params(dram_type)) {
		if (index >= ARRAY_SIZE(ddr4_banks))
			return -1;
		return ddr4_banks[index];
	} else {
		if (index >= ARRAY_SIZE(ddr3_banks))
			return -1;
		return ddr3_banks[index];
	}
}

static int spd_get_capmb(const uint8_t spd[])
{
	static const int spd_capmb[13] = { 1, 2, 4, 8, 16, 32, 64,
					   128, 48, 96, 12, 24, 72 };
	int index = spd[SPD_DENSITY_BANKS] & 0xf;
	if (index >= ARRAY_SIZE(spd_capmb))
		return -1;
	return spd_capmb[index] * 256;
}

static int spd_get_rows(const uint8_t spd[])
{
	static const int spd_rows[7]  = { 12, 13, 14, 15, 16, 17, 18 };
	int index = (spd[SPD_ADDRESSING] >> 3) & 7;
	if (index >= ARRAY_SIZE(spd_rows))
		return -1;
	return spd_rows[index];
}

static int spd_get_cols(const uint8_t spd[])
{
	static const int spd_cols[4]  = { 9, 10, 11, 12 };
	int index = spd[SPD_ADDRESSING] & 7;
	if (index >= ARRAY_SIZE(spd_cols))
		return -1;
	return spd_cols[index];
}

static int spd_get_ranks(const uint8_t spd[], int dram_type)
{
	static const int spd_ranks[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
	int organ_offset = use_ddr4_params(dram_type) ? DDR4_ORGANIZATION
						      : DDR3_ORGANIZATION;
	int index = (spd[organ_offset] >> 3) & 7;
	if (index >= ARRAY_SIZE(spd_ranks))
		return -1;
	return spd_ranks[index];
}

static int spd_get_devw(const uint8_t spd[], int dram_type)
{
	static const int spd_devw[4]  = { 4, 8, 16, 32 };
	int organ_offset = use_ddr4_params(dram_type) ? DDR4_ORGANIZATION
						      : DDR3_ORGANIZATION;
	int index = spd[organ_offset] & 7;
	if (index >= ARRAY_SIZE(spd_devw))
		return -1;
	return spd_devw[index];
}

static int spd_get_busw(const uint8_t spd[], int dram_type)
{
	static const int spd_busw[4]  = { 8, 16, 32, 64 };
	int busw_offset = use_ddr4_params(dram_type) ? DDR4_BUS_DEV_WIDTH
						     : DDR3_BUS_DEV_WIDTH;
	int index = spd[busw_offset] & 7;
	if (index >= ARRAY_SIZE(spd_busw))
		return -1;
	return spd_busw[index];
}

static void spd_get_name(const uint8_t spd[], int type, const char **spd_name, size_t *len)
{
	*spd_name = mainboard_get_dram_part_num();
	if (*spd_name != NULL) {
		*len = strlen(*spd_name);
		return;
	}

	switch (type) {
	case SPD_DRAM_DDR3:
		*spd_name = (const char *) &spd[DDR3_SPD_PART_OFF];
		*len = DDR3_SPD_PART_LEN;
		break;
	case SPD_DRAM_LPDDR3_INTEL:
		*spd_name = (const char *) &spd[LPDDR3_SPD_PART_OFF];
		*len = LPDDR3_SPD_PART_LEN;
		break;
	/* LPDDR3, LPDDR4 and DDR4 have same part number offset and length */
	case SPD_DRAM_LPDDR3_JEDEC:
	case SPD_DRAM_DDR4:
	case SPD_DRAM_DDR5:
	case SPD_DRAM_LPDDR4:
	case SPD_DRAM_LPDDR4X:
		*spd_name = (const char *) &spd[DDR4_SPD_PART_OFF];
		*len = DDR4_SPD_PART_LEN;
		break;
	default:
		*len = 0;
		break;
	}
}

void print_spd_info(uint8_t spd[])
{
	const char *nameptr = NULL;
	size_t len;
	int type  = spd[SPD_DRAM_TYPE];
	int banks = spd_get_banks(spd, type);
	int capmb = spd_get_capmb(spd);
	int rows  = spd_get_rows(spd);
	int cols  = spd_get_cols(spd);
	int ranks = spd_get_ranks(spd, type);
	int devw  = spd_get_devw(spd, type);
	int busw  = spd_get_busw(spd, type);

	/* Module type */
	printk(BIOS_INFO, "SPD: module type is %s\n",
		spd_get_module_type_string(type));
	/* Module Part Number */
	spd_get_name(spd, type, &nameptr, &len);
	if (nameptr)
		printk(BIOS_INFO, "SPD: module part number is %.*s\n", (int) len, nameptr);

	printk(BIOS_INFO,
		"SPD: banks %d, ranks %d, rows %d, columns %d, density %d Mb\n",
		banks, ranks, rows, cols, capmb);
	printk(BIOS_INFO, "SPD: device width %d bits, bus width %d bits\n",
		devw, busw);

	if (capmb > 0 && busw > 0 && devw > 0 && ranks > 0) {
		/* SIZE = DENSITY / 8 * BUS_WIDTH / SDRAM_WIDTH * RANKS */
		printk(BIOS_INFO, "SPD: module size is %u MB (per channel)\n",
			capmb / 8 * busw / devw * ranks);
	}
}

uintptr_t spd_cbfs_map(u8 spd_index)
{
	enum cbfs_type cbfs_type = CBFS_TYPE_SPD;
	size_t size;

	void *map = cbfs_type_map("spd.bin", &size, &cbfs_type);
	if (!map || size < (spd_index + 1) * CONFIG_DIMM_SPD_SIZE)
		return 0;

	return (uintptr_t)map + spd_index * CONFIG_DIMM_SPD_SIZE;
}

#if CONFIG_DIMM_SPD_SIZE == 128
int read_ddr3_spd_from_cbfs(u8 *buf, int idx)
{
	const int SPD_CRC_HI = 127;
	const int SPD_CRC_LO = 126;

	char *spd_file;
	size_t spd_file_len = 0;
	size_t min_len = (idx + 1) * CONFIG_DIMM_SPD_SIZE;

	spd_file = cbfs_map("spd.bin", &spd_file_len);
	if (!spd_file)
		printk(BIOS_EMERG, "file [spd.bin] not found in CBFS");
	if (spd_file_len < min_len)
		printk(BIOS_EMERG, "Missing SPD data.");
	if (!spd_file || spd_file_len < min_len)
		return -1;

	memcpy(buf, spd_file + (idx * CONFIG_DIMM_SPD_SIZE),
		CONFIG_DIMM_SPD_SIZE);
	cbfs_unmap(spd_file);

	u16 crc = spd_ddr3_calc_crc(buf, CONFIG_DIMM_SPD_SIZE);

	if (((buf[SPD_CRC_LO] == 0) && (buf[SPD_CRC_HI] == 0))
		|| (buf[SPD_CRC_LO] != (crc & 0xff))
		|| (buf[SPD_CRC_HI] != (crc >> 8))) {
		printk(BIOS_WARNING,
			"SPD CRC %02x%02x is invalid, should be %04x\n",
			buf[SPD_CRC_HI], buf[SPD_CRC_LO], crc);
		buf[SPD_CRC_LO] = crc & 0xff;
		buf[SPD_CRC_HI] = crc >> 8;
		u16 i;
		printk(BIOS_WARNING, "\nDisplay the SPD");
		for (i = 0; i < CONFIG_DIMM_SPD_SIZE; i++) {
			if ((i % 16) == 0x00)
				printk(BIOS_WARNING, "\n%02x:  ", i);
			printk(BIOS_WARNING, "%02x ", buf[i]);
		}
		printk(BIOS_WARNING, "\n");
	}
	return 0;
}
#endif
