// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (c) 2014 Google, Inc.
 */

#define IOTRACE_IMPL

#include <common.h>
#include <mapmem.h>
#include <asm/io.h>

DECLARE_GLOBAL_DATA_PTR;

/* Support up to the machine word length for now */
typedef ulong iovalue_t;

enum iotrace_flags {
	IOT_8 = 0,
	IOT_16,
	IOT_32,

	IOT_READ = 0 << 3,
	IOT_WRITE = 1 << 3,
};

/**
 * struct iotrace_record - Holds a single I/O trace record
 *
 * @flags: I/O access type
 * @addr: Address of access
 * @value: Value written or read
 */
struct iotrace_record {
	enum iotrace_flags flags;
	phys_addr_t addr;
	iovalue_t value;
};

/**
 * struct iotrace - current trace status and checksum
 *
 * @start:	Start address of iotrace buffer
 * @size:	Size of iotrace buffer in bytes
 * @offset:	Current write offset into iotrace buffer
 * @crc32:	Current value of CRC chceksum of trace records
 * @enabled:	true if enabled, false if disabled
 */
static struct iotrace {
	ulong start;
	ulong size;
	ulong offset;
	u32 crc32;
	bool enabled;
} iotrace;

static void add_record(int flags, const void *ptr, ulong value)
{
	struct iotrace_record srec, *rec = &srec;

	/*
	 * We don't support iotrace before relocation. Since the trace buffer
	 * is set up by a command, it can't be enabled at present. To change
	 * this we would need to set the iotrace buffer at build-time. See
	 * lib/trace.c for how this might be done if you are interested.
	 */
	if (!(gd->flags & GD_FLG_RELOC) || !iotrace.enabled)
		return;

	/* Store it if there is room */
	if (iotrace.offset + sizeof(*rec) < iotrace.size) {
		rec = (struct iotrace_record *)map_sysmem(
					iotrace.start + iotrace.offset,
					sizeof(value));
	}

	rec->flags = flags;
	rec->addr = map_to_sysmem(ptr);
	rec->value = value;

	/* Update our checksum */
	iotrace.crc32 = crc32(iotrace.crc32, (unsigned char *)rec,
			      sizeof(*rec));

	iotrace.offset += sizeof(struct iotrace_record);
}

u32 iotrace_readl(const void *ptr)
{
	u32 v;

	v = readl(ptr);
	add_record(IOT_32 | IOT_READ, ptr, v);

	return v;
}

void iotrace_writel(ulong value, const void *ptr)
{
	add_record(IOT_32 | IOT_WRITE, ptr, value);
	writel(value, ptr);
}

u16 iotrace_readw(const void *ptr)
{
	u32 v;

	v = readw(ptr);
	add_record(IOT_16 | IOT_READ, ptr, v);

	return v;
}

void iotrace_writew(ulong value, const void *ptr)
{
	add_record(IOT_16 | IOT_WRITE, ptr, value);
	writew(value, ptr);
}

u8 iotrace_readb(const void *ptr)
{
	u32 v;

	v = readb(ptr);
	add_record(IOT_8 | IOT_READ, ptr, v);

	return v;
}

void iotrace_writeb(ulong value, const void *ptr)
{
	add_record(IOT_8 | IOT_WRITE, ptr, value);
	writeb(value, ptr);
}

void iotrace_reset_checksum(void)
{
	iotrace.crc32 = 0;
}

u32 iotrace_get_checksum(void)
{
	return iotrace.crc32;
}

void iotrace_set_enabled(int enable)
{
	iotrace.enabled = enable;
}

int iotrace_get_enabled(void)
{
	return iotrace.enabled;
}

void iotrace_set_buffer(ulong start, ulong size)
{
	iotrace.start = start;
	iotrace.size = size;
	iotrace.offset = 0;
	iotrace.crc32 = 0;
}

void iotrace_get_buffer(ulong *start, ulong *size, ulong *offset, ulong *count)
{
	*start = iotrace.start;
	*size = iotrace.size;
	*offset = iotrace.offset;
	*count = iotrace.offset / sizeof(struct iotrace_record);
}
