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

#include <common.h>
#include <spl.h>
#include <asm/io.h>
#include <errno.h>
#include <command.h>
#include <asm/io.h>
#include <asm/arch/lpddr4_define.h>
#include <asm/mach-imx/iomux-v3.h>
#include <asm/mach-imx/gpio.h>
#include <asm-generic/gpio.h>
#include <asm/arch/ddr.h>
#include <asm/arch/imx8mq_pins.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/clock.h>
#include <asm/mach-imx/gpio.h>
#include "ddr.h"

#include <linux/delay.h>

static unsigned int lpddr4_mr_read(unsigned int mr_rank, unsigned int mr_addr)
{
	unsigned int tmp;

	reg32_write(DRC_PERF_MON_MRR0_DAT(0), 0x1);
	do {
		tmp = reg32_read(DDRC_MRSTAT(0));
	} while (tmp & 0x1);

	reg32_write(DDRC_MRCTRL0(0), (mr_rank << 4) | 0x1);
	reg32_write(DDRC_MRCTRL1(0), (mr_addr << 8));
	reg32setbit(DDRC_MRCTRL0(0), 31);
	do {
		tmp = reg32_read(DRC_PERF_MON_MRR0_DAT(0));
	} while ((tmp & 0x8) == 0);
	tmp = reg32_read(DRC_PERF_MON_MRR1_DAT(0));
	reg32_write(DRC_PERF_MON_MRR0_DAT(0), 0x4);
	while (tmp) { //try to find a significant byte in the word
		if (tmp & 0xff) {
			tmp &= 0xff;
			break;
		}
		tmp >>= 8;
	}
	return tmp;
}

struct lpddr4_desc {
	char name[16];
	unsigned int id;
	unsigned int size;
	unsigned int count;
	/* an optional field
	 * use it if default is not the
	 * 1-st array entry
	 */
	unsigned int _default;
	/* An optional field to distiguish DRAM chips that
	 * have different geometry, though return the same MRR.
	 * Default value 0xff
	 */
	u8	subind;
	struct dram_timing_info *timing;
	char *desc[4];
};

#define DEFAULT (('D' << 24) + ('E' << 16) + ('F' << 8) + 'A')
static const struct lpddr4_desc lpddr4_array[] = {
	{ .name = "Nanya",	.id = 0x05000010, .subind = 0xff,
	  .size = 2048, .count = 1, .timing = &ucm_dram_timing_01061010},
	{ .name = "Samsung",	.id = 0x01061010, .subind = 0xff,
	  .size = 2048, .count = 1, .timing = &ucm_dram_timing_01061010},
	{ .name = "Kingston",	.id = 0xff000010, .subind = 0x04,
	  .size = 4096, .count = 1, .timing = &ucm_dram_timing_ff000110},
	{ .name = "Kingston",	.id = 0xff000010, .subind = 0x02,
	  .size = 2048, .count = 1, .timing = &ucm_dram_timing_01061010},
	{ .name = "Micron",	.id = 0xff020008, .subind = 0xff,
	  .size = 2048, .count = 1, .timing = &ucm_dram_timing_ff020008},
	{ .name = "Micron",	.id = 0xff000110, .subind = 0xff,
	  .size = 4096, .count = 1, .timing = &ucm_dram_timing_ff000110},
};

static unsigned int lpddr4_get_mr(void)
{
	int i = 0, attempts = 5;
	unsigned int ddr_info = 0;
	unsigned int regs[] = { 5, 6, 7, 8 };

	do {
		for (i = 0 ; i < ARRAY_SIZE(regs) ; i++) {
			unsigned int data = 0;

			data = lpddr4_mr_read(0xF, regs[i]);
			ddr_info <<= 8;
			ddr_info += (data & 0xFF);
		}
		if (ddr_info != 0xFFFFFFFF && ddr_info != 0)
			break; // The attempt was successful
	} while (--attempts);
	return	ddr_info;
}

static void spl_tcm_init(struct lpddr4_tcm_desc *lpddr4_tcm_desc)
{
	if (lpddr4_tcm_desc->sign == DEFAULT)
		return;

	lpddr4_tcm_desc->sign = DEFAULT;
	lpddr4_tcm_desc->index = 0;
}

static void spl_tcm_fini(struct lpddr4_tcm_desc *lpddr4_tcm_desc)
{
	if (lpddr4_tcm_desc->sign != DEFAULT)
		return;

	lpddr4_tcm_desc->sign = ~DEFAULT;
	lpddr4_tcm_desc->index = 0;
}

#define SPL_TCM_DATA 0x7e0000
#define SPL_TCM_INIT spl_tcm_init(lpddr4_tcm_desc)
#define SPL_TCM_FINI spl_tcm_fini(lpddr4_tcm_desc)

void spl_dram_init_compulab(void)
{
	unsigned int ddr_info = 0xdeadbeef;
	unsigned int ddr_info_mrr = 0xdeadbeef;
	unsigned int ddr_found = 0;
	int i = 0;

	struct lpddr4_tcm_desc *lpddr4_tcm_desc =
		(struct lpddr4_tcm_desc *)SPL_TCM_DATA;

	if (lpddr4_tcm_desc->sign != DEFAULT) {
		/* get ddr type from the eeprom if not in tcm scan mode */
		ddr_info = cl_eeprom_get_ddrinfo();
		for (i = 0; i < ARRAY_SIZE(lpddr4_array); i++) {
			if (lpddr4_array[i].id == ddr_info &&
			lpddr4_array[i].subind == cl_eeprom_get_subind()) {
				ddr_found = 1;
				break;
			}
		}
	}

	/* Walk trought all available ddr ids and apply
	 * one by one. Save the index at the tcm memory that
	 * persists after the reset.
	 */
	if (ddr_found == 0) {
		SPL_TCM_INIT;

		if (lpddr4_tcm_desc->index < ARRAY_SIZE(lpddr4_array)) {
			printf("DDRINFO: Cfg attempt: [ %d/%lu ]\n",
			       lpddr4_tcm_desc->index + 1,
			       ARRAY_SIZE(lpddr4_array));
			i = lpddr4_tcm_desc->index;
			lpddr4_tcm_desc->index += 1;
		} else {
			/* Ran out all available ddr setings */
			printf("DDRINFO: Ran out all [ %lu ] cfg attempts. A non supported configuration.\n",
			       ARRAY_SIZE(lpddr4_array));
			while (1)
				;
		}
		ddr_info = lpddr4_array[i].id;
	} else {
		printf("DDRINFO(%s): %s %dG\n", (ddr_found ? "D" : "?"),
		       lpddr4_array[i].name,
		       lpddr4_array[i].size);
	}

	if (ddr_init(lpddr4_array[i].timing)) {
		SPL_TCM_INIT;
		do_reset(NULL, 0, 0, NULL);
	}

	ddr_info_mrr = lpddr4_get_mr();
	if (ddr_info_mrr == 0xFFFFFFFF) {
		printf("DDRINFO(M): mr5-8 [ 0x%x ] is invalid; reset\n",
		       ddr_info_mrr);
		SPL_TCM_INIT;
		do_reset(NULL, 0, 0, NULL);
	}

	printf("DDRINFO(M): mr5-8 [ 0x%x ]\n", ddr_info_mrr);
	printf("DDRINFO(%s): mr5-8 [ 0x%x ]\n", (ddr_found ? "E" : "T"),
	       ddr_info);

	if (ddr_info_mrr != ddr_info) {
		SPL_TCM_INIT;
		do_reset(NULL, 0, 0, NULL);
	}

	SPL_TCM_FINI;

	if (ddr_found == 0) {
		/* Update eeprom */
		cl_eeprom_set_ddrinfo(ddr_info_mrr);
		mdelay(10);
		ddr_info = cl_eeprom_get_ddrinfo();
		mdelay(10);
		cl_eeprom_set_subind(lpddr4_array[i].subind);
		/* make sure that the ddr_info has reached the eeprom */
		printf("DDRINFO(E): mr5-8 [ 0x%x ], read back\n", ddr_info);
		if (ddr_info_mrr != ddr_info || cl_eeprom_get_subind() != lpddr4_array[i].subind) {
			printf("DDRINFO(EEPROM): make sure that the eeprom is accessible\n");
			printf("DDRINFO(EEPROM): i2c dev 1; i2c md 0x51 0x40 0x50\n");
		}
	}

	/* Pass the dram size to th U-Boot through the tcm memory */
	{ /* To figure out what to store into the TCM buffer */
	  /* For debug purpouse only. To override the real memsize */
		unsigned int ddr_tcm_size = cl_eeprom_get_osize();

		if (ddr_tcm_size == 0 || ddr_tcm_size == -1)
			ddr_tcm_size = lpddr4_array[i].size;

		lpddr4_tcm_desc->size = ddr_tcm_size;
	}
}
