From patchwork Tue Oct 29 21:08:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suneel Garapati X-Patchwork-Id: 1186306 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="raXJKFNn"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 472ktV56Lxz9s7T for ; Wed, 30 Oct 2019 08:17:06 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 38CE7C21DE8; Tue, 29 Oct 2019 21:14:11 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 1BCFFC21DED; Tue, 29 Oct 2019 21:09:42 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 6E1CFC21C8B; Tue, 29 Oct 2019 21:08:55 +0000 (UTC) Received: from mail-pf1-f196.google.com (mail-pf1-f196.google.com [209.85.210.196]) by lists.denx.de (Postfix) with ESMTPS id 8A308C21D56 for ; Tue, 29 Oct 2019 21:08:50 +0000 (UTC) Received: by mail-pf1-f196.google.com with SMTP id b128so10541096pfa.1 for ; Tue, 29 Oct 2019 14:08:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=f9TrJvrEdIG7i9xm9bREbsY3qd39SvJCnh2FVFEBtBs=; b=raXJKFNnDR9linixyZuAkKr+4rSx1tjUc4q315ExMjN9PePAMshA7QYv1ApffKC0TE o6L8wwX4MhizTTihLpBmL/F8zG3XHHeL9nDmhRzIYngwNn2+Or1aqzWrNGKG+KG1XlwO 9ZuwWK/Oaso10o8QRNDYL1iO2y/lSh432jpoe5bUqfiFtk6gM1S1JRfkphShZ8EJZ11r 88eCWSJ/Wly11ARsJbh7Firq9UJLO9eZ/3b+HiwWtALFNMm6ree/4goAOwlrtOs0/uRj tkb5WjBrYJDYdNqHXPTLdWG+zMWIW9UkSxo5NSfdruUSKj4GlaGmrceiKcLPnAENAVAy 5XSQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=f9TrJvrEdIG7i9xm9bREbsY3qd39SvJCnh2FVFEBtBs=; b=UipfYHLYEgFQOcXDVABvUjw3Xs/KYjBD2nA7m4FFCPfKPOxmm1u2VPsSe6JwIhsqHx JICo+f7a0RyMy0wb52HoXf3NSZJJlL8GlGwnEN80egcIMJ5zT+B1iddc9oFcqaQL0MCh QChUrpRv0oHIORtTDAVsFZQqy9k1cjkD5Cx6j0oALQKM8VUTlWB8OCiGybDeIoXTZfax KUPE32As08P1GudFDf+klUGAzBMO4EGuF2g1OM60cieLyAscvl7uxQ7GyDdNm7U2iqnN j7Ra3z2I54PDd8qVFLgmxozNJ8dfdVjC7HzXxLEpzB2e530S3o4kECo4G216WbBLMOcp X/GA== X-Gm-Message-State: APjAAAWmOuTgHHw9Dgoxg/ls2Wm8Nrk5/wyNz5+QYha8kLo5QovrZh/+ zBCUJNrloG6ex53eCKBnVnMUuMhp X-Google-Smtp-Source: APXvYqziwECB3wZpGH2LGl1eIhgUC6AeZXcEw04s67AnEDRQsJ1IdF3A5bkEwmXMQzNHlapxhqVsrw== X-Received: by 2002:a17:90a:e2c7:: with SMTP id fr7mr9595137pjb.116.1572383328835; Tue, 29 Oct 2019 14:08:48 -0700 (PDT) Received: from suneel.hsd1.ca.comcast.net ([2601:641:4000:c9c0:7044:5eef:7096:2413]) by smtp.gmail.com with ESMTPSA id q3sm131160pgj.54.2019.10.29.14.08.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Oct 2019 14:08:48 -0700 (PDT) From: Suneel Garapati To: u-boot Date: Tue, 29 Oct 2019 14:08:10 -0700 Message-Id: <20191029210821.1954-19-suneelglinux@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191029210821.1954-1-suneelglinux@gmail.com> References: <20191029210821.1954-1-suneelglinux@gmail.com> MIME-Version: 1.0 Cc: Tom Rini , Matthias Brugger , Joe Hershberger , Prasun Kapoor , Maen Suleiman , Chandrakala Chavva , Zi Shen Lim , Stefan Roese , Chris Packham Subject: [U-Boot] [RFC PATCH 18/29] drivers: pci: add PCI controller driver for OcteonTX X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: Suneel Garapati Adds support for PCI ECAM/PEM controllers found on OcteonTX or OcteonTX2 SoC platforms. Signed-off-by: Suneel Garapati --- drivers/pci/Kconfig | 8 + drivers/pci/Makefile | 1 + drivers/pci/pci_octeontx.c | 538 +++++++++++++++++++++++++++++++++++++ 3 files changed, 547 insertions(+) create mode 100644 drivers/pci/pci_octeontx.c diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 752439afcf..e865a06749 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -115,6 +115,14 @@ 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_OCTEONTX + bool "OcteonTX PCI support" + depends on (ARCH_OCTEONTX || ARCH_OCTEONTX2) + help + Enable support for the OcteonTX/TX2 SoC family ECAM/PEM 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 b1d3dc8610..7119d8bcb2 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -40,3 +40,4 @@ obj-$(CONFIG_PCI_XILINX) += pcie_xilinx.o obj-$(CONFIG_PCIE_INTEL_FPGA) += pcie_intel_fpga.o obj-$(CONFIG_PCI_KEYSTONE) += pcie_dw_ti.o obj-$(CONFIG_PCIE_MEDIATEK) += pcie_mediatek.o +obj-$(CONFIG_PCI_OCTEONTX) += pci_octeontx.o diff --git a/drivers/pci/pci_octeontx.c b/drivers/pci/pci_octeontx.c new file mode 100644 index 0000000000..d754f98bbd --- /dev/null +++ b/drivers/pci/pci_octeontx.c @@ -0,0 +1,538 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * https://spdx.org/licenses + */ + +#include +#include +#include +#include +#include +#include + +#include + +#if defined(CONFIG_ARCH_OCTEONTX2) + +#define PEM_CFG_WR 0x18 +#define PEM_CFG_RD 0x20 + +#define PCIERC_RASDP_DE_ME 0x440 +#define PCIERC_RASDP_EP_CTL 0x420 +#define PCIERC_RAS_EINJ_EN 0x348 +#define PCIERC_RAS_EINJ_CTL6PE 0x3A4 +#define PCIERC_RAS_EINJ_CTL6_CMPP0 0x364 +#define PCIERC_RAS_EINJ_CTL6_CMPV0 0x374 +#define PCIERC_RAS_EINJ_CTL6_CHGP1 0x388 +#define PCIERC_RAS_EINJ_CTL6_CHGV1 0x398 + +#endif + +DECLARE_GLOBAL_DATA_PTR; + +struct octeontx_pci { + unsigned int type; + + struct fdt_resource cfg; + struct fdt_resource bus; +#if defined(CONFIG_ARCH_OCTEONTX2) + struct fdt_resource pem; +#endif +}; + +static int pci_octeontx_ecam_read_config(struct udevice *bus, pci_dev_t bdf, + uint offset, ulong *valuep, + enum pci_size_t size) +{ + struct octeontx_pci *pcie = (void *)dev_get_priv(bus); + struct pci_controller *hose = dev_get_uclass_priv(bus); + uintptr_t address; + u32 b, d, f; + + b = PCI_BUS(bdf) + pcie->bus.start - hose->first_busno; + d = PCI_DEV(bdf); + f = PCI_FUNC(bdf); + + address = (b << 20) | (d << 15) | (f << 12) | offset; + + address += pcie->cfg.start; + + switch (size) { + case PCI_SIZE_8: + *valuep = readb(address); + break; + case PCI_SIZE_16: + *valuep = readw(address); + break; + case PCI_SIZE_32: + *valuep = readl(address); + break; + }; + + debug("%02x.%02x.%02x: u%d %x -> %lx\n", + b, d, f, size, offset, *valuep); + return 0; +} + +static int pci_octeontx_ecam_write_config(struct udevice *bus, pci_dev_t bdf, + uint offset, ulong valuep, + enum pci_size_t size) +{ + struct octeontx_pci *pcie = (void *)dev_get_priv(bus); + struct pci_controller *hose = dev_get_uclass_priv(bus); + uintptr_t address; + u32 b, d, f; + + b = PCI_BUS(bdf) + pcie->bus.start - hose->first_busno; + d = PCI_DEV(bdf); + f = PCI_FUNC(bdf); + + address = (b << 20) | (d << 15) | (f << 12) | offset; + + address += pcie->cfg.start; + + switch (size) { + case PCI_SIZE_8: + writeb(valuep, address); + break; + case PCI_SIZE_16: + writew(valuep, address); + break; + case PCI_SIZE_32: + writel(valuep, address); + break; + }; + + debug("%02x.%02x.%02x: u%d %x <- %lx\n", + b, d, f, size, offset, valuep); + return 0; +} + +static int pci_octeontx_pem_read_config(struct udevice *bus, pci_dev_t bdf, + uint offset, ulong *valuep, + enum pci_size_t size) +{ + struct octeontx_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); + } + debug("%02x.%02x.%02x: u%d %x (%lx) -> %lx\n", + b, d, f, size, offset, address, *valuep); + return 0; +} + +static int pci_octeontx_pem_write_config(struct udevice *bus, pci_dev_t bdf, + uint offset, ulong value, + enum pci_size_t size) +{ + struct octeontx_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"); + } + debug("%02x.%02x.%02x: u%d %x (%lx) <- %lx\n", + b, d, f, size, offset, address, value); + return 0; +} + +static int pci_octeontx2_pem_read_config(struct udevice *bus, pci_dev_t bdf, + uint offset, ulong *valuep, + enum pci_size_t size) +{ + struct octeontx_pci *pcie = (void *)dev_get_priv(bus); + struct pci_controller *hose = dev_get_uclass_priv(bus); + uintptr_t address; + u32 b, d, f; + + b = PCI_BUS(bdf) + 1 - hose->first_busno; + d = PCI_DEV(bdf); + f = PCI_FUNC(bdf); + + address = (b << 20) | (d << 15) | (f << 12); + + debug("bdf %x %02x.%02x.%02x: u%d %x (%lx)\n", + bdf, b, d, f, size, offset, address); + address += pcie->cfg.start; + + debug("%02x.%02x.%02x: u%d %x (%lx) %lx\n", + b, d, f, size, offset, address, *valuep); + *valuep = pci_conv_32_to_size(~0UL, offset, size); + + if (b == 1 && d > 0) + return 0; + + switch (size) { + case PCI_SIZE_8: + debug("byte %lx\n", address + offset); + *valuep = readb(address + offset); + break; + case PCI_SIZE_16: + debug("word %lx\n", address + offset); + *valuep = readw(address + offset); + break; + case PCI_SIZE_32: + debug("long %lx\n", address + offset); + *valuep = readl(address + offset); + break; + default: + printf("Invalid size\n"); + } + + debug("%02x.%02x.%02x: u%d %x (%lx) -> %lx\n", + b, d, f, size, offset, address, *valuep); + + return 0; +} + +static void pci_octeontx2_pem_workaround(struct udevice *bus, uint offset, + enum pci_size_t size) +{ +#if defined(CONFIG_ARCH_OCTEONTX2) + struct octeontx_pci *pcie = (void *)dev_get_priv(bus); + u64 rval, wval; + u32 cfg_off, data; + u64 raddr, waddr; + u8 shift; + + raddr = pcie->pem.start + PEM_CFG_RD; + waddr = pcie->pem.start + PEM_CFG_WR; + + debug("%s raddr %llx waddr %llx\n", __func__, raddr, waddr); + cfg_off = PCIERC_RASDP_DE_ME; + wval = cfg_off; + debug("%s DE_ME raddr %llx wval %llx\n", __func__, raddr, wval); + writeq(wval, raddr); + rval = readq(raddr); + debug("%s DE_ME raddr %llx rval %llx\n", __func__, raddr, rval); + data = rval >> 32; + if (data & 0x1) { + data = (data & (~0x1)); + wval |= ((u64)data << 32); + debug("%s DE_ME waddr %llx wval %llx\n", __func__, waddr, wval); + writeq(wval, waddr); + } + + cfg_off = PCIERC_RAS_EINJ_CTL6_CMPP0; + wval = cfg_off; + data = 0xFE000000; + wval |= ((u64)data << 32); + debug("%s CMPP0 waddr %llx wval %llx\n", __func__, waddr, wval); + writeq(wval, waddr); + + cfg_off = PCIERC_RAS_EINJ_CTL6_CMPV0; + wval = cfg_off; + data = 0x44000000; + wval |= ((u64)data << 32); + debug("%s CMPV0 waddr %llx wval %llx\n", __func__, waddr, wval); + writeq(wval, waddr); + + cfg_off = PCIERC_RAS_EINJ_CTL6_CHGP1; + wval = cfg_off; + data = 0xFF; + wval |= ((u64)data << 32); + debug("%s CHGP1 waddr %llx wval %llx\n", __func__, waddr, wval); + writeq(wval, waddr); + + cfg_off = PCIERC_RAS_EINJ_EN; + wval = cfg_off; + data = 0x40; + wval |= ((u64)data << 32); + debug("%s EINJ_EN waddr %llx wval %llx\n", __func__, waddr, wval); + writeq(wval, waddr); + + cfg_off = PCIERC_RAS_EINJ_CTL6PE; + wval = cfg_off; + data = 0x1; + wval |= ((u64)data << 32); + debug("%s EINJ_CTL6PE waddr %llx wval %llx\n", __func__, waddr, wval); + writeq(wval, waddr); + + switch (size) { + case PCI_SIZE_8: + shift = offset % 4; + data = (0x1 << shift); + break; + case PCI_SIZE_16: + shift = (offset % 4) ? 2 : 0; + data = (0x3 << shift); + break; + default: + case PCI_SIZE_32: + data = 0xF; + break; + } + + cfg_off = PCIERC_RAS_EINJ_CTL6_CHGV1; + wval = cfg_off; + wval |= ((u64)data << 32); + debug("%s EINJ_CHGV1 waddr %llx <= wval %llx\n", __func__, waddr, wval); + writeq(wval, waddr); + + cfg_off = PCIERC_RASDP_EP_CTL; + wval = cfg_off; + wval |= ((u64)0x1 << 32); + debug("%s EP_CTL waddr %llx <= wval %llx\n", __func__, waddr, wval); + writeq(wval, waddr); + + wval = readq(waddr); + debug("%s EP_CTL waddr %llx => wval %llx\n", __func__, waddr, wval); +#endif +} + +static int pci_octeontx2_pem_write_config(struct udevice *bus, pci_dev_t bdf, + uint offset, ulong value, + enum pci_size_t size) +{ + struct octeontx_pci *pcie = (void *)dev_get_priv(bus); + struct pci_controller *hose = dev_get_uclass_priv(bus); + uintptr_t address, addr; + u32 b, d, f; + u32 data; + int tmp; + + b = PCI_BUS(bdf) + 1 - hose->first_busno; + d = PCI_DEV(bdf); + f = PCI_FUNC(bdf); + + address = (b << 20) | (d << 15) | (f << 12); + + debug("bdf %x %02x.%02x.%02x: u%d %x (%lx)\n", + bdf, b, d, f, size, offset, address); + address += pcie->cfg.start; + + debug("%02x.%02x.%02x: u%d %x (%lx) %lx\n", + b, d, f, size, offset, address, value); + + if (b == 1 && d > 0) + return 0; + + addr = (address + offset) & ~0x3UL; + switch (size) { + case PCI_SIZE_8: + tmp = (address + offset) & 0x3; + size = PCI_SIZE_32; + data = readl(addr); + debug("tmp 8 long %lx %x\n", addr, data); + tmp *= 8; + value = (data & ~(0xFFUL << tmp)) | ((value & 0xFF) << tmp); + break; + case PCI_SIZE_16: + tmp = (address + offset) & 0x3; + size = PCI_SIZE_32; + data = readl(addr); + debug("tmp 16 long %lx %x\n", addr, data); + tmp *= 8; + value = (data & 0xFFFF) | (value << tmp); + break; + case PCI_SIZE_32: + break; + } + debug("tmp long %lx %lx\n", addr, value); + + pci_octeontx2_pem_workaround(bus, offset, size); + + switch (size) { + case PCI_SIZE_8: + debug("byte %lx %lx\n", address + offset, value); + writeb(value, address + offset); + break; + case PCI_SIZE_16: + debug("word %lx %lx\n", address + offset, value); + writew(value, address + offset); + break; + case PCI_SIZE_32: + debug("long %lx %lx\n", addr, value); + writel(value, addr); + break; + default: + printf("Invalid size\n"); + } + + debug("%02x.%02x.%02x: u%d %x (%lx) <- %lx\n", + b, d, f, size, offset, addr, value); + + return 0; +} + +static int pci_octeontx_ofdata_to_platdata(struct udevice *dev) +{ + return 0; +} + +static int pci_octeontx_ecam_probe(struct udevice *dev) +{ + struct octeontx_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; + } + +#if defined(CONFIG_ARCH_OCTEONTX2) + err = fdt_node_check_compatible(gd->fdt_blob, dev->node.of_offset, + "marvell,pci-host-octeontx2-pem"); + if (!err) { + err = fdt_get_resource(gd->fdt_blob, dev->node.of_offset, + "reg", 1, &pcie->pem); + + if (err) { + printf("Error reading resource: %s\n", + fdt_strerror(err)); + return err; + } + } +#endif + 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_octeontx_ecam_ops = { + .read_config = pci_octeontx_ecam_read_config, + .write_config = pci_octeontx_ecam_write_config, +}; + +static const struct udevice_id pci_octeontx_ecam_ids[] = { + { .compatible = "cavium,pci-host-thunder-ecam" }, + { .compatible = "cavium,pci-host-octeontx-ecam" }, + { .compatible = "pci-host-ecam-generic" }, + { } +}; + +static const struct dm_pci_ops pci_octeontx_pem_ops = { + .read_config = pci_octeontx_pem_read_config, + .write_config = pci_octeontx_pem_write_config, +}; + +static const struct udevice_id pci_octeontx_pem_ids[] = { + { .compatible = "cavium,pci-host-thunder-pem" }, + { } +}; + +static const struct dm_pci_ops pci_octeontx2_pem_ops = { + .read_config = pci_octeontx2_pem_read_config, + .write_config = pci_octeontx2_pem_write_config, +}; + +static const struct udevice_id pci_octeontx2_pem_ids[] = { + { .compatible = "marvell,pci-host-octeontx2-pem" }, + { } +}; + +U_BOOT_DRIVER(pci_octeontx_ecam) = { + .name = "pci_octeontx_ecam", + .id = UCLASS_PCI, + .of_match = pci_octeontx_ecam_ids, + .ops = &pci_octeontx_ecam_ops, + .ofdata_to_platdata = pci_octeontx_ofdata_to_platdata, + .probe = pci_octeontx_ecam_probe, + .priv_auto_alloc_size = sizeof(struct octeontx_pci), + .flags = DM_FLAG_PRE_RELOC, +}; + +U_BOOT_DRIVER(pci_octeontx2_pcie) = { + .name = "pci_octeontx2_pem", + .id = UCLASS_PCI, + .of_match = pci_octeontx2_pem_ids, + .ops = &pci_octeontx2_pem_ops, + .ofdata_to_platdata = pci_octeontx_ofdata_to_platdata, + .probe = pci_octeontx_ecam_probe, + .priv_auto_alloc_size = sizeof(struct octeontx_pci), +}; + +U_BOOT_DRIVER(pci_octeontx_pcie) = { + .name = "pci_octeontx_pem", + .id = UCLASS_PCI, + .of_match = pci_octeontx_pem_ids, + .ops = &pci_octeontx_pem_ops, + .ofdata_to_platdata = pci_octeontx_ofdata_to_platdata, + .probe = pci_octeontx_ecam_probe, + .priv_auto_alloc_size = sizeof(struct octeontx_pci), +};