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

#include <stdint.h>
#include <lib.h>
#include <console/console.h>
#include <device/mmio.h>

#if ENV_X86 && CONFIG(SSE2)
/* Assembler in lib/ is ugly. */
static void write_phys(uintptr_t addr, u32 value)
{
	asm volatile (
		"movnti %1, (%0)"
		: /* outputs */
		: "r" (addr), "r" (value) /* inputs */
	);
}

static void phys_memory_barrier(void)
{
	// Needed for movnti
	asm volatile ("sfence" ::: "memory");
}
#else
static void write_phys(uintptr_t addr, u32 value)
{
	write32p(addr, value);
}

static void phys_memory_barrier(void)
{
	asm volatile ("" ::: "memory");
}
#endif

static u32 read_phys(uintptr_t addr)
{
	return read32p(addr);
}

/**
 * Rotate ones test pattern that access every bit on a 128bit wide
 * memory bus. To test most address lines, addresses are scattered
 * using 256B, 4kB and 64kB increments.
 *
 * @param idx	Index to test pattern (0=<idx<0x400)
 * @param addr	Memory to access on idx
 * @param value	Value to write or read at addr
 */
static inline void test_pattern(unsigned short int idx,
	unsigned long *addr, unsigned long *value)
{
	uint8_t j, k;

	k = (idx >> 8) + 1;
	j = (idx >> 4) & 0x0f;
	*addr = idx & 0x0f;
	*addr |= j << (4*k);
	*value = 0x01010101 << (j & 7);
	if (j & 8)
		*value = ~(*value);
}

/**
 * Simple write-read-verify memory test. See console debug output for
 * any dislocated bytes.
 *
 * Tests 1MiB of memory starting from start.
 *
 * @param start   System memory offset, aligned to 128bytes
 */
static int ram_bitset_nodie(uintptr_t start)
{
	unsigned long addr, value, value2;
	unsigned short int idx;
	unsigned char failed, failures;
	uint8_t verbose = 0;

	printk(BIOS_DEBUG, "DRAM bitset write: 0x%08lx\n", start);
	for (idx = 0; idx < 0x400; idx += 4) {
		test_pattern(idx, &addr, &value);
		write_phys(start + addr, value);
	}

	/* Make sure we don't read before we wrote */
	phys_memory_barrier();

	printk(BIOS_DEBUG, "DRAM bitset verify: 0x%08lx\n", start);
	failures = 0;
	for (idx = 0; idx < 0x400; idx += 4) {
		test_pattern(idx, &addr, &value);
		value2 = read_phys(start + addr);

		failed = (value2 != value);
		failures |= failed;
		if (failed && !verbose) {
			printk(BIOS_ERR, "0x%08lx wr: 0x%08lx rd: 0x%08lx FAIL\n",
				 start + addr, value, value2);
		}
		if (verbose) {
			if ((addr & 0x0f) == 0)
				printk(BIOS_DEBUG, "%08lx wr: %08lx rd:",
					start + addr, value);
			if (failed)
				printk(BIOS_DEBUG, " %08lx!", value2);
			else
				printk(BIOS_DEBUG, " %08lx ", value2);
			if ((addr & 0x0f) == 0xc)
				printk(BIOS_DEBUG, "\n");
		}
	}
	if (failures) {
		post_code(POSTCODE_RAM_FAILURE);
		printk(BIOS_DEBUG, "\nDRAM did _NOT_ verify!\n");
		return 1;
	}
	printk(BIOS_DEBUG, "\nDRAM range verified.\n");
	return 0;
}


void ram_check(uintptr_t start)
{
	/*
	 * This is much more of a "Is my DRAM properly configured?"
	 * test than a "Is my DRAM faulty?" test.  Not all bits
	 * are tested.   -Tyson
	 */
	printk(BIOS_DEBUG, "Testing DRAM at: %08lx\n", start);
	if (ram_bitset_nodie(start))
		die("DRAM ERROR");
	printk(BIOS_DEBUG, "Done.\n");
}


int ram_check_nodie(uintptr_t start)
{
	int ret;
	/*
	 * This is much more of a "Is my DRAM properly configured?"
	 * test than a "Is my DRAM faulty?" test.  Not all bits
	 * are tested.   -Tyson
	 */
	printk(BIOS_DEBUG, "Testing DRAM at : %08lx\n", start);

	ret = ram_bitset_nodie(start);
	printk(BIOS_DEBUG, "Done.\n");
	return ret;
}

int ram_check_noprint_nodie(uintptr_t start)
{
	unsigned long addr, value, value2;
	unsigned short int idx;
	unsigned char failed, failures;

	for (idx = 0; idx < 0x400; idx += 4) {
		test_pattern(idx, &addr, &value);
		write_phys(start + addr, value);
	}

	/* Make sure we don't read before we wrote */
	phys_memory_barrier();

	failures = 0;
	for (idx = 0; idx < 0x400; idx += 4) {
		test_pattern(idx, &addr, &value);
		value2 = read_phys(start + addr);

		failed = (value2 != value);
		failures |= failed;
	}
	return failures;
}

/* Assumption is 32-bit addressable UC memory at dst. This also executes
 * on S3 resume path so target memory must be restored.
 */
void quick_ram_check_or_die(uintptr_t dst)
{
	int fail = 0;
	u32 backup;
	backup = read_phys(dst);
	write_phys(dst, 0x55555555);
	phys_memory_barrier();
	if (read_phys(dst) != 0x55555555)
		fail = 1;
	write_phys(dst, 0xaaaaaaaa);
	phys_memory_barrier();
	if (read_phys(dst) != 0xaaaaaaaa)
		fail = 1;
	write_phys(dst, 0x00000000);
	phys_memory_barrier();
	if (read_phys(dst) != 0x00000000)
		fail = 1;
	write_phys(dst, 0xffffffff);
	phys_memory_barrier();
	if (read_phys(dst) != 0xffffffff)
		fail = 1;

	write_phys(dst, backup);
	if (fail) {
		post_code(POSTCODE_RAM_FAILURE);
		die("RAM INIT FAILURE!\n");
	}
	phys_memory_barrier();
}
