pci: pci_mvebu: Add DM_PCI support and move CONFIG_PCI_MVEBU to defconfig
authorStefan Roese <sr@denx.de>
Fri, 25 Jan 2019 10:52:43 +0000 (11:52 +0100)
committerStefan Roese <sr@denx.de>
Tue, 5 Feb 2019 13:22:38 +0000 (14:22 +0100)
This patch adds DM_PCI support to the MVEBU PCIe driver. This is
necessary, since all PCI drivers have to be moved to DM (driver model)
until the v2019.07 release.

To not break git bisect'ablility, this patch also moves CONFIG_PCI_MVEBU
from config headers to the defconfig files.

Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Dirk Eibach <dirk.eibach@gdsys.cc>
Cc: Mario Six <mario.six@gdsys.cc>
Cc: Chris Packham <chris.packham@alliedtelesis.co.nz>
Cc: Phil Sutter <phil@nwl.cc>
Cc: Marek BehĂșn <marek.behun@nic.cz>
Cc: VlaoMao <vlaomao@gmail.com>
21 files changed:
configs/clearfog_defconfig
configs/controlcenterdc_defconfig
configs/db-88f6820-amc_defconfig
configs/db-88f6820-gp_defconfig
configs/db-mv784mp-gp_defconfig
configs/ds414_defconfig
configs/theadorable_debug_defconfig
configs/turris_omnia_defconfig
configs/x530_defconfig
drivers/pci/Kconfig
drivers/pci/pci_mvebu.c
include/configs/clearfog.h
include/configs/controlcenterdc.h
include/configs/db-88f6820-amc.h
include/configs/db-88f6820-gp.h
include/configs/db-mv784mp-gp.h
include/configs/ds414.h
include/configs/theadorable.h
include/configs/turris_omnia.h
include/configs/x530.h
scripts/config_whitelist.txt

index e1c5a1fa13b46b253f34e7ff71d3f554f54e1e87..0f69ff606dba4aa6865491e98f3b7cb060362a24 100644 (file)
@@ -56,6 +56,7 @@ CONFIG_PHY_GIGE=y
 CONFIG_MVNETA=y
 CONFIG_MII=y
 CONFIG_PCI=y
+CONFIG_PCI_MVEBU=y
 CONFIG_SCSI=y
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
index 0c762ad77c1602ebc24380f30693b2ea7b0f0095..f22a3ab819c70ac742469db1961a2fdc11e8b8be 100644 (file)
@@ -58,6 +58,9 @@ CONFIG_PHY_MARVELL=y
 CONFIG_PHY_GIGE=y
 CONFIG_MVNETA=y
 CONFIG_MII=y
+CONFIG_PCI=y
+CONFIG_DM_PCI_COMPAT=y
+CONFIG_PCI_MVEBU=y
 CONFIG_SCSI=y
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
index 9068a584060a0d4162284da1674f66e2fa5e6212..03bf2bcafcb80aab47395b3f0549ce4faf2148eb 100644 (file)
@@ -60,6 +60,7 @@ CONFIG_PHY_GIGE=y
 CONFIG_MVNETA=y
 CONFIG_MII=y
 CONFIG_PCI=y
+CONFIG_PCI_MVEBU=y
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_KIRKWOOD_SPI=y
index 413010c4efb15fa5162fa74bd2946de824056dcb..b36b7c3b2c316ba5aef92c3caba2020fdbe4d0a7 100644 (file)
@@ -56,6 +56,7 @@ CONFIG_PHY_GIGE=y
 CONFIG_MVNETA=y
 CONFIG_MII=y
 CONFIG_PCI=y
+CONFIG_PCI_MVEBU=y
 CONFIG_SCSI=y
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
index 3f140986b692f0a638ff4edf17eaf786c84b6583..b6c61c3a48436212c9e5e8f03e3165e603ec6824 100644 (file)
@@ -55,6 +55,7 @@ CONFIG_PHY_GIGE=y
 CONFIG_MVNETA=y
 CONFIG_MII=y
 CONFIG_PCI=y
+CONFIG_PCI_MVEBU=y
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_KIRKWOOD_SPI=y
index 5325bd9968a828d69cfce81c9c30826264b2cb93..32f37440c31d3eb66581ea7ced220c093e935d9d 100644 (file)
@@ -52,6 +52,7 @@ CONFIG_PHY_GIGE=y
 CONFIG_MVNETA=y
 CONFIG_MII=y
 CONFIG_PCI=y
+CONFIG_PCI_MVEBU=y
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_KIRKWOOD_SPI=y
index 9e99618998c09b0e1dd4a35932e4452b0097092c..ac6dfd6844241686ef518798dd035752adb05992 100644 (file)
@@ -62,6 +62,8 @@ CONFIG_PHY_GIGE=y
 CONFIG_MVNETA=y
 CONFIG_MII=y
 CONFIG_PCI=y
+CONFIG_DM_PCI_COMPAT=y
+CONFIG_PCI_MVEBU=y
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_KIRKWOOD_SPI=y
index 4a1e23c86c80ea57a0ebd1ff0b0631bf502a639f..5cafe2ee340a3060e4924df81d882daa18fad813 100644 (file)
@@ -37,7 +37,6 @@ CONFIG_DEFAULT_DEVICE_TREE="armada-385-turris-omnia"
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SPL_OF_TRANSLATE=y
 CONFIG_SCSI_AHCI=y
-CONFIG_MISC=y
 CONFIG_ATSHA204A=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_MV=y
@@ -45,6 +44,8 @@ CONFIG_PHY_MARVELL=y
 CONFIG_PHY_GIGE=y
 CONFIG_MVNETA=y
 CONFIG_MII=y
+CONFIG_PCI=y
+CONFIG_PCI_MVEBU=y
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_KIRKWOOD_SPI=y
index 22482f8d39be92721d6ad9772164c37a601913d9..25b9e885d8e6788a8f8556e1ab61774227d463a1 100644 (file)
@@ -46,7 +46,6 @@ CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_MVTWSI=y
 CONFIG_I2C_MUX=y
 CONFIG_I2C_MUX_PCA954x=y
-CONFIG_MISC=y
 # CONFIG_MMC is not set
 CONFIG_NAND=y
 CONFIG_NAND_PXA3XX=y
@@ -57,6 +56,8 @@ CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_SPI_FLASH_SST=y
 CONFIG_MTD_UBI=y
 CONFIG_PCI=y
+CONFIG_DM_PCI_COMPAT=y
+CONFIG_PCI_MVEBU=y
 CONFIG_DM_RTC=y
 CONFIG_RTC_DS1307=y
 CONFIG_DEBUG_UART_SHIFT=2
index f59803dbd650589ab8dd8a422e530cea98a4b88b..1521885bdeb201078bf3f89bdd6c99f06e6328ef 100644 (file)
@@ -112,4 +112,13 @@ config PCIE_INTEL_FPGA
          Say Y here if you want to enable PCIe controller support on Intel
          FPGA, example Stratix 10.
 
+config PCI_MVEBU
+       bool "Enable Armada XP/38x PCIe driver"
+       depends on ARCH_MVEBU
+       select DM_PCI
+       select MISC
+       help
+         Say Y here if you want to enable PCIe controller support on
+         Armada XP/38x SoCs.
+
 endif
index affe9f98adff4c27b8761749ffcc2dd68e93afd6..6026fa67f92e5fb2e5c2de8742c48287ba047e56 100644 (file)
  */
 
 #include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/of_access.h>
 #include <pci.h>
-#include <linux/errno.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
 #include <linux/mbus.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -59,26 +64,22 @@ DECLARE_GLOBAL_DATA_PTR;
 #define PCIE_DEBUG_CTRL                        0x1a60
 #define  PCIE_DEBUG_SOFT_RESET         BIT(20)
 
-struct resource {
-       u32 start;
-       u32 end;
-};
-
 struct mvebu_pcie {
        struct pci_controller hose;
-       char *name;
        void __iomem *base;
        void __iomem *membase;
        struct resource mem;
        void __iomem *iobase;
        u32 port;
        u32 lane;
+       int devfn;
        u32 lane_mask;
        pci_dev_t dev;
+       char name[16];
+       unsigned int mem_target;
+       unsigned int mem_attr;
 };
 
-#define to_pcie(_hc)   container_of(_hc, struct mvebu_pcie, pci)
-
 /*
  * MVEBU PCIe controller needs MEMORY and I/O BARs to be mapped
  * into SoCs address space. Each controller will map 128M of MEM
@@ -87,82 +88,6 @@ struct mvebu_pcie {
 static void __iomem *mvebu_pcie_membase = (void __iomem *)MBUS_PCI_MEM_BASE;
 #define PCIE_MEM_SIZE  (128 << 20)
 
-#if defined(CONFIG_ARMADA_38X)
-#define PCIE_BASE(if)                                  \
-       ((if) == 0 ?                                    \
-        MVEBU_REG_PCIE0_BASE :                         \
-        (MVEBU_REG_PCIE_BASE + 0x4000 * (if - 1)))
-
-/*
- * On A38x MV6820 these PEX ports are supported:
- *  0 - Port 0.0
- *  1 - Port 1.0
- *  2 - Port 2.0
- *  3 - Port 3.0
- */
-#define MAX_PEX 4
-static struct mvebu_pcie pcie_bus[MAX_PEX];
-
-static void mvebu_get_port_lane(struct mvebu_pcie *pcie, int pex_idx,
-                               int *mem_target, int *mem_attr)
-{
-       u8 port[] = { 0, 1, 2, 3 };
-       u8 lane[] = { 0, 0, 0, 0 };
-       u8 target[] = { 8, 4, 4, 4 };
-       u8 attr[] = { 0xe8, 0xe8, 0xd8, 0xb8 };
-
-       pcie->port = port[pex_idx];
-       pcie->lane = lane[pex_idx];
-       *mem_target = target[pex_idx];
-       *mem_attr = attr[pex_idx];
-}
-#else
-#define PCIE_BASE(if)                                                  \
-       ((if) < 8 ?                                                     \
-        (MVEBU_REG_PCIE_BASE + ((if) / 4) * 0x40000 + ((if) % 4) * 0x4000) : \
-        (MVEBU_REG_PCIE_BASE + 0x2000 + ((if) % 8) * 0x40000))
-
-/*
- * On AXP MV78460 these PEX ports are supported:
- *  0 - Port 0.0
- *  1 - Port 0.1
- *  2 - Port 0.2
- *  3 - Port 0.3
- *  4 - Port 1.0
- *  5 - Port 1.1
- *  6 - Port 1.2
- *  7 - Port 1.3
- *  8 - Port 2.0
- *  9 - Port 3.0
- */
-#define MAX_PEX 10
-static struct mvebu_pcie pcie_bus[MAX_PEX];
-
-static void mvebu_get_port_lane(struct mvebu_pcie *pcie, int pex_idx,
-                               int *mem_target, int *mem_attr)
-{
-       u8 port[] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 3 };
-       u8 lane[] = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 0 };
-       u8 target[] = { 4, 4, 4, 4, 8, 8, 8, 8, 4, 8 };
-       u8 attr[] = { 0xe8, 0xd8, 0xb8, 0x78,
-                     0xe8, 0xd8, 0xb8, 0x78,
-                     0xf8, 0xf8 };
-
-       pcie->port = port[pex_idx];
-       pcie->lane = lane[pex_idx];
-       *mem_target = target[pex_idx];
-       *mem_attr = attr[pex_idx];
-}
-#endif
-
-static int mvebu_pex_unit_is_x4(int pex_idx)
-{
-       int pex_unit = pex_idx < 9 ? pex_idx >> 2 : 3;
-       u32 mask = (0x0f << (pex_unit * 8));
-
-       return (readl(COMPHY_REFCLK_ALIGNMENT) & mask) == mask;
-}
-
 static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie)
 {
        u32 val;
@@ -211,67 +136,83 @@ static inline struct mvebu_pcie *hose_to_pcie(struct pci_controller *hose)
        return container_of(hose, struct mvebu_pcie, hose);
 }
 
-static int mvebu_pcie_read_config_dword(struct pci_controller *hose,
-               pci_dev_t dev, int offset, u32 *val)
+static int mvebu_pcie_read_config(struct udevice *bus, pci_dev_t bdf,
+                                 uint offset, ulong *valuep,
+                                 enum pci_size_t size)
 {
-       struct mvebu_pcie *pcie = hose_to_pcie(hose);
+       struct mvebu_pcie *pcie = dev_get_platdata(bus);
        int local_bus = PCI_BUS(pcie->dev);
        int local_dev = PCI_DEV(pcie->dev);
        u32 reg;
+       u32 data;
+
+       debug("PCIE CFG read:  (b,d,f)=(%2d,%2d,%2d) ",
+             PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
 
        /* Only allow one other device besides the local one on the local bus */
-       if (PCI_BUS(dev) == local_bus && PCI_DEV(dev) != local_dev) {
-               if (local_dev == 0 && PCI_DEV(dev) != 1) {
+       if (PCI_BUS(bdf) == local_bus && PCI_DEV(bdf) != local_dev) {
+               if (local_dev == 0 && PCI_DEV(bdf) != 1) {
+                       debug("- out of range\n");
                        /*
                         * If local dev is 0, the first other dev can
                         * only be 1
                         */
-                       *val = 0xffffffff;
-                       return 1;
-               } else if (local_dev != 0 && PCI_DEV(dev) != 0) {
+                       *valuep = pci_get_ff(size);
+                       return 0;
+               } else if (local_dev != 0 && PCI_DEV(bdf) != 0) {
+                       debug("- out of range\n");
                        /*
                         * If local dev is not 0, the first other dev can
                         * only be 0
                         */
-                       *val = 0xffffffff;
-                       return 1;
+                       *valuep = pci_get_ff(size);
+                       return 0;
                }
        }
 
        /* write address */
-       reg = PCIE_CONF_ADDR(dev, offset);
+       reg = PCIE_CONF_ADDR(bdf, offset);
        writel(reg, pcie->base + PCIE_CONF_ADDR_OFF);
-       *val = readl(pcie->base + PCIE_CONF_DATA_OFF);
+       data = readl(pcie->base + PCIE_CONF_DATA_OFF);
+       debug("(addr,val)=(0x%04x, 0x%08x)\n", offset, data);
+       *valuep = pci_conv_32_to_size(data, offset, size);
 
        return 0;
 }
 
-static int mvebu_pcie_write_config_dword(struct pci_controller *hose,
-               pci_dev_t dev, int offset, u32 val)
+static int mvebu_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
+                                  uint offset, ulong value,
+                                  enum pci_size_t size)
 {
-       struct mvebu_pcie *pcie = hose_to_pcie(hose);
+       struct mvebu_pcie *pcie = dev_get_platdata(bus);
        int local_bus = PCI_BUS(pcie->dev);
        int local_dev = PCI_DEV(pcie->dev);
+       u32 data;
+
+       debug("PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ",
+             PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
+       debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
 
        /* Only allow one other device besides the local one on the local bus */
-       if (PCI_BUS(dev) == local_bus && PCI_DEV(dev) != local_dev) {
-               if (local_dev == 0 && PCI_DEV(dev) != 1) {
+       if (PCI_BUS(bdf) == local_bus && PCI_DEV(bdf) != local_dev) {
+               if (local_dev == 0 && PCI_DEV(bdf) != 1) {
                        /*
                         * If local dev is 0, the first other dev can
                         * only be 1
                         */
-                       return 1;
-               } else if (local_dev != 0 && PCI_DEV(dev) != 0) {
+                       return 0;
+               } else if (local_dev != 0 && PCI_DEV(bdf) != 0) {
                        /*
                         * If local dev is not 0, the first other dev can
                         * only be 0
                         */
-                       return 1;
+                       return 0;
                }
        }
 
-       writel(PCIE_CONF_ADDR(dev, offset), pcie->base + PCIE_CONF_ADDR_OFF);
-       writel(val, pcie->base + PCIE_CONF_DATA_OFF);
+       writel(PCIE_CONF_ADDR(bdf, offset), pcie->base + PCIE_CONF_ADDR_OFF);
+       data = pci_conv_size_to_32(0, value, offset, size);
+       writel(data, pcie->base + PCIE_CONF_DATA_OFF);
 
        return 0;
 }
@@ -331,107 +272,242 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie)
               pcie->base + PCIE_BAR_CTRL_OFF(1));
 }
 
-void pci_init_board(void)
+static int mvebu_pcie_probe(struct udevice *dev)
 {
-       int mem_target, mem_attr, i;
-       int bus = 0;
+       struct mvebu_pcie *pcie = dev_get_platdata(dev);
+       struct udevice *ctlr = pci_get_controller(dev);
+       struct pci_controller *hose = dev_get_uclass_priv(ctlr);
+       static int bus;
        u32 reg;
-       u32 soc_ctrl = readl(MVEBU_SYSTEM_REG_BASE + 0x4);
 
-       /* Check SoC Control Power State */
-       debug("%s: SoC Control %08x, 0en %01lx, 1en %01lx, 2en %01lx\n",
-             __func__, soc_ctrl, SELECT(soc_ctrl, 0), SELECT(soc_ctrl, 1),
-             SELECT(soc_ctrl, 2));
+       debug("%s: PCIe %d.%d - up, base %08x\n", __func__,
+             pcie->port, pcie->lane, (u32)pcie->base);
+
+       /* Read Id info and local bus/dev */
+       debug("direct conf read %08x, local bus %d, local dev %d\n",
+             readl(pcie->base), mvebu_pcie_get_local_bus_nr(pcie),
+             mvebu_pcie_get_local_dev_nr(pcie));
+
+       mvebu_pcie_set_local_bus_nr(pcie, bus);
+       mvebu_pcie_set_local_dev_nr(pcie, 0);
+       pcie->dev = PCI_BDF(bus, 0, 0);
+
+       pcie->mem.start = (u32)mvebu_pcie_membase;
+       pcie->mem.end = pcie->mem.start + PCIE_MEM_SIZE - 1;
+       mvebu_pcie_membase += PCIE_MEM_SIZE;
+
+       if (mvebu_mbus_add_window_by_id(pcie->mem_target, pcie->mem_attr,
+                                       (phys_addr_t)pcie->mem.start,
+                                       PCIE_MEM_SIZE)) {
+               printf("PCIe unable to add mbus window for mem at %08x+%08x\n",
+                      (u32)pcie->mem.start, PCIE_MEM_SIZE);
+       }
+
+       /* Setup windows and configure host bridge */
+       mvebu_pcie_setup_wins(pcie);
+
+       /* Master + slave enable. */
+       reg = readl(pcie->base + PCIE_CMD_OFF);
+       reg |= PCI_COMMAND_MEMORY;
+       reg |= PCI_COMMAND_MASTER;
+       reg |= BIT(10);         /* disable interrupts */
+       writel(reg, pcie->base + PCIE_CMD_OFF);
+
+       /* Set BAR0 to internal registers */
+       writel(SOC_REGS_PHY_BASE, pcie->base + PCIE_BAR_LO_OFF(0));
+       writel(0, pcie->base + PCIE_BAR_HI_OFF(0));
 
-       for (i = 0; i < MAX_PEX; i++) {
-               struct mvebu_pcie *pcie = &pcie_bus[i];
-               struct pci_controller *hose = &pcie->hose;
+       /* PCI memory space */
+       pci_set_region(hose->regions + 0, pcie->mem.start,
+                      pcie->mem.start, PCIE_MEM_SIZE, PCI_REGION_MEM);
+       pci_set_region(hose->regions + 1,
+                      0, 0,
+                      gd->ram_size,
+                      PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+       hose->region_count = 2;
 
-               /* Get port number, lane number and memory target / attr */
-               mvebu_get_port_lane(pcie, i, &mem_target, &mem_attr);
+       bus++;
 
-               /* Don't read at all from pci registers if port power is down */
-               if (SELECT(soc_ctrl, pcie->port) == 0) {
-                       if (pcie->lane == 0)
-                               debug("%s: skipping port %d\n", __func__, pcie->port);
+       return 0;
+}
+
+static int mvebu_pcie_port_parse_dt(ofnode node, struct mvebu_pcie *pcie)
+{
+       const u32 *addr;
+       int len;
+
+       addr = ofnode_get_property(node, "assigned-addresses", &len);
+       if (!addr) {
+               pr_err("property \"assigned-addresses\" not found");
+               return -FDT_ERR_NOTFOUND;
+       }
+
+       pcie->base = (void *)(fdt32_to_cpu(addr[2]) + SOC_REGS_PHY_BASE);
+
+       return 0;
+}
+
+#define DT_FLAGS_TO_TYPE(flags)       (((flags) >> 24) & 0x03)
+#define    DT_TYPE_IO                 0x1
+#define    DT_TYPE_MEM32              0x2
+#define DT_CPUADDR_TO_TARGET(cpuaddr) (((cpuaddr) >> 56) & 0xFF)
+#define DT_CPUADDR_TO_ATTR(cpuaddr)   (((cpuaddr) >> 48) & 0xFF)
+
+static int mvebu_get_tgt_attr(ofnode node, int devfn,
+                             unsigned long type,
+                             unsigned int *tgt,
+                             unsigned int *attr)
+{
+       const int na = 3, ns = 2;
+       const __be32 *range;
+       int rlen, nranges, rangesz, pna, i;
+
+       *tgt = -1;
+       *attr = -1;
+
+       range = ofnode_get_property(node, "ranges", &rlen);
+       if (!range)
+               return -EINVAL;
+
+       pna = 2; /* hardcoded for now because of lack of of_n_addr_cells() */
+       rangesz = pna + na + ns;
+       nranges = rlen / sizeof(__be32) / rangesz;
+
+       for (i = 0; i < nranges; i++, range += rangesz) {
+               u32 flags = of_read_number(range, 1);
+               u32 slot = of_read_number(range + 1, 1);
+               u64 cpuaddr = of_read_number(range + na, pna);
+               unsigned long rtype;
+
+               if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_IO)
+                       rtype = IORESOURCE_IO;
+               else if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_MEM32)
+                       rtype = IORESOURCE_MEM;
+               else
                        continue;
+
+               /*
+                * The Linux code used PCI_SLOT() here, which expects devfn
+                * in bits 7..0. PCI_DEV() in U-Boot is similar to PCI_SLOT(),
+                * only expects devfn in 15..8, where its saved in this driver.
+                */
+               if (slot == PCI_DEV(devfn) && type == rtype) {
+                       *tgt = DT_CPUADDR_TO_TARGET(cpuaddr);
+                       *attr = DT_CPUADDR_TO_ATTR(cpuaddr);
+                       return 0;
                }
+       }
+
+       return -ENOENT;
+}
+
+static int mvebu_pcie_ofdata_to_platdata(struct udevice *dev)
+{
+       struct mvebu_pcie *pcie = dev_get_platdata(dev);
+       int ret = 0;
+
+       /* Get port number, lane number and memory target / attr */
+       if (ofnode_read_u32(dev_ofnode(dev), "marvell,pcie-port",
+                           &pcie->port)) {
+               ret = -ENODEV;
+               goto err;
+       }
+
+       if (ofnode_read_u32(dev_ofnode(dev), "marvell,pcie-lane", &pcie->lane))
+               pcie->lane = 0;
 
-               pcie->base = (void __iomem *)PCIE_BASE(i);
+       sprintf(pcie->name, "pcie%d.%d", pcie->port, pcie->lane);
 
-               /* Check link and skip ports that have no link */
-               if (!mvebu_pcie_link_up(pcie)) {
-                       debug("%s: PCIe %d.%d - down\n", __func__,
-                             pcie->port, pcie->lane);
+       /* pci_get_devfn() returns devfn in bits 15..8, see PCI_DEV usage */
+       pcie->devfn = pci_get_devfn(dev);
+       if (pcie->devfn < 0) {
+               ret = -ENODEV;
+               goto err;
+       }
+
+       ret = mvebu_get_tgt_attr(dev_ofnode(dev->parent), pcie->devfn,
+                                IORESOURCE_MEM,
+                                &pcie->mem_target, &pcie->mem_attr);
+       if (ret < 0) {
+               printf("%s: cannot get tgt/attr for mem window\n", pcie->name);
+               goto err;
+       }
+
+       /* Parse PCIe controller register base from DT */
+       ret = mvebu_pcie_port_parse_dt(dev_ofnode(dev), pcie);
+       if (ret < 0)
+               goto err;
+
+       /* Check link and skip ports that have no link */
+       if (!mvebu_pcie_link_up(pcie)) {
+               debug("%s: %s - down\n", __func__, pcie->name);
+               ret = -ENODEV;
+               goto err;
+       }
+
+       return 0;
+
+err:
+       return ret;
+}
+
+static const struct dm_pci_ops mvebu_pcie_ops = {
+       .read_config    = mvebu_pcie_read_config,
+       .write_config   = mvebu_pcie_write_config,
+};
+
+static struct driver pcie_mvebu_drv = {
+       .name                   = "pcie_mvebu",
+       .id                     = UCLASS_PCI,
+       .ops                    = &mvebu_pcie_ops,
+       .probe                  = mvebu_pcie_probe,
+       .ofdata_to_platdata     = mvebu_pcie_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct mvebu_pcie),
+};
+
+/*
+ * Use a MISC device to bind the n instances (child nodes) of the
+ * PCIe base controller in UCLASS_PCI.
+ */
+static int mvebu_pcie_bind(struct udevice *parent)
+{
+       struct mvebu_pcie *pcie;
+       struct uclass_driver *drv;
+       struct udevice *dev;
+       ofnode subnode;
+
+       /* Lookup eth driver */
+       drv = lists_uclass_lookup(UCLASS_PCI);
+       if (!drv) {
+               puts("Cannot find PCI driver\n");
+               return -ENOENT;
+       }
+
+       ofnode_for_each_subnode(subnode, dev_ofnode(parent)) {
+               if (!ofnode_is_available(subnode))
                        continue;
-               }
-               debug("%s: PCIe %d.%d - up, base %08x\n", __func__,
-                     pcie->port, pcie->lane, (u32)pcie->base);
-
-               /* Read Id info and local bus/dev */
-               debug("direct conf read %08x, local bus %d, local dev %d\n",
-                     readl(pcie->base), mvebu_pcie_get_local_bus_nr(pcie),
-                     mvebu_pcie_get_local_dev_nr(pcie));
-
-               mvebu_pcie_set_local_bus_nr(pcie, bus);
-               mvebu_pcie_set_local_dev_nr(pcie, 0);
-               pcie->dev = PCI_BDF(bus, 0, 0);
-
-               pcie->mem.start = (u32)mvebu_pcie_membase;
-               pcie->mem.end = pcie->mem.start + PCIE_MEM_SIZE - 1;
-               mvebu_pcie_membase += PCIE_MEM_SIZE;
-
-               if (mvebu_mbus_add_window_by_id(mem_target, mem_attr,
-                                               (phys_addr_t)pcie->mem.start,
-                                               PCIE_MEM_SIZE)) {
-                       printf("PCIe unable to add mbus window for mem at %08x+%08x\n",
-                              (u32)pcie->mem.start, PCIE_MEM_SIZE);
-               }
 
-               /* Setup windows and configure host bridge */
-               mvebu_pcie_setup_wins(pcie);
-
-               /* Master + slave enable. */
-               reg = readl(pcie->base + PCIE_CMD_OFF);
-               reg |= PCI_COMMAND_MEMORY;
-               reg |= PCI_COMMAND_MASTER;
-               reg |= BIT(10);         /* disable interrupts */
-               writel(reg, pcie->base + PCIE_CMD_OFF);
-
-               /* Setup U-Boot PCI Controller */
-               hose->first_busno = 0;
-               hose->current_busno = bus;
-
-               /* PCI memory space */
-               pci_set_region(hose->regions + 0, pcie->mem.start,
-                              pcie->mem.start, PCIE_MEM_SIZE, PCI_REGION_MEM);
-               pci_set_region(hose->regions + 1,
-                              0, 0,
-                              gd->ram_size,
-                              PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
-               hose->region_count = 2;
-
-               pci_set_ops(hose,
-                           pci_hose_read_config_byte_via_dword,
-                           pci_hose_read_config_word_via_dword,
-                           mvebu_pcie_read_config_dword,
-                           pci_hose_write_config_byte_via_dword,
-                           pci_hose_write_config_word_via_dword,
-                           mvebu_pcie_write_config_dword);
-               pci_register_hose(hose);
-
-               hose->last_busno = pci_hose_scan(hose);
-
-               /* Set BAR0 to internal registers */
-               writel(SOC_REGS_PHY_BASE, pcie->base + PCIE_BAR_LO_OFF(0));
-               writel(0, pcie->base + PCIE_BAR_HI_OFF(0));
-
-               bus = hose->last_busno + 1;
-
-               /* need to skip more for X4 links, otherwise scan will hang */
-               if (mvebu_soc_family() == MVEBU_SOC_AXP) {
-                       if (mvebu_pex_unit_is_x4(i))
-                               i += 3;
-               }
+               pcie = calloc(1, sizeof(*pcie));
+               if (!pcie)
+                       return -ENOMEM;
+
+               /* Create child device UCLASS_PCI and bind it */
+               device_bind_ofnode(parent, &pcie_mvebu_drv, pcie->name, pcie,
+                                  subnode, &dev);
        }
+
+       return 0;
 }
+
+static const struct udevice_id mvebu_pcie_ids[] = {
+       { .compatible = "marvell,armada-xp-pcie" },
+       { .compatible = "marvell,armada-370-pcie" },
+       { }
+};
+
+U_BOOT_DRIVER(pcie_mvebu_base) = {
+       .name                   = "pcie_mvebu_base",
+       .id                     = UCLASS_MISC,
+       .of_match               = mvebu_pcie_ids,
+       .bind                   = mvebu_pcie_bind,
+};
index 77ab6caf52c0db6bf50ba1ea74552f260151ac4a..f9510826d7df8ede2203cb476cab6cf39136ed6d 100644 (file)
@@ -55,7 +55,6 @@
 
 /* PCIe support */
 #ifndef CONFIG_SPL_BUILD
-#define CONFIG_PCI_MVEBU
 #define CONFIG_PCI_SCAN_SHOW
 #endif
 
index b38cab11641c57bdd5f3239f32dd3fa5a53de513..06c93c3e664cbf78de5cbf1e0fef3096da424c59 100644 (file)
@@ -63,9 +63,6 @@
 
 /* PCIe support */
 #ifndef CONFIG_SPL_BUILD
-#define CONFIG_PCI
-#define CONFIG_PCI_MVEBU
-#define CONFIG_PCI_PNP
 #define CONFIG_PCI_SCAN_SHOW
 #endif
 
index e68246cc0f4f6b15f9e70ad3994bbe5d4768c51e..626a406cff81b0894d1aef57dcb7a43e6afbc870 100644 (file)
@@ -34,7 +34,6 @@
 
 /* PCIe support */
 #ifndef CONFIG_SPL_BUILD
-#define CONFIG_PCI_MVEBU
 #define CONFIG_PCI_SCAN_SHOW
 #endif
 
index 3900cbed2d70b1f9a44bfe0430f73df80d7c7363..1f328e97c54547e34cc4abaa2d62c1d455ede2fe 100644 (file)
@@ -59,7 +59,6 @@
 
 /* PCIe support */
 #ifndef CONFIG_SPL_BUILD
-#define CONFIG_PCI_MVEBU
 #define CONFIG_PCI_SCAN_SHOW
 #endif
 
index 8ad007cc491293f840f271d7b865ff50fc44eea2..6cba3269278e9a38cda4f43547fd64755937b7d1 100644 (file)
@@ -46,7 +46,6 @@
 
 /* PCIe support */
 #ifndef CONFIG_SPL_BUILD
-#define CONFIG_PCI_MVEBU
 #define CONFIG_PCI_SCAN_SHOW
 #endif
 
index b9b708ad41d905cbb18b5d9de3b300a2b3554178..4ba050553a549d438a8f33530a9e8b5d9b496a5d 100644 (file)
@@ -41,7 +41,6 @@
 
 /* PCIe support */
 #ifndef CONFIG_SPL_BUILD
-#define CONFIG_PCI_MVEBU
 #define CONFIG_PCI_SCAN_SHOW
 #endif
 
index 2526a000840acc33cd29b63bc9175f68163c2cfd..27c858013d7d8226c549a4eded96ee7c4d8289d9 100644 (file)
 #define CONFIG_SYS_SATA_MAX_DEVICE     1
 #define CONFIG_LBA48
 
-/* PCIe support */
-#ifdef CONFIG_CMD_PCI
-#ifndef CONFIG_SPL_BUILD
-#define CONFIG_PCI_MVEBU
-#endif
-#endif
-
 /* Enable LCD and reserve 512KB from top of memory*/
 #define CONFIG_SYS_MEM_TOP_HIDE                0x80000
 
index 598674c96e8539a6f2102a2fe6cedb8af7f7cd4e..710b8991a4c22e4515ab69056f641a2e2f2b78aa 100644 (file)
@@ -66,7 +66,6 @@
 
 /* PCIe support */
 #ifndef CONFIG_SPL_BUILD
-#define CONFIG_PCI_MVEBU
 #define CONFIG_PCI_SCAN_SHOW
 #endif
 
index a1ef301d35e0e8b414182305320614d5d40aad2f..a83d49ba356e4f161872583dd35783205d25dd86 100644 (file)
@@ -75,7 +75,6 @@
 
 /* PCIe support */
 #ifndef CONFIG_SPL_BUILD
-#define CONFIG_PCI_MVEBU
 #define CONFIG_PCI_SCAN_SHOW
 #endif
 
index b425cc360fe18ca6e0780b057868dc6729ede415..f7f30d15aeea785e3db4abe05d384f9690b52b04 100644 (file)
@@ -1443,7 +1443,6 @@ CONFIG_PCI_MEM_BUS
 CONFIG_PCI_MEM_PHYS
 CONFIG_PCI_MEM_SIZE
 CONFIG_PCI_MSC01
-CONFIG_PCI_MVEBU
 CONFIG_PCI_NOSCAN
 CONFIG_PCI_OHCI
 CONFIG_PCI_OHCI_DEVNO