brcm2708: organize kernel patches
[openwrt/staging/chunkeey.git] / target / linux / brcm2708 / patches-4.19 / 950-0531-pcie-brcmstb-Changes-for-BCM2711.patch
diff --git a/target/linux/brcm2708/patches-4.19/950-0531-pcie-brcmstb-Changes-for-BCM2711.patch b/target/linux/brcm2708/patches-4.19/950-0531-pcie-brcmstb-Changes-for-BCM2711.patch
deleted file mode 100644 (file)
index 58803a8..0000000
+++ /dev/null
@@ -1,1411 +0,0 @@
-From 545951be6cabac8b1df85771c44335a0eaaa3c5d Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 19 Feb 2019 22:06:59 +0000
-Subject: [PATCH 531/806] pcie-brcmstb: Changes for BCM2711
-
-The initial brcmstb PCIe driver - originally taken from the V3(?)
-patch set - has been modified significantly for the BCM2711.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/dma/bcm2835-dma.c                    | 107 ++++
- drivers/pci/controller/Makefile              |   4 +
- drivers/pci/controller/pcie-brcmstb-bounce.c | 564 +++++++++++++++++++
- drivers/pci/controller/pcie-brcmstb-bounce.h |  32 ++
- drivers/pci/controller/pcie-brcmstb.c        | 237 ++++----
- drivers/soc/bcm/brcmstb/Makefile             |   2 +-
- drivers/soc/bcm/brcmstb/memory.c             | 158 ++++++
- 7 files changed, 996 insertions(+), 108 deletions(-)
- create mode 100644 drivers/pci/controller/pcie-brcmstb-bounce.c
- create mode 100644 drivers/pci/controller/pcie-brcmstb-bounce.h
- create mode 100644 drivers/soc/bcm/brcmstb/memory.c
-
---- a/drivers/dma/bcm2835-dma.c
-+++ b/drivers/dma/bcm2835-dma.c
-@@ -68,6 +68,17 @@ struct bcm2835_dma_cb {
-       uint32_t pad[2];
- };
-+struct bcm2838_dma40_scb {
-+      uint32_t ti;
-+      uint32_t src;
-+      uint32_t srci;
-+      uint32_t dst;
-+      uint32_t dsti;
-+      uint32_t len;
-+      uint32_t next_cb;
-+      uint32_t rsvd;
-+};
-+
- struct bcm2835_cb_entry {
-       struct bcm2835_dma_cb *cb;
-       dma_addr_t paddr;
-@@ -185,6 +196,45 @@ struct bcm2835_desc {
- #define MAX_DMA_LEN SZ_1G
- #define MAX_LITE_DMA_LEN (SZ_64K - 4)
-+/* 40-bit DMA support */
-+#define BCM2838_DMA40_CS      0x00
-+#define BCM2838_DMA40_CB      0x04
-+#define BCM2838_DMA40_DEBUG   0x0c
-+#define BCM2858_DMA40_TI      0x10
-+#define BCM2838_DMA40_SRC     0x14
-+#define BCM2838_DMA40_SRCI    0x18
-+#define BCM2838_DMA40_DEST    0x1c
-+#define BCM2838_DMA40_DESTI   0x20
-+#define BCM2838_DMA40_LEN     0x24
-+#define BCM2838_DMA40_NEXT_CB 0x28
-+#define BCM2838_DMA40_DEBUG2  0x2c
-+
-+#define BCM2838_DMA40_CS_ACTIVE       BIT(0)
-+#define BCM2838_DMA40_CS_END  BIT(1)
-+
-+#define BCM2838_DMA40_CS_QOS(x)       (((x) & 0x1f) << 16)
-+#define BCM2838_DMA40_CS_PANIC_QOS(x) (((x) & 0x1f) << 20)
-+#define BCM2838_DMA40_CS_WRITE_WAIT   BIT(28)
-+
-+#define BCM2838_DMA40_BURST_LEN(x)    ((((x) - 1) & 0xf) << 8)
-+#define BCM2838_DMA40_INC             BIT(12)
-+#define BCM2838_DMA40_SIZE_128        (2 << 13)
-+
-+#define BCM2838_DMA40_MEMCPY_QOS \
-+      (BCM2838_DMA40_CS_QOS(0x0) | \
-+       BCM2838_DMA40_CS_PANIC_QOS(0x0) | \
-+       BCM2838_DMA40_CS_WRITE_WAIT)
-+
-+#define BCM2838_DMA40_MEMCPY_XFER_INFO \
-+      (BCM2838_DMA40_SIZE_128 | \
-+       BCM2838_DMA40_INC | \
-+       BCM2838_DMA40_BURST_LEN(16))
-+
-+static void __iomem *memcpy_chan;
-+static struct bcm2838_dma40_scb *memcpy_scb;
-+static dma_addr_t memcpy_scb_dma;
-+DEFINE_SPINLOCK(memcpy_lock);
-+
- static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c)
- {
-       /* lite and normal channels have different max frame length */
-@@ -868,6 +918,56 @@ static void bcm2835_dma_free(struct bcm2
-       }
- }
-+int bcm2838_dma40_memcpy_init(struct device *dev)
-+{
-+      if (memcpy_scb)
-+              return 0;
-+
-+      memcpy_scb = dma_alloc_coherent(dev, sizeof(*memcpy_scb),
-+                                      &memcpy_scb_dma, GFP_KERNEL);
-+
-+      if (!memcpy_scb) {
-+              pr_err("bcm2838_dma40_memcpy_init failed!\n");
-+              return -ENOMEM;
-+      }
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL(bcm2838_dma40_memcpy_init);
-+
-+void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size)
-+{
-+      struct bcm2838_dma40_scb *scb = memcpy_scb;
-+      unsigned long flags;
-+
-+      if (!scb) {
-+              pr_err("bcm2838_dma40_memcpy not initialised!\n");
-+              return;
-+      }
-+
-+      spin_lock_irqsave(&memcpy_lock, flags);
-+
-+      scb->ti = 0;
-+      scb->src = lower_32_bits(src);
-+      scb->srci = upper_32_bits(src) | BCM2838_DMA40_MEMCPY_XFER_INFO;
-+      scb->dst = lower_32_bits(dst);
-+      scb->dsti = upper_32_bits(dst) | BCM2838_DMA40_MEMCPY_XFER_INFO;
-+      scb->len = size;
-+      scb->next_cb = 0;
-+
-+      writel((u32)(memcpy_scb_dma >> 5), memcpy_chan + BCM2838_DMA40_CB);
-+      writel(BCM2838_DMA40_MEMCPY_QOS + BCM2838_DMA40_CS_ACTIVE,
-+             memcpy_chan + BCM2838_DMA40_CS);
-+      /* Poll for completion */
-+      while (!(readl(memcpy_chan + BCM2838_DMA40_CS) & BCM2838_DMA40_CS_END))
-+              cpu_relax();
-+
-+      writel(BCM2838_DMA40_CS_END, memcpy_chan + BCM2838_DMA40_CS);
-+
-+      spin_unlock_irqrestore(&memcpy_lock, flags);
-+}
-+EXPORT_SYMBOL(bcm2838_dma40_memcpy);
-+
- static const struct of_device_id bcm2835_dma_of_match[] = {
-       { .compatible = "brcm,bcm2835-dma", },
-       {},
-@@ -966,6 +1066,13 @@ static int bcm2835_dma_probe(struct plat
-       /* Channel 0 is used by the legacy API */
-       chans_available &= ~BCM2835_DMA_BULK_MASK;
-+      /* We can't use channels 11-13 yet */
-+      chans_available &= ~(BIT(11) | BIT(12) | BIT(13));
-+
-+      /* Grab channel 14 for the 40-bit DMA memcpy */
-+      chans_available &= ~BIT(14);
-+      memcpy_chan = BCM2835_DMA_CHANIO(base, 14);
-+
-       /* get irqs for each channel that we support */
-       for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
-               /* skip masked out channels */
---- a/drivers/pci/controller/Makefile
-+++ b/drivers/pci/controller/Makefile
-@@ -29,6 +29,10 @@ obj-$(CONFIG_PCIE_MEDIATEK) += pcie-medi
- obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
- obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
- obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
-+ifdef CONFIG_ARM
-+obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb-bounce.o
-+endif
-+
- obj-$(CONFIG_VMD) += vmd.o
- # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
- obj-y                         += dwc/
---- /dev/null
-+++ b/drivers/pci/controller/pcie-brcmstb-bounce.c
-@@ -0,0 +1,564 @@
-+/*
-+ *  This code started out as a version of arch/arm/common/dmabounce.c,
-+ *  modified to cope with highmem pages. Now it has been changed heavily -
-+ *  it now preallocates a large block (currently 4MB) and carves it up
-+ *  sequentially in ring fashion, and DMA is used to copy the data - to the
-+ *  point where very little of the original remains.
-+ *
-+ *  Copyright (C) 2019 Raspberry Pi (Trading) Ltd.
-+ *
-+ *  Original version by Brad Parker (brad@heeltoe.com)
-+ *  Re-written by Christopher Hoover <ch@murgatroid.com>
-+ *  Made generic by Deepak Saxena <dsaxena@plexity.net>
-+ *
-+ *  Copyright (C) 2002 Hewlett Packard Company.
-+ *  Copyright (C) 2004 MontaVista Software, Inc.
-+ *
-+ *  This program is free software; you can redistribute it and/or
-+ *  modify it under the terms of the GNU General Public License
-+ *  version 2 as published by the Free Software Foundation.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/page-flags.h>
-+#include <linux/device.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/dmapool.h>
-+#include <linux/list.h>
-+#include <linux/scatterlist.h>
-+#include <linux/bitmap.h>
-+
-+#include <asm/cacheflush.h>
-+#include <asm/dma-iommu.h>
-+
-+#define STATS
-+
-+#ifdef STATS
-+#define DO_STATS(X) do { X ; } while (0)
-+#else
-+#define DO_STATS(X) do { } while (0)
-+#endif
-+
-+/* ************************************************** */
-+
-+struct safe_buffer {
-+      struct list_head node;
-+
-+      /* original request */
-+      size_t          size;
-+      int             direction;
-+
-+      struct dmabounce_pool *pool;
-+      void            *safe;
-+      dma_addr_t      unsafe_dma_addr;
-+      dma_addr_t      safe_dma_addr;
-+};
-+
-+struct dmabounce_pool {
-+      unsigned long   pages;
-+      void            *virt_addr;
-+      dma_addr_t      dma_addr;
-+      unsigned long   *alloc_map;
-+      unsigned long   alloc_pos;
-+      spinlock_t      lock;
-+      struct device   *dev;
-+      unsigned long   num_pages;
-+#ifdef STATS
-+      size_t          max_size;
-+      unsigned long   num_bufs;
-+      unsigned long   max_bufs;
-+      unsigned long   max_pages;
-+#endif
-+};
-+
-+struct dmabounce_device_info {
-+      struct device *dev;
-+      dma_addr_t threshold;
-+      struct list_head safe_buffers;
-+      struct dmabounce_pool pool;
-+      rwlock_t lock;
-+#ifdef STATS
-+      unsigned long map_count;
-+      unsigned long unmap_count;
-+      unsigned long sync_dev_count;
-+      unsigned long sync_cpu_count;
-+      unsigned long fail_count;
-+      int attr_res;
-+#endif
-+};
-+
-+static struct dmabounce_device_info *g_dmabounce_device_info;
-+
-+extern int bcm2838_dma40_memcpy_init(struct device *dev);
-+extern void bcm2838_dma40_memcpy(dma_addr_t dst, dma_addr_t src, size_t size);
-+
-+#ifdef STATS
-+static ssize_t
-+bounce_show(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+      struct dmabounce_device_info *device_info = g_dmabounce_device_info;
-+      return sprintf(buf, "m:%lu/%lu s:%lu/%lu f:%lu s:%zu b:%lu/%lu a:%lu/%lu\n",
-+              device_info->map_count,
-+              device_info->unmap_count,
-+              device_info->sync_dev_count,
-+              device_info->sync_cpu_count,
-+              device_info->fail_count,
-+              device_info->pool.max_size,
-+              device_info->pool.num_bufs,
-+              device_info->pool.max_bufs,
-+              device_info->pool.num_pages * PAGE_SIZE,
-+              device_info->pool.max_pages * PAGE_SIZE);
-+}
-+
-+static DEVICE_ATTR(dmabounce_stats, 0444, bounce_show, NULL);
-+#endif
-+
-+static int bounce_create(struct dmabounce_pool *pool, struct device *dev,
-+                       unsigned long buffer_size)
-+{
-+      int ret = -ENOMEM;
-+      pool->pages = (buffer_size + PAGE_SIZE - 1)/PAGE_SIZE;
-+      pool->alloc_map = bitmap_zalloc(pool->pages, GFP_KERNEL);
-+      if (!pool->alloc_map)
-+              goto err_bitmap;
-+      pool->virt_addr = dma_alloc_coherent(dev, pool->pages * PAGE_SIZE,
-+                                           &pool->dma_addr, GFP_KERNEL);
-+      if (!pool->virt_addr)
-+              goto err_dmabuf;
-+
-+      pool->alloc_pos = 0;
-+      spin_lock_init(&pool->lock);
-+      pool->dev = dev;
-+      pool->num_pages = 0;
-+
-+      DO_STATS(pool->max_size = 0);
-+      DO_STATS(pool->num_bufs = 0);
-+      DO_STATS(pool->max_bufs = 0);
-+      DO_STATS(pool->max_pages = 0);
-+
-+      return  0;
-+
-+err_dmabuf:
-+      bitmap_free(pool->alloc_map);
-+err_bitmap:
-+      return ret;
-+}
-+
-+static void bounce_destroy(struct dmabounce_pool *pool)
-+{
-+      dma_free_coherent(pool->dev, pool->pages * PAGE_SIZE, pool->virt_addr,
-+                        pool->dma_addr);
-+
-+      bitmap_free(pool->alloc_map);
-+}
-+
-+static void *bounce_alloc(struct dmabounce_pool *pool, size_t size,
-+                        dma_addr_t *dmaaddrp)
-+{
-+      unsigned long pages;
-+      unsigned long flags;
-+      unsigned long pos;
-+
-+      pages = (size + PAGE_SIZE - 1)/PAGE_SIZE;
-+
-+      DO_STATS(pool->max_size = max(size, pool->max_size));
-+
-+      spin_lock_irqsave(&pool->lock, flags);
-+      pos = bitmap_find_next_zero_area(pool->alloc_map, pool->pages,
-+                                       pool->alloc_pos, pages, 0);
-+      /* If not found, try from the start */
-+      if (pos >= pool->pages && pool->alloc_pos)
-+              pos = bitmap_find_next_zero_area(pool->alloc_map, pool->pages,
-+                                               0, pages, 0);
-+
-+      if (pos >= pool->pages) {
-+              spin_unlock_irqrestore(&pool->lock, flags);
-+              return NULL;
-+      }
-+
-+      bitmap_set(pool->alloc_map, pos, pages);
-+      pool->alloc_pos = (pos + pages) % pool->pages;
-+      pool->num_pages += pages;
-+
-+      DO_STATS(pool->num_bufs++);
-+      DO_STATS(pool->max_bufs = max(pool->num_bufs, pool->max_bufs));
-+      DO_STATS(pool->max_pages = max(pool->num_pages, pool->max_pages));
-+
-+      spin_unlock_irqrestore(&pool->lock, flags);
-+
-+      *dmaaddrp = pool->dma_addr + pos * PAGE_SIZE;
-+
-+      return pool->virt_addr + pos * PAGE_SIZE;
-+}
-+
-+static void
-+bounce_free(struct dmabounce_pool *pool, void *buf, size_t size)
-+{
-+      unsigned long pages;
-+      unsigned long flags;
-+      unsigned long pos;
-+
-+      pages = (size + PAGE_SIZE - 1)/PAGE_SIZE;
-+      pos = (buf - pool->virt_addr)/PAGE_SIZE;
-+
-+      BUG_ON((buf - pool->virt_addr) & (PAGE_SIZE - 1));
-+
-+      spin_lock_irqsave(&pool->lock, flags);
-+      bitmap_clear(pool->alloc_map, pos, pages);
-+      pool->num_pages -= pages;
-+      if (pool->num_pages == 0)
-+              pool->alloc_pos = 0;
-+      DO_STATS(pool->num_bufs--);
-+      spin_unlock_irqrestore(&pool->lock, flags);
-+}
-+
-+/* allocate a 'safe' buffer and keep track of it */
-+static struct safe_buffer *
-+alloc_safe_buffer(struct dmabounce_device_info *device_info,
-+                dma_addr_t dma_addr, size_t size, enum dma_data_direction dir)
-+{
-+      struct safe_buffer *buf;
-+      struct dmabounce_pool *pool = &device_info->pool;
-+      struct device *dev = device_info->dev;
-+      unsigned long flags;
-+
-+      /*
-+       * Although one might expect this to be called in thread context,
-+       * using GFP_KERNEL here leads to hard-to-debug lockups. in_atomic()
-+       * was previously used to select the appropriate allocation mode,
-+       * but this is unsafe.
-+       */
-+      buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC);
-+      if (!buf) {
-+              dev_warn(dev, "%s: kmalloc failed\n", __func__);
-+              return NULL;
-+      }
-+
-+      buf->unsafe_dma_addr = dma_addr;
-+      buf->size = size;
-+      buf->direction = dir;
-+      buf->pool = pool;
-+
-+      buf->safe = bounce_alloc(pool, size, &buf->safe_dma_addr);
-+
-+      if (!buf->safe) {
-+              dev_warn(dev,
-+                       "%s: could not alloc dma memory (size=%d)\n",
-+                       __func__, size);
-+              kfree(buf);
-+              return NULL;
-+      }
-+
-+      write_lock_irqsave(&device_info->lock, flags);
-+      list_add(&buf->node, &device_info->safe_buffers);
-+      write_unlock_irqrestore(&device_info->lock, flags);
-+
-+      return buf;
-+}
-+
-+/* determine if a buffer is from our "safe" pool */
-+static struct safe_buffer *
-+find_safe_buffer(struct dmabounce_device_info *device_info,
-+               dma_addr_t safe_dma_addr)
-+{
-+      struct safe_buffer *b, *rb = NULL;
-+      unsigned long flags;
-+
-+      read_lock_irqsave(&device_info->lock, flags);
-+
-+      list_for_each_entry(b, &device_info->safe_buffers, node)
-+              if (b->safe_dma_addr <= safe_dma_addr &&
-+                  b->safe_dma_addr + b->size > safe_dma_addr) {
-+                      rb = b;
-+                      break;
-+              }
-+
-+      read_unlock_irqrestore(&device_info->lock, flags);
-+      return rb;
-+}
-+
-+static void
-+free_safe_buffer(struct dmabounce_device_info *device_info,
-+               struct safe_buffer *buf)
-+{
-+      unsigned long flags;
-+
-+      write_lock_irqsave(&device_info->lock, flags);
-+      list_del(&buf->node);
-+      write_unlock_irqrestore(&device_info->lock, flags);
-+
-+      bounce_free(buf->pool, buf->safe, buf->size);
-+
-+      kfree(buf);
-+}
-+
-+/* ************************************************** */
-+
-+static struct safe_buffer *
-+find_safe_buffer_dev(struct device *dev, dma_addr_t dma_addr, const char *where)
-+{
-+      if (!dev || !g_dmabounce_device_info)
-+              return NULL;
-+      if (dma_mapping_error(dev, dma_addr)) {
-+              dev_err(dev, "Trying to %s invalid mapping\n", where);
-+              return NULL;
-+      }
-+      return find_safe_buffer(g_dmabounce_device_info, dma_addr);
-+}
-+
-+static dma_addr_t
-+map_single(struct device *dev, struct safe_buffer *buf, size_t size,
-+         enum dma_data_direction dir, unsigned long attrs)
-+{
-+      BUG_ON(buf->size != size);
-+      BUG_ON(buf->direction != dir);
-+
-+      dev_dbg(dev, "map: %llx->%llx\n", (u64)buf->unsafe_dma_addr,
-+              (u64)buf->safe_dma_addr);
-+
-+      if ((dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) &&
-+          !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-+              bcm2838_dma40_memcpy(buf->safe_dma_addr, buf->unsafe_dma_addr,
-+                                   size);
-+
-+      return buf->safe_dma_addr;
-+}
-+
-+static dma_addr_t
-+unmap_single(struct device *dev, struct safe_buffer *buf, size_t size,
-+           enum dma_data_direction dir, unsigned long attrs)
-+{
-+      BUG_ON(buf->size != size);
-+      BUG_ON(buf->direction != dir);
-+
-+      if ((dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) &&
-+          !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
-+              dev_dbg(dev, "unmap: %llx->%llx\n", (u64)buf->safe_dma_addr,
-+                      (u64)buf->unsafe_dma_addr);
-+
-+              bcm2838_dma40_memcpy(buf->unsafe_dma_addr, buf->safe_dma_addr,
-+                                   size);
-+      }
-+      return buf->unsafe_dma_addr;
-+}
-+
-+/* ************************************************** */
-+
-+/*
-+ * see if a buffer address is in an 'unsafe' range.  if it is
-+ * allocate a 'safe' buffer and copy the unsafe buffer into it.
-+ * substitute the safe buffer for the unsafe one.
-+ * (basically move the buffer from an unsafe area to a safe one)
-+ */
-+static dma_addr_t
-+dmabounce_map_page(struct device *dev, struct page *page, unsigned long offset,
-+                 size_t size, enum dma_data_direction dir,
-+                 unsigned long attrs)
-+{
-+      struct dmabounce_device_info *device_info = g_dmabounce_device_info;
-+      dma_addr_t dma_addr;
-+
-+      dma_addr = pfn_to_dma(dev, page_to_pfn(page)) + offset;
-+
-+      arm_dma_ops.sync_single_for_device(dev, dma_addr, size, dir);
-+
-+      if (device_info && (dma_addr + size) > device_info->threshold) {
-+              struct safe_buffer *buf;
-+
-+              buf = alloc_safe_buffer(device_info, dma_addr, size, dir);
-+              if (!buf) {
-+                      DO_STATS(device_info->fail_count++);
-+                      return ARM_MAPPING_ERROR;
-+              }
-+
-+              DO_STATS(device_info->map_count++);
-+
-+              dma_addr = map_single(dev, buf, size, dir, attrs);
-+      }
-+
-+      return dma_addr;
-+}
-+
-+/*
-+ * see if a mapped address was really a "safe" buffer and if so, copy
-+ * the data from the safe buffer back to the unsafe buffer and free up
-+ * the safe buffer.  (basically return things back to the way they
-+ * should be)
-+ */
-+static void
-+dmabounce_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
-+                   enum dma_data_direction dir, unsigned long attrs)
-+{
-+      struct safe_buffer *buf;
-+
-+      buf = find_safe_buffer_dev(dev, dma_addr, __func__);
-+      if (buf) {
-+              DO_STATS(g_dmabounce_device_info->unmap_count++);
-+              dma_addr = unmap_single(dev, buf, size, dir, attrs);
-+              free_safe_buffer(g_dmabounce_device_info, buf);
-+      }
-+
-+      arm_dma_ops.sync_single_for_cpu(dev, dma_addr, size, dir);
-+}
-+
-+/*
-+ * A version of dmabounce_map_page that assumes the mapping has already
-+ * been created - intended for streaming operation.
-+ */
-+static void
-+dmabounce_sync_for_device(struct device *dev, dma_addr_t dma_addr, size_t size,
-+                        enum dma_data_direction dir)
-+{
-+      struct safe_buffer *buf;
-+
-+      arm_dma_ops.sync_single_for_device(dev, dma_addr, size, dir);
-+
-+      buf = find_safe_buffer_dev(dev, dma_addr, __func__);
-+      if (buf) {
-+              DO_STATS(g_dmabounce_device_info->sync_dev_count++);
-+              map_single(dev, buf, size, dir, 0);
-+      }
-+}
-+
-+/*
-+ * A version of dmabounce_unmap_page that doesn't destroy the mapping -
-+ * intended for streaming operation.
-+ */
-+static void
-+dmabounce_sync_for_cpu(struct device *dev, dma_addr_t dma_addr,
-+                     size_t size, enum dma_data_direction dir)
-+{
-+      struct safe_buffer *buf;
-+
-+      buf = find_safe_buffer_dev(dev, dma_addr, __func__);
-+      if (buf) {
-+              DO_STATS(g_dmabounce_device_info->sync_cpu_count++);
-+              dma_addr = unmap_single(dev, buf, size, dir, 0);
-+      }
-+
-+      arm_dma_ops.sync_single_for_cpu(dev, dma_addr, size, dir);
-+}
-+
-+static int dmabounce_dma_supported(struct device *dev, u64 dma_mask)
-+{
-+      if (g_dmabounce_device_info)
-+              return 0;
-+
-+      return arm_dma_ops.dma_supported(dev, dma_mask);
-+}
-+
-+static int dmabounce_mapping_error(struct device *dev, dma_addr_t dma_addr)
-+{
-+      return arm_dma_ops.mapping_error(dev, dma_addr);
-+}
-+
-+static const struct dma_map_ops dmabounce_ops = {
-+      .alloc                  = arm_dma_alloc,
-+      .free                   = arm_dma_free,
-+      .mmap                   = arm_dma_mmap,
-+      .get_sgtable            = arm_dma_get_sgtable,
-+      .map_page               = dmabounce_map_page,
-+      .unmap_page             = dmabounce_unmap_page,
-+      .sync_single_for_cpu    = dmabounce_sync_for_cpu,
-+      .sync_single_for_device = dmabounce_sync_for_device,
-+      .map_sg                 = arm_dma_map_sg,
-+      .unmap_sg               = arm_dma_unmap_sg,
-+      .sync_sg_for_cpu        = arm_dma_sync_sg_for_cpu,
-+      .sync_sg_for_device     = arm_dma_sync_sg_for_device,
-+      .dma_supported          = dmabounce_dma_supported,
-+      .mapping_error          = dmabounce_mapping_error,
-+};
-+
-+int brcm_pcie_bounce_register_dev(struct device *dev,
-+                                unsigned long buffer_size,
-+                                dma_addr_t threshold)
-+{
-+      struct dmabounce_device_info *device_info;
-+      int ret;
-+
-+      /* Only support a single client */
-+      if (g_dmabounce_device_info)
-+              return -EBUSY;
-+
-+      ret = bcm2838_dma40_memcpy_init(dev);
-+      if (ret)
-+          return ret;
-+
-+      device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
-+      if (!device_info) {
-+              dev_err(dev,
-+                      "Could not allocated dmabounce_device_info\n");
-+              return -ENOMEM;
-+      }
-+
-+      ret = bounce_create(&device_info->pool, dev, buffer_size);
-+      if (ret) {
-+              dev_err(dev,
-+                      "dmabounce: could not allocate %ld byte DMA pool\n",
-+                      buffer_size);
-+              goto err_bounce;
-+      }
-+
-+      device_info->dev = dev;
-+      device_info->threshold = threshold;
-+      INIT_LIST_HEAD(&device_info->safe_buffers);
-+      rwlock_init(&device_info->lock);
-+
-+      DO_STATS(device_info->map_count = 0);
-+      DO_STATS(device_info->unmap_count = 0);
-+      DO_STATS(device_info->sync_dev_count = 0);
-+      DO_STATS(device_info->sync_cpu_count = 0);
-+      DO_STATS(device_info->fail_count = 0);
-+      DO_STATS(device_info->attr_res =
-+               device_create_file(dev, &dev_attr_dmabounce_stats));
-+
-+      g_dmabounce_device_info = device_info;
-+      set_dma_ops(dev, &dmabounce_ops);
-+
-+      dev_info(dev, "dmabounce: registered device - %ld kB, threshold %pad\n",
-+               buffer_size / 1024, &threshold);
-+
-+      return 0;
-+
-+ err_bounce:
-+      kfree(device_info);
-+      return ret;
-+}
-+EXPORT_SYMBOL(brcm_pcie_bounce_register_dev);
-+
-+void brcm_pcie_bounce_unregister_dev(struct device *dev)
-+{
-+      struct dmabounce_device_info *device_info = g_dmabounce_device_info;
-+
-+      g_dmabounce_device_info = NULL;
-+      set_dma_ops(dev, NULL);
-+
-+      if (!device_info) {
-+              dev_warn(dev,
-+                       "Never registered with dmabounce but attempting"
-+                       "to unregister!\n");
-+              return;
-+      }
-+
-+      if (!list_empty(&device_info->safe_buffers)) {
-+              dev_err(dev,
-+                      "Removing from dmabounce with pending buffers!\n");
-+              BUG();
-+      }
-+
-+      bounce_destroy(&device_info->pool);
-+
-+      DO_STATS(if (device_info->attr_res == 0)
-+                       device_remove_file(dev, &dev_attr_dmabounce_stats));
-+
-+      kfree(device_info);
-+
-+      dev_info(dev, "dmabounce: device unregistered\n");
-+}
-+EXPORT_SYMBOL(brcm_pcie_bounce_unregister_dev);
-+
-+MODULE_AUTHOR("Phil Elwell <phil@raspberrypi.org>");
-+MODULE_DESCRIPTION("Dedicate DMA bounce support for pcie-brcmstb");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/pci/controller/pcie-brcmstb-bounce.h
-@@ -0,0 +1,32 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ *  Copyright (C) 2019 Raspberry Pi (Trading) Ltd.
-+ */
-+
-+#ifndef _PCIE_BRCMSTB_BOUNCE_H
-+#define _PCIE_BRCMSTB_BOUNCE_H
-+
-+#ifdef CONFIG_ARM
-+
-+int brcm_pcie_bounce_register_dev(struct device *dev, unsigned long buffer_size,
-+                                dma_addr_t threshold);
-+
-+int brcm_pcie_bounce_unregister_dev(struct device *dev);
-+
-+#else
-+
-+static inline int brcm_pcie_bounce_register_dev(struct device *dev,
-+                                              unsigned long buffer_size,
-+                                              dma_addr_t threshold)
-+{
-+      return 0;
-+}
-+
-+static inline int brcm_pcie_bounce_unregister_dev(struct device *dev)
-+{
-+      return 0;
-+}
-+
-+#endif
-+
-+#endif /* _PCIE_BRCMSTB_BOUNCE_H */
---- a/drivers/pci/controller/pcie-brcmstb.c
-+++ b/drivers/pci/controller/pcie-brcmstb.c
-@@ -29,6 +29,7 @@
- #include <linux/string.h>
- #include <linux/types.h>
- #include "../pci.h"
-+#include "pcie-brcmstb-bounce.h"
- /* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */
- #define BRCM_PCIE_CAP_REGS                            0x00ac
-@@ -53,6 +54,7 @@
- #define PCIE_MISC_MSI_BAR_CONFIG_LO                   0x4044
- #define PCIE_MISC_MSI_BAR_CONFIG_HI                   0x4048
- #define PCIE_MISC_MSI_DATA_CONFIG                     0x404c
-+#define PCIE_MISC_EOI_CTRL                            0x4060
- #define PCIE_MISC_PCIE_CTRL                           0x4064
- #define PCIE_MISC_PCIE_STATUS                         0x4068
- #define PCIE_MISC_REVISION                            0x406c
-@@ -260,12 +262,14 @@ struct brcm_pcie {
-       unsigned int            rev;
-       const int               *reg_offsets;
-       const int               *reg_field_info;
-+      u32                     max_burst_size;
-       enum pcie_type          type;
- };
- struct pcie_cfg_data {
-       const int               *reg_field_info;
-       const int               *offsets;
-+      const u32               max_burst_size;
-       const enum pcie_type    type;
- };
-@@ -288,24 +292,27 @@ static const int pcie_offset_bcm7425[] =
- static const struct pcie_cfg_data bcm7425_cfg = {
-       .reg_field_info = pcie_reg_field_info,
-       .offsets        = pcie_offset_bcm7425,
-+      .max_burst_size = BURST_SIZE_256,
-       .type           = BCM7425,
- };
- static const int pcie_offsets[] = {
-       [RGR1_SW_INIT_1] = 0x9210,
-       [EXT_CFG_INDEX]  = 0x9000,
--      [EXT_CFG_DATA]   = 0x9004,
-+      [EXT_CFG_DATA]   = 0x8000,
- };
- static const struct pcie_cfg_data bcm7435_cfg = {
-       .reg_field_info = pcie_reg_field_info,
-       .offsets        = pcie_offsets,
-+      .max_burst_size = BURST_SIZE_256,
-       .type           = BCM7435,
- };
- static const struct pcie_cfg_data generic_cfg = {
-       .reg_field_info = pcie_reg_field_info,
-       .offsets        = pcie_offsets,
-+      .max_burst_size = BURST_SIZE_128, // before BURST_SIZE_512
-       .type           = GENERIC,
- };
-@@ -318,6 +325,7 @@ static const int pcie_offset_bcm7278[] =
- static const struct pcie_cfg_data bcm7278_cfg = {
-       .reg_field_info = pcie_reg_field_info_bcm7278,
-       .offsets        = pcie_offset_bcm7278,
-+      .max_burst_size = BURST_SIZE_512,
-       .type           = BCM7278,
- };
-@@ -360,7 +368,6 @@ static struct pci_ops brcm_pcie_ops = {
-        (reg##_##field##_MASK & (field_val << reg##_##field##_SHIFT)))
- static const struct dma_map_ops *arch_dma_ops;
--static const struct dma_map_ops *brcm_dma_ops_ptr;
- static struct of_pci_range *dma_ranges;
- static int num_dma_ranges;
-@@ -369,6 +376,16 @@ static int num_memc;
- static int num_pcie;
- static DEFINE_MUTEX(brcm_pcie_lock);
-+static unsigned int bounce_buffer = 32*1024*1024;
-+module_param(bounce_buffer, uint, 0644);
-+MODULE_PARM_DESC(bounce_buffer, "Size of bounce buffer");
-+
-+static unsigned int bounce_threshold = 0xc0000000;
-+module_param(bounce_threshold, uint, 0644);
-+MODULE_PARM_DESC(bounce_threshold, "Bounce threshold");
-+
-+static struct brcm_pcie *g_pcie;
-+
- static dma_addr_t brcm_to_pci(dma_addr_t addr)
- {
-       struct of_pci_range *p;
-@@ -457,12 +474,10 @@ static int brcm_map_sg(struct device *de
-       struct scatterlist *sg;
-       for_each_sg(sgl, sg, nents, i) {
--#ifdef CONFIG_NEED_SG_DMA_LENGTH
--              sg->dma_length = sg->length;
--#endif
-+              sg_dma_len(sg) = sg->length;
-               sg->dma_address =
--                      brcm_dma_ops_ptr->map_page(dev, sg_page(sg), sg->offset,
--                                                 sg->length, dir, attrs);
-+                      brcm_map_page(dev, sg_page(sg), sg->offset,
-+                                    sg->length, dir, attrs);
-               if (dma_mapping_error(dev, sg->dma_address))
-                       goto bad_mapping;
-       }
-@@ -470,8 +485,8 @@ static int brcm_map_sg(struct device *de
- bad_mapping:
-       for_each_sg(sgl, sg, i, j)
--              brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
--                                           sg_dma_len(sg), dir, attrs);
-+              brcm_unmap_page(dev, sg_dma_address(sg),
-+                              sg_dma_len(sg), dir, attrs);
-       return 0;
- }
-@@ -484,8 +499,8 @@ static void brcm_unmap_sg(struct device
-       struct scatterlist *sg;
-       for_each_sg(sgl, sg, nents, i)
--              brcm_dma_ops_ptr->unmap_page(dev, sg_dma_address(sg),
--                                           sg_dma_len(sg), dir, attrs);
-+              brcm_unmap_page(dev, sg_dma_address(sg),
-+                              sg_dma_len(sg), dir, attrs);
- }
- static void brcm_sync_single_for_cpu(struct device *dev,
-@@ -531,8 +546,8 @@ void brcm_sync_sg_for_cpu(struct device
-       int i;
-       for_each_sg(sgl, sg, nents, i)
--              brcm_dma_ops_ptr->sync_single_for_cpu(dev, sg_dma_address(sg),
--                                                    sg->length, dir);
-+              brcm_sync_single_for_cpu(dev, sg_dma_address(sg),
-+                                       sg->length, dir);
- }
- void brcm_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
-@@ -542,9 +557,9 @@ void brcm_sync_sg_for_device(struct devi
-       int i;
-       for_each_sg(sgl, sg, nents, i)
--              brcm_dma_ops_ptr->sync_single_for_device(dev,
--                                                       sg_dma_address(sg),
--                                                       sg->length, dir);
-+              brcm_sync_single_for_device(dev,
-+                                          sg_dma_address(sg),
-+                                          sg->length, dir);
- }
- static int brcm_mapping_error(struct device *dev, dma_addr_t dma_addr)
-@@ -633,17 +648,47 @@ static void brcm_set_dma_ops(struct devi
-       set_dma_ops(dev, &brcm_dma_ops);
- }
-+static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie,
-+                                     unsigned int val);
- static int brcmstb_platform_notifier(struct notifier_block *nb,
-                                    unsigned long event, void *__dev)
- {
-+      extern unsigned long max_pfn;
-       struct device *dev = __dev;
-+      const char *rc_name = "0000:00:00.0";
--      brcm_dma_ops_ptr = &brcm_dma_ops;
--      if (event != BUS_NOTIFY_ADD_DEVICE)
--              return NOTIFY_DONE;
-+      switch (event) {
-+      case BUS_NOTIFY_ADD_DEVICE:
-+              if (max_pfn > (bounce_threshold/PAGE_SIZE) &&
-+                  strcmp(dev->kobj.name, rc_name)) {
-+                      int ret;
-+
-+                      ret = brcm_pcie_bounce_register_dev(dev, bounce_buffer,
-+                                                          (dma_addr_t)bounce_threshold);
-+                      if (ret) {
-+                              dev_err(dev,
-+                                      "brcm_pcie_bounce_register_dev() failed: %d\n",
-+                              ret);
-+                              return ret;
-+                      }
-+              }
-+              brcm_set_dma_ops(dev);
-+              return NOTIFY_OK;
-+
-+      case BUS_NOTIFY_DEL_DEVICE:
-+              if (!strcmp(dev->kobj.name, rc_name) && g_pcie) {
-+                      /* Force a bus reset */
-+                      brcm_pcie_perst_set(g_pcie, 1);
-+                      msleep(100);
-+                      brcm_pcie_perst_set(g_pcie, 0);
-+              } else if (max_pfn > (bounce_threshold/PAGE_SIZE)) {
-+                      brcm_pcie_bounce_unregister_dev(dev);
-+              }
-+              return NOTIFY_OK;
--      brcm_set_dma_ops(dev);
--      return NOTIFY_OK;
-+      default:
-+              return NOTIFY_DONE;
-+      }
- }
- static struct notifier_block brcmstb_platform_nb = {
-@@ -914,6 +959,7 @@ static void brcm_pcie_msi_isr(struct irq
-               }
-       }
-       chained_irq_exit(chip, desc);
-+      bcm_writel(1, msi->base + PCIE_MISC_EOI_CTRL);
- }
- static void brcm_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
-@@ -930,7 +976,8 @@ static void brcm_compose_msi_msg(struct
- static int brcm_msi_set_affinity(struct irq_data *irq_data,
-                                const struct cpumask *mask, bool force)
- {
--      return -EINVAL;
-+      struct brcm_msi *msi = irq_data_get_irq_chip_data(irq_data);
-+      return __irq_set_affinity(msi->irq, mask, force);
- }
- static struct irq_chip brcm_msi_bottom_irq_chip = {
-@@ -1168,9 +1215,9 @@ static void __iomem *brcm_pcie_map_conf(
-               return PCI_SLOT(devfn) ? NULL : base + where;
-       /* For devices, write to the config space index register */
--      idx = cfg_index(bus->number, devfn, where);
-+      idx = cfg_index(bus->number, devfn, 0);
-       bcm_writel(idx, pcie->base + IDX_ADDR(pcie));
--      return base + DATA_ADDR(pcie) + (where & 0x3);
-+      return base + DATA_ADDR(pcie) + where;
- }
- static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie,
-@@ -1238,20 +1285,6 @@ static int brcm_pcie_parse_map_dma_range
-                       num_dma_ranges++;
-       }
--      for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
--              u64 size = brcmstb_memory_memc_size(i);
--
--              if (size == (u64)-1) {
--                      dev_err(pcie->dev, "cannot get memc%d size", i);
--                      return -EINVAL;
--              } else if (size) {
--                      scb_size[i] = roundup_pow_of_two_64(size);
--                      num_memc++;
--              } else {
--                      break;
--              }
--      }
--
-       return 0;
- }
-@@ -1275,26 +1308,25 @@ static int brcm_pcie_add_controller(stru
-       if (ret)
-               goto done;
--      /* Determine num_memc and their sizes */
--      for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
--              u64 size = brcmstb_memory_memc_size(i);
--
--              if (size == (u64)-1) {
--                      dev_err(dev, "cannot get memc%d size\n", i);
--                      ret = -EINVAL;
--                      goto done;
--              } else if (size) {
--                      scb_size[i] = roundup_pow_of_two_64(size);
--                      num_memc++;
--              } else {
--                      break;
-+      if (!num_dma_ranges) {
-+              /* Determine num_memc and their sizes by other means */
-+              for (i = 0, num_memc = 0; i < BRCM_MAX_SCB; i++) {
-+                      u64 size = brcmstb_memory_memc_size(i);
-+
-+                      if (size == (u64)-1) {
-+                              dev_err(dev, "cannot get memc%d size\n", i);
-+                              ret = -EINVAL;
-+                              goto done;
-+                      } else if (size) {
-+                              scb_size[i] = roundup_pow_of_two_64(size);
-+                      } else {
-+                              break;
-+                      }
-               }
--      }
--      if (!ret && num_memc == 0) {
--              ret = -EINVAL;
--              goto done;
-+              num_memc = i;
-       }
-+      g_pcie = pcie;
-       num_pcie++;
- done:
-       mutex_unlock(&brcm_pcie_lock);
-@@ -1307,6 +1339,7 @@ static void brcm_pcie_remove_controller(
-       if (--num_pcie > 0)
-               goto out;
-+      g_pcie = NULL;
-       if (brcm_unregister_notifier())
-               dev_err(pcie->dev, "failed to unregister pci bus notifier\n");
-       kfree(dma_ranges);
-@@ -1367,7 +1400,7 @@ static int brcm_pcie_setup(struct brcm_p
-       void __iomem *base = pcie->base;
-       unsigned int scb_size_val;
-       u64 rc_bar2_offset, rc_bar2_size, total_mem_size = 0;
--      u32 tmp, burst;
-+      u32 tmp;
-       int i, j, ret, limit;
-       u16 nlw, cls, lnksta;
-       bool ssc_good = false;
-@@ -1400,20 +1433,15 @@ static int brcm_pcie_setup(struct brcm_p
-       /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */
-       tmp = INSERT_FIELD(0, PCIE_MISC_MISC_CTRL, SCB_ACCESS_EN, 1);
-       tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, CFG_READ_UR_MODE, 1);
--      burst = (pcie->type == GENERIC || pcie->type == BCM7278)
--              ? BURST_SIZE_512 : BURST_SIZE_256;
--      tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE, burst);
-+      tmp = INSERT_FIELD(tmp, PCIE_MISC_MISC_CTRL, MAX_BURST_SIZE,
-+                         pcie->max_burst_size);
-       bcm_writel(tmp, base + PCIE_MISC_MISC_CTRL);
-       /*
-        * Set up inbound memory view for the EP (called RC_BAR2,
-        * not to be confused with the BARs that are advertised by
-        * the EP).
--       */
--      for (i = 0; i < num_memc; i++)
--              total_mem_size += scb_size[i];
--
--      /*
-+       *
-        * The PCIe host controller by design must set the inbound
-        * viewport to be a contiguous arrangement of all of the
-        * system's memory.  In addition, its size mut be a power of
-@@ -1429,55 +1457,49 @@ static int brcm_pcie_setup(struct brcm_p
-        * the controller will know to send outbound memory downstream
-        * and everything else upstream.
-        */
--      rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
--      if (dma_ranges) {
-+      if (num_dma_ranges) {
-               /*
--               * The best-case scenario is to place the inbound
--               * region in the first 4GB of pcie-space, as some
--               * legacy devices can only address 32bits.
--               * We would also like to put the MSI under 4GB
--               * as well, since some devices require a 32bit
--               * MSI target address.
-+               * Use the base address and size(s) provided in the dma-ranges
-+               * property.
-                */
--              if (total_mem_size <= 0xc0000000ULL &&
--                  rc_bar2_size <= 0x100000000ULL) {
--                      rc_bar2_offset = 0;
--                      /* If the viewport is less then 4GB we can fit
--                       * the MSI target address under 4GB. Otherwise
--                       * put it right below 64GB.
--                       */
--                      msi_target_addr =
--                              (rc_bar2_size == 0x100000000ULL)
--                              ? BRCM_MSI_TARGET_ADDR_GT_4GB
--                              : BRCM_MSI_TARGET_ADDR_LT_4GB;
--              } else {
--                      /*
--                       * The system memory is 4GB or larger so we
--                       * cannot start the inbound region at location
--                       * 0 (since we have to allow some space for
--                       * outbound memory @ 3GB).  So instead we
--                       * start it at the 1x multiple of its size
--                       */
--                      rc_bar2_offset = rc_bar2_size;
--
--                      /* Since we are starting the viewport at 4GB or
--                       * higher, put the MSI target address below 4GB
--                       */
--                      msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
--              }
--      } else {
-+              for (i = 0; i < num_dma_ranges; i++)
-+                      scb_size[i] = roundup_pow_of_two_64(dma_ranges[i].size);
-+
-+              num_memc = num_dma_ranges;
-+              rc_bar2_offset = dma_ranges[0].pci_addr;
-+      } else if (num_memc) {
-               /*
-                * Set simple configuration based on memory sizes
--               * only.  We always start the viewport at address 0,
--               * and set the MSI target address accordingly.
-+               * only.  We always start the viewport at address 0.
-                */
-               rc_bar2_offset = 0;
-+      } else {
-+              return -EINVAL;
-+      }
-+
-+      for (i = 0; i < num_memc; i++)
-+              total_mem_size += scb_size[i];
-+
-+      rc_bar2_size = roundup_pow_of_two_64(total_mem_size);
--              msi_target_addr = (rc_bar2_size >= 0x100000000ULL)
--                      ? BRCM_MSI_TARGET_ADDR_GT_4GB
--                      : BRCM_MSI_TARGET_ADDR_LT_4GB;
-+      /* Verify the alignment is correct */
-+      if (rc_bar2_offset & (rc_bar2_size - 1)) {
-+              dev_err(dev, "inbound window is misaligned\n");
-+              return -EINVAL;
-       }
-+
-+      /*
-+       * Position the MSI target low if possible.
-+       *
-+       * TO DO: Consider outbound window when choosing MSI target and
-+       * verifying configuration.
-+       */
-+      msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
-+      if (rc_bar2_offset <= msi_target_addr &&
-+          rc_bar2_offset + rc_bar2_size > msi_target_addr)
-+              msi_target_addr = BRCM_MSI_TARGET_ADDR_GT_4GB;
-+
-       pcie->msi_target_addr = msi_target_addr;
-       tmp = lower_32_bits(rc_bar2_offset);
-@@ -1713,6 +1735,7 @@ static int brcm_pcie_probe(struct platfo
-       data = of_id->data;
-       pcie->reg_offsets = data->offsets;
-       pcie->reg_field_info = data->reg_field_info;
-+      pcie->max_burst_size = data->max_burst_size;
-       pcie->type = data->type;
-       pcie->dn = dn;
-       pcie->dev = &pdev->dev;
-@@ -1732,7 +1755,7 @@ static int brcm_pcie_probe(struct platfo
-       pcie->clk = of_clk_get_by_name(dn, "sw_pcie");
-       if (IS_ERR(pcie->clk)) {
--              dev_err(&pdev->dev, "could not get clock\n");
-+              dev_warn(&pdev->dev, "could not get clock\n");
-               pcie->clk = NULL;
-       }
-       pcie->base = base;
-@@ -1755,7 +1778,8 @@ static int brcm_pcie_probe(struct platfo
-       ret = clk_prepare_enable(pcie->clk);
-       if (ret) {
--              dev_err(&pdev->dev, "could not enable clock\n");
-+              if (ret != -EPROBE_DEFER)
-+                      dev_err(&pdev->dev, "could not enable clock\n");
-               return ret;
-       }
-@@ -1818,7 +1842,6 @@ static struct platform_driver brcm_pcie_
-       .remove = brcm_pcie_remove,
-       .driver = {
-               .name = "brcm-pcie",
--              .owner = THIS_MODULE,
-               .of_match_table = brcm_pcie_match,
-               .pm = &brcm_pcie_pm_ops,
-       },
---- a/drivers/soc/bcm/brcmstb/Makefile
-+++ b/drivers/soc/bcm/brcmstb/Makefile
-@@ -1,2 +1,2 @@
--obj-y                         += common.o biuctrl.o
-+obj-y                         += common.o biuctrl.o memory.o
- obj-$(CONFIG_BRCMSTB_PM)      += pm/
---- /dev/null
-+++ b/drivers/soc/bcm/brcmstb/memory.c
-@@ -0,0 +1,158 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/* Copyright © 2015-2017 Broadcom */
-+
-+#include <linux/device.h>
-+#include <linux/io.h>
-+#include <linux/libfdt.h>
-+#include <linux/of_address.h>
-+#include <linux/of_fdt.h>
-+#include <linux/sizes.h>
-+#include <soc/brcmstb/memory_api.h>
-+
-+/* Macro to help extract property data */
-+#define DT_PROP_DATA_TO_U32(b, offs) (fdt32_to_cpu(*(u32 *)(b + offs)))
-+
-+/* Constants used when retrieving memc info */
-+#define NUM_BUS_RANGES 10
-+#define BUS_RANGE_ULIMIT_SHIFT 4
-+#define BUS_RANGE_LLIMIT_SHIFT 4
-+#define BUS_RANGE_PA_SHIFT 12
-+
-+enum {
-+      BUSNUM_MCP0 = 0x4,
-+      BUSNUM_MCP1 = 0x5,
-+      BUSNUM_MCP2 = 0x6,
-+};
-+
-+/*
-+ * If the DT nodes are handy, determine which MEMC holds the specified
-+ * physical address.
-+ */
-+#ifdef CONFIG_ARCH_BRCMSTB
-+int __brcmstb_memory_phys_addr_to_memc(phys_addr_t pa, void __iomem *base)
-+{
-+      int memc = -1;
-+      int i;
-+
-+      for (i = 0; i < NUM_BUS_RANGES; i++, base += 8) {
-+              const u64 ulimit_raw = readl(base);
-+              const u64 llimit_raw = readl(base + 4);
-+              const u64 ulimit =
-+                      ((ulimit_raw >> BUS_RANGE_ULIMIT_SHIFT)
-+                       << BUS_RANGE_PA_SHIFT) | 0xfff;
-+              const u64 llimit = (llimit_raw >> BUS_RANGE_LLIMIT_SHIFT)
-+                                 << BUS_RANGE_PA_SHIFT;
-+              const u32 busnum = (u32)(ulimit_raw & 0xf);
-+
-+              if (pa >= llimit && pa <= ulimit) {
-+                      if (busnum >= BUSNUM_MCP0 && busnum <= BUSNUM_MCP2) {
-+                              memc = busnum - BUSNUM_MCP0;
-+                              break;
-+                      }
-+              }
-+      }
-+
-+      return memc;
-+}
-+
-+int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa)
-+{
-+      int memc = -1;
-+      struct device_node *np;
-+      void __iomem *cpubiuctrl;
-+
-+      np = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl");
-+      if (!np)
-+              return memc;
-+
-+      cpubiuctrl = of_iomap(np, 0);
-+      if (!cpubiuctrl)
-+              goto cleanup;
-+
-+      memc = __brcmstb_memory_phys_addr_to_memc(pa, cpubiuctrl);
-+      iounmap(cpubiuctrl);
-+
-+cleanup:
-+      of_node_put(np);
-+
-+      return memc;
-+}
-+
-+#elif defined(CONFIG_MIPS)
-+int brcmstb_memory_phys_addr_to_memc(phys_addr_t pa)
-+{
-+      /* The logic here is fairly simple and hardcoded: if pa <= 0x5000_0000,
-+       * then this is MEMC0, else MEMC1.
-+       *
-+       * For systems with 2GB on MEMC0, MEMC1 starts at 9000_0000, with 1GB
-+       * on MEMC0, MEMC1 starts at 6000_0000.
-+       */
-+      if (pa >= 0x50000000ULL)
-+              return 1;
-+      else
-+              return 0;
-+}
-+#endif
-+
-+u64 brcmstb_memory_memc_size(int memc)
-+{
-+      const void *fdt = initial_boot_params;
-+      const int mem_offset = fdt_path_offset(fdt, "/memory");
-+      int addr_cells = 1, size_cells = 1;
-+      const struct fdt_property *prop;
-+      int proplen, cellslen;
-+      u64 memc_size = 0;
-+      int i;
-+
-+      /* Get root size and address cells if specified */
-+      prop = fdt_get_property(fdt, 0, "#size-cells", &proplen);
-+      if (prop)
-+              size_cells = DT_PROP_DATA_TO_U32(prop->data, 0);
-+
-+      prop = fdt_get_property(fdt, 0, "#address-cells", &proplen);
-+      if (prop)
-+              addr_cells = DT_PROP_DATA_TO_U32(prop->data, 0);
-+
-+      if (mem_offset < 0)
-+              return -1;
-+
-+      prop = fdt_get_property(fdt, mem_offset, "reg", &proplen);
-+      cellslen = (int)sizeof(u32) * (addr_cells + size_cells);
-+      if ((proplen % cellslen) != 0)
-+              return -1;
-+
-+      for (i = 0; i < proplen / cellslen; ++i) {
-+              u64 addr = 0;
-+              u64 size = 0;
-+              int memc_idx;
-+              int j;
-+
-+              for (j = 0; j < addr_cells; ++j) {
-+                      int offset = (cellslen * i) + (sizeof(u32) * j);
-+
-+                      addr |= (u64)DT_PROP_DATA_TO_U32(prop->data, offset) <<
-+                              ((addr_cells - j - 1) * 32);
-+              }
-+              for (j = 0; j < size_cells; ++j) {
-+                      int offset = (cellslen * i) +
-+                              (sizeof(u32) * (j + addr_cells));
-+
-+                      size |= (u64)DT_PROP_DATA_TO_U32(prop->data, offset) <<
-+                              ((size_cells - j - 1) * 32);
-+              }
-+
-+              if ((phys_addr_t)addr != addr) {
-+                      pr_err("phys_addr_t is smaller than provided address 0x%llx!\n",
-+                             addr);
-+                      return -1;
-+              }
-+
-+              memc_idx = brcmstb_memory_phys_addr_to_memc((phys_addr_t)addr);
-+              if (memc_idx == memc)
-+                      memc_size += size;
-+      }
-+
-+      return memc_size;
-+}
-+EXPORT_SYMBOL_GPL(brcmstb_memory_memc_size);
-+