summaryrefslogtreecommitdiffstats
path: root/Raspberry-Pi-4-PCIe-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'Raspberry-Pi-4-PCIe-support.patch')
-rw-r--r--Raspberry-Pi-4-PCIe-support.patch1702
1 files changed, 0 insertions, 1702 deletions
diff --git a/Raspberry-Pi-4-PCIe-support.patch b/Raspberry-Pi-4-PCIe-support.patch
index d87f6f512..fff2de619 100644
--- a/Raspberry-Pi-4-PCIe-support.patch
+++ b/Raspberry-Pi-4-PCIe-support.patch
@@ -1,245 +1,3 @@
-From patchwork Mon Dec 16 11:01:07 2019
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-X-Patchwork-Id: 11293801
-Return-Path:
- <SRS0=BOSQ=2G=lists.infradead.org=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@kernel.org>
-Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org
- [172.30.200.123])
- by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1A73D930
- for <patchwork-linux-arm@patchwork.kernel.org>;
- Mon, 16 Dec 2019 11:01:44 +0000 (UTC)
-Received: from bombadil.infradead.org (bombadil.infradead.org
- [198.137.202.133])
- (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
- (No client certificate requested)
- by mail.kernel.org (Postfix) with ESMTPS id B59B620700
- for <patchwork-linux-arm@patchwork.kernel.org>;
- Mon, 16 Dec 2019 11:01:43 +0000 (UTC)
-Authentication-Results: mail.kernel.org;
- dkim=pass (2048-bit key) header.d=lists.infradead.org
- header.i=@lists.infradead.org header.b="cb79RIet"
-DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B59B620700
-Authentication-Results: mail.kernel.org;
- dmarc=none (p=none dis=none) header.from=suse.de
-Authentication-Results: mail.kernel.org;
- spf=none
- smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org
-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
- d=lists.infradead.org; s=bombadil.20170209; h=Sender:
- Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post:
- List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:
- Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description:
- Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:
- List-Owner; bh=BIaxi8TW6/7kc2+ri3jCQvUDcvRqu4DcRQH+PcSrqFE=; b=cb79RIetq9xDMB
- WjzGeSpWqqJFBoypJgtl/f0hMNvDJo23OqyPAA3XiHnd/1OiFVtIaHj0rl0/7mBUqLfVJzym3AJq8
- MbvE4H5sbjLxLskuQnjMJoITqCzh1fly6HBgLOQJRHZU3rLBVnkbRPgRv+nRt5Nqi5M3aJp1a3qsL
- 8hPhH1PkGeofP4XjfWvnfl7nhg21+dC3Bxu86pb1aKPogRL6Rw4FGwOawF3ySHMGue4t9OfGcUh+B
- NI08Au81lvrfZys52Hfb5S7BXmj8vd/1fGqW97GjBdZcHjdUNMfFHHlC4SmLwJqvKdVWpgJH01sdP
- 29RmPOdzQSiBF+WIhx2w==;
-Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org)
- by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux))
- id 1igo8E-0003Jg-15; Mon, 16 Dec 2019 11:01:42 +0000
-Received: from mx2.suse.de ([195.135.220.15] helo=mx1.suse.de)
- by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux))
- id 1igo80-00036F-By; Mon, 16 Dec 2019 11:01:30 +0000
-X-Virus-Scanned: by amavisd-new at test-mx.suse.de
-Received: from relay2.suse.de (unknown [195.135.220.254])
- by mx1.suse.de (Postfix) with ESMTP id 0A418ABF4;
- Mon, 16 Dec 2019 11:01:27 +0000 (UTC)
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-To: andrew.murray@arm.com, maz@kernel.org, linux-kernel@vger.kernel.org,
- Florian Fainelli <f.fainelli@gmail.com>,
- bcm-kernel-feedback-list@broadcom.com,
- Nicolas Saenz Julienne <nsaenzjulienne@suse.de>,
- Bjorn Helgaas <bhelgaas@google.com>
-Subject: [PATCH v5 1/6] dt-bindings: PCI: Add bindings for brcmstb's PCIe
- device
-Date: Mon, 16 Dec 2019 12:01:07 +0100
-Message-Id: <20191216110113.30436-2-nsaenzjulienne@suse.de>
-X-Mailer: git-send-email 2.24.0
-In-Reply-To: <20191216110113.30436-1-nsaenzjulienne@suse.de>
-References: <20191216110113.30436-1-nsaenzjulienne@suse.de>
-MIME-Version: 1.0
-X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3
-X-CRM114-CacheID: sfid-20191216_030128_695398_7DDDD9AA
-X-CRM114-Status: GOOD ( 12.44 )
-X-Spam-Score: -2.3 (--)
-X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary:
- Content analysis details: (-2.3 points)
- pts rule name description
- ---- ----------------------
- --------------------------------------------------
- 0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3)
- [195.135.220.15 listed in wl.mailspike.net]
- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/,
- medium trust [195.135.220.15 listed in list.dnswl.org]
- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record
- -0.0 SPF_PASS SPF: sender matches SPF record
- 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders
-X-BeenThere: linux-arm-kernel@lists.infradead.org
-X-Mailman-Version: 2.1.29
-Precedence: list
-List-Id: <linux-arm-kernel.lists.infradead.org>
-List-Unsubscribe:
- <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
- <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
-List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
-List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
-List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
-List-Subscribe:
- <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
- <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
-Cc: Mark Rutland <mark.rutland@arm.com>, Rob Herring <robh@kernel.org>,
- mbrugger@suse.com, devicetree@vger.kernel.org, linux-pci@vger.kernel.org,
- phil@raspberrypi.org, jeremy.linton@arm.com,
- Rob Herring <robh+dt@kernel.org>,
- wahrenst@gmx.net, james.quinlan@broadcom.com,
- linux-arm-kernel@lists.infradead.org, linux-rpi-kernel@lists.infradead.org
-Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
-Errors-To:
- linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org
-
-From: Jim Quinlan <james.quinlan@broadcom.com>
-
-The DT bindings description of the brcmstb PCIe device is described.
-This node can only be used for now on the Raspberry Pi 4.
-
-Signed-off-by: Jim Quinlan <james.quinlan@broadcom.com>
-Co-developed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Rob Herring <robh@kernel.org>
-Reviewed-by: Andrew Murray <andrew.murray@arm.com>
----
-
-Changes since v2:
- - Add pci reference schema
- - Drop all default properties
- - Assume msi-controller and msi-parent are properly defined
- - Add num entries on multiple properties
- - use unevaluatedProperties
- - Update required properties
- - Fix license
-
-Changes since v1:
- - Fix commit Subject
- - Remove linux,pci-domain
-
-This was based on Jim's original submission[1], converted to yaml and
-adapted to the RPi4 case.
-
-[1] https://patchwork.kernel.org/patch/10605937/
-
- .../bindings/pci/brcm,stb-pcie.yaml | 97 +++++++++++++++++++
- 1 file changed, 97 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
-
-diff --git a/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml b/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
-new file mode 100644
-index 000000000000..77d3e81a437b
---- /dev/null
-+++ b/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
-@@ -0,0 +1,97 @@
-+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/pci/brcm,stb-pcie.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: Brcmstb PCIe Host Controller Device Tree Bindings
-+
-+maintainers:
-+ - Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-+
-+allOf:
-+ - $ref: /schemas/pci/pci-bus.yaml#
-+
-+properties:
-+ compatible:
-+ const: brcm,bcm2711-pcie # The Raspberry Pi 4
-+
-+ reg:
-+ maxItems: 1
-+
-+ interrupts:
-+ minItems: 1
-+ maxItems: 2
-+ items:
-+ - description: PCIe host controller
-+ - description: builtin MSI controller
-+
-+ interrupt-names:
-+ minItems: 1
-+ maxItems: 2
-+ items:
-+ - const: pcie
-+ - const: msi
-+
-+ ranges:
-+ maxItems: 1
-+
-+ dma-ranges:
-+ maxItems: 1
-+
-+ clocks:
-+ maxItems: 1
-+
-+ clock-names:
-+ items:
-+ - const: sw_pcie
-+
-+ msi-controller:
-+ description: Identifies the node as an MSI controller.
-+
-+ msi-parent:
-+ description: MSI controller the device is capable of using.
-+
-+ brcm,enable-ssc:
-+ description: Indicates usage of spread-spectrum clocking.
-+ type: boolean
-+
-+required:
-+ - reg
-+ - dma-ranges
-+ - "#interrupt-cells"
-+ - interrupts
-+ - interrupt-names
-+ - interrupt-map-mask
-+ - interrupt-map
-+ - msi-controller
-+
-+unevaluatedProperties: false
-+
-+examples:
-+ - |
-+ #include <dt-bindings/interrupt-controller/irq.h>
-+ #include <dt-bindings/interrupt-controller/arm-gic.h>
-+
-+ scb {
-+ #address-cells = <2>;
-+ #size-cells = <1>;
-+ pcie0: pcie@7d500000 {
-+ compatible = "brcm,bcm2711-pcie";
-+ reg = <0x0 0x7d500000 0x9310>;
-+ device_type = "pci";
-+ #address-cells = <3>;
-+ #size-cells = <2>;
-+ #interrupt-cells = <1>;
-+ interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
-+ <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
-+ interrupt-names = "pcie", "msi";
-+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
-+ interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
-+ msi-parent = <&pcie0>;
-+ msi-controller;
-+ ranges = <0x02000000 0x0 0xf8000000 0x6 0x00000000 0x0 0x04000000>;
-+ dma-ranges = <0x02000000 0x0 0x00000000 0x0 0x00000000 0x0 0x80000000>;
-+ brcm,enable-ssc;
-+ };
-+ };
-
From patchwork Mon Dec 16 11:01:08 2019
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
@@ -411,1466 +169,6 @@ index e2f6ffb00aa9..b56388ce1216 100644
genet: ethernet@7d580000 {
compatible = "brcm,bcm2711-genet-v5";
-From patchwork Mon Dec 16 11:01:09 2019
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-X-Patchwork-Id: 11293817
-Return-Path:
- <SRS0=BOSQ=2G=lists.infradead.org=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@kernel.org>
-Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org
- [172.30.200.123])
- by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5258B138C
- for <patchwork-linux-arm@patchwork.kernel.org>;
- Mon, 16 Dec 2019 11:02:16 +0000 (UTC)
-Received: from bombadil.infradead.org (bombadil.infradead.org
- [198.137.202.133])
- (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
- (No client certificate requested)
- by mail.kernel.org (Postfix) with ESMTPS id 2BC2C206EC
- for <patchwork-linux-arm@patchwork.kernel.org>;
- Mon, 16 Dec 2019 11:02:16 +0000 (UTC)
-Authentication-Results: mail.kernel.org;
- dkim=pass (2048-bit key) header.d=lists.infradead.org
- header.i=@lists.infradead.org header.b="ESaFz97K"
-DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2BC2C206EC
-Authentication-Results: mail.kernel.org;
- dmarc=none (p=none dis=none) header.from=suse.de
-Authentication-Results: mail.kernel.org;
- spf=none
- smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org
-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
- d=lists.infradead.org; s=bombadil.20170209; h=Sender:
- Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post:
- List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:
- Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description:
- Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:
- List-Owner; bh=+5ayi0cziQL3ZyCMj3iZr+38A6c8osp+1etjz8lMcs0=; b=ESaFz97K8D7L5Q
- eP6cOr4xBwD8JGVEOalDJHmTA7YrfsYPlyqEmoV5jf6647ddqM+dXZE2HpqGgiKBSvQmg3bbSh92t
- DokvbV8Iglu0LlQvliFFakzKq3z/SEtdiQ67DhNsyC8/6150TSWOQ3bgblVRH3pBCettQmRRCdSPG
- S0nb5uLQ0mpfLJvfcpN6lDJepIxpaCo4My4i5OPN5rCVQgW0b181kKQ0CiOpn6+RHsZ8TZQT3oGLt
- lXuYTni2GgcysGX3UNYbzsex6v8wqmSxchH+qpnwdJw7G/oxFcNTvVQ5BIjU62CZmX6qC+RjOwwnB
- LwtY7yRrtR/lXNVBKOFQ==;
-Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org)
- by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux))
- id 1igo8l-0003rT-Fs; Mon, 16 Dec 2019 11:02:15 +0000
-Received: from mx2.suse.de ([195.135.220.15] helo=mx1.suse.de)
- by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux))
- id 1igo82-00036x-Ea; Mon, 16 Dec 2019 11:01:34 +0000
-X-Virus-Scanned: by amavisd-new at test-mx.suse.de
-Received: from relay2.suse.de (unknown [195.135.220.254])
- by mx1.suse.de (Postfix) with ESMTP id 25A22ACC6;
- Mon, 16 Dec 2019 11:01:29 +0000 (UTC)
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-To: andrew.murray@arm.com, maz@kernel.org, linux-kernel@vger.kernel.org,
- Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>,
- Florian Fainelli <f.fainelli@gmail.com>,
- bcm-kernel-feedback-list@broadcom.com,
- Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Subject: [PATCH v5 3/6] PCI: brcmstb: Add Broadcom STB PCIe host controller
- driver
-Date: Mon, 16 Dec 2019 12:01:09 +0100
-Message-Id: <20191216110113.30436-4-nsaenzjulienne@suse.de>
-X-Mailer: git-send-email 2.24.0
-In-Reply-To: <20191216110113.30436-1-nsaenzjulienne@suse.de>
-References: <20191216110113.30436-1-nsaenzjulienne@suse.de>
-MIME-Version: 1.0
-X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3
-X-CRM114-CacheID: sfid-20191216_030130_800432_3B8FE2E4
-X-CRM114-Status: GOOD ( 18.27 )
-X-Spam-Score: -2.3 (--)
-X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary:
- Content analysis details: (-2.3 points)
- pts rule name description
- ---- ----------------------
- --------------------------------------------------
- 0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3)
- [195.135.220.15 listed in wl.mailspike.net]
- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/,
- medium trust [195.135.220.15 listed in list.dnswl.org]
- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record
- -0.0 SPF_PASS SPF: sender matches SPF record
- 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders
-X-BeenThere: linux-arm-kernel@lists.infradead.org
-X-Mailman-Version: 2.1.29
-Precedence: list
-List-Id: <linux-arm-kernel.lists.infradead.org>
-List-Unsubscribe:
- <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
- <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
-List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
-List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
-List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
-List-Subscribe:
- <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
- <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
-Cc: mbrugger@suse.com, linux-pci@vger.kernel.org, phil@raspberrypi.org,
- jeremy.linton@arm.com, wahrenst@gmx.net, james.quinlan@broadcom.com,
- Bjorn Helgaas <bhelgaas@google.com>, linux-arm-kernel@lists.infradead.org,
- linux-rpi-kernel@lists.infradead.org
-Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
-Errors-To:
- linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org
-
-From: Jim Quinlan <james.quinlan@broadcom.com>
-
-This adds a basic driver for Broadcom's STB PCIe controller, for now
-aimed at Raspberry Pi 4's SoC, bcm2711.
-
-Signed-off-by: Jim Quinlan <james.quinlan@broadcom.com>
-Co-developed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Andrew Murray <andrew.murray@arm.com>
-Reviewed-by: Jeremy Linton <jeremy.linton@arm.com>
----
-
-Changes since v3:
- - Update commit message
- - rollback roundup_pow_two usage, it'll be updated later down the line
- - Remove comment in register definition
-
-Changes since v2:
- - Correct rc_bar2_offset sign
- - Invert IRQ clear and masking in setup code
- - Use bitfield.h, redo all register ops while keeping the register
- names intact
- - Remove all SHIFT register definitions
- - Get rid of all _RB writes
- - Get rid of of_data
- - Don't iterate over inexisting dma-ranges
- - Add comment regarding dma-ranges validation
- - Small cosmetic cleanups
- - Fix license mismatch
- - Set driver Kconfig tristate
- - Didn't add any comment about the controller not being I/O coherent
- for now as I wait for Jeremy's reply
-
-Changes since v1:
- - Fix Kconfig
- - Remove pci domain check
- - Remove all MSI related code
- - Remove supend/resume code
- - Simplify link state wait routine
- - Prefix all functions
- - Use of_device_get_match_data()
- - Use devm_clk_get_optional()
- - Get rid of irq variable
- - Use STB all over the driver
- - Simplify map_bus() function
- - Fix license mismatch
- - Remove unused register definitions
- - Small cleanups, spell errors
-
-This is based on Jim's original submission[1] but adapted and tailored
-specifically to bcm2711's needs (that's the Raspberry Pi 4). Support for
-the rest of the brcmstb family will soon follow once we get support for
-multiple dma-ranges in dma/direct.
-
-[1] https://patchwork.kernel.org/patch/10605959/
-
- drivers/pci/controller/Kconfig | 8 +
- drivers/pci/controller/Makefile | 1 +
- drivers/pci/controller/pcie-brcmstb.c | 748 ++++++++++++++++++++++++++
- 3 files changed, 757 insertions(+)
- create mode 100644 drivers/pci/controller/pcie-brcmstb.c
-
-diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
-index c77069c8ee5d..27504f108ee5 100644
---- a/drivers/pci/controller/Kconfig
-+++ b/drivers/pci/controller/Kconfig
-@@ -253,6 +253,14 @@ config VMD
- To compile this driver as a module, choose M here: the
- module will be called vmd.
-
-+config PCIE_BRCMSTB
-+ tristate "Broadcom Brcmstb PCIe host controller"
-+ depends on ARCH_BCM2835 || COMPILE_TEST
-+ depends on OF
-+ help
-+ Say Y here to enable PCIe host controller support for
-+ Broadcom STB based SoCs, like the Raspberry Pi 4.
-+
- config PCI_HYPERV_INTERFACE
- tristate "Hyper-V PCI Interface"
- depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64
-diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
-index 3d4f597f15ce..01b2502a5323 100644
---- a/drivers/pci/controller/Makefile
-+++ b/drivers/pci/controller/Makefile
-@@ -28,6 +28,7 @@ obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
- obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
- obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
- obj-$(CONFIG_VMD) += vmd.o
-+obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
- # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
- obj-y += dwc/
-
-diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
-new file mode 100644
-index 000000000000..dd681164faa0
---- /dev/null
-+++ b/drivers/pci/controller/pcie-brcmstb.c
-@@ -0,0 +1,748 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/* Copyright (C) 2009 - 2019 Broadcom */
-+
-+#include <linux/bitfield.h>
-+#include <linux/clk.h>
-+#include <linux/compiler.h>
-+#include <linux/delay.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/ioport.h>
-+#include <linux/irqdomain.h>
-+#include <linux/kernel.h>
-+#include <linux/list.h>
-+#include <linux/log2.h>
-+#include <linux/module.h>
-+#include <linux/of_address.h>
-+#include <linux/of_irq.h>
-+#include <linux/of_pci.h>
-+#include <linux/of_platform.h>
-+#include <linux/pci.h>
-+#include <linux/printk.h>
-+#include <linux/sizes.h>
-+#include <linux/slab.h>
-+#include <linux/string.h>
-+#include <linux/types.h>
-+
-+#include "../pci.h"
-+
-+/* BRCM_PCIE_CAP_REGS - Offset for the mandatory capability config regs */
-+#define BRCM_PCIE_CAP_REGS 0x00ac
-+
-+/* Broadcom STB PCIe Register Offsets */
-+#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1 0x0188
-+#define PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK 0xc
-+#define PCIE_RC_CFG_VENDOR_SPCIFIC_REG1_LITTLE_ENDIAN 0x0
-+
-+#define PCIE_RC_CFG_PRIV1_ID_VAL3 0x043c
-+#define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK 0xffffff
-+
-+#define PCIE_RC_DL_MDIO_ADDR 0x1100
-+#define PCIE_RC_DL_MDIO_WR_DATA 0x1104
-+#define PCIE_RC_DL_MDIO_RD_DATA 0x1108
-+
-+#define PCIE_MISC_MISC_CTRL 0x4008
-+#define PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK 0x1000
-+#define PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK 0x2000
-+#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK 0x300000
-+#define PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_128 0x0
-+#define PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK 0xf8000000
-+
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO 0x400c
-+#define PCIE_MEM_WIN0_LO(win) \
-+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO + ((win) * 4)
-+
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI 0x4010
-+#define PCIE_MEM_WIN0_HI(win) \
-+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_HI + ((win) * 4)
-+
-+#define PCIE_MISC_RC_BAR1_CONFIG_LO 0x402c
-+#define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK 0x1f
-+
-+#define PCIE_MISC_RC_BAR2_CONFIG_LO 0x4034
-+#define PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_MASK 0x1f
-+#define PCIE_MISC_RC_BAR2_CONFIG_HI 0x4038
-+
-+#define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c
-+#define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f
-+
-+#define PCIE_MISC_PCIE_CTRL 0x4064
-+#define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK 0x1
-+
-+#define PCIE_MISC_PCIE_STATUS 0x4068
-+#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK 0x80
-+#define PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_MASK 0x20
-+#define PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK 0x10
-+#define PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK 0x40
-+
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT 0x4070
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK 0xfff00000
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK 0xfff0
-+#define PCIE_MEM_WIN0_BASE_LIMIT(win) \
-+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT + ((win) * 4)
-+
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI 0x4080
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_MASK 0xff
-+#define PCIE_MEM_WIN0_BASE_HI(win) \
-+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI + ((win) * 8)
-+
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI 0x4084
-+#define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK 0xff
-+#define PCIE_MEM_WIN0_LIMIT_HI(win) \
-+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI + ((win) * 8)
-+
-+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG 0x4204
-+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2
-+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
-+
-+#define PCIE_MSI_INTR2_STATUS 0x4500
-+#define PCIE_MSI_INTR2_CLR 0x4508
-+#define PCIE_MSI_INTR2_MASK_SET 0x4510
-+#define PCIE_MSI_INTR2_MASK_CLR 0x4514
-+
-+#define PCIE_EXT_CFG_DATA 0x8000
-+
-+#define PCIE_EXT_CFG_INDEX 0x9000
-+#define PCIE_EXT_BUSNUM_SHIFT 20
-+#define PCIE_EXT_SLOT_SHIFT 15
-+#define PCIE_EXT_FUNC_SHIFT 12
-+
-+#define PCIE_RGR1_SW_INIT_1 0x9210
-+#define PCIE_RGR1_SW_INIT_1_PERST_MASK 0x1
-+#define PCIE_RGR1_SW_INIT_1_INIT_MASK 0x2
-+
-+/* PCIe parameters */
-+#define BRCM_NUM_PCIE_OUT_WINS 0x4
-+
-+/* MDIO registers */
-+#define MDIO_PORT0 0x0
-+#define MDIO_DATA_MASK 0x7fffffff
-+#define MDIO_PORT_MASK 0xf0000
-+#define MDIO_REGAD_MASK 0xffff
-+#define MDIO_CMD_MASK 0xfff00000
-+#define MDIO_CMD_READ 0x1
-+#define MDIO_CMD_WRITE 0x0
-+#define MDIO_DATA_DONE_MASK 0x80000000
-+#define MDIO_RD_DONE(x) (((x) & MDIO_DATA_DONE_MASK) ? 1 : 0)
-+#define MDIO_WT_DONE(x) (((x) & MDIO_DATA_DONE_MASK) ? 0 : 1)
-+#define SSC_REGS_ADDR 0x1100
-+#define SET_ADDR_OFFSET 0x1f
-+#define SSC_CNTL_OFFSET 0x2
-+#define SSC_CNTL_OVRD_EN_MASK 0x8000
-+#define SSC_CNTL_OVRD_VAL_MASK 0x4000
-+#define SSC_STATUS_OFFSET 0x1
-+#define SSC_STATUS_SSC_MASK 0x400
-+#define SSC_STATUS_PLL_LOCK_MASK 0x800
-+
-+/* Internal PCIe Host Controller Information.*/
-+struct brcm_pcie {
-+ struct device *dev;
-+ void __iomem *base;
-+ struct clk *clk;
-+ struct pci_bus *root_bus;
-+ struct device_node *np;
-+ bool ssc;
-+ int gen;
-+};
-+
-+/*
-+ * This is to convert the size of the inbound "BAR" region to the
-+ * non-linear values of PCIE_X_MISC_RC_BAR[123]_CONFIG_LO.SIZE
-+ */
-+static int brcm_pcie_encode_ibar_size(u64 size)
-+{
-+ int log2_in = ilog2(size);
-+
-+ if (log2_in >= 12 && log2_in <= 15)
-+ /* Covers 4KB to 32KB (inclusive) */
-+ return (log2_in - 12) + 0x1c;
-+ else if (log2_in >= 16 && log2_in <= 35)
-+ /* Covers 64KB to 32GB, (inclusive) */
-+ return log2_in - 15;
-+ /* Something is awry so disable */
-+ return 0;
-+}
-+
-+static u32 brcm_pcie_mdio_form_pkt(int port, int regad, int cmd)
-+{
-+ u32 pkt = 0;
-+
-+ pkt |= FIELD_PREP(MDIO_PORT_MASK, port);
-+ pkt |= FIELD_PREP(MDIO_REGAD_MASK, regad);
-+ pkt |= FIELD_PREP(MDIO_CMD_MASK, cmd);
-+
-+ return pkt;
-+}
-+
-+/* negative return value indicates error */
-+static int brcm_pcie_mdio_read(void __iomem *base, u8 port, u8 regad, u32 *val)
-+{
-+ int tries;
-+ u32 data;
-+
-+ writel(brcm_pcie_mdio_form_pkt(port, regad, MDIO_CMD_READ),
-+ base + PCIE_RC_DL_MDIO_ADDR);
-+ readl(base + PCIE_RC_DL_MDIO_ADDR);
-+
-+ data = readl(base + PCIE_RC_DL_MDIO_RD_DATA);
-+ for (tries = 0; !MDIO_RD_DONE(data) && tries < 10; tries++) {
-+ udelay(10);
-+ data = readl(base + PCIE_RC_DL_MDIO_RD_DATA);
-+ }
-+
-+ *val = FIELD_GET(MDIO_DATA_MASK, data);
-+ return MDIO_RD_DONE(data) ? 0 : -EIO;
-+}
-+
-+/* negative return value indicates error */
-+static int brcm_pcie_mdio_write(void __iomem *base, u8 port,
-+ u8 regad, u16 wrdata)
-+{
-+ int tries;
-+ u32 data;
-+
-+ writel(brcm_pcie_mdio_form_pkt(port, regad, MDIO_CMD_WRITE),
-+ base + PCIE_RC_DL_MDIO_ADDR);
-+ readl(base + PCIE_RC_DL_MDIO_ADDR);
-+ writel(MDIO_DATA_DONE_MASK | wrdata, base + PCIE_RC_DL_MDIO_WR_DATA);
-+
-+ data = readl(base + PCIE_RC_DL_MDIO_WR_DATA);
-+ for (tries = 0; !MDIO_WT_DONE(data) && tries < 10; tries++) {
-+ udelay(10);
-+ data = readl(base + PCIE_RC_DL_MDIO_WR_DATA);
-+ }
-+
-+ return MDIO_WT_DONE(data) ? 0 : -EIO;
-+}
-+
-+/*
-+ * Configures device for Spread Spectrum Clocking (SSC) mode; a negative
-+ * return value indicates error.
-+ */
-+static int brcm_pcie_set_ssc(struct brcm_pcie *pcie)
-+{
-+ int pll, ssc;
-+ int ret;
-+ u32 tmp;
-+
-+ ret = brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, SET_ADDR_OFFSET,
-+ SSC_REGS_ADDR);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = brcm_pcie_mdio_read(pcie->base, MDIO_PORT0,
-+ SSC_CNTL_OFFSET, &tmp);
-+ if (ret < 0)
-+ return ret;
-+
-+ u32p_replace_bits(&tmp, 1, SSC_CNTL_OVRD_EN_MASK);
-+ u32p_replace_bits(&tmp, 1, SSC_CNTL_OVRD_VAL_MASK);
-+ ret = brcm_pcie_mdio_write(pcie->base, MDIO_PORT0,
-+ SSC_CNTL_OFFSET, tmp);
-+ if (ret < 0)
-+ return ret;
-+
-+ usleep_range(1000, 2000);
-+ ret = brcm_pcie_mdio_read(pcie->base, MDIO_PORT0,
-+ SSC_STATUS_OFFSET, &tmp);
-+ if (ret < 0)
-+ return ret;
-+
-+ ssc = FIELD_GET(SSC_STATUS_SSC_MASK, tmp);
-+ pll = FIELD_GET(SSC_STATUS_PLL_LOCK_MASK, tmp);
-+
-+ return ssc && pll ? 0 : -EIO;
-+}
-+
-+/* Limits operation to a specific generation (1, 2, or 3) */
-+static void brcm_pcie_set_gen(struct brcm_pcie *pcie, int gen)
-+{
-+ u16 lnkctl2 = readw(pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
-+ u32 lnkcap = readl(pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
-+
-+ lnkcap = (lnkcap & ~PCI_EXP_LNKCAP_SLS) | gen;
-+ writel(lnkcap, pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP);
-+
-+ lnkctl2 = (lnkctl2 & ~0xf) | gen;
-+ writew(lnkctl2, pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2);
-+}
-+
-+static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie,
-+ unsigned int win, u64 cpu_addr,
-+ u64 pcie_addr, u64 size)
-+{
-+ u32 cpu_addr_mb_high, limit_addr_mb_high;
-+ phys_addr_t cpu_addr_mb, limit_addr_mb;
-+ int high_addr_shift;
-+ u32 tmp;
-+
-+ /* Set the base of the pcie_addr window */
-+ writel(lower_32_bits(pcie_addr), pcie->base + PCIE_MEM_WIN0_LO(win));
-+ writel(upper_32_bits(pcie_addr), pcie->base + PCIE_MEM_WIN0_HI(win));
-+
-+ /* Write the addr base & limit lower bits (in MBs) */
-+ cpu_addr_mb = cpu_addr / SZ_1M;
-+ limit_addr_mb = (cpu_addr + size - 1) / SZ_1M;
-+
-+ tmp = readl(pcie->base + PCIE_MEM_WIN0_BASE_LIMIT(win));
-+ u32p_replace_bits(&tmp, cpu_addr_mb,
-+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK);
-+ u32p_replace_bits(&tmp, limit_addr_mb,
-+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_LIMIT_MASK);
-+ writel(tmp, pcie->base + PCIE_MEM_WIN0_BASE_LIMIT(win));
-+
-+ /* Write the cpu & limit addr upper bits */
-+ high_addr_shift =
-+ HWEIGHT32(PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT_BASE_MASK);
-+
-+ cpu_addr_mb_high = cpu_addr_mb >> high_addr_shift;
-+ tmp = readl(pcie->base + PCIE_MEM_WIN0_BASE_HI(win));
-+ u32p_replace_bits(&tmp, cpu_addr_mb_high,
-+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI_BASE_MASK);
-+ writel(tmp, pcie->base + PCIE_MEM_WIN0_BASE_HI(win));
-+
-+ limit_addr_mb_high = limit_addr_mb >> high_addr_shift;
-+ tmp = readl(pcie->base + PCIE_MEM_WIN0_LIMIT_HI(win));
-+ u32p_replace_bits(&tmp, limit_addr_mb_high,
-+ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI_LIMIT_MASK);
-+ writel(tmp, pcie->base + PCIE_MEM_WIN0_LIMIT_HI(win));
-+}
-+
-+/* The controller is capable of serving in both RC and EP roles */
-+static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie)
-+{
-+ void __iomem *base = pcie->base;
-+ u32 val = readl(base + PCIE_MISC_PCIE_STATUS);
-+
-+ return !!FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK, val);
-+}
-+
-+static bool brcm_pcie_link_up(struct brcm_pcie *pcie)
-+{
-+ u32 val = readl(pcie->base + PCIE_MISC_PCIE_STATUS);
-+ u32 dla = FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_DL_ACTIVE_MASK, val);
-+ u32 plu = FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_PHYLINKUP_MASK, val);
-+
-+ return dla && plu;
-+}
-+
-+/* Configuration space read/write support */
-+static inline int brcm_pcie_cfg_index(int busnr, int devfn, int reg)
-+{
-+ return ((PCI_SLOT(devfn) & 0x1f) << PCIE_EXT_SLOT_SHIFT)
-+ | ((PCI_FUNC(devfn) & 0x07) << PCIE_EXT_FUNC_SHIFT)
-+ | (busnr << PCIE_EXT_BUSNUM_SHIFT)
-+ | (reg & ~3);
-+}
-+
-+static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned int devfn,
-+ int where)
-+{
-+ struct brcm_pcie *pcie = bus->sysdata;
-+ void __iomem *base = pcie->base;
-+ int idx;
-+
-+ /* Accesses to the RC go right to the RC registers if slot==0 */
-+ if (pci_is_root_bus(bus))
-+ return PCI_SLOT(devfn) ? NULL : base + where;
-+
-+ /* For devices, write to the config space index register */
-+ idx = brcm_pcie_cfg_index(bus->number, devfn, 0);
-+ writel(idx, pcie->base + PCIE_EXT_CFG_INDEX);
-+ return base + PCIE_EXT_CFG_DATA + where;
-+}
-+
-+static struct pci_ops brcm_pcie_ops = {
-+ .map_bus = brcm_pcie_map_conf,
-+ .read = pci_generic_config_read,
-+ .write = pci_generic_config_write,
-+};
-+
-+static inline void brcm_pcie_bridge_sw_init_set(struct brcm_pcie *pcie, u32 val)
-+{
-+ u32 tmp;
-+
-+ tmp = readl(pcie->base + PCIE_RGR1_SW_INIT_1);
-+ u32p_replace_bits(&tmp, val, PCIE_RGR1_SW_INIT_1_INIT_MASK);
-+ writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1);
-+}
-+
-+static inline void brcm_pcie_perst_set(struct brcm_pcie *pcie, u32 val)
-+{
-+ u32 tmp;
-+
-+ tmp = readl(pcie->base + PCIE_RGR1_SW_INIT_1);
-+ u32p_replace_bits(&tmp, val, PCIE_RGR1_SW_INIT_1_PERST_MASK);
-+ writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1);
-+}
-+
-+static inline int brcm_pcie_get_rc_bar2_size_and_offset(struct brcm_pcie *pcie,
-+ u64 *rc_bar2_size,
-+ u64 *rc_bar2_offset)
-+{
-+ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
-+ struct device *dev = pcie->dev;
-+ struct resource_entry *entry;
-+
-+ entry = resource_list_first_type(&bridge->dma_ranges, IORESOURCE_MEM);
-+ if (!entry)
-+ return -ENODEV;
-+
-+ *rc_bar2_offset = -entry->offset;
-+ *rc_bar2_size = 1ULL << fls64(entry->res->end - entry->res->start);
-+
-+ /*
-+ * We validate the inbound memory view even though we should trust
-+ * whatever the device-tree provides. This is because of an HW issue on
-+ * early Raspberry Pi 4's revisions (bcm2711). It turns out its
-+ * firmware has to dynamically edit dma-ranges due to a bug on the
-+ * PCIe controller integration, which prohibits any access above the
-+ * lower 3GB of memory. Given this, we decided to keep the dma-ranges
-+ * in check, avoiding hard to debug device-tree related issues in the
-+ * future:
-+ *
-+ * 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 two. To further complicate
-+ * matters, the viewport must start on a pcie-address that is aligned
-+ * on a multiple of its size. If a portion of the viewport does not
-+ * represent system memory -- e.g. 3GB of memory requires a 4GB
-+ * viewport -- we can map the outbound memory in or after 3GB and even
-+ * though the viewport will overlap the outbound memory the controller
-+ * will know to send outbound memory downstream and everything else
-+ * upstream.
-+ *
-+ * For example:
-+ *
-+ * - The best-case scenario, memory up to 3GB, 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.
-+ *
-+ * - If the system memory is 4GB or larger we cannot start the inbound
-+ * region at location 0 (since we have to allow some space for
-+ * outbound memory @ 3GB). So instead it will start at the 1x
-+ * multiple of its size
-+ */
-+ if (!*rc_bar2_size || *rc_bar2_offset % *rc_bar2_size ||
-+ (*rc_bar2_offset < SZ_4G && *rc_bar2_offset > SZ_2G)) {
-+ dev_err(dev, "Invalid rc_bar2_offset/size: size 0x%llx, off 0x%llx\n",
-+ *rc_bar2_size, *rc_bar2_offset);
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static int brcm_pcie_setup(struct brcm_pcie *pcie)
-+{
-+ struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
-+ u64 rc_bar2_offset, rc_bar2_size;
-+ void __iomem *base = pcie->base;
-+ struct device *dev = pcie->dev;
-+ struct resource_entry *entry;
-+ unsigned int scb_size_val;
-+ bool ssc_good = false;
-+ struct resource *res;
-+ int num_out_wins = 0;
-+ u16 nlw, cls, lnksta;
-+ int i, ret;
-+ u32 tmp;
-+
-+ /* Reset the bridge */
-+ brcm_pcie_bridge_sw_init_set(pcie, 1);
-+
-+ usleep_range(100, 200);
-+
-+ /* Take the bridge out of reset */
-+ brcm_pcie_bridge_sw_init_set(pcie, 0);
-+
-+ tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
-+ tmp &= ~PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK;
-+ writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
-+ /* Wait for SerDes to be stable */
-+ usleep_range(100, 200);
-+
-+ /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */
-+ u32p_replace_bits(&tmp, 1, PCIE_MISC_MISC_CTRL_SCB_ACCESS_EN_MASK);
-+ u32p_replace_bits(&tmp, 1, PCIE_MISC_MISC_CTRL_CFG_READ_UR_MODE_MASK);
-+ u32p_replace_bits(&tmp, PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_128,
-+ PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK);
-+ writel(tmp, base + PCIE_MISC_MISC_CTRL);
-+
-+ ret = brcm_pcie_get_rc_bar2_size_and_offset(pcie, &rc_bar2_size,
-+ &rc_bar2_offset);
-+ if (ret)
-+ return ret;
-+
-+ tmp = lower_32_bits(rc_bar2_offset);
-+ u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(rc_bar2_size),
-+ PCIE_MISC_RC_BAR2_CONFIG_LO_SIZE_MASK);
-+ writel(tmp, base + PCIE_MISC_RC_BAR2_CONFIG_LO);
-+ writel(upper_32_bits(rc_bar2_offset),
-+ base + PCIE_MISC_RC_BAR2_CONFIG_HI);
-+
-+ scb_size_val = rc_bar2_size ?
-+ ilog2(rc_bar2_size) - 15 : 0xf; /* 0xf is 1GB */
-+ tmp = readl(base + PCIE_MISC_MISC_CTRL);
-+ u32p_replace_bits(&tmp, scb_size_val,
-+ PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK);
-+ writel(tmp, base + PCIE_MISC_MISC_CTRL);
-+
-+ /* disable the PCIe->GISB memory window (RC_BAR1) */
-+ tmp = readl(base + PCIE_MISC_RC_BAR1_CONFIG_LO);
-+ tmp &= ~PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK;
-+ writel(tmp, base + PCIE_MISC_RC_BAR1_CONFIG_LO);
-+
-+ /* disable the PCIe->SCB memory window (RC_BAR3) */
-+ tmp = readl(base + PCIE_MISC_RC_BAR3_CONFIG_LO);
-+ tmp &= ~PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK;
-+ writel(tmp, base + PCIE_MISC_RC_BAR3_CONFIG_LO);
-+
-+ /* Mask all interrupts since we are not handling any yet */
-+ writel(0xffffffff, pcie->base + PCIE_MSI_INTR2_MASK_SET);
-+
-+ /* clear any interrupts we find on boot */
-+ writel(0xffffffff, pcie->base + PCIE_MSI_INTR2_CLR);
-+
-+ if (pcie->gen)
-+ brcm_pcie_set_gen(pcie, pcie->gen);
-+
-+ /* Unassert the fundamental reset */
-+ brcm_pcie_perst_set(pcie, 0);
-+
-+ /*
-+ * Give the RC/EP time to wake up, before trying to configure RC.
-+ * Intermittently check status for link-up, up to a total of 100ms.
-+ */
-+ for (i = 0; i < 100 && !brcm_pcie_link_up(pcie); i += 5)
-+ msleep(5);
-+
-+ if (!brcm_pcie_link_up(pcie)) {
-+ dev_err(dev, "link down\n");
-+ return -ENODEV;
-+ }
-+
-+ if (!brcm_pcie_rc_mode(pcie)) {
-+ dev_err(dev, "PCIe misconfigured; is in EP mode\n");
-+ return -EINVAL;
-+ }
-+
-+ resource_list_for_each_entry(entry, &bridge->windows) {
-+ res = entry->res;
-+
-+ if (resource_type(res) != IORESOURCE_MEM)
-+ continue;
-+
-+ if (num_out_wins >= BRCM_NUM_PCIE_OUT_WINS) {
-+ dev_err(pcie->dev, "too many outbound wins\n");
-+ return -EINVAL;
-+ }
-+
-+ brcm_pcie_set_outbound_win(pcie, num_out_wins, res->start,
-+ res->start - entry->offset,
-+ res->end - res->start + 1);
-+ num_out_wins++;
-+ }
-+
-+ /*
-+ * For config space accesses on the RC, show the right class for
-+ * a PCIe-PCIe bridge (the default setting is to be EP mode).
-+ */
-+ tmp = readl(base + PCIE_RC_CFG_PRIV1_ID_VAL3);
-+ u32p_replace_bits(&tmp, 0x060400,
-+ PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK);
-+ writel(tmp, base + PCIE_RC_CFG_PRIV1_ID_VAL3);
-+
-+ if (pcie->ssc) {
-+ ret = brcm_pcie_set_ssc(pcie);
-+ if (ret == 0)
-+ ssc_good = true;
-+ else
-+ dev_err(dev, "failed attempt to enter ssc mode\n");
-+ }
-+
-+ lnksta = readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKSTA);
-+ cls = FIELD_GET(PCI_EXP_LNKSTA_CLS, lnksta);
-+ nlw = FIELD_GET(PCI_EXP_LNKSTA_NLW, lnksta);
-+ dev_info(dev, "link up, %s x%u %s\n",
-+ PCIE_SPEED2STR(cls + PCI_SPEED_133MHz_PCIX_533),
-+ nlw, ssc_good ? "(SSC)" : "(!SSC)");
-+
-+ /* PCIe->SCB endian mode for BAR */
-+ tmp = readl(base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1);
-+ u32p_replace_bits(&tmp, PCIE_RC_CFG_VENDOR_SPCIFIC_REG1_LITTLE_ENDIAN,
-+ PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK);
-+ writel(tmp, base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1);
-+
-+ /*
-+ * Refclk from RC should be gated with CLKREQ# input when ASPM L0s,L1
-+ * is enabled => setting the CLKREQ_DEBUG_ENABLE field to 1.
-+ */
-+ tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
-+ tmp |= PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK;
-+ writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
-+
-+ return 0;
-+}
-+
-+/* L23 is a low-power PCIe link state */
-+static void brcm_pcie_enter_l23(struct brcm_pcie *pcie)
-+{
-+ void __iomem *base = pcie->base;
-+ int l23, i;
-+ u32 tmp;
-+
-+ /* Assert request for L23 */
-+ tmp = readl(base + PCIE_MISC_PCIE_CTRL);
-+ u32p_replace_bits(&tmp, 1, PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK);
-+ writel(tmp, base + PCIE_MISC_PCIE_CTRL);
-+
-+ /* Wait up to 36 msec for L23 */
-+ tmp = readl(base + PCIE_MISC_PCIE_STATUS);
-+ l23 = FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK, tmp);
-+ for (i = 0; i < 15 && !l23; i++) {
-+ usleep_range(2000, 2400);
-+ tmp = readl(base + PCIE_MISC_PCIE_STATUS);
-+ l23 = FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_LINK_IN_L23_MASK,
-+ tmp);
-+ }
-+
-+ if (!l23)
-+ dev_err(pcie->dev, "failed to enter low-power link state\n");
-+}
-+
-+static void brcm_pcie_turn_off(struct brcm_pcie *pcie)
-+{
-+ void __iomem *base = pcie->base;
-+ int tmp;
-+
-+ if (brcm_pcie_link_up(pcie))
-+ brcm_pcie_enter_l23(pcie);
-+ /* Assert fundamental reset */
-+ brcm_pcie_perst_set(pcie, 1);
-+
-+ /* Deassert request for L23 in case it was asserted */
-+ tmp = readl(base + PCIE_MISC_PCIE_CTRL);
-+ u32p_replace_bits(&tmp, 0, PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK);
-+ writel(tmp, base + PCIE_MISC_PCIE_CTRL);
-+
-+ /* Turn off SerDes */
-+ tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
-+ u32p_replace_bits(&tmp, 1, PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK);
-+ writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
-+
-+ /* Shutdown PCIe bridge */
-+ brcm_pcie_bridge_sw_init_set(pcie, 1);
-+}
-+
-+static void __brcm_pcie_remove(struct brcm_pcie *pcie)
-+{
-+ brcm_pcie_turn_off(pcie);
-+ clk_disable_unprepare(pcie->clk);
-+ clk_put(pcie->clk);
-+}
-+
-+static int brcm_pcie_remove(struct platform_device *pdev)
-+{
-+ struct brcm_pcie *pcie = platform_get_drvdata(pdev);
-+
-+ pci_stop_root_bus(pcie->root_bus);
-+ pci_remove_root_bus(pcie->root_bus);
-+ __brcm_pcie_remove(pcie);
-+
-+ return 0;
-+}
-+
-+static int brcm_pcie_probe(struct platform_device *pdev)
-+{
-+ struct device_node *np = pdev->dev.of_node;
-+ struct pci_host_bridge *bridge;
-+ struct brcm_pcie *pcie;
-+ struct pci_bus *child;
-+ struct resource *res;
-+ int ret;
-+
-+ bridge = devm_pci_alloc_host_bridge(&pdev->dev, sizeof(*pcie));
-+ if (!bridge)
-+ return -ENOMEM;
-+
-+ pcie = pci_host_bridge_priv(bridge);
-+ pcie->dev = &pdev->dev;
-+ pcie->np = np;
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ pcie->base = devm_ioremap_resource(&pdev->dev, res);
-+ if (IS_ERR(pcie->base))
-+ return PTR_ERR(pcie->base);
-+
-+ pcie->clk = devm_clk_get_optional(&pdev->dev, "sw_pcie");
-+ if (IS_ERR(pcie->clk))
-+ return PTR_ERR(pcie->clk);
-+
-+ ret = of_pci_get_max_link_speed(np);
-+ pcie->gen = (ret < 0) ? 0 : ret;
-+
-+ pcie->ssc = of_property_read_bool(np, "brcm,enable-ssc");
-+
-+ ret = pci_parse_request_of_pci_ranges(pcie->dev, &bridge->windows,
-+ &bridge->dma_ranges, NULL);
-+ if (ret)
-+ return ret;
-+
-+ ret = clk_prepare_enable(pcie->clk);
-+ if (ret) {
-+ dev_err(&pdev->dev, "could not enable clock\n");
-+ return ret;
-+ }
-+
-+ ret = brcm_pcie_setup(pcie);
-+ if (ret)
-+ goto fail;
-+
-+ bridge->dev.parent = &pdev->dev;
-+ bridge->busnr = 0;
-+ bridge->ops = &brcm_pcie_ops;
-+ bridge->sysdata = pcie;
-+ bridge->map_irq = of_irq_parse_and_map_pci;
-+ bridge->swizzle_irq = pci_common_swizzle;
-+
-+ ret = pci_scan_root_bus_bridge(bridge);
-+ if (ret < 0) {
-+ dev_err(pcie->dev, "Scanning root bridge failed\n");
-+ goto fail;
-+ }
-+
-+ pci_assign_unassigned_bus_resources(bridge->bus);
-+ list_for_each_entry(child, &bridge->bus->children, node)
-+ pcie_bus_configure_settings(child);
-+ pci_bus_add_devices(bridge->bus);
-+ platform_set_drvdata(pdev, pcie);
-+ pcie->root_bus = bridge->bus;
-+
-+ return 0;
-+fail:
-+ __brcm_pcie_remove(pcie);
-+ return ret;
-+}
-+
-+static const struct of_device_id brcm_pcie_match[] = {
-+ { .compatible = "brcm,bcm2711-pcie" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, brcm_pcie_match);
-+
-+static struct platform_driver brcm_pcie_driver = {
-+ .probe = brcm_pcie_probe,
-+ .remove = brcm_pcie_remove,
-+ .driver = {
-+ .name = "brcm-pcie",
-+ .of_match_table = brcm_pcie_match,
-+ },
-+};
-+module_platform_driver(brcm_pcie_driver);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Broadcom STB PCIe RC driver");
-+MODULE_AUTHOR("Broadcom");
-
-From patchwork Mon Dec 16 11:01:10 2019
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-X-Patchwork-Id: 11293819
-Return-Path:
- <SRS0=BOSQ=2G=lists.infradead.org=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@kernel.org>
-Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org
- [172.30.200.123])
- by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0FB1A930
- for <patchwork-linux-arm@patchwork.kernel.org>;
- Mon, 16 Dec 2019 11:02:26 +0000 (UTC)
-Received: from bombadil.infradead.org (bombadil.infradead.org
- [198.137.202.133])
- (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
- (No client certificate requested)
- by mail.kernel.org (Postfix) with ESMTPS id DA5D2206EC
- for <patchwork-linux-arm@patchwork.kernel.org>;
- Mon, 16 Dec 2019 11:02:25 +0000 (UTC)
-Authentication-Results: mail.kernel.org;
- dkim=pass (2048-bit key) header.d=lists.infradead.org
- header.i=@lists.infradead.org header.b="L57a4G/z"
-DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org DA5D2206EC
-Authentication-Results: mail.kernel.org;
- dmarc=none (p=none dis=none) header.from=suse.de
-Authentication-Results: mail.kernel.org;
- spf=none
- smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org
-DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
- d=lists.infradead.org; s=bombadil.20170209; h=Sender:
- Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post:
- List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:
- Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description:
- Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:
- List-Owner; bh=iItojdIKeV2oJC/4nHltnSdo0OFytKQEQSG83gc3mIo=; b=L57a4G/zV1L3EX
- zFjTyLpmW4uweymZSoPuNKRbbLfHfV8GJzdk0+AIcGY8T/0LDSubyqm52QwbEIKIZF6q1tYQMV01x
- dCx/B3rV8B0EcUM/RedeUUqXgMXKYn7pdmzUYR2jRB1NEOucFv6xZA1Ap8ZF1k7A2oACSkf/SBoXA
- PKbjs2hB/33AoX7kK98vVxVctzuUBE2CkGB419pPh1eXx3QyybSGYoBsNLsQ1BFfL3YwCV2unHoCx
- h4QSzJ7vBkuNHDVCdq/t6NRFs98dk6ooDHlISOhJW6F3bdR36Vx1/+5tC1MBjm/Wy1oZmLGR+MeSo
- 0J11yccg2BRitcgEv2gw==;
-Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org)
- by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux))
- id 1igo8u-00043K-US; Mon, 16 Dec 2019 11:02:24 +0000
-Received: from mx2.suse.de ([195.135.220.15] helo=mx1.suse.de)
- by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux))
- id 1igo83-00037J-Ob; Mon, 16 Dec 2019 11:01:35 +0000
-X-Virus-Scanned: by amavisd-new at test-mx.suse.de
-Received: from relay2.suse.de (unknown [195.135.220.254])
- by mx1.suse.de (Postfix) with ESMTP id 502A3AC7D;
- Mon, 16 Dec 2019 11:01:30 +0000 (UTC)
-From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-To: andrew.murray@arm.com, maz@kernel.org, linux-kernel@vger.kernel.org,
- Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>,
- Florian Fainelli <f.fainelli@gmail.com>,
- bcm-kernel-feedback-list@broadcom.com,
- Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Subject: [PATCH v5 4/6] PCI: brcmstb: Add MSI support
-Date: Mon, 16 Dec 2019 12:01:10 +0100
-Message-Id: <20191216110113.30436-5-nsaenzjulienne@suse.de>
-X-Mailer: git-send-email 2.24.0
-In-Reply-To: <20191216110113.30436-1-nsaenzjulienne@suse.de>
-References: <20191216110113.30436-1-nsaenzjulienne@suse.de>
-MIME-Version: 1.0
-X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3
-X-CRM114-CacheID: sfid-20191216_030132_128008_DE7B462C
-X-CRM114-Status: GOOD ( 23.12 )
-X-Spam-Score: -2.3 (--)
-X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary:
- Content analysis details: (-2.3 points)
- pts rule name description
- ---- ----------------------
- --------------------------------------------------
- 0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3)
- [195.135.220.15 listed in wl.mailspike.net]
- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/,
- medium trust [195.135.220.15 listed in list.dnswl.org]
- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record
- -0.0 SPF_PASS SPF: sender matches SPF record
- 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders
-X-BeenThere: linux-arm-kernel@lists.infradead.org
-X-Mailman-Version: 2.1.29
-Precedence: list
-List-Id: <linux-arm-kernel.lists.infradead.org>
-List-Unsubscribe:
- <http://lists.infradead.org/mailman/options/linux-arm-kernel>,
- <mailto:linux-arm-kernel-request@lists.infradead.org?subject=unsubscribe>
-List-Archive: <http://lists.infradead.org/pipermail/linux-arm-kernel/>
-List-Post: <mailto:linux-arm-kernel@lists.infradead.org>
-List-Help: <mailto:linux-arm-kernel-request@lists.infradead.org?subject=help>
-List-Subscribe:
- <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>,
- <mailto:linux-arm-kernel-request@lists.infradead.org?subject=subscribe>
-Cc: mbrugger@suse.com, linux-pci@vger.kernel.org, phil@raspberrypi.org,
- jeremy.linton@arm.com, wahrenst@gmx.net, james.quinlan@broadcom.com,
- Bjorn Helgaas <bhelgaas@google.com>, linux-arm-kernel@lists.infradead.org,
- linux-rpi-kernel@lists.infradead.org
-Sender: "linux-arm-kernel" <linux-arm-kernel-bounces@lists.infradead.org>
-Errors-To:
- linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org
-
-From: Jim Quinlan <james.quinlan@broadcom.com>
-
-This adds MSI support to the Broadcom STB PCIe host controller. The MSI
-controller is physically located within the PCIe block, however, there
-is no reason why the MSI controller could not be moved elsewhere in the
-future. MSIX is not supported by the HW.
-
-Since the internal Brcmstb MSI controller is intertwined with the PCIe
-controller, it is not its own platform device but rather part of the
-PCIe platform device.
-
-Signed-off-by: Jim Quinlan <james.quinlan@broadcom.com>
-Co-developed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
-Reviewed-by: Marc Zyngier <maz@kernel.org>
-Reviewed-by: Andrew Murray <andrew.murray@arm.com>
----
-
-Changes since v3 (kept Marc's reviewed by as changes seem small enough):
- - Use define to access MSI_DATA_CONFIG_VAL
- - Update commit message
-
-Changes since v2:
- - Use standard APIs on register operations
- - Get rid of revision code
- - Update rules to msi_target_addr selection
- - Remove unwarranted MSI_FLAG_PCI_MSIX
- - Small cosmetic changes
-
-Changes since v1:
- - Move revision code and some registers to this patch
- - Use PCIE_MSI_IRQ_DOMAIN in Kconfig
- - Remove redundant register read from ISR
- - Fail probe on MSI init error
- - Get rid of msi_internal
- - Use bitmap family of functions
- - Use edge triggered setup
- - Add comment regarding MultiMSI
- - Simplify compose_msi_msg to avoid reg read
-
-This is based on Jim's original submission[1] with some slight changes
-regarding how pcie->msi_target_addr is decided.
-
-[1] https://patchwork.kernel.org/patch/10605955/
-
- drivers/pci/controller/Kconfig | 1 +
- drivers/pci/controller/pcie-brcmstb.c | 261 +++++++++++++++++++++++++-
- 2 files changed, 261 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
-index 27504f108ee5..918e283bbff1 100644
---- a/drivers/pci/controller/Kconfig
-+++ b/drivers/pci/controller/Kconfig
-@@ -257,6 +257,7 @@ config PCIE_BRCMSTB
- tristate "Broadcom Brcmstb PCIe host controller"
- depends on ARCH_BCM2835 || COMPILE_TEST
- depends on OF
-+ depends on PCI_MSI_IRQ_DOMAIN
- help
- Say Y here to enable PCIe host controller support for
- Broadcom STB based SoCs, like the Raspberry Pi 4.
-diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
-index dd681164faa0..7ba06a0e1a71 100644
---- a/drivers/pci/controller/pcie-brcmstb.c
-+++ b/drivers/pci/controller/pcie-brcmstb.c
-@@ -2,6 +2,7 @@
- /* Copyright (C) 2009 - 2019 Broadcom */
-
- #include <linux/bitfield.h>
-+#include <linux/bitops.h>
- #include <linux/clk.h>
- #include <linux/compiler.h>
- #include <linux/delay.h>
-@@ -9,11 +10,13 @@
- #include <linux/interrupt.h>
- #include <linux/io.h>
- #include <linux/ioport.h>
-+#include <linux/irqchip/chained_irq.h>
- #include <linux/irqdomain.h>
- #include <linux/kernel.h>
- #include <linux/list.h>
- #include <linux/log2.h>
- #include <linux/module.h>
-+#include <linux/msi.h>
- #include <linux/of_address.h>
- #include <linux/of_irq.h>
- #include <linux/of_pci.h>
-@@ -67,6 +70,12 @@
- #define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c
- #define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f
-
-+#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_MSI_DATA_CONFIG_VAL 0xffe06540
-+
- #define PCIE_MISC_PCIE_CTRL 0x4064
- #define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK 0x1
-
-@@ -114,6 +123,11 @@
-
- /* PCIe parameters */
- #define BRCM_NUM_PCIE_OUT_WINS 0x4
-+#define BRCM_INT_PCI_MSI_NR 32
-+
-+/* MSI target adresses */
-+#define BRCM_MSI_TARGET_ADDR_LT_4GB 0x0fffffffcULL
-+#define BRCM_MSI_TARGET_ADDR_GT_4GB 0xffffffffcULL
-
- /* MDIO registers */
- #define MDIO_PORT0 0x0
-@@ -135,6 +149,19 @@
- #define SSC_STATUS_SSC_MASK 0x400
- #define SSC_STATUS_PLL_LOCK_MASK 0x800
-
-+struct brcm_msi {
-+ struct device *dev;
-+ void __iomem *base;
-+ struct device_node *np;
-+ struct irq_domain *msi_domain;
-+ struct irq_domain *inner_domain;
-+ struct mutex lock; /* guards the alloc/free operations */
-+ u64 target_addr;
-+ int irq;
-+ /* used indicates which MSI interrupts have been alloc'd */
-+ unsigned long used;
-+};
-+
- /* Internal PCIe Host Controller Information.*/
- struct brcm_pcie {
- struct device *dev;
-@@ -144,6 +171,8 @@ struct brcm_pcie {
- struct device_node *np;
- bool ssc;
- int gen;
-+ u64 msi_target_addr;
-+ struct brcm_msi *msi;
- };
-
- /*
-@@ -309,6 +338,214 @@ static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie,
- writel(tmp, pcie->base + PCIE_MEM_WIN0_LIMIT_HI(win));
- }
-
-+static struct irq_chip brcm_msi_irq_chip = {
-+ .name = "BRCM STB PCIe MSI",
-+ .irq_ack = irq_chip_ack_parent,
-+ .irq_mask = pci_msi_mask_irq,
-+ .irq_unmask = pci_msi_unmask_irq,
-+};
-+
-+static struct msi_domain_info brcm_msi_domain_info = {
-+ /* Multi MSI is supported by the controller, but not by this driver */
-+ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
-+ .chip = &brcm_msi_irq_chip,
-+};
-+
-+static void brcm_pcie_msi_isr(struct irq_desc *desc)
-+{
-+ struct irq_chip *chip = irq_desc_get_chip(desc);
-+ unsigned long status, virq;
-+ struct brcm_msi *msi;
-+ struct device *dev;
-+ u32 bit;
-+
-+ chained_irq_enter(chip, desc);
-+ msi = irq_desc_get_handler_data(desc);
-+ dev = msi->dev;
-+
-+ status = readl(msi->base + PCIE_MSI_INTR2_STATUS);
-+ for_each_set_bit(bit, &status, BRCM_INT_PCI_MSI_NR) {
-+ virq = irq_find_mapping(msi->inner_domain, bit);
-+ if (virq)
-+ generic_handle_irq(virq);
-+ else
-+ dev_dbg(dev, "unexpected MSI\n");
-+ }
-+
-+ chained_irq_exit(chip, desc);
-+}
-+
-+static void brcm_msi_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
-+{
-+ struct brcm_msi *msi = irq_data_get_irq_chip_data(data);
-+
-+ msg->address_lo = lower_32_bits(msi->target_addr);
-+ msg->address_hi = upper_32_bits(msi->target_addr);
-+ msg->data = (0xffff & PCIE_MISC_MSI_DATA_CONFIG_VAL) | data->hwirq;
-+}
-+
-+static int brcm_msi_set_affinity(struct irq_data *irq_data,
-+ const struct cpumask *mask, bool force)
-+{
-+ return -EINVAL;
-+}
-+
-+static void brcm_msi_ack_irq(struct irq_data *data)
-+{
-+ struct brcm_msi *msi = irq_data_get_irq_chip_data(data);
-+
-+ writel(1 << data->hwirq, msi->base + PCIE_MSI_INTR2_CLR);
-+}
-+
-+
-+static struct irq_chip brcm_msi_bottom_irq_chip = {
-+ .name = "BRCM STB MSI",
-+ .irq_compose_msi_msg = brcm_msi_compose_msi_msg,
-+ .irq_set_affinity = brcm_msi_set_affinity,
-+ .irq_ack = brcm_msi_ack_irq,
-+};
-+
-+static int brcm_msi_alloc(struct brcm_msi *msi)
-+{
-+ int hwirq;
-+
-+ mutex_lock(&msi->lock);
-+ hwirq = bitmap_find_free_region(&msi->used, BRCM_INT_PCI_MSI_NR, 0);
-+ mutex_unlock(&msi->lock);
-+
-+ return hwirq;
-+}
-+
-+static void brcm_msi_free(struct brcm_msi *msi, unsigned long hwirq)
-+{
-+ mutex_lock(&msi->lock);
-+ bitmap_release_region(&msi->used, hwirq, 0);
-+ mutex_unlock(&msi->lock);
-+}
-+
-+static int brcm_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
-+ unsigned int nr_irqs, void *args)
-+{
-+ struct brcm_msi *msi = domain->host_data;
-+ int hwirq;
-+
-+ hwirq = brcm_msi_alloc(msi);
-+
-+ if (hwirq < 0)
-+ return hwirq;
-+
-+ irq_domain_set_info(domain, virq, (irq_hw_number_t)hwirq,
-+ &brcm_msi_bottom_irq_chip, domain->host_data,
-+ handle_edge_irq, NULL, NULL);
-+ return 0;
-+}
-+
-+static void brcm_irq_domain_free(struct irq_domain *domain,
-+ unsigned int virq, unsigned int nr_irqs)
-+{
-+ struct irq_data *d = irq_domain_get_irq_data(domain, virq);
-+ struct brcm_msi *msi = irq_data_get_irq_chip_data(d);
-+
-+ brcm_msi_free(msi, d->hwirq);
-+}
-+
-+static const struct irq_domain_ops msi_domain_ops = {
-+ .alloc = brcm_irq_domain_alloc,
-+ .free = brcm_irq_domain_free,
-+};
-+
-+static int brcm_allocate_domains(struct brcm_msi *msi)
-+{
-+ struct fwnode_handle *fwnode = of_node_to_fwnode(msi->np);
-+ struct device *dev = msi->dev;
-+
-+ msi->inner_domain = irq_domain_add_linear(NULL, BRCM_INT_PCI_MSI_NR,
-+ &msi_domain_ops, msi);
-+ if (!msi->inner_domain) {
-+ dev_err(dev, "failed to create IRQ domain\n");
-+ return -ENOMEM;
-+ }
-+
-+ msi->msi_domain = pci_msi_create_irq_domain(fwnode,
-+ &brcm_msi_domain_info,
-+ msi->inner_domain);
-+ if (!msi->msi_domain) {
-+ dev_err(dev, "failed to create MSI domain\n");
-+ irq_domain_remove(msi->inner_domain);
-+ return -ENOMEM;
-+ }
-+
-+ return 0;
-+}
-+
-+static void brcm_free_domains(struct brcm_msi *msi)
-+{
-+ irq_domain_remove(msi->msi_domain);
-+ irq_domain_remove(msi->inner_domain);
-+}
-+
-+static void brcm_msi_remove(struct brcm_pcie *pcie)
-+{
-+ struct brcm_msi *msi = pcie->msi;
-+
-+ if (!msi)
-+ return;
-+ irq_set_chained_handler(msi->irq, NULL);
-+ irq_set_handler_data(msi->irq, NULL);
-+ brcm_free_domains(msi);
-+}
-+
-+static void brcm_msi_set_regs(struct brcm_msi *msi)
-+{
-+ writel(0xffffffff, msi->base + PCIE_MSI_INTR2_MASK_CLR);
-+
-+ /*
-+ * The 0 bit of PCIE_MISC_MSI_BAR_CONFIG_LO is repurposed to MSI
-+ * enable, which we set to 1.
-+ */
-+ writel(lower_32_bits(msi->target_addr) | 0x1,
-+ msi->base + PCIE_MISC_MSI_BAR_CONFIG_LO);
-+ writel(upper_32_bits(msi->target_addr),
-+ msi->base + PCIE_MISC_MSI_BAR_CONFIG_HI);
-+
-+ writel(PCIE_MISC_MSI_DATA_CONFIG_VAL,
-+ msi->base + PCIE_MISC_MSI_DATA_CONFIG);
-+}
-+
-+static int brcm_pcie_enable_msi(struct brcm_pcie *pcie)
-+{
-+ struct brcm_msi *msi;
-+ int irq, ret;
-+ struct device *dev = pcie->dev;
-+
-+ irq = irq_of_parse_and_map(dev->of_node, 1);
-+ if (irq <= 0) {
-+ dev_err(dev, "cannot map MSI interrupt\n");
-+ return -ENODEV;
-+ }
-+
-+ msi = devm_kzalloc(dev, sizeof(struct brcm_msi), GFP_KERNEL);
-+ if (!msi)
-+ return -ENOMEM;
-+
-+ msi->dev = dev;
-+ msi->base = pcie->base;
-+ msi->np = pcie->np;
-+ msi->target_addr = pcie->msi_target_addr;
-+ msi->irq = irq;
-+
-+ ret = brcm_allocate_domains(msi);
-+ if (ret)
-+ return ret;
-+
-+ irq_set_chained_handler_and_data(msi->irq, brcm_pcie_msi_isr, msi);
-+
-+ brcm_msi_set_regs(msi);
-+ pcie->msi = msi;
-+
-+ return 0;
-+}
-+
- /* The controller is capable of serving in both RC and EP roles */
- static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie)
- {
-@@ -490,6 +727,18 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie)
- PCIE_MISC_MISC_CTRL_SCB0_SIZE_MASK);
- writel(tmp, base + PCIE_MISC_MISC_CTRL);
-
-+ /*
-+ * We ideally want the MSI target address to be located in the 32bit
-+ * addressable memory area. Some devices might depend on it. This is
-+ * possible either when the inbound window is located above the lower
-+ * 4GB or when the inbound area is smaller than 4GB (taking into
-+ * account the rounding-up we're forced to perform).
-+ */
-+ if (rc_bar2_offset >= SZ_4G || (rc_bar2_size + rc_bar2_offset) < SZ_4G)
-+ pcie->msi_target_addr = BRCM_MSI_TARGET_ADDR_LT_4GB;
-+ else
-+ pcie->msi_target_addr = BRCM_MSI_TARGET_ADDR_GT_4GB;
-+
- /* disable the PCIe->GISB memory window (RC_BAR1) */
- tmp = readl(base + PCIE_MISC_RC_BAR1_CONFIG_LO);
- tmp &= ~PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK;
-@@ -639,6 +888,7 @@ static void brcm_pcie_turn_off(struct brcm_pcie *pcie)
-
- static void __brcm_pcie_remove(struct brcm_pcie *pcie)
- {
-+ brcm_msi_remove(pcie);
- brcm_pcie_turn_off(pcie);
- clk_disable_unprepare(pcie->clk);
- clk_put(pcie->clk);
-@@ -657,7 +907,7 @@ static int brcm_pcie_remove(struct platform_device *pdev)
-
- static int brcm_pcie_probe(struct platform_device *pdev)
- {
-- struct device_node *np = pdev->dev.of_node;
-+ struct device_node *np = pdev->dev.of_node, *msi_np;
- struct pci_host_bridge *bridge;
- struct brcm_pcie *pcie;
- struct pci_bus *child;
-@@ -701,6 +951,15 @@ static int brcm_pcie_probe(struct platform_device *pdev)
- if (ret)
- goto fail;
-
-+ msi_np = of_parse_phandle(pcie->np, "msi-parent", 0);
-+ if (pci_msi_enabled() && msi_np == pcie->np) {
-+ ret = brcm_pcie_enable_msi(pcie);
-+ if (ret) {
-+ dev_err(pcie->dev, "probe of internal MSI failed");
-+ goto fail;
-+ }
-+ }
-+
- bridge->dev.parent = &pdev->dev;
- bridge->busnr = 0;
- bridge->ops = &brcm_pcie_ops;
-
From patchwork Mon Dec 16 11:01:12 2019
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0