bcm53xx: update iProc patches (V5 accepted in helgaas/pci.git next)

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>

SVN-Revision: 48375
This commit is contained in:
Rafał Miłecki 2016-01-19 21:53:23 +00:00
parent 76b903a415
commit b9fb3d4524
12 changed files with 341 additions and 190 deletions

View file

@ -0,0 +1,42 @@
From c1b98e41b356a1807d7083d958790da2027c0d9d Mon Sep 17 00:00:00 2001
From: Arnd Bergmann <arnd@arndb.de>
Date: Tue, 24 Nov 2015 15:28:48 -0600
Subject: [PATCH] PCI: iproc: Hide CONFIG_PCIE_IPROC
PCIE_IPROC_BCMA does not require CONFIG_OF in Kconfig, but
CONFIG_PCIE_IPROC does, so we can get a warning when building for an ARM
platform without DT support:
warning: (PCIE_IPROC_PLATFORM && PCIE_IPROC_BCMA) selects PCIE_IPROC which has unmet direct dependencies (PCI && OF && (ARM || ARM64))
It turns out that CONFIG_PCIE_IPROC never needs to be enabled by a user
anyway, we can simply rely on it being selected implictly through either
PCIE_IPROC_PLATFORM or PCIE_IPROC_BCMA.
Fixes: 4785ffbdc9b5 ("PCI: iproc: Add BCMA PCIe driver")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Hauke Mehrtens <hauke@hauke-m.de>
---
drivers/pci/host/Kconfig | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -107,13 +107,11 @@ config PCI_VERSATILE
depends on ARCH_VERSATILE
config PCIE_IPROC
- tristate "Broadcom iProc PCIe controller"
- depends on OF && (ARM || ARM64)
- default n
+ tristate
help
This enables the iProc PCIe core controller support for Broadcom's
- iProc family of SoCs. An appropriate bus interface driver also needs
- to be enabled
+ iProc family of SoCs. An appropriate bus interface driver needs
+ to be enabled to select this.
config PCIE_IPROC_PLATFORM
tristate "Broadcom iProc PCIe platform bus driver"

View file

@ -0,0 +1,27 @@
From 57303e92f48a0e307fd86977ec9be5aa6a7ea681 Mon Sep 17 00:00:00 2001
From: "Dmitry V. Krivenok" <krivenok.dmitry@gmail.com>
Date: Mon, 30 Nov 2015 23:45:49 +0300
Subject: [PATCH] PCI: iproc: Do not use 0x in front of %pap
The "%pap" format adds a "0x" prefix, so using "0x%pap" results in output
of "0x0x...". Drop the "0x" prefix in the format string.
[bhelgaas: changelog]
Signed-off-by: Dmitry V. Krivenok <krivenok.dmitry@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Ray Jui <rjui@broadcom.com>
---
drivers/pci/host/pcie-iproc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/pci/host/pcie-iproc.c
+++ b/drivers/pci/host/pcie-iproc.c
@@ -245,7 +245,7 @@ static int iproc_pcie_setup_ob(struct ip
if (size > max_size) {
dev_err(pcie->dev,
- "res size 0x%pap exceeds max supported size 0x%llx\n",
+ "res size %pap exceeds max supported size 0x%llx\n",
&size, max_size);
return -EINVAL;
}

View file

@ -1,13 +1,14 @@
From d85a955118c8d8679d4f746fe2189c172d7c365f Mon Sep 17 00:00:00 2001 From e8b8318de645c04f8600cb5af6f6773a1878ee9d Mon Sep 17 00:00:00 2001
From: Ray Jui <rjui@broadcom.com> From: Ray Jui <rjui@broadcom.com>
Date: Mon, 16 Nov 2015 17:18:05 -0800 Date: Fri, 4 Dec 2015 09:34:58 -0800
Subject: [PATCH 150/154] PCI: iproc: Update iProc PCIe device tree binding Subject: [PATCH 1/5] PCI: iproc: Update iProc PCIe device tree binding
Add a new compatible string "brcm,iproc-pcie-paxc", for PAXC based iProc Add a new compatible string "brcm,iproc-pcie-paxc", for PAXC-based iProc
PCIe root complex. A PAXC based PCIe root complex is connected to PCIe root complex. A PAXC-based PCIe root complex is connected to emulated
emulated endpoint devices internal to the ASIC endpoint devices internal to the ASIC.
Signed-off-by: Ray Jui <rjui@broadcom.com> Signed-off-by: Ray Jui <rjui@broadcom.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Scott Branden <sbranden@broadcom.com> Reviewed-by: Scott Branden <sbranden@broadcom.com>
--- ---
Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt | 5 ++++- Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt | 5 ++++-
@ -21,8 +22,8 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
Required properties: Required properties:
-- compatible: Must be "brcm,iproc-pcie" -- compatible: Must be "brcm,iproc-pcie"
+- compatible: Must be "brcm,iproc-pcie" for PAXB, or "brcm,iproc-pcie-paxc" +- compatible: Must be "brcm,iproc-pcie" for PAXB, or "brcm,iproc-pcie-paxc"
+ for PAXC. PAXB based root complex is used for external endpoint devices. + for PAXC. PAXB-based root complex is used for external endpoint devices.
+ PAXC based root complex is connected to emulated endpoint devices + PAXC-based root complex is connected to emulated endpoint devices
+ internal to the ASIC + internal to the ASIC
- reg: base address and length of the PCIe controller I/O register space - reg: base address and length of the PCIe controller I/O register space
- #interrupt-cells: set to <1> - #interrupt-cells: set to <1>

View file

@ -1,20 +1,21 @@
From a13fc4733b25d6dad6ec1826f09225c69ee21e3a Mon Sep 17 00:00:00 2001 From 943ebae781f519ecfecbfa1b997f15f59116e41d Mon Sep 17 00:00:00 2001
From: Ray Jui <rjui@broadcom.com> From: Ray Jui <rjui@broadcom.com>
Date: Mon, 16 Nov 2015 17:41:43 -0800 Date: Fri, 4 Dec 2015 09:34:59 -0800
Subject: [PATCH 151/154] PCI: iproc: Add PAXC interface support Subject: [PATCH 2/5] PCI: iproc: Add PAXC interface support
Traditionally, all iProc PCIe root complexes use PAXB based wrapper, Traditionally, all iProc PCIe root complexes use PAXB-based wrapper, with
with an integrated on-chip Serdes to support external endpoint devices. an integrated on-chip Serdes to support external endpoint devices. On
On newer iProc platforms, a PAXC based wrapper is introduced, for newer iProc platforms, a PAXC-based wrapper is introduced, for connection
connection with internally emulated PCIe endpoint devices in the ASIC with internally emulated PCIe endpoint devices in the ASIC.
This patch adds support for PAXC based iProc PCIe root complex in the Add support for PAXC-based iProc PCIe root complex in the iProc PCIe core
iProc PCIe core driver. This change fators out common logic between driver. This change factors out common logic between PAXB and PAXC, and
PAXB and PAXC, and use tables to store register offsets that are uses tables to store register offsets that are different between PAXB and
different between PAXB and PAXC. This allows the driver to be scaled to PAXC. This allows the driver to be scaled to support subsequent PAXC
support subsequent PAXC revisions in the future revisions in the future.
Signed-off-by: Ray Jui <rjui@broadcom.com> Signed-off-by: Ray Jui <rjui@broadcom.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Scott Branden <sbranden@broadcom.com> Reviewed-by: Scott Branden <sbranden@broadcom.com>
--- ---
drivers/pci/host/pcie-iproc-platform.c | 24 +++- drivers/pci/host/pcie-iproc-platform.c | 24 +++-
@ -324,7 +325,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
- val = readl(pcie->base + PCIE_LINK_STATUS_OFFSET); - val = readl(pcie->base + PCIE_LINK_STATUS_OFFSET);
+ /* + /*
+ * PAXC connects to emulated endpoint devices directly and does not + * PAXC connects to emulated endpoint devices directly and does not
+ * have a Serdes. Therefore skip the link detection logic here + * have a Serdes. Therefore skip the link detection logic here.
+ */ + */
+ if (pcie->type == IPROC_PCIE_PAXC) + if (pcie->type == IPROC_PCIE_PAXC)
+ return 0; + return 0;
@ -392,10 +393,10 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ * iProc PCIe interface type + * iProc PCIe interface type
+ * + *
+ * PAXB is the wrapper used in root complex that can be connected to an + * PAXB is the wrapper used in root complex that can be connected to an
+ * external endpoint device + * external endpoint device.
+ * + *
+ * PAXC is the wrapper used in root complex dedicated for internal emulated + * PAXC is the wrapper used in root complex dedicated for internal emulated
+ * endpoint devices + * endpoint devices.
+ */ + */
+enum iproc_pcie_type { +enum iproc_pcie_type {
+ IPROC_PCIE_PAXB = 0, + IPROC_PCIE_PAXB = 0,

View file

@ -1,12 +1,13 @@
From 96b40de5e36ec479dabb88500f1830a87818a809 Mon Sep 17 00:00:00 2001 From c7bd48195377435ecaf38869b936be8e7abe3489 Mon Sep 17 00:00:00 2001
From: Ray Jui <rjui@broadcom.com> From: Ray Jui <rjui@broadcom.com>
Date: Mon, 16 Nov 2015 17:57:33 -0800 Date: Fri, 4 Dec 2015 09:35:00 -0800
Subject: [PATCH 152/154] PCI: iproc: Add iProc PCIe MSI device tree binding Subject: [PATCH 3/5] PCI: iproc: Add iProc PCIe MSI device tree binding
This patch updates the iProc PCIe device tree bindings with added Update the iProc PCIe device tree bindings with added binding information
binding information for MSI for MSI.
Signed-off-by: Ray Jui <rjui@broadcom.com> Signed-off-by: Ray Jui <rjui@broadcom.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Anup Patel <anup.patel@broadcom.com> Reviewed-by: Anup Patel <anup.patel@broadcom.com>
Reviewed-by: Vikram Prakash <vikramp@broadcom.com> Reviewed-by: Vikram Prakash <vikramp@broadcom.com>
Reviewed-by: Scott Branden <sbranden@broadcom.com> Reviewed-by: Scott Branden <sbranden@broadcom.com>
@ -23,13 +24,13 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+MSI support (optional): +MSI support (optional):
+ +
+For older platforms without MSI integrated in the GIC, iProc PCIe core provides +For older platforms without MSI integrated in the GIC, iProc PCIe core provides
+an event queue based MSI support. The iProc MSI uses host memories to store +an event queue based MSI support. The iProc MSI uses host memories to store
+MSI posted writes in the event queues +MSI posted writes in the event queues
+ +
+- msi-parent: Link to the device node of the MSI controller. On newer iProc +- msi-parent: Link to the device node of the MSI controller. On newer iProc
+platforms, the MSI controller may be gicv2m or gicv3-its. On older iProc +platforms, the MSI controller may be gicv2m or gicv3-its. On older iProc
+platforms without MSI support in its interrupt controller, one may use the +platforms without MSI support in its interrupt controller, one may use the
+event queue based MSI support integrated within the iProc PCIe core +event queue based MSI support integrated within the iProc PCIe core.
+ +
+When the iProc event queue based MSI is used, one needs to define the +When the iProc event queue based MSI is used, one needs to define the
+following properties in the MSI device node: +following properties in the MSI device node:

View file

@ -1,73 +1,76 @@
From c81922174d61127ff5baad6059ae148794c72276 Mon Sep 17 00:00:00 2001 From 3bc2b2348835f6edd33c383a2fbcf15fe3dac3b2 Mon Sep 17 00:00:00 2001
From: Ray Jui <rjui@broadcom.com> From: Ray Jui <rjui@broadcom.com>
Date: Tue, 17 Nov 2015 13:14:37 -0800 Date: Wed, 6 Jan 2016 18:04:35 -0600
Subject: [PATCH 153/154] PCI: iproc: Add iProc PCIe MSI support Subject: [PATCH 4/5] PCI: iproc: Add iProc PCIe MSI support
This patch adds PCIe MSI support for both PAXB and PAXC interfaces on Add PCIe MSI support for both PAXB and PAXC interfaces on all iProc-based
all iProc based platforms platforms.
The iProc PCIe MSI support deploys an event queue based implementation. The iProc PCIe MSI support deploys an event queue-based implementation.
Each event queue is serviced by a GIC interrupt and can support up to 64 Each event queue is serviced by a GIC interrupt and can support up to 64
MSI vectors. Host memory is allocated for the event queues, and each event MSI vectors. Host memory is allocated for the event queues, and each event
queue consists of 64 word-sized entries. MSI data is written to the queue consists of 64 word-sized entries. MSI data is written to the lower
lower 16-bit of each entry, whereas the upper 16-bit of the entry is 16-bit of each entry, whereas the upper 16-bit of the entry is reserved for
reserved for the controller for internal processing the controller for internal processing.
Each event queue is tracked by a head pointer and tail pointer. Head Each event queue is tracked by a head pointer and tail pointer. Head
pointer indicates the next entry in the event queue to be processed by pointer indicates the next entry in the event queue to be processed by
the driver and is updated by the driver after processing is done. the driver and is updated by the driver after processing is done.
The controller uses the tail pointer as the next MSI data insertion The controller uses the tail pointer as the next MSI data insertion
point. The controller ensures MSI data is flushed to host memory before point. The controller ensures MSI data is flushed to host memory before
updating the tail pointer and then triggering the interrupt updating the tail pointer and then triggering the interrupt.
MSI IRQ affinity is supported by evenly distributing the interrupts to MSI IRQ affinity is supported by evenly distributing the interrupts to each
each CPU core. MSI vector is moved from one GIC interrupt to another in CPU core. MSI vector is moved from one GIC interrupt to another in order
order to steer to the target CPU to steer to the target CPU.
Therefore, the actual number of supported MSI vectors is: Therefore, the actual number of supported MSI vectors is:
M * 64 / N M * 64 / N
where M denotes the number of GIC interrupts (event queues), and N where M denotes the number of GIC interrupts (event queues), and N denotes
denotes the number of CPU cores the number of CPU cores.
This iProc event queue based MSI support should not be used with newer This iProc event queue-based MSI support should not be used with newer
platforms with integrated MSI support in the GIC (e.g., giv2m or platforms with integrated MSI support in the GIC (e.g., giv2m or
gicv3-its) gicv3-its).
[bhelgaas: fold in Kconfig fixes from Arnd Bergmann <arnd@arndb.de>]
Signed-off-by: Ray Jui <rjui@broadcom.com> Signed-off-by: Ray Jui <rjui@broadcom.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Anup Patel <anup.patel@broadcom.com> Reviewed-by: Anup Patel <anup.patel@broadcom.com>
Reviewed-by: Vikram Prakash <vikramp@broadcom.com> Reviewed-by: Vikram Prakash <vikramp@broadcom.com>
Reviewed-by: Scott Branden <sbranden@broadcom.com> Reviewed-by: Scott Branden <sbranden@broadcom.com>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
--- ---
drivers/pci/host/Kconfig | 9 + drivers/pci/host/Kconfig | 10 +
drivers/pci/host/Makefile | 1 + drivers/pci/host/Makefile | 1 +
drivers/pci/host/pcie-iproc-bcma.c | 1 + drivers/pci/host/pcie-iproc-bcma.c | 1 +
drivers/pci/host/pcie-iproc-msi.c | 675 +++++++++++++++++++++++++++++++++ drivers/pci/host/pcie-iproc-msi.c | 675 +++++++++++++++++++++++++++++++++
drivers/pci/host/pcie-iproc-platform.c | 1 + drivers/pci/host/pcie-iproc-platform.c | 1 +
drivers/pci/host/pcie-iproc.c | 26 ++ drivers/pci/host/pcie-iproc.c | 26 ++
drivers/pci/host/pcie-iproc.h | 23 +- drivers/pci/host/pcie-iproc.h | 23 +-
7 files changed, 734 insertions(+), 2 deletions(-) 7 files changed, 735 insertions(+), 2 deletions(-)
create mode 100644 drivers/pci/host/pcie-iproc-msi.c create mode 100644 drivers/pci/host/pcie-iproc-msi.c
--- a/drivers/pci/host/Kconfig --- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig
@@ -115,6 +115,15 @@ config PCIE_IPROC @@ -133,5 +133,15 @@ config PCIE_IPROC_BCMA
iProc family of SoCs. An appropriate bus interface driver also needs help
to be enabled Say Y here if you want to use the Broadcom iProc PCIe controller
through the BCMA bus interface
+
+config PCIE_IPROC_MSI +config PCIE_IPROC_MSI
+ bool "Broadcom iProc PCIe MSI support" + bool "Broadcom iProc PCIe MSI support"
+ depends on ARCH_BCM_IPROC && PCI_MSI + depends on PCIE_IPROC_PLATFORM || PCIE_IPROC_BCMA
+ depends on PCI_MSI
+ select PCI_MSI_IRQ_DOMAIN + select PCI_MSI_IRQ_DOMAIN
+ default ARCH_BCM_IPROC + default ARCH_BCM_IPROC
+ help + help
+ Say Y here if you want to enable MSI support for Broadcom's iProc + Say Y here if you want to enable MSI support for Broadcom's iProc
+ PCIe controller + PCIe controller
+
config PCIE_IPROC_PLATFORM endmenu
tristate "Broadcom iProc PCIe platform bus driver"
depends on ARCH_BCM_IPROC || (ARM && COMPILE_TEST)
--- a/drivers/pci/host/Makefile --- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile
@@ -14,5 +14,6 @@ obj-$(CONFIG_PCI_XGENE) += pci-xgene.o @@ -14,5 +14,6 @@ obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
@ -122,16 +125,16 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ +
+#define IPROC_MSI_EQ_MASK 0x3f +#define IPROC_MSI_EQ_MASK 0x3f
+ +
+/* max number of GIC interrupts */ +/* Max number of GIC interrupts */
+#define NR_HW_IRQS 6 +#define NR_HW_IRQS 6
+ +
+/* number of entries in each event queue */ +/* Number of entries in each event queue */
+#define EQ_LEN 64 +#define EQ_LEN 64
+ +
+/* size of each event queue memory region */ +/* Size of each event queue memory region */
+#define EQ_MEM_REGION_SIZE SZ_4K +#define EQ_MEM_REGION_SIZE SZ_4K
+ +
+/* size of each MSI address region */ +/* Size of each MSI address region */
+#define MSI_MEM_REGION_SIZE SZ_4K +#define MSI_MEM_REGION_SIZE SZ_4K
+ +
+enum iproc_msi_reg { +enum iproc_msi_reg {
@ -152,7 +155,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ * iProc MSI group + * iProc MSI group
+ * + *
+ * One MSI group is allocated per GIC interrupt, serviced by one iProc MSI + * One MSI group is allocated per GIC interrupt, serviced by one iProc MSI
+ * event queue + * event queue.
+ * + *
+ * @msi: pointer to iProc MSI data + * @msi: pointer to iProc MSI data
+ * @gic_irq: GIC interrupt + * @gic_irq: GIC interrupt
@ -168,7 +171,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ * iProc event queue based MSI + * iProc event queue based MSI
+ * + *
+ * Only meant to be used on platforms without MSI support integrated into the + * Only meant to be used on platforms without MSI support integrated into the
+ * GIC + * GIC.
+ * + *
+ * @pcie: pointer to iProc PCIe data + * @pcie: pointer to iProc PCIe data
+ * @reg_offsets: MSI register offsets + * @reg_offsets: MSI register offsets
@ -277,12 +280,12 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ +
+/* +/*
+ * In iProc PCIe core, each MSI group is serviced by a GIC interrupt and a + * In iProc PCIe core, each MSI group is serviced by a GIC interrupt and a
+ * dedicated event queue. Each MSI group can support up to 64 MSI vectors + * dedicated event queue. Each MSI group can support up to 64 MSI vectors.
+ * + *
+ * The number of MSI groups varies between different iProc SoCs. The total + * The number of MSI groups varies between different iProc SoCs. The total
+ * number of CPU cores also varies. To support MSI IRQ affinity, we + * number of CPU cores also varies. To support MSI IRQ affinity, we
+ * distribute GIC interrupts across all available CPUs. MSI vector is moved + * distribute GIC interrupts across all available CPUs. MSI vector is moved
+ * from one GIC interrupt to another to steer to the target CPU + * from one GIC interrupt to another to steer to the target CPU.
+ * + *
+ * Assuming: + * Assuming:
+ * - the number of MSI groups is M + * - the number of MSI groups is M
@ -347,7 +350,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ +
+ mutex_lock(&msi->bitmap_lock); + mutex_lock(&msi->bitmap_lock);
+ +
+ /* allocate 'nr_cpus' number of MSI vectors each time */ + /* Allocate 'nr_cpus' number of MSI vectors each time */
+ hwirq = bitmap_find_next_zero_area(msi->bitmap, msi->nr_msi_vecs, 0, + hwirq = bitmap_find_next_zero_area(msi->bitmap, msi->nr_msi_vecs, 0,
+ msi->nr_cpus, 0); + msi->nr_cpus, 0);
+ if (hwirq < msi->nr_msi_vecs) { + if (hwirq < msi->nr_msi_vecs) {
@ -398,8 +401,8 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ +
+ /* + /*
+ * Since we have multiple hwirq mapped to a single MSI vector, + * Since we have multiple hwirq mapped to a single MSI vector,
+ * now we need to derive the hwirq at CPU0. It can then be used to + * now we need to derive the hwirq at CPU0. It can then be used to
+ * mapped back to virq + * mapped back to virq.
+ */ + */
+ return hwirq_to_canonical_hwirq(msi, hwirq); + return hwirq_to_canonical_hwirq(msi, hwirq);
+} +}
@ -422,14 +425,14 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ eq = grp->eq; + eq = grp->eq;
+ +
+ /* + /*
+ * iProc MSI event queue is tracked by head and tail pointers. Head + * iProc MSI event queue is tracked by head and tail pointers. Head
+ * pointer indicates the next entry (MSI data) to be consumed by SW in + * pointer indicates the next entry (MSI data) to be consumed by SW in
+ * the queue and needs to be updated by SW. iProc MSI core uses the + * the queue and needs to be updated by SW. iProc MSI core uses the
+ * tail pointer as the next data insertion point + * tail pointer as the next data insertion point.
+ * + *
+ * Entries between head and tail pointers contain valid MSI data. MSI + * Entries between head and tail pointers contain valid MSI data. MSI
+ * data is guaranteed to be in the event queue memory before the tail + * data is guaranteed to be in the event queue memory before the tail
+ * pointer is updated by the iProc MSI core + * pointer is updated by the iProc MSI core.
+ */ + */
+ head = iproc_msi_read_reg(msi, IPROC_MSI_EQ_HEAD, + head = iproc_msi_read_reg(msi, IPROC_MSI_EQ_HEAD,
+ eq) & IPROC_MSI_EQ_MASK; + eq) & IPROC_MSI_EQ_MASK;
@ -439,7 +442,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ +
+ /* + /*
+ * Figure out total number of events (MSI data) to be + * Figure out total number of events (MSI data) to be
+ * processed + * processed.
+ */ + */
+ nr_events = (tail < head) ? + nr_events = (tail < head) ?
+ (EQ_LEN - (head - tail)) : (tail - head); + (EQ_LEN - (head - tail)) : (tail - head);
@ -457,14 +460,14 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ } + }
+ +
+ /* + /*
+ * Now all outstanding events have been processed. Update the + * Now all outstanding events have been processed. Update the
+ * head pointer + * head pointer.
+ */ + */
+ iproc_msi_write_reg(msi, IPROC_MSI_EQ_HEAD, eq, head); + iproc_msi_write_reg(msi, IPROC_MSI_EQ_HEAD, eq, head);
+ +
+ /* + /*
+ * Now go read the tail pointer again to see if there are new + * Now go read the tail pointer again to see if there are new
+ * oustanding events that came in during the above window + * oustanding events that came in during the above window.
+ */ + */
+ } while (true); + } while (true);
+ +
@ -476,7 +479,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ int i, eq; + int i, eq;
+ u32 val; + u32 val;
+ +
+ /* program memory region for each event queue */ + /* Program memory region for each event queue */
+ for (i = 0; i < msi->nr_eq_region; i++) { + for (i = 0; i < msi->nr_eq_region; i++) {
+ dma_addr_t addr = msi->eq_dma + (i * EQ_MEM_REGION_SIZE); + dma_addr_t addr = msi->eq_dma + (i * EQ_MEM_REGION_SIZE);
+ +
@ -486,7 +489,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ upper_32_bits(addr)); + upper_32_bits(addr));
+ } + }
+ +
+ /* program address region for MSI posted writes */ + /* Program address region for MSI posted writes */
+ for (i = 0; i < msi->nr_msi_region; i++) { + for (i = 0; i < msi->nr_msi_region; i++) {
+ phys_addr_t addr = msi->msi_addr + (i * MSI_MEM_REGION_SIZE); + phys_addr_t addr = msi->msi_addr + (i * MSI_MEM_REGION_SIZE);
+ +
@ -497,14 +500,14 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ } + }
+ +
+ for (eq = 0; eq < msi->nr_irqs; eq++) { + for (eq = 0; eq < msi->nr_irqs; eq++) {
+ /* enable MSI event queue */ + /* Enable MSI event queue */
+ val = IPROC_MSI_INTR_EN | IPROC_MSI_INT_N_EVENT | + val = IPROC_MSI_INTR_EN | IPROC_MSI_INT_N_EVENT |
+ IPROC_MSI_EQ_EN; + IPROC_MSI_EQ_EN;
+ iproc_msi_write_reg(msi, IPROC_MSI_CTRL, eq, val); + iproc_msi_write_reg(msi, IPROC_MSI_CTRL, eq, val);
+ +
+ /* + /*
+ * Some legacy platforms require the MSI interrupt enable + * Some legacy platforms require the MSI interrupt enable
+ * register to be set explicitly + * register to be set explicitly.
+ */ + */
+ if (msi->has_inten_reg) { + if (msi->has_inten_reg) {
+ val = iproc_msi_read_reg(msi, IPROC_MSI_INTS_EN, eq); + val = iproc_msi_read_reg(msi, IPROC_MSI_INTS_EN, eq);
@ -580,7 +583,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ irq_set_chained_handler_and_data(msi->grps[i].gic_irq, + irq_set_chained_handler_and_data(msi->grps[i].gic_irq,
+ iproc_msi_handler, + iproc_msi_handler,
+ &msi->grps[i]); + &msi->grps[i]);
+ /* dedicate GIC interrupt to each CPU core */ + /* Dedicate GIC interrupt to each CPU core */
+ if (alloc_cpumask_var(&mask, GFP_KERNEL)) { + if (alloc_cpumask_var(&mask, GFP_KERNEL)) {
+ cpumask_clear(mask); + cpumask_clear(mask);
+ cpumask_set_cpu(cpu, mask); + cpumask_set_cpu(cpu, mask);
@ -596,7 +599,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ } + }
+ +
+ if (ret) { + if (ret) {
+ /* free all configured/unconfigured irqs */ + /* Free all configured/unconfigured IRQs */
+ iproc_msi_irq_free(msi, cpu); + iproc_msi_irq_free(msi, cpu);
+ return ret; + return ret;
+ } + }
@ -697,7 +700,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ msi->grps[i].eq = i; + msi->grps[i].eq = i;
+ } + }
+ +
+ /* reserve memory for event queue and make sure memories are zeroed */ + /* Reserve memory for event queue and make sure memories are zeroed */
+ msi->eq_cpu = dma_zalloc_coherent(pcie->dev, + msi->eq_cpu = dma_zalloc_coherent(pcie->dev,
+ msi->nr_eq_region * EQ_MEM_REGION_SIZE, + msi->nr_eq_region * EQ_MEM_REGION_SIZE,
+ &msi->eq_dma, GFP_KERNEL); + &msi->eq_dma, GFP_KERNEL);
@ -869,7 +872,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res); int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res);
int iproc_pcie_remove(struct iproc_pcie *pcie); int iproc_pcie_remove(struct iproc_pcie *pcie);
+#ifdef CONFIG_PCI_MSI +#ifdef CONFIG_PCIE_IPROC_MSI
+int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node); +int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node);
+void iproc_msi_exit(struct iproc_pcie *pcie); +void iproc_msi_exit(struct iproc_pcie *pcie);
+#else +#else
@ -878,7 +881,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+{ +{
+ return -ENODEV; + return -ENODEV;
+} +}
+static void iproc_msi_exit(struct iproc_pcie *pcie) +static inline void iproc_msi_exit(struct iproc_pcie *pcie)
+{ +{
+} +}
+#endif +#endif

View file

@ -0,0 +1,42 @@
From c1b98e41b356a1807d7083d958790da2027c0d9d Mon Sep 17 00:00:00 2001
From: Arnd Bergmann <arnd@arndb.de>
Date: Tue, 24 Nov 2015 15:28:48 -0600
Subject: [PATCH] PCI: iproc: Hide CONFIG_PCIE_IPROC
PCIE_IPROC_BCMA does not require CONFIG_OF in Kconfig, but
CONFIG_PCIE_IPROC does, so we can get a warning when building for an ARM
platform without DT support:
warning: (PCIE_IPROC_PLATFORM && PCIE_IPROC_BCMA) selects PCIE_IPROC which has unmet direct dependencies (PCI && OF && (ARM || ARM64))
It turns out that CONFIG_PCIE_IPROC never needs to be enabled by a user
anyway, we can simply rely on it being selected implictly through either
PCIE_IPROC_PLATFORM or PCIE_IPROC_BCMA.
Fixes: 4785ffbdc9b5 ("PCI: iproc: Add BCMA PCIe driver")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Hauke Mehrtens <hauke@hauke-m.de>
---
drivers/pci/host/Kconfig | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -119,13 +119,11 @@ config PCI_VERSATILE
depends on ARCH_VERSATILE
config PCIE_IPROC
- tristate "Broadcom iProc PCIe controller"
- depends on OF && (ARM || ARM64)
- default n
+ tristate
help
This enables the iProc PCIe core controller support for Broadcom's
- iProc family of SoCs. An appropriate bus interface driver also needs
- to be enabled
+ iProc family of SoCs. An appropriate bus interface driver needs
+ to be enabled to select this.
config PCIE_IPROC_PLATFORM
tristate "Broadcom iProc PCIe platform bus driver"

View file

@ -0,0 +1,27 @@
From 57303e92f48a0e307fd86977ec9be5aa6a7ea681 Mon Sep 17 00:00:00 2001
From: "Dmitry V. Krivenok" <krivenok.dmitry@gmail.com>
Date: Mon, 30 Nov 2015 23:45:49 +0300
Subject: [PATCH] PCI: iproc: Do not use 0x in front of %pap
The "%pap" format adds a "0x" prefix, so using "0x%pap" results in output
of "0x0x...". Drop the "0x" prefix in the format string.
[bhelgaas: changelog]
Signed-off-by: Dmitry V. Krivenok <krivenok.dmitry@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Ray Jui <rjui@broadcom.com>
---
drivers/pci/host/pcie-iproc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/pci/host/pcie-iproc.c
+++ b/drivers/pci/host/pcie-iproc.c
@@ -245,7 +245,7 @@ static int iproc_pcie_setup_ob(struct ip
if (size > max_size) {
dev_err(pcie->dev,
- "res size 0x%pap exceeds max supported size 0x%llx\n",
+ "res size %pap exceeds max supported size 0x%llx\n",
&size, max_size);
return -EINVAL;
}

View file

@ -1,13 +1,14 @@
From d85a955118c8d8679d4f746fe2189c172d7c365f Mon Sep 17 00:00:00 2001 From e8b8318de645c04f8600cb5af6f6773a1878ee9d Mon Sep 17 00:00:00 2001
From: Ray Jui <rjui@broadcom.com> From: Ray Jui <rjui@broadcom.com>
Date: Mon, 16 Nov 2015 17:18:05 -0800 Date: Fri, 4 Dec 2015 09:34:58 -0800
Subject: [PATCH 150/154] PCI: iproc: Update iProc PCIe device tree binding Subject: [PATCH 1/5] PCI: iproc: Update iProc PCIe device tree binding
Add a new compatible string "brcm,iproc-pcie-paxc", for PAXC based iProc Add a new compatible string "brcm,iproc-pcie-paxc", for PAXC-based iProc
PCIe root complex. A PAXC based PCIe root complex is connected to PCIe root complex. A PAXC-based PCIe root complex is connected to emulated
emulated endpoint devices internal to the ASIC endpoint devices internal to the ASIC.
Signed-off-by: Ray Jui <rjui@broadcom.com> Signed-off-by: Ray Jui <rjui@broadcom.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Scott Branden <sbranden@broadcom.com> Reviewed-by: Scott Branden <sbranden@broadcom.com>
--- ---
Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt | 5 ++++- Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt | 5 ++++-
@ -21,8 +22,8 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
Required properties: Required properties:
-- compatible: Must be "brcm,iproc-pcie" -- compatible: Must be "brcm,iproc-pcie"
+- compatible: Must be "brcm,iproc-pcie" for PAXB, or "brcm,iproc-pcie-paxc" +- compatible: Must be "brcm,iproc-pcie" for PAXB, or "brcm,iproc-pcie-paxc"
+ for PAXC. PAXB based root complex is used for external endpoint devices. + for PAXC. PAXB-based root complex is used for external endpoint devices.
+ PAXC based root complex is connected to emulated endpoint devices + PAXC-based root complex is connected to emulated endpoint devices
+ internal to the ASIC + internal to the ASIC
- reg: base address and length of the PCIe controller I/O register space - reg: base address and length of the PCIe controller I/O register space
- #interrupt-cells: set to <1> - #interrupt-cells: set to <1>

View file

@ -1,20 +1,21 @@
From a13fc4733b25d6dad6ec1826f09225c69ee21e3a Mon Sep 17 00:00:00 2001 From 943ebae781f519ecfecbfa1b997f15f59116e41d Mon Sep 17 00:00:00 2001
From: Ray Jui <rjui@broadcom.com> From: Ray Jui <rjui@broadcom.com>
Date: Mon, 16 Nov 2015 17:41:43 -0800 Date: Fri, 4 Dec 2015 09:34:59 -0800
Subject: [PATCH 151/154] PCI: iproc: Add PAXC interface support Subject: [PATCH 2/5] PCI: iproc: Add PAXC interface support
Traditionally, all iProc PCIe root complexes use PAXB based wrapper, Traditionally, all iProc PCIe root complexes use PAXB-based wrapper, with
with an integrated on-chip Serdes to support external endpoint devices. an integrated on-chip Serdes to support external endpoint devices. On
On newer iProc platforms, a PAXC based wrapper is introduced, for newer iProc platforms, a PAXC-based wrapper is introduced, for connection
connection with internally emulated PCIe endpoint devices in the ASIC with internally emulated PCIe endpoint devices in the ASIC.
This patch adds support for PAXC based iProc PCIe root complex in the Add support for PAXC-based iProc PCIe root complex in the iProc PCIe core
iProc PCIe core driver. This change fators out common logic between driver. This change factors out common logic between PAXB and PAXC, and
PAXB and PAXC, and use tables to store register offsets that are uses tables to store register offsets that are different between PAXB and
different between PAXB and PAXC. This allows the driver to be scaled to PAXC. This allows the driver to be scaled to support subsequent PAXC
support subsequent PAXC revisions in the future revisions in the future.
Signed-off-by: Ray Jui <rjui@broadcom.com> Signed-off-by: Ray Jui <rjui@broadcom.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Scott Branden <sbranden@broadcom.com> Reviewed-by: Scott Branden <sbranden@broadcom.com>
--- ---
drivers/pci/host/pcie-iproc-platform.c | 24 +++- drivers/pci/host/pcie-iproc-platform.c | 24 +++-
@ -324,7 +325,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
- val = readl(pcie->base + PCIE_LINK_STATUS_OFFSET); - val = readl(pcie->base + PCIE_LINK_STATUS_OFFSET);
+ /* + /*
+ * PAXC connects to emulated endpoint devices directly and does not + * PAXC connects to emulated endpoint devices directly and does not
+ * have a Serdes. Therefore skip the link detection logic here + * have a Serdes. Therefore skip the link detection logic here.
+ */ + */
+ if (pcie->type == IPROC_PCIE_PAXC) + if (pcie->type == IPROC_PCIE_PAXC)
+ return 0; + return 0;
@ -392,10 +393,10 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ * iProc PCIe interface type + * iProc PCIe interface type
+ * + *
+ * PAXB is the wrapper used in root complex that can be connected to an + * PAXB is the wrapper used in root complex that can be connected to an
+ * external endpoint device + * external endpoint device.
+ * + *
+ * PAXC is the wrapper used in root complex dedicated for internal emulated + * PAXC is the wrapper used in root complex dedicated for internal emulated
+ * endpoint devices + * endpoint devices.
+ */ + */
+enum iproc_pcie_type { +enum iproc_pcie_type {
+ IPROC_PCIE_PAXB = 0, + IPROC_PCIE_PAXB = 0,

View file

@ -1,12 +1,13 @@
From 96b40de5e36ec479dabb88500f1830a87818a809 Mon Sep 17 00:00:00 2001 From c7bd48195377435ecaf38869b936be8e7abe3489 Mon Sep 17 00:00:00 2001
From: Ray Jui <rjui@broadcom.com> From: Ray Jui <rjui@broadcom.com>
Date: Mon, 16 Nov 2015 17:57:33 -0800 Date: Fri, 4 Dec 2015 09:35:00 -0800
Subject: [PATCH 152/154] PCI: iproc: Add iProc PCIe MSI device tree binding Subject: [PATCH 3/5] PCI: iproc: Add iProc PCIe MSI device tree binding
This patch updates the iProc PCIe device tree bindings with added Update the iProc PCIe device tree bindings with added binding information
binding information for MSI for MSI.
Signed-off-by: Ray Jui <rjui@broadcom.com> Signed-off-by: Ray Jui <rjui@broadcom.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Anup Patel <anup.patel@broadcom.com> Reviewed-by: Anup Patel <anup.patel@broadcom.com>
Reviewed-by: Vikram Prakash <vikramp@broadcom.com> Reviewed-by: Vikram Prakash <vikramp@broadcom.com>
Reviewed-by: Scott Branden <sbranden@broadcom.com> Reviewed-by: Scott Branden <sbranden@broadcom.com>
@ -23,13 +24,13 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+MSI support (optional): +MSI support (optional):
+ +
+For older platforms without MSI integrated in the GIC, iProc PCIe core provides +For older platforms without MSI integrated in the GIC, iProc PCIe core provides
+an event queue based MSI support. The iProc MSI uses host memories to store +an event queue based MSI support. The iProc MSI uses host memories to store
+MSI posted writes in the event queues +MSI posted writes in the event queues
+ +
+- msi-parent: Link to the device node of the MSI controller. On newer iProc +- msi-parent: Link to the device node of the MSI controller. On newer iProc
+platforms, the MSI controller may be gicv2m or gicv3-its. On older iProc +platforms, the MSI controller may be gicv2m or gicv3-its. On older iProc
+platforms without MSI support in its interrupt controller, one may use the +platforms without MSI support in its interrupt controller, one may use the
+event queue based MSI support integrated within the iProc PCIe core +event queue based MSI support integrated within the iProc PCIe core.
+ +
+When the iProc event queue based MSI is used, one needs to define the +When the iProc event queue based MSI is used, one needs to define the
+following properties in the MSI device node: +following properties in the MSI device node:

View file

@ -1,73 +1,77 @@
From c81922174d61127ff5baad6059ae148794c72276 Mon Sep 17 00:00:00 2001 From 3bc2b2348835f6edd33c383a2fbcf15fe3dac3b2 Mon Sep 17 00:00:00 2001
From: Ray Jui <rjui@broadcom.com> From: Ray Jui <rjui@broadcom.com>
Date: Tue, 17 Nov 2015 13:14:37 -0800 Date: Wed, 6 Jan 2016 18:04:35 -0600
Subject: [PATCH 153/154] PCI: iproc: Add iProc PCIe MSI support Subject: [PATCH 4/5] PCI: iproc: Add iProc PCIe MSI support
This patch adds PCIe MSI support for both PAXB and PAXC interfaces on Add PCIe MSI support for both PAXB and PAXC interfaces on all iProc-based
all iProc based platforms platforms.
The iProc PCIe MSI support deploys an event queue based implementation. The iProc PCIe MSI support deploys an event queue-based implementation.
Each event queue is serviced by a GIC interrupt and can support up to 64 Each event queue is serviced by a GIC interrupt and can support up to 64
MSI vectors. Host memory is allocated for the event queues, and each event MSI vectors. Host memory is allocated for the event queues, and each event
queue consists of 64 word-sized entries. MSI data is written to the queue consists of 64 word-sized entries. MSI data is written to the lower
lower 16-bit of each entry, whereas the upper 16-bit of the entry is 16-bit of each entry, whereas the upper 16-bit of the entry is reserved for
reserved for the controller for internal processing the controller for internal processing.
Each event queue is tracked by a head pointer and tail pointer. Head Each event queue is tracked by a head pointer and tail pointer. Head
pointer indicates the next entry in the event queue to be processed by pointer indicates the next entry in the event queue to be processed by
the driver and is updated by the driver after processing is done. the driver and is updated by the driver after processing is done.
The controller uses the tail pointer as the next MSI data insertion The controller uses the tail pointer as the next MSI data insertion
point. The controller ensures MSI data is flushed to host memory before point. The controller ensures MSI data is flushed to host memory before
updating the tail pointer and then triggering the interrupt updating the tail pointer and then triggering the interrupt.
MSI IRQ affinity is supported by evenly distributing the interrupts to MSI IRQ affinity is supported by evenly distributing the interrupts to each
each CPU core. MSI vector is moved from one GIC interrupt to another in CPU core. MSI vector is moved from one GIC interrupt to another in order
order to steer to the target CPU to steer to the target CPU.
Therefore, the actual number of supported MSI vectors is: Therefore, the actual number of supported MSI vectors is:
M * 64 / N M * 64 / N
where M denotes the number of GIC interrupts (event queues), and N where M denotes the number of GIC interrupts (event queues), and N denotes
denotes the number of CPU cores the number of CPU cores.
This iProc event queue based MSI support should not be used with newer This iProc event queue-based MSI support should not be used with newer
platforms with integrated MSI support in the GIC (e.g., giv2m or platforms with integrated MSI support in the GIC (e.g., giv2m or
gicv3-its) gicv3-its).
[bhelgaas: fold in Kconfig fixes from Arnd Bergmann <arnd@arndb.de>]
Signed-off-by: Ray Jui <rjui@broadcom.com> Signed-off-by: Ray Jui <rjui@broadcom.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Anup Patel <anup.patel@broadcom.com> Reviewed-by: Anup Patel <anup.patel@broadcom.com>
Reviewed-by: Vikram Prakash <vikramp@broadcom.com> Reviewed-by: Vikram Prakash <vikramp@broadcom.com>
Reviewed-by: Scott Branden <sbranden@broadcom.com> Reviewed-by: Scott Branden <sbranden@broadcom.com>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
--- ---
drivers/pci/host/Kconfig | 9 + drivers/pci/host/Kconfig | 10 +
drivers/pci/host/Makefile | 1 + drivers/pci/host/Makefile | 1 +
drivers/pci/host/pcie-iproc-bcma.c | 1 + drivers/pci/host/pcie-iproc-bcma.c | 1 +
drivers/pci/host/pcie-iproc-msi.c | 675 +++++++++++++++++++++++++++++++++ drivers/pci/host/pcie-iproc-msi.c | 675 +++++++++++++++++++++++++++++++++
drivers/pci/host/pcie-iproc-platform.c | 1 + drivers/pci/host/pcie-iproc-platform.c | 1 +
drivers/pci/host/pcie-iproc.c | 26 ++ drivers/pci/host/pcie-iproc.c | 26 ++
drivers/pci/host/pcie-iproc.h | 23 +- drivers/pci/host/pcie-iproc.h | 23 +-
7 files changed, 734 insertions(+), 2 deletions(-) 7 files changed, 735 insertions(+), 2 deletions(-)
create mode 100644 drivers/pci/host/pcie-iproc-msi.c create mode 100644 drivers/pci/host/pcie-iproc-msi.c
--- a/drivers/pci/host/Kconfig --- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig
@@ -127,6 +127,15 @@ config PCIE_IPROC @@ -146,6 +146,16 @@ config PCIE_IPROC_BCMA
iProc family of SoCs. An appropriate bus interface driver also needs Say Y here if you want to use the Broadcom iProc PCIe controller
to be enabled through the BCMA bus interface
+config PCIE_IPROC_MSI +config PCIE_IPROC_MSI
+ bool "Broadcom iProc PCIe MSI support" + bool "Broadcom iProc PCIe MSI support"
+ depends on ARCH_BCM_IPROC && PCI_MSI + depends on PCIE_IPROC_PLATFORM || PCIE_IPROC_BCMA
+ depends on PCI_MSI
+ select PCI_MSI_IRQ_DOMAIN + select PCI_MSI_IRQ_DOMAIN
+ default ARCH_BCM_IPROC + default ARCH_BCM_IPROC
+ help + help
+ Say Y here if you want to enable MSI support for Broadcom's iProc + Say Y here if you want to enable MSI support for Broadcom's iProc
+ PCIe controller + PCIe controller
+ +
config PCIE_IPROC_PLATFORM config PCIE_ALTERA
tristate "Broadcom iProc PCIe platform bus driver" bool "Altera PCIe controller"
depends on ARCH_BCM_IPROC || (ARM && COMPILE_TEST) depends on ARM || NIOS2
--- a/drivers/pci/host/Makefile --- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene @@ -15,6 +15,7 @@ obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene
@ -123,16 +127,16 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ +
+#define IPROC_MSI_EQ_MASK 0x3f +#define IPROC_MSI_EQ_MASK 0x3f
+ +
+/* max number of GIC interrupts */ +/* Max number of GIC interrupts */
+#define NR_HW_IRQS 6 +#define NR_HW_IRQS 6
+ +
+/* number of entries in each event queue */ +/* Number of entries in each event queue */
+#define EQ_LEN 64 +#define EQ_LEN 64
+ +
+/* size of each event queue memory region */ +/* Size of each event queue memory region */
+#define EQ_MEM_REGION_SIZE SZ_4K +#define EQ_MEM_REGION_SIZE SZ_4K
+ +
+/* size of each MSI address region */ +/* Size of each MSI address region */
+#define MSI_MEM_REGION_SIZE SZ_4K +#define MSI_MEM_REGION_SIZE SZ_4K
+ +
+enum iproc_msi_reg { +enum iproc_msi_reg {
@ -153,7 +157,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ * iProc MSI group + * iProc MSI group
+ * + *
+ * One MSI group is allocated per GIC interrupt, serviced by one iProc MSI + * One MSI group is allocated per GIC interrupt, serviced by one iProc MSI
+ * event queue + * event queue.
+ * + *
+ * @msi: pointer to iProc MSI data + * @msi: pointer to iProc MSI data
+ * @gic_irq: GIC interrupt + * @gic_irq: GIC interrupt
@ -169,7 +173,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ * iProc event queue based MSI + * iProc event queue based MSI
+ * + *
+ * Only meant to be used on platforms without MSI support integrated into the + * Only meant to be used on platforms without MSI support integrated into the
+ * GIC + * GIC.
+ * + *
+ * @pcie: pointer to iProc PCIe data + * @pcie: pointer to iProc PCIe data
+ * @reg_offsets: MSI register offsets + * @reg_offsets: MSI register offsets
@ -278,12 +282,12 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ +
+/* +/*
+ * In iProc PCIe core, each MSI group is serviced by a GIC interrupt and a + * In iProc PCIe core, each MSI group is serviced by a GIC interrupt and a
+ * dedicated event queue. Each MSI group can support up to 64 MSI vectors + * dedicated event queue. Each MSI group can support up to 64 MSI vectors.
+ * + *
+ * The number of MSI groups varies between different iProc SoCs. The total + * The number of MSI groups varies between different iProc SoCs. The total
+ * number of CPU cores also varies. To support MSI IRQ affinity, we + * number of CPU cores also varies. To support MSI IRQ affinity, we
+ * distribute GIC interrupts across all available CPUs. MSI vector is moved + * distribute GIC interrupts across all available CPUs. MSI vector is moved
+ * from one GIC interrupt to another to steer to the target CPU + * from one GIC interrupt to another to steer to the target CPU.
+ * + *
+ * Assuming: + * Assuming:
+ * - the number of MSI groups is M + * - the number of MSI groups is M
@ -348,7 +352,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ +
+ mutex_lock(&msi->bitmap_lock); + mutex_lock(&msi->bitmap_lock);
+ +
+ /* allocate 'nr_cpus' number of MSI vectors each time */ + /* Allocate 'nr_cpus' number of MSI vectors each time */
+ hwirq = bitmap_find_next_zero_area(msi->bitmap, msi->nr_msi_vecs, 0, + hwirq = bitmap_find_next_zero_area(msi->bitmap, msi->nr_msi_vecs, 0,
+ msi->nr_cpus, 0); + msi->nr_cpus, 0);
+ if (hwirq < msi->nr_msi_vecs) { + if (hwirq < msi->nr_msi_vecs) {
@ -399,8 +403,8 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ +
+ /* + /*
+ * Since we have multiple hwirq mapped to a single MSI vector, + * Since we have multiple hwirq mapped to a single MSI vector,
+ * now we need to derive the hwirq at CPU0. It can then be used to + * now we need to derive the hwirq at CPU0. It can then be used to
+ * mapped back to virq + * mapped back to virq.
+ */ + */
+ return hwirq_to_canonical_hwirq(msi, hwirq); + return hwirq_to_canonical_hwirq(msi, hwirq);
+} +}
@ -423,14 +427,14 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ eq = grp->eq; + eq = grp->eq;
+ +
+ /* + /*
+ * iProc MSI event queue is tracked by head and tail pointers. Head + * iProc MSI event queue is tracked by head and tail pointers. Head
+ * pointer indicates the next entry (MSI data) to be consumed by SW in + * pointer indicates the next entry (MSI data) to be consumed by SW in
+ * the queue and needs to be updated by SW. iProc MSI core uses the + * the queue and needs to be updated by SW. iProc MSI core uses the
+ * tail pointer as the next data insertion point + * tail pointer as the next data insertion point.
+ * + *
+ * Entries between head and tail pointers contain valid MSI data. MSI + * Entries between head and tail pointers contain valid MSI data. MSI
+ * data is guaranteed to be in the event queue memory before the tail + * data is guaranteed to be in the event queue memory before the tail
+ * pointer is updated by the iProc MSI core + * pointer is updated by the iProc MSI core.
+ */ + */
+ head = iproc_msi_read_reg(msi, IPROC_MSI_EQ_HEAD, + head = iproc_msi_read_reg(msi, IPROC_MSI_EQ_HEAD,
+ eq) & IPROC_MSI_EQ_MASK; + eq) & IPROC_MSI_EQ_MASK;
@ -440,7 +444,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ +
+ /* + /*
+ * Figure out total number of events (MSI data) to be + * Figure out total number of events (MSI data) to be
+ * processed + * processed.
+ */ + */
+ nr_events = (tail < head) ? + nr_events = (tail < head) ?
+ (EQ_LEN - (head - tail)) : (tail - head); + (EQ_LEN - (head - tail)) : (tail - head);
@ -458,14 +462,14 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ } + }
+ +
+ /* + /*
+ * Now all outstanding events have been processed. Update the + * Now all outstanding events have been processed. Update the
+ * head pointer + * head pointer.
+ */ + */
+ iproc_msi_write_reg(msi, IPROC_MSI_EQ_HEAD, eq, head); + iproc_msi_write_reg(msi, IPROC_MSI_EQ_HEAD, eq, head);
+ +
+ /* + /*
+ * Now go read the tail pointer again to see if there are new + * Now go read the tail pointer again to see if there are new
+ * oustanding events that came in during the above window + * oustanding events that came in during the above window.
+ */ + */
+ } while (true); + } while (true);
+ +
@ -477,7 +481,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ int i, eq; + int i, eq;
+ u32 val; + u32 val;
+ +
+ /* program memory region for each event queue */ + /* Program memory region for each event queue */
+ for (i = 0; i < msi->nr_eq_region; i++) { + for (i = 0; i < msi->nr_eq_region; i++) {
+ dma_addr_t addr = msi->eq_dma + (i * EQ_MEM_REGION_SIZE); + dma_addr_t addr = msi->eq_dma + (i * EQ_MEM_REGION_SIZE);
+ +
@ -487,7 +491,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ upper_32_bits(addr)); + upper_32_bits(addr));
+ } + }
+ +
+ /* program address region for MSI posted writes */ + /* Program address region for MSI posted writes */
+ for (i = 0; i < msi->nr_msi_region; i++) { + for (i = 0; i < msi->nr_msi_region; i++) {
+ phys_addr_t addr = msi->msi_addr + (i * MSI_MEM_REGION_SIZE); + phys_addr_t addr = msi->msi_addr + (i * MSI_MEM_REGION_SIZE);
+ +
@ -498,14 +502,14 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ } + }
+ +
+ for (eq = 0; eq < msi->nr_irqs; eq++) { + for (eq = 0; eq < msi->nr_irqs; eq++) {
+ /* enable MSI event queue */ + /* Enable MSI event queue */
+ val = IPROC_MSI_INTR_EN | IPROC_MSI_INT_N_EVENT | + val = IPROC_MSI_INTR_EN | IPROC_MSI_INT_N_EVENT |
+ IPROC_MSI_EQ_EN; + IPROC_MSI_EQ_EN;
+ iproc_msi_write_reg(msi, IPROC_MSI_CTRL, eq, val); + iproc_msi_write_reg(msi, IPROC_MSI_CTRL, eq, val);
+ +
+ /* + /*
+ * Some legacy platforms require the MSI interrupt enable + * Some legacy platforms require the MSI interrupt enable
+ * register to be set explicitly + * register to be set explicitly.
+ */ + */
+ if (msi->has_inten_reg) { + if (msi->has_inten_reg) {
+ val = iproc_msi_read_reg(msi, IPROC_MSI_INTS_EN, eq); + val = iproc_msi_read_reg(msi, IPROC_MSI_INTS_EN, eq);
@ -581,7 +585,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ irq_set_chained_handler_and_data(msi->grps[i].gic_irq, + irq_set_chained_handler_and_data(msi->grps[i].gic_irq,
+ iproc_msi_handler, + iproc_msi_handler,
+ &msi->grps[i]); + &msi->grps[i]);
+ /* dedicate GIC interrupt to each CPU core */ + /* Dedicate GIC interrupt to each CPU core */
+ if (alloc_cpumask_var(&mask, GFP_KERNEL)) { + if (alloc_cpumask_var(&mask, GFP_KERNEL)) {
+ cpumask_clear(mask); + cpumask_clear(mask);
+ cpumask_set_cpu(cpu, mask); + cpumask_set_cpu(cpu, mask);
@ -597,7 +601,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ } + }
+ +
+ if (ret) { + if (ret) {
+ /* free all configured/unconfigured irqs */ + /* Free all configured/unconfigured IRQs */
+ iproc_msi_irq_free(msi, cpu); + iproc_msi_irq_free(msi, cpu);
+ return ret; + return ret;
+ } + }
@ -698,7 +702,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+ msi->grps[i].eq = i; + msi->grps[i].eq = i;
+ } + }
+ +
+ /* reserve memory for event queue and make sure memories are zeroed */ + /* Reserve memory for event queue and make sure memories are zeroed */
+ msi->eq_cpu = dma_zalloc_coherent(pcie->dev, + msi->eq_cpu = dma_zalloc_coherent(pcie->dev,
+ msi->nr_eq_region * EQ_MEM_REGION_SIZE, + msi->nr_eq_region * EQ_MEM_REGION_SIZE,
+ &msi->eq_dma, GFP_KERNEL); + &msi->eq_dma, GFP_KERNEL);
@ -870,7 +874,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res); int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res);
int iproc_pcie_remove(struct iproc_pcie *pcie); int iproc_pcie_remove(struct iproc_pcie *pcie);
+#ifdef CONFIG_PCI_MSI +#ifdef CONFIG_PCIE_IPROC_MSI
+int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node); +int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node);
+void iproc_msi_exit(struct iproc_pcie *pcie); +void iproc_msi_exit(struct iproc_pcie *pcie);
+#else +#else
@ -879,7 +883,7 @@ Reviewed-by: Scott Branden <sbranden@broadcom.com>
+{ +{
+ return -ENODEV; + return -ENODEV;
+} +}
+static void iproc_msi_exit(struct iproc_pcie *pcie) +static inline void iproc_msi_exit(struct iproc_pcie *pcie)
+{ +{
+} +}
+#endif +#endif