From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001
From: Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com>
Date: Tue, 10 Oct 2023 14:33:42 +0000
Subject: Add submodule dependency files

Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
---
 roms/u-boot/drivers/pci_endpoint/Kconfig           |  34 +++
 roms/u-boot/drivers/pci_endpoint/Makefile          |   8 +
 roms/u-boot/drivers/pci_endpoint/pci_ep-uclass.c   | 225 +++++++++++++++
 roms/u-boot/drivers/pci_endpoint/pcie-cadence-ep.c | 178 ++++++++++++
 roms/u-boot/drivers/pci_endpoint/pcie-cadence.h    | 310 +++++++++++++++++++++
 roms/u-boot/drivers/pci_endpoint/sandbox-pci_ep.c  | 179 ++++++++++++
 6 files changed, 934 insertions(+)
 create mode 100644 roms/u-boot/drivers/pci_endpoint/Kconfig
 create mode 100644 roms/u-boot/drivers/pci_endpoint/Makefile
 create mode 100644 roms/u-boot/drivers/pci_endpoint/pci_ep-uclass.c
 create mode 100644 roms/u-boot/drivers/pci_endpoint/pcie-cadence-ep.c
 create mode 100644 roms/u-boot/drivers/pci_endpoint/pcie-cadence.h
 create mode 100644 roms/u-boot/drivers/pci_endpoint/sandbox-pci_ep.c

(limited to 'roms/u-boot/drivers/pci_endpoint')

diff --git a/roms/u-boot/drivers/pci_endpoint/Kconfig b/roms/u-boot/drivers/pci_endpoint/Kconfig
new file mode 100644
index 000000000..19cfa0aaf
--- /dev/null
+++ b/roms/u-boot/drivers/pci_endpoint/Kconfig
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# PCI Endpoint Support
+#
+
+menu "PCI Endpoint"
+
+config PCI_ENDPOINT
+	bool "PCI Endpoint Support"
+	depends on DM
+	help
+	   Enable this configuration option to support configurable PCI
+	   endpoints. This should be enabled if the platform has a PCI
+	   controllers that can operate in endpoint mode (as a device
+	   connected to PCI host or bridge).
+
+config PCIE_CADENCE_EP
+	bool "Cadence PCIe endpoint controller"
+	depends on PCI_ENDPOINT
+	help
+	  Say Y here if you want to support the Cadence PCIe controller in
+	  endpoint mode. This PCIe controller may be embedded into many
+	  different vendors SoCs.
+
+config PCI_SANDBOX_EP
+	bool "Sandbox PCIe endpoint controller"
+	depends on PCI_ENDPOINT
+	help
+	  Say Y here if you want to support the Sandbox PCIe controller in
+	  endpoint mode.
+	  The sandbox driver act as a dummy driver which stores and
+	  retrieves PCIe endpoint configuration as is.
+
+endmenu
diff --git a/roms/u-boot/drivers/pci_endpoint/Makefile b/roms/u-boot/drivers/pci_endpoint/Makefile
new file mode 100644
index 000000000..3cd987259
--- /dev/null
+++ b/roms/u-boot/drivers/pci_endpoint/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2019
+# Ramon Fried <ramon.fried@gmail.com>
+
+obj-y += pci_ep-uclass.o
+obj-$(CONFIG_PCIE_CADENCE_EP) += pcie-cadence-ep.o
+obj-$(CONFIG_PCI_SANDBOX_EP) += sandbox-pci_ep.o
diff --git a/roms/u-boot/drivers/pci_endpoint/pci_ep-uclass.c b/roms/u-boot/drivers/pci_endpoint/pci_ep-uclass.c
new file mode 100644
index 000000000..5555cf5a8
--- /dev/null
+++ b/roms/u-boot/drivers/pci_endpoint/pci_ep-uclass.c
@@ -0,0 +1,225 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * PCI Endpoint uclass
+ *
+ * Based on Linux PCI-EP driver written by
+ * Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * Copyright (c) 2019
+ * Written by Ramon Fried <ramon.fried@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/global_data.h>
+#include <linux/log2.h>
+#include <pci_ep.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int pci_ep_write_header(struct udevice *dev, uint fn, struct pci_ep_header *hdr)
+{
+	struct pci_ep_ops *ops = pci_ep_get_ops(dev);
+
+	if (!ops->write_header)
+		return -ENOSYS;
+
+	return ops->write_header(dev, fn, hdr);
+}
+
+int pci_ep_read_header(struct udevice *dev, uint fn, struct pci_ep_header *hdr)
+{
+	struct pci_ep_ops *ops = pci_ep_get_ops(dev);
+
+	if (!ops->read_header)
+		return -ENOSYS;
+
+	return ops->read_header(dev, fn, hdr);
+}
+
+int pci_ep_set_bar(struct udevice *dev, uint func_no, struct pci_bar *ep_bar)
+{
+	struct pci_ep_ops *ops = pci_ep_get_ops(dev);
+	int flags = ep_bar->flags;
+
+	/* Some basic bar validity checks */
+	if (ep_bar->barno > BAR_5 || ep_bar->barno < BAR_0)
+		return -EINVAL;
+
+	if ((ep_bar->barno == BAR_5 &&
+	     (flags & PCI_BASE_ADDRESS_MEM_TYPE_64)) ||
+	    ((flags & PCI_BASE_ADDRESS_SPACE_IO) &&
+	     (flags & PCI_BASE_ADDRESS_IO_MASK)) ||
+	    (upper_32_bits(ep_bar->size) &&
+	     !(flags & PCI_BASE_ADDRESS_MEM_TYPE_64)))
+		return -EINVAL;
+
+	if (!ops->set_bar)
+		return -ENOSYS;
+
+	return ops->set_bar(dev, func_no, ep_bar);
+}
+
+int pci_ep_read_bar(struct udevice *dev, uint func_no, struct pci_bar *ep_bar,
+		    enum pci_barno barno)
+{
+	struct pci_ep_ops *ops = pci_ep_get_ops(dev);
+
+	/* Some basic bar validity checks */
+	if (barno > BAR_5 || barno < BAR_0)
+		return -EINVAL;
+
+	if (!ops->read_bar)
+		return -ENOSYS;
+
+	return ops->read_bar(dev, func_no, ep_bar, barno);
+}
+
+int pci_ep_clear_bar(struct udevice *dev, uint func_num, enum pci_barno bar)
+{
+	struct pci_ep_ops *ops = pci_ep_get_ops(dev);
+
+	if (!ops->clear_bar)
+		return -ENOSYS;
+
+	return ops->clear_bar(dev, func_num, bar);
+}
+
+int pci_ep_map_addr(struct udevice *dev, uint func_no, phys_addr_t addr,
+		    u64 pci_addr, size_t size)
+{
+	struct pci_ep_ops *ops = pci_ep_get_ops(dev);
+
+	if (!ops->map_addr)
+		return -ENOSYS;
+
+	return ops->map_addr(dev, func_no, addr, pci_addr, size);
+}
+
+int pci_ep_unmap_addr(struct udevice *dev, uint func_no, phys_addr_t addr)
+{
+	struct pci_ep_ops *ops = pci_ep_get_ops(dev);
+
+	if (!ops->unmap_addr)
+		return -ENOSYS;
+
+	return ops->unmap_addr(dev, func_no, addr);
+}
+
+int pci_ep_set_msi(struct udevice *dev, uint func_no, uint interrupts)
+{
+	struct pci_ep_ops *ops = pci_ep_get_ops(dev);
+	uint encode_int;
+
+	if (interrupts > 32)
+		return -EINVAL;
+
+	if (!ops->set_msi)
+		return -ENOSYS;
+
+	/* MSI spec permits allocation of
+	 * only 1, 2, 4, 8, 16, 32 interrupts
+	 */
+	encode_int = order_base_2(interrupts);
+
+	return ops->set_msi(dev, func_no, encode_int);
+}
+
+int pci_ep_get_msi(struct udevice *dev, uint func_no)
+{
+	struct pci_ep_ops *ops = pci_ep_get_ops(dev);
+	int interrupt;
+
+	if (!ops->get_msi)
+		return -ENOSYS;
+
+	interrupt = ops->get_msi(dev, func_no);
+
+	if (interrupt < 0)
+		return 0;
+
+	/* Translate back from order base 2*/
+	interrupt = 1 << interrupt;
+
+	return interrupt;
+}
+
+int pci_ep_set_msix(struct udevice *dev, uint func_no, uint interrupts)
+{
+	struct pci_ep_ops *ops = pci_ep_get_ops(dev);
+
+	if (interrupts < 1 || interrupts > 2048)
+		return -EINVAL;
+
+	if (!ops->set_msix)
+		return -ENOSYS;
+
+	return ops->set_msix(dev, func_no, interrupts - 1);
+}
+
+int pci_ep_get_msix(struct udevice *dev, uint func_no)
+{
+	struct pci_ep_ops *ops = pci_ep_get_ops(dev);
+	int interrupt;
+
+	if (!ops->get_msix)
+		return -ENOSYS;
+
+	interrupt = ops->get_msix(dev, func_no);
+
+	if (interrupt < 0)
+		return 0;
+
+	return interrupt + 1;
+}
+
+int pci_ep_raise_irq(struct udevice *dev, uint func_no,
+		     enum pci_ep_irq_type type, uint interrupt_num)
+{
+	struct pci_ep_ops *ops = pci_ep_get_ops(dev);
+
+	if (!ops->raise_irq)
+		return -ENOSYS;
+
+	return ops->raise_irq(dev, func_no, type, interrupt_num);
+}
+
+int pci_ep_start(struct udevice *dev)
+{
+	struct pci_ep_ops *ops = pci_ep_get_ops(dev);
+
+	if (!ops->start)
+		return -ENOSYS;
+
+	return ops->start(dev);
+}
+
+int pci_ep_stop(struct udevice *dev)
+{
+	struct pci_ep_ops *ops = pci_ep_get_ops(dev);
+
+	if (!ops->stop)
+		return -ENOSYS;
+
+	return ops->stop(dev);
+}
+
+UCLASS_DRIVER(pci_ep) = {
+	.id		= UCLASS_PCI_EP,
+	.name		= "pci_ep",
+	.flags		= DM_UC_FLAG_SEQ_ALIAS,
+};
+
+int pci_ep_init(void)
+{
+	struct udevice *dev;
+
+	for (uclass_first_device_check(UCLASS_PCI_EP, &dev);
+	     dev;
+	     uclass_next_device_check(&dev)) {
+		;
+	}
+
+	return 0;
+}
diff --git a/roms/u-boot/drivers/pci_endpoint/pcie-cadence-ep.c b/roms/u-boot/drivers/pci_endpoint/pcie-cadence-ep.c
new file mode 100644
index 000000000..d58c64982
--- /dev/null
+++ b/roms/u-boot/drivers/pci_endpoint/pcie-cadence-ep.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2019
+ * Written by Ramon Fried <ramon.fried@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <pci_ep.h>
+#include <asm/global_data.h>
+#include <linux/sizes.h>
+#include <linux/log2.h>
+#include "pcie-cadence.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int cdns_write_header(struct udevice *dev, uint fn,
+			     struct pci_ep_header *hdr)
+{
+	struct cdns_pcie *pcie = dev_get_priv(dev);
+
+	cdns_pcie_ep_fn_writew(pcie, fn, PCI_DEVICE_ID, hdr->deviceid);
+	cdns_pcie_ep_fn_writeb(pcie, fn, PCI_REVISION_ID, hdr->revid);
+	cdns_pcie_ep_fn_writeb(pcie, fn, PCI_CLASS_PROG,
+			       hdr->progif_code);
+	cdns_pcie_ep_fn_writew(pcie, fn, PCI_CLASS_DEVICE,
+			       hdr->subclass_code |
+			       hdr->baseclass_code << 8);
+	cdns_pcie_ep_fn_writeb(pcie, fn, PCI_CACHE_LINE_SIZE,
+			       hdr->cache_line_size);
+	cdns_pcie_ep_fn_writew(pcie, fn, PCI_SUBSYSTEM_ID,
+			       hdr->subsys_id);
+	cdns_pcie_ep_fn_writeb(pcie, fn, PCI_INTERRUPT_PIN,
+			       hdr->interrupt_pin);
+
+	/*
+	 * Vendor ID can only be modified from function 0, all other functions
+	 * use the same vendor ID as function 0.
+	 */
+	if (fn == 0) {
+		/* Update the vendor IDs. */
+		u32 id = CDNS_PCIE_LM_ID_VENDOR(hdr->vendorid) |
+			 CDNS_PCIE_LM_ID_SUBSYS(hdr->subsys_vendor_id);
+
+		cdns_pcie_writel(pcie, CDNS_PCIE_LM_ID, id);
+	}
+
+	return 0;
+}
+
+static int cdns_set_bar(struct udevice *dev, uint fn, struct pci_bar *ep_bar)
+{
+	struct cdns_pcie *pcie = dev_get_priv(dev);
+	dma_addr_t bar_phys = ep_bar->phys_addr;
+	enum pci_barno bar = ep_bar->barno;
+	int flags = ep_bar->flags;
+	u32 addr0, addr1, reg, cfg, b, aperture, ctrl;
+	u64 sz;
+
+	/* BAR size is 2^(aperture + 7) */
+	sz = max_t(size_t, ep_bar->size, CDNS_PCIE_EP_MIN_APERTURE);
+	/*
+	 * roundup_pow_of_two() returns an unsigned long, which is not suited
+	 * for 64bit values.
+	 */
+	sz = 1ULL << fls64(sz - 1);
+	aperture = ilog2(sz) - 7; /* 128B -> 0, 256B -> 1, 512B -> 2, ... */
+
+	if ((flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
+		ctrl = CDNS_PCIE_LM_BAR_CFG_CTRL_IO_32BITS;
+	} else {
+		bool is_prefetch = !!(flags & PCI_BASE_ADDRESS_MEM_PREFETCH);
+		bool is_64bits = (sz > SZ_2G) |
+			!!(ep_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64);
+
+		if (is_64bits && (bar & 1))
+			return -EINVAL;
+
+		if (is_64bits && !(flags & PCI_BASE_ADDRESS_MEM_TYPE_64))
+			ep_bar->flags |= PCI_BASE_ADDRESS_MEM_TYPE_64;
+
+		if (is_64bits && is_prefetch)
+			ctrl = CDNS_PCIE_LM_BAR_CFG_CTRL_PREFETCH_MEM_64BITS;
+		else if (is_prefetch)
+			ctrl = CDNS_PCIE_LM_BAR_CFG_CTRL_PREFETCH_MEM_32BITS;
+		else if (is_64bits)
+			ctrl = CDNS_PCIE_LM_BAR_CFG_CTRL_MEM_64BITS;
+		else
+			ctrl = CDNS_PCIE_LM_BAR_CFG_CTRL_MEM_32BITS;
+	}
+
+	addr0 = lower_32_bits(bar_phys);
+	addr1 = upper_32_bits(bar_phys);
+	cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar),
+			 addr0);
+	cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar),
+			 addr1);
+
+	if (bar < BAR_4) {
+		reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG0(fn);
+		b = bar;
+	} else {
+		reg = CDNS_PCIE_LM_EP_FUNC_BAR_CFG1(fn);
+		b = bar - BAR_4;
+	}
+
+	cfg = cdns_pcie_readl(pcie, reg);
+	cfg &= ~(CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_APERTURE_MASK(b) |
+		 CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL_MASK(b));
+	cfg |= (CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_APERTURE(b, aperture) |
+		CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL(b, ctrl));
+	cdns_pcie_writel(pcie, reg, cfg);
+
+	return 0;
+}
+
+static int cdns_set_msi(struct udevice *dev, uint fn, uint mmc)
+{
+	struct cdns_pcie *pcie = dev_get_priv(dev);
+	u32 cap = CDNS_PCIE_EP_FUNC_MSI_CAP_OFFSET;
+
+	/*
+	 * Set the Multiple Message Capable bitfield into the Message Control
+	 * register.
+	 */
+	u16 flags;
+
+	flags = cdns_pcie_ep_fn_readw(pcie, fn, cap + PCI_MSI_FLAGS);
+	flags = (flags & ~PCI_MSI_FLAGS_QMASK) | (mmc << 1);
+	flags |= PCI_MSI_FLAGS_64BIT;
+	flags &= ~PCI_MSI_FLAGS_MASKBIT;
+	cdns_pcie_ep_fn_writew(pcie, fn, cap + PCI_MSI_FLAGS, flags);
+
+	return 0;
+}
+
+static struct pci_ep_ops cdns_pci_ep_ops = {
+	.write_header = cdns_write_header,
+	.set_bar = cdns_set_bar,
+	.set_msi = cdns_set_msi,
+};
+
+static int cdns_pci_ep_probe(struct udevice *dev)
+{
+	struct cdns_pcie *pdata = dev_get_priv(dev);
+
+	pdata->reg_base = dev_read_addr_ptr(dev);
+	if (!pdata->reg_base)
+		return -ENOMEM;
+
+	pdata->max_functions = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+					      "max-functions", 1);
+	pdata->max_regions = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+					    "cdns,max-outbound-regions", 8);
+
+	return 0;
+}
+
+static int cdns_pci_ep_remove(struct udevice *dev)
+{
+	return 0;
+}
+
+const struct udevice_id cadence_pci_ep_of_match[] = {
+	{ .compatible = "cdns,cdns-pcie-ep" },
+	{ }
+};
+
+U_BOOT_DRIVER(cdns_pcie) = {
+	.name	= "cdns,pcie-ep",
+	.id	= UCLASS_PCI_EP,
+	.of_match = cadence_pci_ep_of_match,
+	.ops = &cdns_pci_ep_ops,
+	.probe = cdns_pci_ep_probe,
+	.remove = cdns_pci_ep_remove,
+	.priv_auto	= sizeof(struct cdns_pcie),
+};
diff --git a/roms/u-boot/drivers/pci_endpoint/pcie-cadence.h b/roms/u-boot/drivers/pci_endpoint/pcie-cadence.h
new file mode 100644
index 000000000..8a659c36a
--- /dev/null
+++ b/roms/u-boot/drivers/pci_endpoint/pcie-cadence.h
@@ -0,0 +1,310 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Cadence PCIe controlloer definitions
+ * Adapted from linux kernel driver.
+ * Copyright (c) 2017 Cadence
+ *
+ * Copyright (c) 2019
+ * Written by Ramon Fried <ramon.fried@gmail.com>
+ */
+
+#ifndef PCIE_CADENCE_H
+#define PCIE_CADENCE_H
+
+#include <common.h>
+#include <pci_ep.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+
+/*
+ * Local Management Registers
+ */
+#define CDNS_PCIE_LM_BASE	0x00100000
+
+/* Vendor ID Register */
+#define CDNS_PCIE_LM_ID		(CDNS_PCIE_LM_BASE + 0x0044)
+#define  CDNS_PCIE_LM_ID_VENDOR_MASK	GENMASK(15, 0)
+#define  CDNS_PCIE_LM_ID_VENDOR_SHIFT	0
+#define  CDNS_PCIE_LM_ID_VENDOR(vid) \
+	(((vid) << CDNS_PCIE_LM_ID_VENDOR_SHIFT) & CDNS_PCIE_LM_ID_VENDOR_MASK)
+#define  CDNS_PCIE_LM_ID_SUBSYS_MASK	GENMASK(31, 16)
+#define  CDNS_PCIE_LM_ID_SUBSYS_SHIFT	16
+#define  CDNS_PCIE_LM_ID_SUBSYS(sub) \
+	(((sub) << CDNS_PCIE_LM_ID_SUBSYS_SHIFT) & CDNS_PCIE_LM_ID_SUBSYS_MASK)
+
+/* Root Port Requestor ID Register */
+#define CDNS_PCIE_LM_RP_RID	(CDNS_PCIE_LM_BASE + 0x0228)
+#define  CDNS_PCIE_LM_RP_RID_MASK	GENMASK(15, 0)
+#define  CDNS_PCIE_LM_RP_RID_SHIFT	0
+#define  CDNS_PCIE_LM_RP_RID_(rid) \
+	(((rid) << CDNS_PCIE_LM_RP_RID_SHIFT) & CDNS_PCIE_LM_RP_RID_MASK)
+
+/* Endpoint Bus and Device Number Register */
+#define CDNS_PCIE_LM_EP_ID	(CDNS_PCIE_LM_BASE + 0x022c)
+#define  CDNS_PCIE_LM_EP_ID_DEV_MASK	GENMASK(4, 0)
+#define  CDNS_PCIE_LM_EP_ID_DEV_SHIFT	0
+#define  CDNS_PCIE_LM_EP_ID_BUS_MASK	GENMASK(15, 8)
+#define  CDNS_PCIE_LM_EP_ID_BUS_SHIFT	8
+
+/* Endpoint Function f BAR b Configuration Registers */
+#define CDNS_PCIE_LM_EP_FUNC_BAR_CFG0(fn) \
+	(CDNS_PCIE_LM_BASE + 0x0240 + (fn) * 0x0008)
+#define CDNS_PCIE_LM_EP_FUNC_BAR_CFG1(fn) \
+	(CDNS_PCIE_LM_BASE + 0x0244 + (fn) * 0x0008)
+#define  CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_APERTURE_MASK(b) \
+	(GENMASK(4, 0) << ((b) * 8))
+#define  CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_APERTURE(b, a) \
+	(((a) << ((b) * 8)) & CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_APERTURE_MASK(b))
+#define  CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL_MASK(b) \
+	(GENMASK(7, 5) << ((b) * 8))
+#define  CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL(b, c) \
+	(((c) << ((b) * 8 + 5)) & CDNS_PCIE_LM_EP_FUNC_BAR_CFG_BAR_CTRL_MASK(b))
+
+/* Endpoint Function Configuration Register */
+#define CDNS_PCIE_LM_EP_FUNC_CFG	(CDNS_PCIE_LM_BASE + 0x02c0)
+
+/* Root Complex BAR Configuration Register */
+#define CDNS_PCIE_LM_RC_BAR_CFG	(CDNS_PCIE_LM_BASE + 0x0300)
+#define  CDNS_PCIE_LM_RC_BAR_CFG_BAR0_APERTURE_MASK	GENMASK(5, 0)
+#define  CDNS_PCIE_LM_RC_BAR_CFG_BAR0_APERTURE(a) \
+	(((a) << 0) & CDNS_PCIE_LM_RC_BAR_CFG_BAR0_APERTURE_MASK)
+#define  CDNS_PCIE_LM_RC_BAR_CFG_BAR0_CTRL_MASK		GENMASK(8, 6)
+#define  CDNS_PCIE_LM_RC_BAR_CFG_BAR0_CTRL(c) \
+	(((c) << 6) & CDNS_PCIE_LM_RC_BAR_CFG_BAR0_CTRL_MASK)
+#define  CDNS_PCIE_LM_RC_BAR_CFG_BAR1_APERTURE_MASK	GENMASK(13, 9)
+#define  CDNS_PCIE_LM_RC_BAR_CFG_BAR1_APERTURE(a) \
+	(((a) << 9) & CDNS_PCIE_LM_RC_BAR_CFG_BAR1_APERTURE_MASK)
+#define  CDNS_PCIE_LM_RC_BAR_CFG_BAR1_CTRL_MASK		GENMASK(16, 14)
+#define  CDNS_PCIE_LM_RC_BAR_CFG_BAR1_CTRL(c) \
+	(((c) << 14) & CDNS_PCIE_LM_RC_BAR_CFG_BAR1_CTRL_MASK)
+#define  CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_ENABLE	BIT(17)
+#define  CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_32BITS	0
+#define  CDNS_PCIE_LM_RC_BAR_CFG_PREFETCH_MEM_64BITS	BIT(18)
+#define  CDNS_PCIE_LM_RC_BAR_CFG_IO_ENABLE		BIT(19)
+#define  CDNS_PCIE_LM_RC_BAR_CFG_IO_16BITS		0
+#define  CDNS_PCIE_LM_RC_BAR_CFG_IO_32BITS		BIT(20)
+#define  CDNS_PCIE_LM_RC_BAR_CFG_CHECK_ENABLE		BIT(31)
+
+/* BAR control values applicable to both Endpoint Function and Root Complex */
+#define  CDNS_PCIE_LM_BAR_CFG_CTRL_DISABLED		0x0
+#define  CDNS_PCIE_LM_BAR_CFG_CTRL_IO_32BITS		0x1
+#define  CDNS_PCIE_LM_BAR_CFG_CTRL_MEM_32BITS		0x4
+#define  CDNS_PCIE_LM_BAR_CFG_CTRL_PREFETCH_MEM_32BITS	0x5
+#define  CDNS_PCIE_LM_BAR_CFG_CTRL_MEM_64BITS		0x6
+#define  CDNS_PCIE_LM_BAR_CFG_CTRL_PREFETCH_MEM_64BITS	0x7
+
+/*
+ * Endpoint Function Registers (PCI configuration space for endpoint functions)
+ */
+#define CDNS_PCIE_EP_FUNC_BASE(fn)	(((fn) << 12) & GENMASK(19, 12))
+
+#define CDNS_PCIE_EP_FUNC_MSI_CAP_OFFSET	0x90
+
+/*
+ * Root Port Registers (PCI configuration space for the root port function)
+ */
+#define CDNS_PCIE_RP_BASE	0x00200000
+
+/*
+ * Address Translation Registers
+ */
+#define CDNS_PCIE_AT_BASE	0x00400000
+
+/* Region r Outbound AXI to PCIe Address Translation Register 0 */
+#define CDNS_PCIE_AT_OB_REGION_PCI_ADDR0(r) \
+	(CDNS_PCIE_AT_BASE + 0x0000 + ((r) & 0x1f) * 0x0020)
+#define  CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_NBITS_MASK	GENMASK(5, 0)
+#define  CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_NBITS(nbits) \
+	(((nbits) - 1) & CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_NBITS_MASK)
+#define  CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN_MASK	GENMASK(19, 12)
+#define  CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN(devfn) \
+	(((devfn) << 12) & CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN_MASK)
+#define  CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK	GENMASK(27, 20)
+#define  CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_BUS(bus) \
+	(((bus) << 20) & CDNS_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK)
+
+/* Region r Outbound AXI to PCIe Address Translation Register 1 */
+#define CDNS_PCIE_AT_OB_REGION_PCI_ADDR1(r) \
+	(CDNS_PCIE_AT_BASE + 0x0004 + ((r) & 0x1f) * 0x0020)
+
+/* Region r Outbound PCIe Descriptor Register 0 */
+#define CDNS_PCIE_AT_OB_REGION_DESC0(r) \
+	(CDNS_PCIE_AT_BASE + 0x0008 + ((r) & 0x1f) * 0x0020)
+#define  CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_MASK		GENMASK(3, 0)
+#define  CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_MEM		0x2
+#define  CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_IO		0x6
+#define  CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE0	0xa
+#define  CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_CONF_TYPE1	0xb
+#define  CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_NORMAL_MSG	0xc
+#define  CDNS_PCIE_AT_OB_REGION_DESC0_TYPE_VENDOR_MSG	0xd
+/* Bit 23 MUST be set in RC mode. */
+#define  CDNS_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID	BIT(23)
+#define  CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK	GENMASK(31, 24)
+#define  CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN(devfn) \
+	(((devfn) << 24) & CDNS_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK)
+
+/* Region r Outbound PCIe Descriptor Register 1 */
+#define CDNS_PCIE_AT_OB_REGION_DESC1(r)	\
+	(CDNS_PCIE_AT_BASE + 0x000c + ((r) & 0x1f) * 0x0020)
+#define  CDNS_PCIE_AT_OB_REGION_DESC1_BUS_MASK	GENMASK(7, 0)
+#define  CDNS_PCIE_AT_OB_REGION_DESC1_BUS(bus) \
+	((bus) & CDNS_PCIE_AT_OB_REGION_DESC1_BUS_MASK)
+
+/* Region r AXI Region Base Address Register 0 */
+#define CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r) \
+	(CDNS_PCIE_AT_BASE + 0x0018 + ((r) & 0x1f) * 0x0020)
+#define  CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS_MASK	GENMASK(5, 0)
+#define  CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS(nbits) \
+	(((nbits) - 1) & CDNS_PCIE_AT_OB_REGION_CPU_ADDR0_NBITS_MASK)
+
+/* Region r AXI Region Base Address Register 1 */
+#define CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r) \
+	(CDNS_PCIE_AT_BASE + 0x001c + ((r) & 0x1f) * 0x0020)
+
+/* Root Port BAR Inbound PCIe to AXI Address Translation Register */
+#define CDNS_PCIE_AT_IB_RP_BAR_ADDR0(bar) \
+	(CDNS_PCIE_AT_BASE + 0x0800 + (bar) * 0x0008)
+#define  CDNS_PCIE_AT_IB_RP_BAR_ADDR0_NBITS_MASK	GENMASK(5, 0)
+#define  CDNS_PCIE_AT_IB_RP_BAR_ADDR0_NBITS(nbits) \
+	(((nbits) - 1) & CDNS_PCIE_AT_IB_RP_BAR_ADDR0_NBITS_MASK)
+#define CDNS_PCIE_AT_IB_RP_BAR_ADDR1(bar) \
+	(CDNS_PCIE_AT_BASE + 0x0804 + (bar) * 0x0008)
+
+/* AXI link down register */
+#define CDNS_PCIE_AT_LINKDOWN (CDNS_PCIE_AT_BASE + 0x0824)
+
+enum cdns_pcie_rp_bar {
+	RP_BAR0,
+	RP_BAR1,
+	RP_NO_BAR
+};
+
+/* Endpoint Function BAR Inbound PCIe to AXI Address Translation Register */
+#define CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar) \
+	(CDNS_PCIE_AT_BASE + 0x0840 + (fn) * 0x0040 + (bar) * 0x0008)
+#define CDNS_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar) \
+	(CDNS_PCIE_AT_BASE + 0x0844 + (fn) * 0x0040 + (bar) * 0x0008)
+
+/* Normal/Vendor specific message access: offset inside some outbound region */
+#define CDNS_PCIE_NORMAL_MSG_ROUTING_MASK	GENMASK(7, 5)
+#define CDNS_PCIE_NORMAL_MSG_ROUTING(route) \
+	(((route) << 5) & CDNS_PCIE_NORMAL_MSG_ROUTING_MASK)
+#define CDNS_PCIE_NORMAL_MSG_CODE_MASK		GENMASK(15, 8)
+#define CDNS_PCIE_NORMAL_MSG_CODE(code) \
+	(((code) << 8) & CDNS_PCIE_NORMAL_MSG_CODE_MASK)
+#define CDNS_PCIE_MSG_NO_DATA			BIT(16)
+
+#define CDNS_PCIE_EP_MIN_APERTURE		128	/* 128 bytes */
+
+enum cdns_pcie_msg_code {
+	MSG_CODE_ASSERT_INTA	= 0x20,
+	MSG_CODE_ASSERT_INTB	= 0x21,
+	MSG_CODE_ASSERT_INTC	= 0x22,
+	MSG_CODE_ASSERT_INTD	= 0x23,
+	MSG_CODE_DEASSERT_INTA	= 0x24,
+	MSG_CODE_DEASSERT_INTB	= 0x25,
+	MSG_CODE_DEASSERT_INTC	= 0x26,
+	MSG_CODE_DEASSERT_INTD	= 0x27,
+};
+
+enum cdns_pcie_msg_routing {
+	/* Route to Root Complex */
+	MSG_ROUTING_TO_RC,
+
+	/* Use Address Routing */
+	MSG_ROUTING_BY_ADDR,
+
+	/* Use ID Routing */
+	MSG_ROUTING_BY_ID,
+
+	/* Route as Broadcast Message from Root Complex */
+	MSG_ROUTING_BCAST,
+
+	/* Local message; terminate at receiver (INTx messages) */
+	MSG_ROUTING_LOCAL,
+
+	/* Gather & route to Root Complex (PME_TO_Ack message) */
+	MSG_ROUTING_GATHER,
+};
+
+struct cdns_pcie {
+	void __iomem *reg_base;
+	u32	max_functions;
+	u32	max_regions;
+};
+
+/* Register access */
+static inline void cdns_pcie_writeb(struct cdns_pcie *pcie, u32 reg, u8 value)
+{
+	writeb(value, pcie->reg_base + reg);
+}
+
+static inline void cdns_pcie_writew(struct cdns_pcie *pcie, u32 reg, u16 value)
+{
+	writew(value, pcie->reg_base + reg);
+}
+
+static inline void cdns_pcie_writel(struct cdns_pcie *pcie, u32 reg, u32 value)
+{
+	writel(value, pcie->reg_base + reg);
+}
+
+static inline u32 cdns_pcie_readl(struct cdns_pcie *pcie, u32 reg)
+{
+	return readl(pcie->reg_base + reg);
+}
+
+/* Root Port register access */
+static inline void cdns_pcie_rp_writeb(struct cdns_pcie *pcie,
+				       u32 reg, u8 value)
+{
+	writeb(value, pcie->reg_base + CDNS_PCIE_RP_BASE + reg);
+}
+
+static inline void cdns_pcie_rp_writew(struct cdns_pcie *pcie,
+				       u32 reg, u16 value)
+{
+	writew(value, pcie->reg_base + CDNS_PCIE_RP_BASE + reg);
+}
+
+static inline void cdns_pcie_rp_writel(struct cdns_pcie *pcie,
+				       u32 reg, u32 value)
+{
+	writel(value, pcie->reg_base + CDNS_PCIE_RP_BASE + reg);
+}
+
+/* Endpoint Function register access */
+static inline void cdns_pcie_ep_fn_writeb(struct cdns_pcie *pcie, u8 fn,
+					  u32 reg, u8 value)
+{
+	writeb(value, pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg);
+}
+
+static inline void cdns_pcie_ep_fn_writew(struct cdns_pcie *pcie, u8 fn,
+					  u32 reg, u16 value)
+{
+	writew(value, pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg);
+}
+
+static inline void cdns_pcie_ep_fn_writel(struct cdns_pcie *pcie, u8 fn,
+					  u32 reg, u32 value)
+{
+	writel(value, pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg);
+}
+
+static inline u8 cdns_pcie_ep_fn_readb(struct cdns_pcie *pcie, u8 fn, u32 reg)
+{
+	return readb(pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg);
+}
+
+static inline u16 cdns_pcie_ep_fn_readw(struct cdns_pcie *pcie, u8 fn, u32 reg)
+{
+	return readw(pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg);
+}
+
+static inline u32 cdns_pcie_ep_fn_readl(struct cdns_pcie *pcie, u8 fn, u32 reg)
+{
+	return readl(pcie->reg_base + CDNS_PCIE_EP_FUNC_BASE(fn) + reg);
+}
+
+#endif /* end of include guard: PCIE_CADENCE_H */
diff --git a/roms/u-boot/drivers/pci_endpoint/sandbox-pci_ep.c b/roms/u-boot/drivers/pci_endpoint/sandbox-pci_ep.c
new file mode 100644
index 000000000..de148cddb
--- /dev/null
+++ b/roms/u-boot/drivers/pci_endpoint/sandbox-pci_ep.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2019 Ramon Fried <ramon.fried@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <pci.h>
+#include <pci_ep.h>
+#include <asm/test.h>
+
+/**
+ * struct sandbox_pci_ep_priv - private data for driver
+ * @hdr: Stores the EP device header
+ * @msix: required MSIx count;
+ * @msi: required MSI count;
+ */
+struct sandbox_pci_ep_priv {
+	struct pci_ep_header hdr;
+	struct pci_bar bars[6];
+	int msix;
+	int msi;
+	int irq_count;
+};
+
+/* Method exported for testing purposes */
+int sandbox_get_pci_ep_irq_count(struct udevice *dev)
+{
+	struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
+
+	return priv->irq_count;
+}
+
+static const struct udevice_id sandbox_pci_ep_ids[] = {
+	{ .compatible = "sandbox,pci_ep" },
+	{ }
+};
+
+static int sandbox_write_header(struct udevice *dev, uint fn,
+				struct pci_ep_header *hdr)
+{
+	struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
+
+	if (fn > 0)
+		return -ENODEV;
+
+	memcpy(&priv->hdr, hdr, sizeof(*hdr));
+
+	return 0;
+}
+
+static int sandbox_read_header(struct udevice *dev, uint fn,
+			       struct pci_ep_header *hdr)
+{
+	struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
+
+	if (fn > 0)
+		return -ENODEV;
+
+	memcpy(hdr, &priv->hdr, sizeof(*hdr));
+
+	return 0;
+}
+
+static int sandbox_set_bar(struct udevice *dev, uint fn,
+			   struct pci_bar *ep_bar)
+{
+	struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
+	int bar_idx;
+
+	if (fn > 0)
+		return -ENODEV;
+
+	bar_idx = ep_bar->barno;
+
+	memcpy(&priv->bars[bar_idx], ep_bar, sizeof(*ep_bar));
+
+	return 0;
+}
+
+static int sandbox_read_bar(struct udevice *dev, uint fn,
+			    struct pci_bar *ep_bar, enum pci_barno barno)
+{
+	struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
+
+	if (fn > 0)
+		return -ENODEV;
+
+	memcpy(ep_bar, &priv->bars[barno], sizeof(*ep_bar));
+
+	return 0;
+}
+
+static int sandbox_set_msi(struct udevice *dev, uint fn, uint interrupts)
+{
+	struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
+
+	if (fn > 0)
+		return -ENODEV;
+
+	priv->msi = interrupts;
+
+	return 0;
+}
+
+static int sandbox_get_msi(struct udevice *dev, uint fn)
+{
+	struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
+
+	if (fn > 0)
+		return -ENODEV;
+
+	return priv->msi;
+}
+
+static int sandbox_set_msix(struct udevice *dev, uint fn, uint interrupts)
+{
+	struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
+
+	if (fn > 0)
+		return -ENODEV;
+
+	priv->msix = interrupts;
+
+	return 0;
+}
+
+static int sandbox_get_msix(struct udevice *dev, uint fn)
+{
+	struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
+
+	if (fn > 0)
+		return -ENODEV;
+
+	return priv->msix;
+}
+
+static int sandbox_raise_irq(struct udevice *dev, uint fn,
+			     enum pci_ep_irq_type type, uint interrupt_num)
+{
+	struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
+
+	if (fn > 0)
+		return -ENODEV;
+
+	priv->irq_count++;
+
+	return 0;
+}
+
+static int sandbox_pci_ep_probe(struct udevice *dev)
+{
+	struct sandbox_pci_ep_priv *priv = dev_get_priv(dev);
+
+	memset(priv, 0, sizeof(*priv));
+	return 0;
+}
+
+static struct pci_ep_ops sandbox_pci_ep_ops = {
+	.write_header = sandbox_write_header,
+	.read_header = sandbox_read_header,
+	.set_bar = sandbox_set_bar,
+	.read_bar = sandbox_read_bar,
+	.set_msi = sandbox_set_msi,
+	.get_msi = sandbox_get_msi,
+	.set_msix = sandbox_set_msix,
+	.get_msix = sandbox_get_msix,
+	.raise_irq = sandbox_raise_irq,
+};
+
+U_BOOT_DRIVER(pci_ep_sandbox) = {
+	.name		= "pci_ep_sandbox",
+	.id		= UCLASS_PCI_EP,
+	.of_match	= sandbox_pci_ep_ids,
+	.probe		= sandbox_pci_ep_probe,
+	.ops		= &sandbox_pci_ep_ops,
+	.priv_auto	= sizeof(struct sandbox_pci_ep_priv),
+};
-- 
cgit