[U-Boot] [RFC 08/22] pci: add thunderx pci/ecam driver

Tim Harvey tharvey at gateworks.com
Fri Feb 22 18:03:05 UTC 2019


Signed-off-by: Tim Harvey <tharvey at gateworks.com>
---
 board/cavium/thunderx/Kconfig    |   4 +
 board/cavium/thunderx/thunderx.c |  16 ++--
 configs/thunderx_81xx_defconfig  |   6 ++
 configs/thunderx_88xx_defconfig  |   6 ++
 drivers/pci/Kconfig              |   9 ++
 drivers/pci/Makefile             |   1 +
 drivers/pci/pci_thunderx.c       | 160 +++++++++++++++++++++++++++++++
 include/pci_ids.h                |  15 +++
 8 files changed, 210 insertions(+), 7 deletions(-)
 create mode 100644 drivers/pci/pci_thunderx.c

diff --git a/board/cavium/thunderx/Kconfig b/board/cavium/thunderx/Kconfig
index 16df1a9fc2..c840f9c1ed 100644
--- a/board/cavium/thunderx/Kconfig
+++ b/board/cavium/thunderx/Kconfig
@@ -1,5 +1,9 @@
 if ARCH_THUNDERX
 
+config SYS_PCI_64BIT
+	bool
+	default y
+
 config SYS_CPU
 	string
 	default "armv8"
diff --git a/board/cavium/thunderx/thunderx.c b/board/cavium/thunderx/thunderx.c
index 0cc03a463f..28cf2aee22 100644
--- a/board/cavium/thunderx/thunderx.c
+++ b/board/cavium/thunderx/thunderx.c
@@ -72,6 +72,15 @@ static struct mm_region thunderx_mem_map[] = {
 
 struct mm_region *mem_map = thunderx_mem_map;
 
+#ifdef CONFIG_BOARD_EARLY_INIT_R
+int board_early_init_r(void)
+{
+	pci_init();
+
+	return 0;
+}
+#endif
+
 int board_init(void)
 {
 #if CONFIG_IS_ENABLED(OF_CONTROL)
@@ -127,10 +136,3 @@ int board_eth_init(bd_t *bis)
 
 	return rc;
 }
-
-#ifdef CONFIG_PCI
-void pci_init_board(void)
-{
-	printf("DEBUG: PCI Init TODO *****\n");
-}
-#endif
diff --git a/configs/thunderx_81xx_defconfig b/configs/thunderx_81xx_defconfig
index 4f6b4ad18c..3ec7d6cd4f 100644
--- a/configs/thunderx_81xx_defconfig
+++ b/configs/thunderx_81xx_defconfig
@@ -12,6 +12,7 @@ CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="console=ttyAMA0,115200n8 earlycon=pl011,0x87e028000000 debug maxcpus=4 rootwait rw root=/dev/mmcblk0p2 coherent_pool=16M"
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ThunderX_81XX> "
 # CONFIG_CMD_EXPORTENV is not set
@@ -20,10 +21,15 @@ CONFIG_SYS_PROMPT="ThunderX_81XX> "
 # CONFIG_CMD_SAVEENV is not set
 # CONFIG_CMD_ENV_EXISTS is not set
 # CONFIG_CMD_FLASH is not set
+CONFIG_CMD_PCI=y
 # CONFIG_CMD_NET is not set
 CONFIG_DEFAULT_DEVICE_TREE="thunderx-81xx"
 CONFIG_DM=y
 # CONFIG_MMC is not set
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_DM_PCI_COMPAT=y
+CONFIG_PCI_THUNDERX=y
 CONFIG_DM_SERIAL=y
 CONFIG_DEBUG_UART_PL011=y
 CONFIG_DEBUG_UART_SKIP_INIT=y
diff --git a/configs/thunderx_88xx_defconfig b/configs/thunderx_88xx_defconfig
index fe4643f52e..e30d549896 100644
--- a/configs/thunderx_88xx_defconfig
+++ b/configs/thunderx_88xx_defconfig
@@ -12,6 +12,7 @@ CONFIG_USE_BOOTARGS=y
 CONFIG_BOOTARGS="console=ttyAMA0,115200n8 earlycon=pl011,0x87e024000000 debug maxcpus=48 rootwait rw root=/dev/sda2 coherent_pool=16M"
 # CONFIG_DISPLAY_CPUINFO is not set
 # CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_BOARD_EARLY_INIT_R=y
 CONFIG_HUSH_PARSER=y
 # CONFIG_AUTO_COMPLETE is not set
 CONFIG_SYS_PROMPT="ThunderX_88XX> "
@@ -21,10 +22,15 @@ CONFIG_SYS_PROMPT="ThunderX_88XX> "
 # CONFIG_CMD_SAVEENV is not set
 # CONFIG_CMD_ENV_EXISTS is not set
 # CONFIG_CMD_FLASH is not set
+CONFIG_CMD_PCI=y
 # CONFIG_CMD_NET is not set
 CONFIG_DEFAULT_DEVICE_TREE="thunderx-88xx"
 CONFIG_DM=y
 # CONFIG_MMC is not set
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_DM_PCI_COMPAT=y
+CONFIG_PCI_THUNDERX=y
 CONFIG_DM_SERIAL=y
 CONFIG_DEBUG_UART_PL011=y
 CONFIG_DEBUG_UART_SKIP_INIT=y
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index f59803dbd6..7be97addc4 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -90,6 +90,15 @@ config PCI_TEGRA
 	  with a total of 5 lanes. Some boards require this for Ethernet
 	  support to work (e.g. beaver, jetson-tk1).
 
+config PCI_THUNDERX
+	bool "ThunderX PCI support"
+	depends on ARCH_THUNDERX
+	select PCIE_ECAM_GENERIC
+	help
+	  Enable support for the Cavium ThunderX SoC family PCI controllers.
+	  These controllers provide PCI configuration access to all on-board
+	  peripherals so it should only be disabled for testing purposes
+
 config PCI_XILINX
 	bool "Xilinx AXI Bridge for PCI Express"
 	depends on DM_PCI
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 4923641895..0974e77789 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_PCI_TEGRA) += pci_tegra.o
 obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
 obj-$(CONFIG_PCIE_DW_MVEBU) += pcie_dw_mvebu.o
 obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape.o
+obj-$(CONFIG_PCI_THUNDERX) += pci_thunderx.o
 obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape_fixup.o
 obj-$(CONFIG_PCI_XILINX) += pcie_xilinx.o
 obj-$(CONFIG_PCIE_INTEL_FPGA) += pcie_intel_fpga.o
diff --git a/drivers/pci/pci_thunderx.c b/drivers/pci/pci_thunderx.c
new file mode 100644
index 0000000000..f22141ca44
--- /dev/null
+++ b/drivers/pci/pci_thunderx.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier:	GPL-2.0+
+/*
+ * Copyright (C) 2018, Cavium Inc.
+ */
+#include <common.h>
+#include <dm.h>
+#include <pci.h>
+
+#include <asm/io.h>
+
+struct thunderx_pci {
+	unsigned int type;
+	struct fdt_resource cfg;
+	struct fdt_resource bus;
+};
+
+static int pci_thunderx_pem_read_config(struct udevice *bus, pci_dev_t bdf,
+					uint offset, ulong *valuep,
+					enum pci_size_t size)
+{
+	struct thunderx_pci *pcie = (void *)dev_get_priv(bus);
+	struct pci_controller *hose = dev_get_uclass_priv(bus);
+	uintptr_t address;
+	u32 b, d, f;
+	u8  hdrtype;
+	u8  pri_bus = pcie->bus.start + 1 - hose->first_busno;
+	u32 bus_offs = (pri_bus << 16) | (pri_bus << 8) | (pri_bus << 0);
+
+	b = PCI_BUS(bdf) + 1 - hose->first_busno;
+	d = PCI_DEV(bdf);
+	f = PCI_FUNC(bdf);
+
+	address = (b << 24) | (d << 19) | (f << 16);
+
+	address += pcie->cfg.start;
+
+	*valuep = pci_conv_32_to_size(~0UL, offset, size);
+
+	if (b == 1 && d > 0)
+		return 0;
+
+	switch (size) {
+	case PCI_SIZE_8:
+		*valuep = readb(address + offset);
+		break;
+	case PCI_SIZE_16:
+		*valuep = readw(address + offset);
+		break;
+	case PCI_SIZE_32:
+		*valuep = readl(address + offset);
+		break;
+	default:
+		printf("Invalid size\n");
+	}
+
+	hdrtype = readb(address + PCI_HEADER_TYPE);
+
+	if ((hdrtype == PCI_HEADER_TYPE_BRIDGE) &&
+	    (offset >= PCI_PRIMARY_BUS) &&
+	    (offset <= PCI_SUBORDINATE_BUS) &&
+	    *valuep != pci_conv_32_to_size(~0UL, offset, size)) {
+		*valuep -= pci_conv_32_to_size(bus_offs, offset, size);
+	}
+	return 0;
+}
+
+static int pci_thunderx_pem_write_config(struct udevice *bus, pci_dev_t bdf,
+					 uint offset, ulong value,
+					 enum pci_size_t size)
+{
+	struct thunderx_pci *pcie = (void *)dev_get_priv(bus);
+	struct pci_controller *hose = dev_get_uclass_priv(bus);
+	uintptr_t address;
+	u32 b, d, f;
+	u8  hdrtype;
+	u8  pri_bus = pcie->bus.start + 1 - hose->first_busno;
+	u32 bus_offs = (pri_bus << 16) | (pri_bus << 8) | (pri_bus << 0);
+
+	b = PCI_BUS(bdf) + 1 - hose->first_busno;
+	d = PCI_DEV(bdf);
+	f = PCI_FUNC(bdf);
+
+	address = (b << 24) | (d << 19) | (f << 16);
+
+	address += pcie->cfg.start;
+
+	hdrtype = readb(address + PCI_HEADER_TYPE);
+
+	if ((hdrtype == PCI_HEADER_TYPE_BRIDGE) &&
+	    (offset >= PCI_PRIMARY_BUS) &&
+	    (offset <= PCI_SUBORDINATE_BUS) &&
+	    (value != pci_conv_32_to_size(~0UL, offset, size))) {
+		value +=  pci_conv_32_to_size(bus_offs, offset, size);
+	}
+
+	if (b == 1 && d > 0)
+		return 0;
+
+	switch (size) {
+	case PCI_SIZE_8:
+		writeb(value, address + offset);
+		break;
+	case PCI_SIZE_16:
+		writew(value, address + offset);
+		break;
+	case PCI_SIZE_32:
+		writel(value, address + offset);
+		break;
+	default:
+		printf("Invalid size\n");
+	}
+	return 0;
+}
+
+static int pci_thunderx_ofdata_to_platdata(struct udevice *dev)
+{
+	return 0;
+}
+
+static int pci_thunderx_probe(struct udevice *dev)
+{
+	struct thunderx_pci *pcie = (void *)dev_get_priv(dev);
+	int err;
+
+	err = fdt_get_resource(gd->fdt_blob, dev->node.of_offset, "reg", 0,
+			       &pcie->cfg);
+	if (err) {
+		printf("Error reading resource: %s\n", fdt_strerror(err));
+		return err;
+	}
+
+	err = fdtdec_get_pci_bus_range(gd->fdt_blob, dev->node.of_offset,
+				       &pcie->bus);
+	if (err) {
+		printf("Error reading resource: %s\n", fdt_strerror(err));
+		return err;
+	}
+
+	return 0;
+}
+
+static const struct dm_pci_ops pci_thunderx_pem_ops = {
+	.read_config	= pci_thunderx_pem_read_config,
+	.write_config	= pci_thunderx_pem_write_config,
+};
+
+static const struct udevice_id pci_thunderx_pem_ids[] = {
+	{ .compatible = "cavium,pci-host-thunder-pem" },
+	{ }
+};
+
+U_BOOT_DRIVER(pci_thunderx_pcie) = {
+	.name	= "pci_thunderx_pem",
+	.id	= UCLASS_PCI,
+	.of_match = pci_thunderx_pem_ids,
+	.ops	= &pci_thunderx_pem_ops,
+	.ofdata_to_platdata = pci_thunderx_ofdata_to_platdata,
+	.probe	= pci_thunderx_probe,
+	.priv_auto_alloc_size = sizeof(struct thunderx_pci),
+};
diff --git a/include/pci_ids.h b/include/pci_ids.h
index fdda679cc0..948771271e 100644
--- a/include/pci_ids.h
+++ b/include/pci_ids.h
@@ -3109,6 +3109,21 @@
 
 #define PCI_VENDOR_ID_3COM_2		0xa727
 
+#define PCI_VENDOR_ID_CAVIUM		0x177d
+#define PCI_DEVICE_ID_THUNDERX_NIC_VF_1	0x0011
+#define PCI_DEVICE_ID_THUNDERX_GPIO	0xa00a
+#define PCI_DEVICE_ID_THUNDERX_SPI	0xa00b
+#define PCI_DEVICE_ID_THUNDERX_MMC	0xa010
+#define PCI_DEVICE_ID_THUNDERX_TWSI	0xa012
+#define PCI_DEVICE_ID_THUNDERX_AHCI	0xa01c
+#define PCI_DEVICE_ID_THUNDERX_NIC_PF	0xa01e
+#define PCI_DEVICE_ID_THUNDERX_SMI	0xa02b
+#define PCI_DEVICE_ID_THUNDERX_BGX	0xa026
+#define PCI_DEVICE_ID_THUNDERX_NIC_VF	0xa034
+#define PCI_DEVICE_ID_THUNDERX_RGX	0xa054
+#define PCI_DEVICE_ID_THUNDERX_XHCI	0xa055
+#define PCI_DEVICE_ID_THUNDERX_NIC_XCV  0xa056
+
 #define PCI_VENDOR_ID_DIGIUM		0xd161
 #define PCI_DEVICE_ID_DIGIUM_HFC4S	0xb410
 
-- 
2.17.1



More information about the U-Boot mailing list