Merge branch '2021-02-02-drop-asm_global_data-when-unused'
[platform/kernel/u-boot.git] / drivers / pci / pci_mvebu.c
index 7d9ad34..235d9bb 100644 (file)
@@ -11,6 +11,9 @@
 
 #include <common.h>
 #include <dm.h>
+#include <log.h>
+#include <malloc.h>
+#include <asm/global_data.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
 #include <dm/of_access.h>
@@ -18,6 +21,7 @@
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
+#include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/mbus.h>
@@ -70,6 +74,7 @@ struct mvebu_pcie {
        void __iomem *membase;
        struct resource mem;
        void __iomem *iobase;
+       struct resource io;
        u32 port;
        u32 lane;
        int devfn;
@@ -78,6 +83,8 @@ struct mvebu_pcie {
        char name[16];
        unsigned int mem_target;
        unsigned int mem_attr;
+       unsigned int io_target;
+       unsigned int io_attr;
 };
 
 /*
@@ -87,6 +94,7 @@ struct mvebu_pcie {
  */
 static void __iomem *mvebu_pcie_membase = (void __iomem *)MBUS_PCI_MEM_BASE;
 #define PCIE_MEM_SIZE  (128 << 20)
+static void __iomem *mvebu_pcie_iobase = (void __iomem *)MBUS_PCI_IO_BASE;
 
 static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie)
 {
@@ -140,34 +148,27 @@ static int mvebu_pcie_read_config(const struct udevice *bus, pci_dev_t bdf,
                                  uint offset, ulong *valuep,
                                  enum pci_size_t size)
 {
-       struct mvebu_pcie *pcie = dev_get_platdata(bus);
+       struct mvebu_pcie *pcie = dev_get_plat(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(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
-                        */
-                       *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
-                        */
-                       *valuep = pci_get_ff(size);
-                       return 0;
-               }
+       debug("PCIE CFG read:  loc_bus=%d loc_dev=%d (b,d,f)=(%2d,%2d,%2d) ",
+             local_bus, local_dev, PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
+
+       /* Don't access the local host controller via this API */
+       if (PCI_BUS(bdf) == local_bus && PCI_DEV(bdf) == local_dev) {
+               debug("- skipping host controller\n");
+               *valuep = pci_get_ff(size);
+               return 0;
+       }
+
+       /* If local dev is 0, the first other dev can only be 1 */
+       if (PCI_BUS(bdf) == local_bus && local_dev == 0 && PCI_DEV(bdf) != 1) {
+               debug("- out of range\n");
+               *valuep = pci_get_ff(size);
+               return 0;
        }
 
        /* write address */
@@ -184,30 +185,25 @@ 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 = dev_get_platdata(bus);
+       struct mvebu_pcie *pcie = dev_get_plat(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("PCIE CFG write: loc_bus=%d loc_dev=%d (b,d,f)=(%2d,%2d,%2d) ",
+             local_bus, local_dev, 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(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 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 0;
-               }
+       /* Don't access the local host controller via this API */
+       if (PCI_BUS(bdf) == local_bus && PCI_DEV(bdf) == local_dev) {
+               debug("- skipping host controller\n");
+               return 0;
+       }
+
+       /* If local dev is 0, the first other dev can only be 1 */
+       if (PCI_BUS(bdf) == local_bus && local_dev == 0 && PCI_DEV(bdf) != 1) {
+               debug("- out of range\n");
+               return 0;
        }
 
        writel(PCIE_CONF_ADDR(bdf, offset), pcie->base + PCIE_CONF_ADDR_OFF);
@@ -274,7 +270,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie)
 
 static int mvebu_pcie_probe(struct udevice *dev)
 {
-       struct mvebu_pcie *pcie = dev_get_platdata(dev);
+       struct mvebu_pcie *pcie = dev_get_plat(dev);
        struct udevice *ctlr = pci_get_controller(dev);
        struct pci_controller *hose = dev_get_uclass_priv(ctlr);
        static int bus;
@@ -303,12 +299,24 @@ static int mvebu_pcie_probe(struct udevice *dev)
                       (u32)pcie->mem.start, PCIE_MEM_SIZE);
        }
 
+       pcie->io.start = (u32)mvebu_pcie_iobase;
+       pcie->io.end = pcie->io.start + MBUS_PCI_IO_SIZE - 1;
+       mvebu_pcie_iobase += MBUS_PCI_IO_SIZE;
+
+       if (mvebu_mbus_add_window_by_id(pcie->io_target, pcie->io_attr,
+                                       (phys_addr_t)pcie->io.start,
+                                       MBUS_PCI_IO_SIZE)) {
+               printf("PCIe unable to add mbus window for IO at %08x+%08x\n",
+                      (u32)pcie->io.start, MBUS_PCI_IO_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_IO;
        reg |= PCI_COMMAND_MASTER;
        reg |= BIT(10);         /* disable interrupts */
        writel(reg, pcie->base + PCIE_CMD_OFF);
@@ -320,7 +328,9 @@ static int mvebu_pcie_probe(struct udevice *dev)
                       0, 0,
                       gd->ram_size,
                       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
-       hose->region_count = 2;
+       pci_set_region(hose->regions + 2, pcie->io.start,
+                      pcie->io.start, MBUS_PCI_IO_SIZE, PCI_REGION_IO);
+       hose->region_count = 3;
 
        /* Set BAR0 to internal registers */
        writel(SOC_REGS_PHY_BASE, pcie->base + PCIE_BAR_LO_OFF(0));
@@ -407,9 +417,9 @@ static int mvebu_get_tgt_attr(ofnode node, int devfn,
        return -ENOENT;
 }
 
-static int mvebu_pcie_ofdata_to_platdata(struct udevice *dev)
+static int mvebu_pcie_of_to_plat(struct udevice *dev)
 {
-       struct mvebu_pcie *pcie = dev_get_platdata(dev);
+       struct mvebu_pcie *pcie = dev_get_plat(dev);
        int ret = 0;
 
        /* Get port number, lane number and memory target / attr */
@@ -439,6 +449,14 @@ static int mvebu_pcie_ofdata_to_platdata(struct udevice *dev)
                goto err;
        }
 
+       ret = mvebu_get_tgt_attr(dev_ofnode(dev->parent), pcie->devfn,
+                                IORESOURCE_IO,
+                                &pcie->io_target, &pcie->io_attr);
+       if (ret < 0) {
+               printf("%s: cannot get tgt/attr for IO 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)
@@ -467,8 +485,8 @@ static struct driver pcie_mvebu_drv = {
        .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),
+       .of_to_plat     = mvebu_pcie_of_to_plat,
+       .plat_auto      = sizeof(struct mvebu_pcie),
 };
 
 /*
@@ -498,8 +516,8 @@ static int mvebu_pcie_bind(struct udevice *parent)
                        return -ENOMEM;
 
                /* Create child device UCLASS_PCI and bind it */
-               device_bind_ofnode(parent, &pcie_mvebu_drv, pcie->name, pcie,
-                                  subnode, &dev);
+               device_bind(parent, &pcie_mvebu_drv, pcie->name, pcie, subnode,
+                           &dev);
        }
 
        return 0;