// SPDX-License-Identifier: GPL-2.0+
/*
 * PCI emulation device for an x86 Primary-to-Sideband bus
 *
 * Copyright 2019 Google LLC
 * Written by Simon Glass <sjg@chromium.org>
 */

#define LOG_CATEGORY UCLASS_MISC
#define LOG_DEBUG

#include <common.h>
#include <axi.h>
#include <dm.h>
#include <pci.h>
#include <asm/test.h>
#include <p2sb.h>

/**
 * struct p2sb_emul_platdata - platform data for this device
 *
 * @command:	Current PCI command value
 * @bar:	Current base address values
 */
struct p2sb_emul_platdata {
	u16 command;
	u32 bar[6];
};

enum {
	/* This emulator supports 16 different devices */
	MEMMAP_SIZE	= 16 << PCR_PORTID_SHIFT,
};

static struct pci_bar {
	int type;
	u32 size;
} barinfo[] = {
	{ PCI_BASE_ADDRESS_MEM_TYPE_32, MEMMAP_SIZE },
	{ 0, 0 },
	{ 0, 0 },
	{ 0, 0 },
	{ 0, 0 },
	{ 0, 0 },
};

struct p2sb_emul_priv {
	u8 regs[16];
};

static int sandbox_p2sb_emul_read_config(const struct udevice *emul,
					 uint offset, ulong *valuep,
					 enum pci_size_t size)
{
	struct p2sb_emul_platdata *plat = dev_get_platdata(emul);

	switch (offset) {
	case PCI_COMMAND:
		*valuep = plat->command;
		break;
	case PCI_HEADER_TYPE:
		*valuep = PCI_HEADER_TYPE_NORMAL;
		break;
	case PCI_VENDOR_ID:
		*valuep = SANDBOX_PCI_VENDOR_ID;
		break;
	case PCI_DEVICE_ID:
		*valuep = SANDBOX_PCI_P2SB_EMUL_ID;
		break;
	case PCI_CLASS_DEVICE:
		if (size == PCI_SIZE_8) {
			*valuep = SANDBOX_PCI_CLASS_SUB_CODE;
		} else {
			*valuep = (SANDBOX_PCI_CLASS_CODE << 8) |
					SANDBOX_PCI_CLASS_SUB_CODE;
		}
		break;
	case PCI_CLASS_CODE:
		*valuep = SANDBOX_PCI_CLASS_CODE;
		break;
	case PCI_BASE_ADDRESS_0:
	case PCI_BASE_ADDRESS_1:
	case PCI_BASE_ADDRESS_2:
	case PCI_BASE_ADDRESS_3:
	case PCI_BASE_ADDRESS_4:
	case PCI_BASE_ADDRESS_5: {
		int barnum;
		u32 *bar;

		barnum = pci_offset_to_barnum(offset);
		bar = &plat->bar[barnum];

		*valuep = sandbox_pci_read_bar(*bar, barinfo[barnum].type,
					       barinfo[barnum].size);
		break;
	}
	case PCI_CAPABILITY_LIST:
		*valuep = PCI_CAP_ID_PM_OFFSET;
		break;
	}

	return 0;
}

static int sandbox_p2sb_emul_write_config(struct udevice *emul, uint offset,
					  ulong value, enum pci_size_t size)
{
	struct p2sb_emul_platdata *plat = dev_get_platdata(emul);

	switch (offset) {
	case PCI_COMMAND:
		plat->command = value;
		break;
	case PCI_BASE_ADDRESS_0:
	case PCI_BASE_ADDRESS_1: {
		int barnum;
		u32 *bar;

		barnum = pci_offset_to_barnum(offset);
		bar = &plat->bar[barnum];

		log_debug("w bar %d=%lx\n", barnum, value);
		*bar = value;
		/* space indicator (bit#0) is read-only */
		*bar |= barinfo[barnum].type;
		break;
	}
	}

	return 0;
}

static int sandbox_p2sb_emul_find_bar(struct udevice *emul, unsigned int addr,
				      int *barnump, unsigned int *offsetp)
{
	struct p2sb_emul_platdata *plat = dev_get_platdata(emul);
	int barnum;

	for (barnum = 0; barnum < ARRAY_SIZE(barinfo); barnum++) {
		unsigned int size = barinfo[barnum].size;
		u32 base = plat->bar[barnum] & ~PCI_BASE_ADDRESS_SPACE;

		if (addr >= base && addr < base + size) {
			*barnump = barnum;
			*offsetp = addr - base;
			return 0;
		}
	}
	*barnump = -1;

	return -ENOENT;
}

static int sandbox_p2sb_emul_read_io(struct udevice *dev, unsigned int addr,
				     ulong *valuep, enum pci_size_t size)
{
	unsigned int offset;
	int barnum;
	int ret;

	ret = sandbox_p2sb_emul_find_bar(dev, addr, &barnum, &offset);
	if (ret)
		return ret;

	if (barnum == 4)
		*valuep = offset;
	else if (barnum == 0)
		*valuep = offset;

	return 0;
}

static int sandbox_p2sb_emul_write_io(struct udevice *dev, unsigned int addr,
				      ulong value, enum pci_size_t size)
{
	unsigned int offset;
	int barnum;
	int ret;

	ret = sandbox_p2sb_emul_find_bar(dev, addr, &barnum, &offset);
	if (ret)
		return ret;

	return 0;
}

static int find_p2sb_channel(struct udevice *emul, uint offset,
			     struct udevice **devp)
{
	uint pid = offset >> PCR_PORTID_SHIFT;
	struct udevice *p2sb, *dev;
	int ret;

	ret = sandbox_pci_get_client(emul, &p2sb);
	if (ret)
		return log_msg_ret("No client", ret);

	device_foreach_child(dev, p2sb) {
		struct p2sb_child_platdata *pplat =
			 dev_get_parent_platdata(dev);

		log_debug("   - child %s, pid %d, want %d\n", dev->name,
			  pplat->pid, pid);
		if (pid == pplat->pid) {
			*devp = dev;
			return 0;
		}
	}

	return -ENOENT;
}

static int sandbox_p2sb_emul_map_physmem(struct udevice *dev,
					 phys_addr_t addr, unsigned long *lenp,
					 void **ptrp)
{
	struct p2sb_emul_priv *priv = dev_get_priv(dev);
	struct udevice *child;
	unsigned int offset;
	int barnum;
	int ret;

	log_debug("map %x: ", (uint)addr);
	ret = sandbox_p2sb_emul_find_bar(dev, addr, &barnum, &offset);
	if (ret)
		return log_msg_ret("Cannot find bar", ret);
	log_debug("bar %d, offset %x\n", barnum, offset);

	if (barnum != 0)
		return log_msg_ret("Unknown BAR", -EINVAL);

	ret = find_p2sb_channel(dev, offset, &child);
	if (ret)
		return log_msg_ret("Cannot find channel", ret);

	offset &= ((1 << PCR_PORTID_SHIFT) - 1);
	ret = axi_read(child, offset, priv->regs, AXI_SIZE_32);
	if (ret)
		return log_msg_ret("Child read failed", ret);
	*ptrp = priv->regs + (offset & 3);
	*lenp = 4;

	return 0;
}

static struct dm_pci_emul_ops sandbox_p2sb_emul_emul_ops = {
	.read_config = sandbox_p2sb_emul_read_config,
	.write_config = sandbox_p2sb_emul_write_config,
	.read_io = sandbox_p2sb_emul_read_io,
	.write_io = sandbox_p2sb_emul_write_io,
	.map_physmem = sandbox_p2sb_emul_map_physmem,
};

static const struct udevice_id sandbox_p2sb_emul_ids[] = {
	{ .compatible = "sandbox,p2sb-emul" },
	{ }
};

U_BOOT_DRIVER(sandbox_p2sb_emul_emul) = {
	.name		= "sandbox_p2sb_emul_emul",
	.id		= UCLASS_PCI_EMUL,
	.of_match	= sandbox_p2sb_emul_ids,
	.ops		= &sandbox_p2sb_emul_emul_ops,
	.priv_auto_alloc_size = sizeof(struct p2sb_emul_priv),
	.platdata_auto_alloc_size = sizeof(struct p2sb_emul_platdata),
};

static struct pci_device_id sandbox_p2sb_emul_supported[] = {
	{ PCI_VDEVICE(SANDBOX, SANDBOX_PCI_PMC_EMUL_ID) },
	{},
};

U_BOOT_PCI_DEVICE(sandbox_p2sb_emul_emul, sandbox_p2sb_emul_supported);
