diff --git a/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2712-msix.yaml b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2712-msix.yaml new file mode 100644 index 00000000000000..c84614663b5d50 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2712-msix.yaml @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/brcm,bcm2712-msix.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom bcm2712 MSI-X Interrupt Peripheral support + +maintainers: + - Stanimir Varbanov + +description: + This interrupt controller is used to provide interrupt vectors to the + generic interrupt controller (GIC) on bcm2712. It will be used as + external MSI-X controller for PCIe root complex. + +allOf: + - $ref: /schemas/interrupt-controller/msi-controller.yaml# + +properties: + compatible: + const: brcm,bcm2712-mip + + reg: + items: + - description: Base register address + - description: PCIe message address + + "#msi-cells": + const: 0 + + brcm,msi-offset: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Shift the allocated MSI's. + +unevaluatedProperties: false + +required: + - compatible + - reg + - msi-controller + - msi-ranges + +examples: + - | + #include + + axi { + #address-cells = <2>; + #size-cells = <2>; + + msi-controller@1000130000 { + compatible = "brcm,bcm2712-mip"; + reg = <0x10 0x00130000 0x00 0xc0>, + <0xff 0xfffff000 0x00 0x1000>; + msi-controller; + #msi-cells = <0>; + msi-ranges = <&gicv2 GIC_SPI 128 IRQ_TYPE_EDGE_RISING 64>; + }; + }; diff --git a/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml b/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml index e4907ad30a4ae1..29f0e1eb50961e 100644 --- a/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml +++ b/Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml @@ -14,6 +14,7 @@ properties: items: - enum: - brcm,bcm2711-pcie # The Raspberry Pi 4 + - brcm,bcm2712-pcie # Raspberry Pi 5 - brcm,bcm4908-pcie - brcm,bcm7211-pcie # Broadcom STB version of RPi4 - brcm,bcm7216-pcie # Broadcom 7216 Arm @@ -101,15 +102,10 @@ properties: reset-names: minItems: 1 - maxItems: 3 - - brcm,tperst-clk-ms: - category: optional - type: int - description: u32 giving the number of milliseconds to extend - the time between internal release of fundamental reset and - the deassertion of the external PERST# pin. This has the - effect of increasing the Tperst_clk phase of link init. + items: + - enum: [perst, rescal] + - const: bridge + - const: swinit required: - compatible diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi index 82d97d4af84bfe..579d16b77c452b 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcm2712-ds.dtsi @@ -350,190 +350,6 @@ brcm,dma-channel-mask = <0x0fc0>; }; - // Single-lane Gen3 PCIe - // Outbound window at 0x14_000000-0x17_ffffff - pcie0: pcie@100000 { - compatible = "brcm,bcm2712-pcie"; - reg = <0x10 0x00100000 0x0 0x9310>; - device_type = "pci"; - max-link-speed = <2>; - #address-cells = <3>; - #interrupt-cells = <1>; - #size-cells = <2>; - /* - * Unused interrupts: - * 208: AER - * 215: NMI - * 216: PME - */ - interrupt-parent = <&gicv2>; - interrupts = , - ; - interrupt-names = "pcie", "msi"; - interrupt-map-mask = <0x0 0x0 0x0 0x7>; - interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 209 - IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 2 &gicv2 GIC_SPI 210 - IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 3 &gicv2 GIC_SPI 211 - IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 4 &gicv2 GIC_SPI 212 - IRQ_TYPE_LEVEL_HIGH>; - resets = <&bcm_reset 5>, <&bcm_reset 42>, <&pcie_rescal>; - reset-names = "swinit", "bridge", "rescal"; - msi-controller; - msi-parent = <&pcie0>; - - ranges = <0x02000000 0x00 0x00000000 - 0x17 0x00000000 - 0x0 0xfffffffc>, - <0x43000000 0x04 0x00000000 - 0x14 0x00000000 - 0x3 0x00000000>; - - dma-ranges = <0x43000000 0x10 0x00000000 - 0x00 0x00000000 - 0x10 0x00000000>; - - status = "disabled"; - }; - - // Single-lane Gen3 PCIe - // Outbound window at 0x18_000000-0x1b_ffffff - pcie1: pcie@110000 { - compatible = "brcm,bcm2712-pcie"; - reg = <0x10 0x00110000 0x0 0x9310>; - device_type = "pci"; - max-link-speed = <2>; - #address-cells = <3>; - #interrupt-cells = <1>; - #size-cells = <2>; - /* - * Unused interrupts: - * 218: AER - * 225: NMI - * 226: PME - */ - interrupt-parent = <&gicv2>; - interrupts = , - ; - interrupt-names = "pcie", "msi"; - interrupt-map-mask = <0x0 0x0 0x0 0x7>; - interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 219 - IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 2 &gicv2 GIC_SPI 220 - IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 3 &gicv2 GIC_SPI 221 - IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 4 &gicv2 GIC_SPI 222 - IRQ_TYPE_LEVEL_HIGH>; - resets = <&bcm_reset 7>, <&bcm_reset 43>, <&pcie_rescal>; - reset-names = "swinit", "bridge", "rescal"; - msi-controller; - msi-parent = <&mip1>; - - // 2GB, 32-bit, non-prefetchable at PCIe 00_80000000 - ranges = <0x02000000 0x00 0x80000000 - 0x1b 0x80000000 - 0x00 0x80000000>, - // 14GB, 64-bit, prefetchable at PCIe 04_00000000 - <0x43000000 0x04 0x00000000 - 0x18 0x00000000 - 0x03 0x80000000>; - - dma-ranges = <0x03000000 0x10 0x00000000 - 0x00 0x00000000 - 0x10 0x00000000>; - - status = "disabled"; - }; - - pcie_rescal: reset-controller@119500 { - compatible = "brcm,bcm7216-pcie-sata-rescal"; - reg = <0x10 0x00119500 0x0 0x10>; - #reset-cells = <0>; - }; - - // Quad-lane Gen3 PCIe - // Outbound window at 0x1c_000000-0x1f_ffffff - pcie2: pcie@120000 { - compatible = "brcm,bcm2712-pcie"; - reg = <0x10 0x00120000 0x0 0x9310>; - device_type = "pci"; - max-link-speed = <2>; - #address-cells = <3>; - #interrupt-cells = <1>; - #size-cells = <2>; - /* - * Unused interrupts: - * 228: AER - * 235: NMI - * 236: PME - */ - interrupt-parent = <&gicv2>; - interrupts = , - ; - interrupt-names = "pcie", "msi"; - interrupt-map-mask = <0x0 0x0 0x0 0x7>; - interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 229 - IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 2 &gicv2 GIC_SPI 230 - IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 3 &gicv2 GIC_SPI 231 - IRQ_TYPE_LEVEL_HIGH>, - <0 0 0 4 &gicv2 GIC_SPI 232 - IRQ_TYPE_LEVEL_HIGH>; - resets = <&bcm_reset 32>, <&bcm_reset 44>, <&pcie_rescal>; - reset-names = "swinit", "bridge", "rescal"; - msi-controller; - msi-parent = <&mip0>; - - // ~4GB, 32-bit, not-prefetchable at PCIe 00_00000000 - ranges = <0x02000000 0x00 0x00000000 - 0x1f 0x00000000 - 0x0 0xfffffffc>, - // 12GB, 64-bit, prefetchable at PCIe 04_00000000 - <0x43000000 0x04 0x00000000 - 0x1c 0x00000000 - 0x03 0x00000000>; - - // 64GB system RAM space at PCIe 10_00000000 - dma-ranges = <0x02000000 0x00 0x00000000 - 0x1f 0x00000000 - 0x00 0x00400000>, - <0x43000000 0x10 0x00000000 - 0x00 0x00000000 - 0x10 0x00000000>; - - status = "disabled"; - }; - - mip0: msi-controller@130000 { - compatible = "brcm,bcm2712-mip-intc"; - reg = <0x10 0x00130000 0x0 0xc0>; - msi-controller; - interrupt-controller; - #interrupt-cells = <2>; - brcm,msi-base-spi = <128>; - brcm,msi-num-spis = <64>; - brcm,msi-offset = <0>; - brcm,msi-pci-addr = <0xff 0xfffff000>; - }; - - mip1: msi-controller@131000 { - compatible = "brcm,bcm2712-mip-intc"; - reg = <0x10 0x00131000 0x0 0xc0>; - msi-controller; - interrupt-controller; - #interrupt-cells = <2>; - brcm,msi-base-spi = <247>; - /* Actually 20 total, but the others are - * both sparse and non-consecutive */ - brcm,msi-num-spis = <8>; - brcm,msi-offset = <8>; - brcm,msi-pci-addr = <0xff 0xffffe000>; - }; - syscon_piarbctl: syscon@400018 { compatible = "brcm,syscon-piarbctl", "syscon", "simple-mfd"; reg = <0x10 0x00400018 0x0 0x18>; @@ -591,12 +407,6 @@ status = "disabled"; }; - bcm_reset: reset-controller@1504318 { - compatible = "brcm,brcmstb-reset"; - reg = <0x10 0x01504318 0x0 0x30>; - #reset-cells = <1>; - }; - v3d: v3d@2000000 { compatible = "brcm,2712-v3d"; reg = <0x10 0x02000000 0x0 0x4000>, diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts index d6f9105087d978..4257ab5d45338a 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts +++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts @@ -764,3 +764,11 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 1>, <&clk_27MHz>; clock-names = "hdmi", "bvb", "audio", "cec"; }; + +&pcie1 { + status = "okay"; +}; + +&pcie2 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi index 3debac358f92ba..4448d1f9067c63 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi +++ b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi @@ -192,6 +192,12 @@ #address-cells = <1>; #size-cells = <1>; + pcie_rescal: reset-controller@119500 { + compatible = "brcm,bcm7216-pcie-sata-rescal"; + reg = <0x00119500 0x10>; + #reset-cells = <0>; + }; + sdio1: mmc@fff000 { compatible = "brcm,bcm2712-sdhci", "brcm,sdhci-brcmstb"; @@ -204,6 +210,12 @@ mmc-ddr-3_3v; }; + bcm_reset: reset-controller@1504318 { + compatible = "brcm,brcmstb-reset"; + reg = <0x01504318 0x30>; + #reset-cells = <1>; + }; + system_timer: timer@7c003000 { compatible = "brcm,bcm2835-system-timer"; reg = <0x7c003000 0x1000>; @@ -426,6 +438,141 @@ vc4: gpu { compatible = "brcm,bcm2712-vc6"; }; + + pcie0: pcie@1000100000 { + compatible = "brcm,bcm2712-pcie"; + reg = <0x10 0x00100000 0x00 0x9310>; + device_type = "pci"; + linux,pci-domain = <0>; + max-link-speed = <2>; + num-lanes = <1>; + #address-cells = <3>; + #interrupt-cells = <1>; + #size-cells = <2>; + interrupt-parent = <&gicv2>; + interrupts = , + ; + interrupt-names = "pcie", "msi"; + interrupt-map-mask = <0x0 0x0 0x0 0x7>; + interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &gicv2 GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gicv2 GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gicv2 GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>; + resets = <&pcie_rescal>, <&bcm_reset 42>; + reset-names = "rescal", "bridge"; + msi-controller; + msi-parent = <&pcie0>; + + ranges = + /* ~4GiB, 32-bit, non-prefetchable at PCIe 00_0000_0000 */ + <0x02000000 0x00 0x00000000 0x17 0x00000000 0x00 0xfffffffc>, + /* 12GiB, 64-bit, prefetchable at PCIe 04_0000_0000 */ + <0x43000000 0x04 0x00000000 0x14 0x00000000 0x03 0x00000000>; + + dma-ranges = + /* 64GiB, 64-bit, prefetchable at PCIe 10_0000_0000 */ + <0x43000000 0x10 0x00000000 0x00 0x00000000 0x10 0x00000000>; + + status = "disabled"; + }; + + pcie1: pcie@1000110000 { + compatible = "brcm,bcm2712-pcie"; + reg = <0x10 0x00110000 0x00 0x9310>; + device_type = "pci"; + linux,pci-domain = <1>; + max-link-speed = <2>; + num-lanes = <1>; + #address-cells = <3>; + #interrupt-cells = <1>; + #size-cells = <2>; + interrupt-parent = <&gicv2>; + interrupts = , + ; + interrupt-names = "pcie", "msi"; + interrupt-map-mask = <0x0 0x0 0x0 0x7>; + interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &gicv2 GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gicv2 GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gicv2 GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>; + resets = <&pcie_rescal>, <&bcm_reset 43>; + reset-names = "rescal", "bridge"; + msi-controller; + msi-parent = <&mip1>; + + ranges = + /* ~4GiB, 32-bit, non-prefetchable at PCIe 00_0000_0000 */ + <0x02000000 0x00 0x00000000 0x1b 0x00000000 0x00 0xfffffffc>, + /* 12GiB, 64-bit, prefetchable at PCIe 04_0000_0000 */ + <0x43000000 0x04 0x00000000 0x18 0x00000000 0x03 0x00000000>; + + dma-ranges = + /* 64GiB, 64-bit, non-prefetchable at PCIe 10_0000_0000 */ + <0x03000000 0x10 0x00000000 0x00 0x00000000 0x10 0x00000000>, + /* 4KiB, 64-bit, non-prefetchable at PCIe ff_ffff_f000 MIP1 */ + <0x03000000 0xff 0xfffff000 0x10 0x00131000 0x00 0x00001000>; + + status = "disabled"; + }; + + pcie2: pcie@1000120000 { + compatible = "brcm,bcm2712-pcie"; + reg = <0x10 0x00120000 0x00 0x9310>; + device_type = "pci"; + linux,pci-domain = <2>; + max-link-speed = <2>; + num-lanes = <4>; + #address-cells = <3>; + #interrupt-cells = <1>; + #size-cells = <2>; + interrupt-parent = <&gicv2>; + interrupts = , + ; + interrupt-names = "pcie", "msi"; + interrupt-map-mask = <0x0 0x0 0x0 0x7>; + interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &gicv2 GIC_SPI 230 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gicv2 GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gicv2 GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>; + resets = <&pcie_rescal>, <&bcm_reset 44>; + reset-names = "rescal", "bridge"; + msi-controller; + msi-parent = <&mip0>; + + ranges = + /* ~4GiB, 32-bit, non-prefetchable at PCIe 00_0000_0000 */ + <0x02000000 0x00 0x00000000 0x1f 0x00000000 0x00 0xfffffffc>, + /* 12GiB, 64-bit, prefetchable at PCIe 04_0000_0000 */ + <0x43000000 0x04 0x00000000 0x1c 0x00000000 0x03 0x00000000>; + + dma-ranges = + /* 4MiB, 32-bit, non-prefetchable at PCIe 00_0000_0000 */ + <0x02000000 0x00 0x00000000 0x1f 0x00000000 0x00 0x00400000>, + /* 64GiB, 64-bit, prefetchable at PCIe 10_0000_0000 */ + <0x43000000 0x10 0x00000000 0x00 0x00000000 0x10 0x00000000>, + /* 4KiB, 64-bit, non-prefetchable at PCIe ff_ffff_f000 MIP0 */ + <0x03000000 0xff 0xfffff000 0x10 0x00130000 0x00 0x00001000>; + + status = "disabled"; + }; + + mip0: msi-controller@1000130000 { + compatible = "brcm,bcm2712-mip"; + reg = <0x10 0x00130000 0x00 0xc0>, + <0xff 0xfffff000 0x00 0x1000>; + msi-controller; + msi-ranges = <&gicv2 GIC_SPI 128 IRQ_TYPE_EDGE_RISING 64>; + brcm,msi-offset = <0>; + }; + + mip1: msi-controller@1000131000 { + compatible = "brcm,bcm2712-mip"; + reg = <0x10 0x00131000 0x00 0xc0>, + <0xff 0xfffff000 0x00 0x1000>; + msi-controller; + msi-ranges = <&gicv2 GIC_SPI 247 IRQ_TYPE_EDGE_RISING 8>; + brcm,msi-offset = <8>; + }; }; timer { diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 09e6893d7ff94c..ba916838b12741 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -110,12 +110,20 @@ config I8259 select IRQ_DOMAIN config BCM2712_MIP - bool "Broadcom 2712 MSI-X Interrupt Peripheral support" + tristate "Broadcom BCM2712 MSI-X Interrupt Peripheral support" + depends on ARCH_BRCMSTB || COMPILE_TEST + default m if ARCH_BRCMSTB depends on ARM_GIC select GENERIC_IRQ_CHIP - select IRQ_DOMAIN + select IRQ_DOMAIN_HIERARCHY + select GENERIC_MSI_IRQ + select IRQ_MSI_LIB help - Enable support for the Broadcom BCM2712 MSI-X target peripheral. + Enable support for the Broadcom BCM2712 MSI-X target peripheral + (MIP) needed by brcmstb PCIe to handle MSI-X interrupts on + Raspberry Pi 5. + + If unsure say n. config BCM6345_L1_IRQ bool diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 382f446bbf62ae..411385c4f3ad64 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -63,7 +63,7 @@ obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o obj-$(CONFIG_XILINX_INTC) += irq-xilinx-intc.o obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o obj-$(CONFIG_SOC_VF610) += irq-vf610-mscm-ir.o -obj-$(CONFIG_BCM2712_MIP) += irq-bcm2712-mip.o +obj-$(CONFIG_BCM2712_MIP) += irq-bcm2712-mip.o obj-$(CONFIG_BCM6345_L1_IRQ) += irq-bcm6345-l1.o obj-$(CONFIG_BCM7038_L1_IRQ) += irq-bcm7038-l1.o obj-$(CONFIG_BCM7120_L2_IRQ) += irq-bcm7120-l2.o diff --git a/drivers/irqchip/irq-bcm2712-mip.c b/drivers/irqchip/irq-bcm2712-mip.c index 2eaa3ac10cb62c..49a19db2d1e1b3 100644 --- a/drivers/irqchip/irq-bcm2712-mip.c +++ b/drivers/irqchip/irq-bcm2712-mip.c @@ -1,19 +1,20 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2021 Raspberry Pi Ltd., All Rights Reserved. + * Copyright (C) 2024 Raspberry Pi Ltd., All Rights Reserved. + * Copyright (c) 2024 SUSE */ -#include +#include +#include +#include #include -#include #include -#include -#include +#include -#include +#include "irq-msi-lib.h" -#define MIP_INT_RAISED 0x00 -#define MIP_INT_CLEARED 0x10 +#define MIP_INT_RAISE 0x00 +#define MIP_INT_CLEAR 0x10 #define MIP_INT_CFGL_HOST 0x20 #define MIP_INT_CFGH_HOST 0x30 #define MIP_INT_MASKL_HOST 0x40 @@ -25,57 +26,40 @@ #define MIP_INT_STATUSL_VPU 0xa0 #define MIP_INT_STATUSH_VPU 0xb0 +/** + * struct mip_priv - MSI-X interrupt controller data + * @lock: Used to protect bitmap alloc/free + * @base: Base address of MMIO area + * @msg_addr: PCIe MSI-X address + * @msi_base: MSI base + * @num_msis: Count of MSIs + * @msi_offset: MSI offset + * @bitmap: A bitmap for hwirqs + * @parent: Parent domain (GIC) + * @dev: A device pointer + */ struct mip_priv { - spinlock_t msi_map_lock; - spinlock_t hw_lock; - void * __iomem base; - phys_addr_t msg_addr; - u32 msi_base; /* The SGI number that MSIs start */ - u32 num_msis; /* The number of SGIs for MSIs */ - u32 msi_offset; /* Shift the allocated msi up by N */ - unsigned long *msi_map; + spinlock_t lock; + void __iomem *base; + u64 msg_addr; + u32 msi_base; + u32 num_msis; + u32 msi_offset; + unsigned long *bitmap; + struct irq_domain *parent; + struct device *dev; }; -static void mip_mask_msi_irq(struct irq_data *d) -{ - pci_msi_mask_irq(d); - irq_chip_mask_parent(d); -} - -static void mip_unmask_msi_irq(struct irq_data *d) -{ - pci_msi_unmask_irq(d); - irq_chip_unmask_parent(d); -} - static void mip_compose_msi_msg(struct irq_data *d, struct msi_msg *msg) { - struct mip_priv *priv = irq_data_get_irq_chip_data(d); + struct mip_priv *mip = irq_data_get_irq_chip_data(d); - msg->address_hi = upper_32_bits(priv->msg_addr); - msg->address_lo = lower_32_bits(priv->msg_addr); + msg->address_hi = upper_32_bits(mip->msg_addr); + msg->address_lo = lower_32_bits(mip->msg_addr); msg->data = d->hwirq; } -// The "bus-specific" irq_chip (the MIP doesn't _have_ to be used with PCIe) - -static struct irq_chip mip_msi_irq_chip = { - .name = "MIP-MSI", - .irq_unmask = mip_unmask_msi_irq, - .irq_mask = mip_mask_msi_irq, - .irq_eoi = irq_chip_eoi_parent, - .irq_set_affinity = irq_chip_set_affinity_parent, -}; - -static struct msi_domain_info mip_msi_domain_info = { - .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | - MSI_FLAG_PCI_MSIX), - .chip = &mip_msi_irq_chip, -}; - -// The "middle" irq_chip (the hardware control part) - -static struct irq_chip mip_irq_chip = { +static struct irq_chip mip_middle_irq_chip = { .name = "MIP", .irq_mask = irq_chip_mask_parent, .irq_unmask = irq_chip_unmask_parent, @@ -85,239 +69,224 @@ static struct irq_chip mip_irq_chip = { .irq_compose_msi_msg = mip_compose_msi_msg, }; +static int mip_alloc_hwirq(struct mip_priv *mip, unsigned int nr_irqs) +{ + guard(spinlock)(&mip->lock); + return bitmap_find_free_region(mip->bitmap, mip->num_msis, ilog2(nr_irqs)); +} -// And a domain to connect it to its parent (the GIC) +static void mip_free_hwirq(struct mip_priv *mip, unsigned int hwirq, + unsigned int nr_irqs) +{ + guard(spinlock)(&mip->lock); + bitmap_release_region(mip->bitmap, hwirq, ilog2(nr_irqs)); +} -static int mip_irq_domain_alloc(struct irq_domain *domain, - unsigned int virq, unsigned int nr_irqs, - void *args) +static int mip_middle_domain_alloc(struct irq_domain *domain, unsigned int virq, + unsigned int nr_irqs, void *arg) { - struct mip_priv *priv = domain->host_data; - struct irq_fwspec fwspec; + struct mip_priv *mip = domain->host_data; + struct irq_fwspec fwspec = {0}; + unsigned int hwirq, i; struct irq_data *irqd; - int hwirq, ret, i; - - spin_lock(&priv->msi_map_lock); + int irq, ret; - hwirq = bitmap_find_free_region(priv->msi_map, priv->num_msis, ilog2(nr_irqs)); + irq = mip_alloc_hwirq(mip, nr_irqs); + if (irq < 0) + return irq; - spin_unlock(&priv->msi_map_lock); + hwirq = irq + mip->msi_offset; - if (hwirq < 0) - return -ENOSPC; - - hwirq += priv->msi_offset; fwspec.fwnode = domain->parent->fwnode; fwspec.param_count = 3; fwspec.param[0] = 0; - fwspec.param[1] = hwirq + priv->msi_base; + fwspec.param[1] = hwirq + mip->msi_base; fwspec.param[2] = IRQ_TYPE_EDGE_RISING; ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &fwspec); if (ret) - return ret; + goto err_free_hwirq; for (i = 0; i < nr_irqs; i++) { irqd = irq_domain_get_irq_data(domain->parent, virq + i); irqd->chip->irq_set_type(irqd, IRQ_TYPE_EDGE_RISING); - irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, - &mip_irq_chip, priv); + ret = irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, + &mip_middle_irq_chip, mip); + if (ret) + goto err_free; + irqd = irq_get_irq_data(virq + i); irqd_set_single_target(irqd); irqd_set_affinity_on_activate(irqd); } return 0; -} - -static void mip_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 mip_priv *priv = irq_data_get_irq_chip_data(d); +err_free: irq_domain_free_irqs_parent(domain, virq, nr_irqs); - d->hwirq -= priv->msi_offset; - - spin_lock(&priv->msi_map_lock); - - bitmap_release_region(priv->msi_map, d->hwirq, ilog2(nr_irqs)); - - spin_unlock(&priv->msi_map_lock); +err_free_hwirq: + mip_free_hwirq(mip, irq, nr_irqs); + return ret; } -#if 0 -static int mip_irq_domain_activate(struct irq_domain *domain, - struct irq_data *d, bool reserve) +static void mip_middle_domain_free(struct irq_domain *domain, unsigned int virq, + unsigned int nr_irqs) { - struct mip_priv *priv = irq_data_get_irq_chip_data(d); - unsigned long flags; - unsigned int irq = d->hwirq; - void *__iomem reg = priv->base + - ((irq < 32) ? MIP_INT_MASKL_HOST : MIP_INT_MASKH_HOST); - u32 val; - - spin_lock_irqsave(&priv->hw_lock, flags); - val = readl(reg); - val &= ~(1 << (irq % 32)); // Clear the mask - writel(val, reg); - spin_unlock_irqrestore(&priv->hw_lock, flags); - return 0; -} + struct irq_data *irqd = irq_domain_get_irq_data(domain, virq); + struct mip_priv *mip; + unsigned int hwirq; -static void mip_irq_domain_deactivate(struct irq_domain *domain, - struct irq_data *d) -{ - struct mip_priv *priv = irq_data_get_irq_chip_data(d); - unsigned long flags; - unsigned int irq = d->hwirq - priv->msi_base; - void *__iomem reg = priv->base + - ((irq < 32) ? MIP_INT_MASKL_HOST : MIP_INT_MASKH_HOST); - u32 val; - - spin_lock_irqsave(&priv->hw_lock, flags); - val = readl(reg); - val |= (1 << (irq % 32)); // Mask it out - writel(val, reg); - spin_unlock_irqrestore(&priv->hw_lock, flags); + if (!irqd) + return; + + mip = irq_data_get_irq_chip_data(irqd); + hwirq = irqd_to_hwirq(irqd); + irq_domain_free_irqs_parent(domain, virq, nr_irqs); + mip_free_hwirq(mip, hwirq - mip->msi_offset, nr_irqs); } -#endif -static const struct irq_domain_ops mip_irq_domain_ops = { - .alloc = mip_irq_domain_alloc, - .free = mip_irq_domain_free, - //.activate = mip_irq_domain_activate, - //.deactivate = mip_irq_domain_deactivate, +static const struct irq_domain_ops mip_middle_domain_ops = { + .select = msi_lib_irq_domain_select, + .alloc = mip_middle_domain_alloc, + .free = mip_middle_domain_free, }; -static int mip_init_domains(struct mip_priv *priv, - struct device_node *node) -{ - struct irq_domain *middle_domain, *msi_domain, *gic_domain; - struct device_node *gic_node; - - gic_node = of_irq_find_parent(node); - if (!gic_node) { - pr_err("Failed to find the GIC node\n"); - return -ENODEV; - } +#define MIP_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ + MSI_FLAG_USE_DEF_CHIP_OPS | \ + MSI_FLAG_PCI_MSI_MASK_PARENT) + +#define MIP_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ + MSI_FLAG_MULTI_PCI_MSI | \ + MSI_FLAG_PCI_MSIX) + +static const struct msi_parent_ops mip_msi_parent_ops = { + .supported_flags = MIP_MSI_FLAGS_SUPPORTED, + .required_flags = MIP_MSI_FLAGS_REQUIRED, + .bus_select_token = DOMAIN_BUS_GENERIC_MSI, + .bus_select_mask = MATCH_PCI_MSI, + .prefix = "MIP-MSI-", + .init_dev_msi_info = msi_lib_init_dev_msi_info, +}; - gic_domain = irq_find_host(gic_node); - if (!gic_domain) { - pr_err("Failed to find the GIC domain\n"); - return -ENXIO; - } +static int mip_init_domains(struct mip_priv *mip, struct device_node *np) +{ + struct irq_domain *middle; - middle_domain = irq_domain_add_hierarchy(gic_domain, 0, 0, NULL, - &mip_irq_domain_ops, - priv); - if (!middle_domain) { - pr_err("Failed to create the MIP middle domain\n"); + middle = irq_domain_add_hierarchy(mip->parent, 0, mip->num_msis, np, + &mip_middle_domain_ops, mip); + if (!middle) return -ENOMEM; - } - msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node), - &mip_msi_domain_info, - middle_domain); - if (!msi_domain) { - pr_err("Failed to create MSI domain\n"); - irq_domain_remove(middle_domain); - return -ENOMEM; - } + irq_domain_update_bus_token(middle, DOMAIN_BUS_GENERIC_MSI); + middle->dev = mip->dev; + middle->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; + middle->msi_parent_ops = &mip_msi_parent_ops; + + /* + * All MSI-X unmasked for the host, masked for the VPU, and edge-triggered. + */ + writel(0, mip->base + MIP_INT_MASKL_HOST); + writel(0, mip->base + MIP_INT_MASKH_HOST); + writel(~0, mip->base + MIP_INT_MASKL_VPU); + writel(~0, mip->base + MIP_INT_MASKH_VPU); + writel(~0, mip->base + MIP_INT_CFGL_HOST); + writel(~0, mip->base + MIP_INT_CFGH_HOST); return 0; } -static int __init mip_of_msi_init(struct device_node *node, - struct device_node *parent) +static int mip_parse_dt(struct mip_priv *mip, struct device_node *np) { - struct mip_priv *priv; - struct resource res; + struct of_phandle_args args; + u64 size; int ret; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; + ret = of_property_read_u32(np, "brcm,msi-offset", &mip->msi_offset); + if (ret) + mip->msi_offset = 0; - spin_lock_init(&priv->msi_map_lock); - spin_lock_init(&priv->hw_lock); + ret = of_parse_phandle_with_args(np, "msi-ranges", "#interrupt-cells", + 0, &args); + if (ret) + return ret; - ret = of_address_to_resource(node, 0, &res); - if (ret) { - pr_err("Failed to allocate resource\n"); - goto err_priv; - } + ret = of_property_read_u32_index(np, "msi-ranges", args.args_count + 1, + &mip->num_msis); + if (ret) + goto err_put; - if (of_property_read_u32(node, "brcm,msi-base-spi", &priv->msi_base)) { - pr_err("Unable to parse MSI base\n"); - ret = -EINVAL; - goto err_priv; - } + ret = of_property_read_reg(np, 1, &mip->msg_addr, &size); + if (ret) + goto err_put; + + mip->msi_base = args.args[1]; - if (of_property_read_u32(node, "brcm,msi-num-spis", &priv->num_msis)) { - pr_err("Unable to parse MSI numbers\n"); + mip->parent = irq_find_host(args.np); + if (!mip->parent) ret = -EINVAL; - goto err_priv; - } - if (of_property_read_u32(node, "brcm,msi-offset", &priv->msi_offset)) - priv->msi_offset = 0; +err_put: + of_node_put(args.np); + return ret; +} - if (of_property_read_u64(node, "brcm,msi-pci-addr", &priv->msg_addr)) { - pr_err("Unable to parse MSI address\n"); - ret = -EINVAL; +static int __init mip_of_msi_init(struct device_node *node, struct device_node *parent) +{ + struct platform_device *pdev; + struct mip_priv *mip; + int ret; + + pdev = of_find_device_by_node(node); + of_node_put(node); + if (!pdev) + return -EPROBE_DEFER; + + mip = kzalloc(sizeof(*mip), GFP_KERNEL); + if (!mip) + return -ENOMEM; + + spin_lock_init(&mip->lock); + mip->dev = &pdev->dev; + + ret = mip_parse_dt(mip, node); + if (ret) goto err_priv; - } - priv->base = ioremap(res.start, resource_size(&res)); - if (!priv->base) { - pr_err("Failed to ioremap regs\n"); - ret = -ENOMEM; + mip->base = of_iomap(node, 0); + if (!mip->base) { + ret = -ENXIO; goto err_priv; } - priv->msi_map = kcalloc(BITS_TO_LONGS(priv->num_msis), - sizeof(*priv->msi_map), - GFP_KERNEL); - if (!priv->msi_map) { + mip->bitmap = bitmap_zalloc(mip->num_msis, GFP_KERNEL); + if (!mip->bitmap) { ret = -ENOMEM; goto err_base; } - pr_debug("Registering %d msixs, starting at %d\n", - priv->num_msis, priv->msi_base); - - /* - * Begin with all MSI-Xs masked in for the host, masked out for the - * VPU, and edge-triggered. - */ - writel(0, priv->base + MIP_INT_MASKL_HOST); - writel(0, priv->base + MIP_INT_MASKH_HOST); - writel(~0, priv->base + MIP_INT_MASKL_VPU); - writel(~0, priv->base + MIP_INT_MASKH_VPU); - writel(~0, priv->base + MIP_INT_CFGL_HOST); - writel(~0, priv->base + MIP_INT_CFGH_HOST); - - ret = mip_init_domains(priv, node); - if (ret) { - pr_err("Failed to allocate msi_map\n"); + ret = mip_init_domains(mip, node); + if (ret) goto err_map; - } + + dev_dbg(&pdev->dev, "MIP: MSI-X count: %u, base: %u, offset: %u, msg_addr: %llx\n", + mip->num_msis, mip->msi_base, mip->msi_offset, mip->msg_addr); return 0; err_map: - kfree(priv->msi_map); - + bitmap_free(mip->bitmap); err_base: - iounmap(priv->base); - + iounmap(mip->base); err_priv: - kfree(priv); - - pr_err("%s: failed - err %d\n", __func__, ret); - + kfree(mip); return ret; } -IRQCHIP_DECLARE(bcm_mip, "brcm,bcm2712-mip-intc", mip_of_msi_init); + +IRQCHIP_PLATFORM_DRIVER_BEGIN(mip_msi) +IRQCHIP_MATCH("brcm,bcm2712-mip", mip_of_msi_init) +IRQCHIP_PLATFORM_DRIVER_END(mip_msi) +MODULE_DESCRIPTION("Broadcom BCM2712 MSI-X interrupt controller"); +MODULE_AUTHOR("Phil Elwell "); +MODULE_AUTHOR("Stanimir Varbanov "); +MODULE_LICENSE("GPL"); diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c index 63020d7040c4b9..1e24e7fc895ca2 100644 --- a/drivers/pci/controller/pcie-brcmstb.c +++ b/drivers/pci/controller/pcie-brcmstb.c @@ -47,15 +47,7 @@ #define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc #define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK 0xc00 - -#define PCIE_RC_TL_VDM_CTL0 0x0a20 -#define PCIE_RC_TL_VDM_CTL0_VDM_ENABLED_MASK 0x10000 -#define PCIE_RC_TL_VDM_CTL0_VDM_IGNORETAG_MASK 0x20000 -#define PCIE_RC_TL_VDM_CTL0_VDM_IGNOREVNDRID_MASK 0x40000 - -#define PCIE_RC_TL_VDM_CTL1 0x0a0c -#define PCIE_RC_TL_VDM_CTL1_VDM_VNDRID0_MASK 0x0000ffff -#define PCIE_RC_TL_VDM_CTL1_VDM_VNDRID1_MASK 0xffff0000 +#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_MAX_LINK_SPEED_MASK 0xf #define PCIE_RC_CFG_PRIV1_ROOT_CAP 0x4f8 #define PCIE_RC_CFG_PRIV1_ROOT_CAP_L1SS_MODE_MASK 0xf8 @@ -98,15 +90,9 @@ #define PCIE_BRCM_MAX_INBOUND_WINS 16 #define PCIE_MISC_RC_BAR1_CONFIG_LO 0x402c #define PCIE_MISC_RC_BAR1_CONFIG_LO_SIZE_MASK 0x1f -#define PCIE_MISC_RC_BAR1_CONFIG_HI 0x4030 -#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_BAR4_CONFIG_LO 0x40d4 -#define PCIE_MISC_RC_BAR3_CONFIG_LO 0x403c -#define PCIE_MISC_RC_BAR3_CONFIG_LO_SIZE_MASK 0x1f -#define PCIE_MISC_RC_BAR3_CONFIG_HI 0x4040 #define PCIE_MISC_MSI_BAR_CONFIG_LO 0x4044 #define PCIE_MISC_MSI_BAR_CONFIG_HI 0x4048 @@ -115,15 +101,12 @@ #define PCIE_MISC_MSI_DATA_CONFIG_VAL_32 0xffe06540 #define PCIE_MISC_MSI_DATA_CONFIG_VAL_8 0xfff86540 -#define PCIE_MISC_RC_CONFIG_RETRY_TIMEOUT 0x405c - #define PCIE_MISC_PCIE_CTRL 0x4064 #define PCIE_MISC_PCIE_CTRL_PCIE_L23_REQUEST_MASK 0x1 #define PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK 0x4 #define PCIE_MISC_PCIE_STATUS 0x4068 #define PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK 0x80 -#define PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK_2712 0x40 #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 @@ -149,7 +132,6 @@ PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI + ((win) * 8) #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2 -#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK 0x8 #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_L1SS_ENABLE_MASK 0x200000 #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000 #define PCIE_BMIPS_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x00800000 @@ -157,74 +139,10 @@ (PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK | \ PCIE_MISC_HARD_PCIE_HARD_DEBUG_L1SS_ENABLE_MASK) - #define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP 0x40ac #define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_ACCESS_EN_MASK BIT(0) #define PCIE_MISC_UBUS_BAR4_CONFIG_REMAP 0x410c -#define PCIE_MISC_CTRL_1 0x40A0 -#define PCIE_MISC_CTRL_1_OUTBOUND_TC_MASK 0xf -#define PCIE_MISC_CTRL_1_OUTBOUND_NO_SNOOP_MASK BIT(3) -#define PCIE_MISC_CTRL_1_OUTBOUND_RO_MASK BIT(4) -#define PCIE_MISC_CTRL_1_EN_VDM_QOS_CONTROL_MASK BIT(5) - -#define PCIE_MISC_UBUS_CTRL 0x40a4 -#define PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_ERR_DIS_MASK BIT(13) -#define PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_DECERR_DIS_MASK BIT(19) - -#define PCIE_MISC_UBUS_TIMEOUT 0x40A8 - -#define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP 0x40ac -#define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_ACCESS_ENABLE_MASK BIT(0) -#define PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_HI 0x40b0 - -#define PCIE_MISC_UBUS_BAR2_CONFIG_REMAP 0x40b4 -#define PCIE_MISC_UBUS_BAR2_CONFIG_REMAP_ACCESS_ENABLE_MASK BIT(0) - -/* Additional RC BARs */ -#define PCIE_MISC_RC_BAR_CONFIG_LO_SIZE_MASK 0x1f -#define PCIE_MISC_RC_BAR4_CONFIG_LO 0x40d4 -#define PCIE_MISC_RC_BAR4_CONFIG_HI 0x40d8 -/* ... */ -#define PCIE_MISC_RC_BAR10_CONFIG_LO 0x4104 -#define PCIE_MISC_RC_BAR10_CONFIG_HI 0x4108 - -#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_ENABLE 0x1 -#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_LO_MASK 0xfffff000 -#define PCIE_MISC_UBUS_BAR_CONFIG_REMAP_HI_MASK 0xff -#define PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_LO 0x410c -#define PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_HI 0x4110 -/* ... */ -#define PCIE_MISC_UBUS_BAR10_CONFIG_REMAP_LO 0x413c -#define PCIE_MISC_UBUS_BAR10_CONFIG_REMAP_HI 0x4140 - -/* AXI priority forwarding - automatic level-based */ -#define PCIE_MISC_TC_QUEUE_TO_QOS_MAP(x) (0x4160 - (x) * 4) -/* Defined in quarter-fullness */ -#define QUEUE_THRESHOLD_34_TO_QOS_MAP_SHIFT 12 -#define QUEUE_THRESHOLD_23_TO_QOS_MAP_SHIFT 8 -#define QUEUE_THRESHOLD_12_TO_QOS_MAP_SHIFT 4 -#define QUEUE_THRESHOLD_01_TO_QOS_MAP_SHIFT 0 -#define QUEUE_THRESHOLD_MASK 0xf - -/* VDM messages indexing TCs to AXI priorities */ -/* Indexes 8-15 */ -#define PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_HI 0x4164 -/* Indexes 0-7 */ -#define PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_LO 0x4168 -#define VDM_PRIORITY_TO_QOS_MAP_SHIFT(x) (4 * (x)) -#define VDM_PRIORITY_TO_QOS_MAP_MASK 0xf - -#define PCIE_MISC_AXI_INTF_CTRL 0x416C -#define AXI_EN_RCLK_QOS_ARRAY_FIX BIT(13) -#define AXI_EN_QOS_UPDATE_TIMING_FIX BIT(12) -#define AXI_DIS_QOS_GATING_IN_MASTER BIT(11) -#define AXI_REQFIFO_EN_QOS_PROPAGATION BIT(7) -#define AXI_BRIDGE_LOW_LATENCY_MODE BIT(6) -#define AXI_MASTER_MAX_OUTSTANDING_REQUESTS_MASK 0x3f - -#define PCIE_MISC_AXI_READ_ERROR_DATA 0x4170 - #define PCIE_MSI_INTR2_BASE 0x4500 /* Offsets from INTR2_CPU and MSI_INTR2 BASE offsets */ @@ -233,9 +151,6 @@ #define MSI_INT_MASK_SET 0x10 #define MSI_INT_MASK_CLR 0x14 -#define PCIE_EXT_CFG_DATA 0x8000 -#define PCIE_EXT_CFG_INDEX 0x9000 - #define PCIE_RGR1_SW_INIT_1_PERST_MASK 0x1 #define PCIE_RGR1_SW_INIT_1_PERST_SHIFT 0x0 @@ -261,8 +176,9 @@ #define MDIO_PORT0 0x0 #define MDIO_DATA_MASK 0x7fffffff #define MDIO_PORT_MASK 0xf0000 +#define MDIO_PORT_EXT_MASK 0x200000 #define MDIO_REGAD_MASK 0xffff -#define MDIO_CMD_MASK 0xfff00000 +#define MDIO_CMD_MASK 0x00100000 #define MDIO_CMD_READ 0x1 #define MDIO_CMD_WRITE 0x0 #define MDIO_DATA_DONE_MASK 0x80000000 @@ -278,11 +194,11 @@ #define SSC_STATUS_PLL_LOCK_MASK 0x800 #define PCIE_BRCM_MAX_MEMC 3 -#define IDX_ADDR(pcie) ((pcie)->reg_offsets[EXT_CFG_INDEX]) -#define DATA_ADDR(pcie) ((pcie)->reg_offsets[EXT_CFG_DATA]) -#define PCIE_RGR1_SW_INIT_1(pcie) ((pcie)->reg_offsets[RGR1_SW_INIT_1]) -#define HARD_DEBUG(pcie) ((pcie)->reg_offsets[PCIE_HARD_DEBUG]) -#define INTR2_CPU_BASE(pcie) ((pcie)->reg_offsets[PCIE_INTR2_CPU_BASE]) +#define IDX_ADDR(pcie) ((pcie)->cfg->offsets[EXT_CFG_INDEX]) +#define DATA_ADDR(pcie) ((pcie)->cfg->offsets[EXT_CFG_DATA]) +#define PCIE_RGR1_SW_INIT_1(pcie) ((pcie)->cfg->offsets[RGR1_SW_INIT_1]) +#define HARD_DEBUG(pcie) ((pcie)->cfg->offsets[PCIE_HARD_DEBUG]) +#define INTR2_CPU_BASE(pcie) ((pcie)->cfg->offsets[PCIE_INTR2_CPU_BASE]) /* Rescal registers */ #define PCIE_DVT_PMU_PCIE_PHY_CTRL 0xc700 @@ -313,7 +229,6 @@ enum pcie_soc_base { BCM7425, BCM7435, BCM7712, - BCM2712, }; struct inbound_win { @@ -322,13 +237,24 @@ struct inbound_win { u64 cpu_addr; }; +/* + * The RESCAL block is tied to PCIe controller #1, regardless of the number of + * controllers, and turning off PCIe controller #1 prevents access to the RESCAL + * register blocks, therefore no other controller can access this register + * space, and depending upon the bus fabric we may get a timeout (UBUS/GISB), + * or a hang (AXI). + */ +#define CFG_QUIRK_AVOID_BRIDGE_SHUTDOWN BIT(0) + struct pcie_cfg_data { const int *offsets; const enum pcie_soc_base soc_base; const bool has_phy; + const u32 quirks; u8 num_inbound_wins; int (*perst_set)(struct brcm_pcie *pcie, u32 val); int (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val); + int (*post_setup)(struct brcm_pcie *pcie); }; struct subdev_regulators { @@ -345,7 +271,7 @@ struct brcm_msi { struct mutex lock; /* guards the alloc/free operations */ u64 target_addr; int irq; - DECLARE_BITMAP(used, 64); + DECLARE_BITMAP(used, BRCM_INT_PCI_MSI_NR); bool legacy; /* Some chips have MSIs in bits [31..24] of a shared register. */ int legacy_shift; @@ -364,8 +290,6 @@ struct brcm_pcie { int gen; u64 msi_target_addr; struct brcm_msi *msi; - const int *reg_offsets; - enum pcie_soc_base soc_base; struct reset_control *rescal; struct reset_control *perst_reset; struct reset_control *bridge_reset; @@ -373,21 +297,14 @@ struct brcm_pcie { int num_memc; u64 memc_size[PCIE_BRCM_MAX_MEMC]; u32 hw_rev; - int (*perst_set)(struct brcm_pcie *pcie, u32 val); - int (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val); struct subdev_regulators *sr; bool ep_wakeup_capable; - bool has_phy; - u8 num_inbound_wins; - bool l1ss; - bool rcb_mps_mode; - u32 qos_map; - u32 tperst_clk_ms; + const struct pcie_cfg_data *cfg; }; static inline bool is_bmips(const struct brcm_pcie *pcie) { - return pcie->soc_base == BCM7435 || pcie->soc_base == BCM7425; + return pcie->cfg->soc_base == BCM7435 || pcie->cfg->soc_base == BCM7425; } /* @@ -412,6 +329,7 @@ static u32 brcm_pcie_mdio_form_pkt(int port, int regad, int cmd) { u32 pkt = 0; + pkt |= FIELD_PREP(MDIO_PORT_EXT_MASK, port >> 4); pkt |= FIELD_PREP(MDIO_PORT_MASK, port); pkt |= FIELD_PREP(MDIO_REGAD_MASK, regad); pkt |= FIELD_PREP(MDIO_CMD_MASK, cmd); @@ -491,47 +409,16 @@ static int brcm_pcie_set_ssc(struct brcm_pcie *pcie) return ssc && pll ? 0 : -EIO; } -static void brcm_pcie_munge_pll(struct brcm_pcie *pcie) -{ - //print "MDIO block 0x1600 written per Dannys instruction" - //tmp = pcie_mdio_write(phyad, &h16&, &h50b9&) - //tmp = pcie_mdio_write(phyad, &h17&, &hbd1a&) - //tmp = pcie_mdio_write(phyad, &h1b&, &h5030&) - //tmp = pcie_mdio_write(phyad, &h1e&, &h0007&) - - u32 tmp; - int ret, i; - u8 regs[] = { 0x16, 0x17, 0x18, 0x19, 0x1b, 0x1c, 0x1e }; - u16 data[] = { 0x50b9, 0xbda1, 0x0094, 0x97b4, 0x5030, 0x5030, 0x0007 }; - - ret = brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, SET_ADDR_OFFSET, - 0x1600); - for (i = 0; i < ARRAY_SIZE(regs); i++) { - brcm_pcie_mdio_read(pcie->base, MDIO_PORT0, regs[i], &tmp); - dev_dbg(pcie->dev, "PCIE MDIO pre_refclk 0x%02x = 0x%04x\n", - regs[i], tmp); - } - for (i = 0; i < ARRAY_SIZE(regs); i++) { - brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, regs[i], data[i]); - brcm_pcie_mdio_read(pcie->base, MDIO_PORT0, regs[i], &tmp); - dev_dbg(pcie->dev, "PCIE MDIO post_refclk 0x%02x = 0x%04x\n", - regs[i], tmp); - } - usleep_range(100, 200); -} - /* 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); - - dev_info(pcie->dev, "Forcing gen %d\n", pcie->gen); + u32 lnkcap = readl(pcie->base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY); - lnkcap = (lnkcap & ~PCI_EXP_LNKCAP_SLS) | gen; - writel(lnkcap, pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCAP); + u32p_replace_bits(&lnkcap, gen, PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_MAX_LINK_SPEED_MASK); + writel(lnkcap, pcie->base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY); - lnkctl2 = (lnkctl2 & ~0xf) | gen; + u16p_replace_bits(&lnkctl2, gen, PCI_EXP_LNKCTL2_TLS); writew(lnkctl2, pcie->base + BRCM_PCIE_CAP_REGS + PCI_EXP_LNKCTL2); } @@ -579,73 +466,6 @@ static void brcm_pcie_set_outbound_win(struct brcm_pcie *pcie, writel(tmp, pcie->base + PCIE_MEM_WIN0_LIMIT_HI(win)); } -static void brcm_pcie_set_tc_qos(struct brcm_pcie *pcie) -{ - int i; - u32 reg; - - if (pcie->soc_base != BCM2712) - return; - - /* Disable broken QOS forwarding search. Set chicken bits for 2712D0 */ - reg = readl(pcie->base + PCIE_MISC_AXI_INTF_CTRL); - reg &= ~AXI_REQFIFO_EN_QOS_PROPAGATION; - reg |= AXI_EN_RCLK_QOS_ARRAY_FIX | AXI_EN_QOS_UPDATE_TIMING_FIX | - AXI_DIS_QOS_GATING_IN_MASTER; - writel(reg, pcie->base + PCIE_MISC_AXI_INTF_CTRL); - - /* - * If the QOS_UPDATE_TIMING_FIX bit is Reserved-0, then this is a - * 2712C1 chip, or a single-lane RC. Use the best-effort alternative - * which is to partially throttle AXI requests in-flight to the SDC. - */ - reg = readl(pcie->base + PCIE_MISC_AXI_INTF_CTRL); - if (!(reg & AXI_EN_QOS_UPDATE_TIMING_FIX)) { - reg &= ~AXI_MASTER_MAX_OUTSTANDING_REQUESTS_MASK; - reg |= 15; - writel(reg, pcie->base + PCIE_MISC_AXI_INTF_CTRL); - } - - /* Disable VDM reception by default - QoS map defaults to 0 */ - reg = readl(pcie->base + PCIE_MISC_CTRL_1); - reg &= ~PCIE_MISC_CTRL_1_EN_VDM_QOS_CONTROL_MASK; - writel(reg, pcie->base + PCIE_MISC_CTRL_1); - - if (!of_property_read_u32(pcie->np, "brcm,fifo-qos-map", &pcie->qos_map)) { - /* - * Backpressure mode - bottom 4 nibbles are QoS for each - * quartile of FIFO level. Each TC gets the same map, because - * this mode is intended for nonrealtime EPs. - */ - - pcie->qos_map &= 0x0000ffff; - for (i = 0; i < 8; i++) - writel(pcie->qos_map, pcie->base + PCIE_MISC_TC_QUEUE_TO_QOS_MAP(i)); - - return; - } - - if (!of_property_read_u32(pcie->np, "brcm,vdm-qos-map", &pcie->qos_map)) { - - reg = readl(pcie->base + PCIE_MISC_CTRL_1); - reg |= PCIE_MISC_CTRL_1_EN_VDM_QOS_CONTROL_MASK; - writel(reg, pcie->base + PCIE_MISC_CTRL_1); - - /* No forwarding means no point separating panic priorities from normal */ - writel(pcie->qos_map, pcie->base + PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_LO); - writel(pcie->qos_map, pcie->base + PCIE_MISC_VDM_PRIORITY_TO_QOS_MAP_HI); - - /* Match Vendor ID of 0 */ - writel(0, pcie->base + PCIE_RC_TL_VDM_CTL1); - /* Forward VDMs to priority interface - at least the rx counters work */ - reg = readl(pcie->base + PCIE_RC_TL_VDM_CTL0); - reg |= PCIE_RC_TL_VDM_CTL0_VDM_ENABLED_MASK | - PCIE_RC_TL_VDM_CTL0_VDM_IGNORETAG_MASK | - PCIE_RC_TL_VDM_CTL0_VDM_IGNOREVNDRID_MASK; - writel(reg, pcie->base + PCIE_RC_TL_VDM_CTL0); - } -} - static struct irq_chip brcm_msi_irq_chip = { .name = "BRCM STB PCIe MSI", .irq_ack = irq_chip_ack_parent, @@ -654,8 +474,8 @@ static struct irq_chip brcm_msi_irq_chip = { }; static struct msi_domain_info brcm_msi_domain_info = { - .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | - MSI_FLAG_NO_AFFINITY | MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX), + .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | + MSI_FLAG_NO_AFFINITY | MSI_FLAG_MULTI_PCI_MSI, .chip = &brcm_msi_irq_chip, }; @@ -674,23 +494,10 @@ static void brcm_pcie_msi_isr(struct irq_desc *desc) status = readl(msi->intr_base + MSI_INT_STATUS); status >>= msi->legacy_shift; - for_each_set_bit(bit, &status, BRCM_INT_PCI_MSI_NR/*msi->nr*/) { - unsigned long virq; - bool found = false; - - virq = irq_find_mapping(msi->inner_domain, bit); - if (virq) { - found = true; - dev_dbg(dev, "MSI -> %ld\n", virq); - generic_handle_irq(virq); - } - virq = irq_find_mapping(msi->inner_domain, bit + 32); - if (virq) { - found = true; - dev_dbg(dev, "MSI -> %ld\n", virq); - generic_handle_irq(virq); - } - if (!found) + for_each_set_bit(bit, &status, msi->nr) { + int ret; + ret = generic_handle_domain_irq(msi->inner_domain, bit); + if (ret) dev_dbg(dev, "unexpected MSI\n"); } @@ -703,13 +510,13 @@ static void brcm_msi_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) 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_32) | (data->hwirq & 0x1f); + msg->data = (0xffff & PCIE_MISC_MSI_DATA_CONFIG_VAL_32) | data->hwirq; } static void brcm_msi_ack_irq(struct irq_data *data) { struct brcm_msi *msi = irq_data_get_irq_chip_data(data); - const int shift_amt = (data->hwirq & 0x1f) + msi->legacy_shift; + const int shift_amt = data->hwirq + msi->legacy_shift; writel(1 << shift_amt, msi->intr_base + MSI_INT_CLR); } @@ -753,7 +560,7 @@ static int brcm_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, return hwirq; for (i = 0; i < nr_irqs; i++) - irq_domain_set_info(domain, virq + i, hwirq + i, + irq_domain_set_info(domain, virq + i, (irq_hw_number_t)hwirq + i, &brcm_msi_bottom_irq_chip, domain->host_data, handle_edge_irq, NULL, NULL); return 0; @@ -869,7 +676,7 @@ static int brcm_pcie_enable_msi(struct brcm_pcie *pcie) msi->legacy_shift = 24; } else { msi->intr_base = msi->base + PCIE_MSI_INTR2_BASE; - msi->nr = 64; //BRCM_INT_PCI_MSI_NR; + msi->nr = BRCM_INT_PCI_MSI_NR; msi->legacy_shift = 0; } @@ -891,9 +698,6 @@ static bool brcm_pcie_rc_mode(struct brcm_pcie *pcie) void __iomem *base = pcie->base; u32 val = readl(base + PCIE_MISC_PCIE_STATUS); - if (pcie->soc_base == BCM2712) - return !!FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK_2712, val) | 1; //XXX - return !!FIELD_GET(PCIE_MISC_PCIE_STATUS_PCIE_PORT_MASK, val); } @@ -923,8 +727,8 @@ static void __iomem *brcm_pcie_map_bus(struct pci_bus *bus, /* For devices, write to the config space index register */ idx = PCIE_ECAM_OFFSET(bus->number, devfn, 0); - writel(idx, pcie->base + PCIE_EXT_CFG_INDEX); - return base + PCIE_EXT_CFG_DATA + PCIE_ECAM_REG(where); + writel(idx, base + IDX_ADDR(pcie)); + return base + DATA_ADDR(pcie) + PCIE_ECAM_REG(where); } static void __iomem *brcm7425_pcie_map_bus(struct pci_bus *bus, @@ -986,21 +790,6 @@ static int brcm_pcie_bridge_sw_init_set_7278(struct brcm_pcie *pcie, u32 val) return 0; } -static int brcm_pcie_bridge_sw_init_set_2712(struct brcm_pcie *pcie, u32 val) -{ - int ret; - - if (WARN_ONCE(!pcie->bridge_reset, "missing bridge reset controller\n")) - return -EINVAL; - - if (val) - ret = reset_control_assert(pcie->bridge_reset); - else - ret = reset_control_deassert(pcie->bridge_reset); - - return ret; -} - static int brcm_pcie_perst_set_4908(struct brcm_pcie *pcie, u32 val) { int ret; @@ -1031,31 +820,49 @@ static int brcm_pcie_perst_set_7278(struct brcm_pcie *pcie, u32 val) return 0; } -static int brcm_pcie_perst_set_2712(struct brcm_pcie *pcie, u32 val) +static int brcm_pcie_perst_set_generic(struct brcm_pcie *pcie, u32 val) { u32 tmp; - /* Perst bit has moved and assert value is 0 */ - tmp = readl(pcie->base + PCIE_MISC_PCIE_CTRL); - u32p_replace_bits(&tmp, !val, PCIE_MISC_PCIE_CTRL_PCIE_PERSTB_MASK); - writel(tmp, pcie->base + PCIE_MISC_PCIE_CTRL); + tmp = readl(pcie->base + PCIE_RGR1_SW_INIT_1(pcie)); + u32p_replace_bits(&tmp, val, PCIE_RGR1_SW_INIT_1_PERST_MASK); + writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1(pcie)); return 0; } -static int brcm_pcie_perst_set_generic(struct brcm_pcie *pcie, u32 val) +static int brcm_pcie_post_setup_bcm2712(struct brcm_pcie *pcie) { + const u16 data[] = { 0x50b9, 0xbda1, 0x0094, 0x97b4, 0x5030, 0x5030, 0x0007 }; + const u8 regs[] = { 0x16, 0x17, 0x18, 0x19, 0x1b, 0x1c, 0x1e }; + int ret, i; u32 tmp; - tmp = readl(pcie->base + PCIE_RGR1_SW_INIT_1(pcie)); - u32p_replace_bits(&tmp, val, PCIE_RGR1_SW_INIT_1_PERST_MASK); - writel(tmp, pcie->base + PCIE_RGR1_SW_INIT_1(pcie)); + /* Allow a 54MHz (xosc) refclk source */ + ret = brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, SET_ADDR_OFFSET, 0x1600); + if (ret < 0) + return ret; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + ret = brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, regs[i], data[i]); + if (ret < 0) + return ret; + } + + usleep_range(100, 200); + + /* + * Set L1SS sub-state timers to avoid lengthy state transitions, + * PM clock period is 18.52ns (1/54MHz, round down). + */ + tmp = readl(pcie->base + PCIE_RC_PL_PHY_CTL_15); + tmp &= ~PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK; + tmp |= 0x12; + writel(tmp, pcie->base + PCIE_RC_PL_PHY_CTL_15); return 0; } - -#if 0 static void add_inbound_win(struct inbound_win *b, u8 *count, u64 size, u64 cpu_addr, u64 pci_offset) { @@ -1090,7 +897,7 @@ static int brcm_pcie_get_inbound_wins(struct brcm_pcie *pcie, * security considerations, and is not implemented in our modern * SoCs. */ - if (pcie->soc_base != BCM7712) + if (pcie->cfg->soc_base != BCM7712) add_inbound_win(b++, &n, 0, 0, 0); resource_list_for_each_entry(entry, &bridge->dma_ranges) { @@ -1107,10 +914,10 @@ static int brcm_pcie_get_inbound_wins(struct brcm_pcie *pcie, * That being said, each BARs size must still be a power of * two. */ - if (pcie->soc_base == BCM7712) + if (pcie->cfg->soc_base == BCM7712) add_inbound_win(b++, &n, size, cpu_start, pcie_start); - if (n > pcie->num_inbound_wins) + if (n > pcie->cfg->num_inbound_wins) break; } @@ -1124,7 +931,7 @@ static int brcm_pcie_get_inbound_wins(struct brcm_pcie *pcie, * that enables multiple memory controllers. As such, it can return * now w/o doing special configuration. */ - if (pcie->soc_base == BCM7712) + if (pcie->cfg->soc_base == BCM7712) return n; ret = of_property_read_variable_u64_array(pcie->np, "brcm,scb-sizes", pcie->memc_size, 1, @@ -1247,7 +1054,7 @@ static void set_inbound_win_registers(struct brcm_pcie *pcie, * 7712: * All of their BARs need to be set. */ - if (pcie->soc_base == BCM7712) { + if (pcie->cfg->soc_base == BCM7712) { /* BUS remap register settings */ reg_offset = brcm_ubus_reg_offset(i); tmp = lower_32_bits(cpu_addr) & ~0xfff; @@ -1258,148 +1065,28 @@ static void set_inbound_win_registers(struct brcm_pcie *pcie, } } } -#endif - -static 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 resource_entry *entry; - struct device *dev = pcie->dev; - u64 lowest_pcie_addr = ~(u64)0; - int ret, i = 0; - u64 size = 0; - - resource_list_for_each_entry(entry, &bridge->dma_ranges) { - u64 pcie_beg = entry->res->start - entry->offset; - - size += entry->res->end - entry->res->start + 1; - if (pcie_beg < lowest_pcie_addr) - lowest_pcie_addr = pcie_beg; - if (pcie->soc_base == BCM2711 || pcie->soc_base == BCM2712) - break; // Only consider the first entry - } - - if (lowest_pcie_addr == ~(u64)0) { - dev_err(dev, "DT node has no dma-ranges\n"); - return -EINVAL; - } - - ret = of_property_read_variable_u64_array(pcie->np, "brcm,scb-sizes", pcie->memc_size, 1, - PCIE_BRCM_MAX_MEMC); - - if (ret <= 0) { - /* Make an educated guess */ - pcie->num_memc = 1; - pcie->memc_size[0] = 1ULL << fls64(size - 1); - } else { - pcie->num_memc = ret; - } - - /* Each memc is viewed through a "port" that is a power of 2 */ - for (i = 0, size = 0; i < pcie->num_memc; i++) - size += pcie->memc_size[i]; - - /* System memory starts at this address in PCIe-space */ - *rc_bar2_offset = lowest_pcie_addr; - /* The sum of all memc views must also be a power of 2 */ - *rc_bar2_size = 1ULL << fls64(size - 1); - - /* - * 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 - 1)) || - (*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_get_rc_bar_n(struct brcm_pcie *pcie, - int idx, - u64 *rc_bar_cpu, - u64 *rc_bar_size, - u64 *rc_bar_pci) -{ - struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); - struct resource_entry *entry; - int i = 0; - - resource_list_for_each_entry(entry, &bridge->dma_ranges) { - if (i == idx) { - *rc_bar_cpu = entry->res->start; - *rc_bar_size = entry->res->end - entry->res->start + 1; - *rc_bar_pci = entry->res->start - entry->offset; - return 0; - } - - i++; - } - - return -EINVAL; -} static int brcm_pcie_setup(struct brcm_pcie *pcie) { -#if 0 struct inbound_win inbound_wins[PCIE_BRCM_MAX_INBOUND_WINS]; -#endif - u64 rc_bar2_offset, rc_bar2_size; void __iomem *base = pcie->base; struct pci_host_bridge *bridge; struct resource_entry *entry; u32 tmp, burst, aspm_support; u8 num_out_wins = 0; -#if 0 int num_inbound_wins = 0; -#endif int memc, ret; - int count, i; /* Reset the bridge */ - ret = pcie->bridge_sw_init_set(pcie, 1); + ret = pcie->cfg->bridge_sw_init_set(pcie, 1); if (ret) return ret; /* Ensure that PERST# is asserted; some bootloaders may deassert it. */ - if (pcie->soc_base == BCM2711) { - ret = pcie->perst_set(pcie, 1); + if (pcie->cfg->soc_base == BCM2711) { + ret = pcie->cfg->perst_set(pcie, 1); if (ret) { - pcie->bridge_sw_init_set(pcie, 0); + pcie->cfg->bridge_sw_init_set(pcie, 0); return ret; } } @@ -1407,7 +1094,7 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie) usleep_range(100, 200); /* Take the bridge out of reset */ - ret = pcie->bridge_sw_init_set(pcie, 0); + ret = pcie->cfg->bridge_sw_init_set(pcie, 0); if (ret) return ret; @@ -1420,17 +1107,6 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie) /* Wait for SerDes to be stable */ usleep_range(100, 200); - if (pcie->soc_base == BCM2712) { - /* Allow a 54MHz (xosc) refclk source */ - brcm_pcie_munge_pll(pcie); - /* Fix for L1SS errata */ - tmp = readl(base + PCIE_RC_PL_PHY_CTL_15); - tmp &= ~PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK; - /* PM clock period is 18.52ns (round down) */ - tmp |= 0x12; - writel(tmp, base + PCIE_RC_PL_PHY_CTL_15); - } - /* * SCB_MAX_BURST_SIZE is a two bit field. For GENERIC chips it * is encoded as 0=128, 1=256, 2=512, 3=Rsvd, for BCM7278 it @@ -1438,49 +1114,36 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie) */ if (is_bmips(pcie)) burst = 0x1; /* 256 bytes */ - else if (pcie->soc_base == BCM2711) + else if (pcie->cfg->soc_base == BCM2711) burst = 0x0; /* 128 bytes */ - else if (pcie->soc_base == BCM2712) - burst = 0x1; /* 128 bytes */ - else if (pcie->soc_base == BCM7278) + else if (pcie->cfg->soc_base == BCM7278) burst = 0x3; /* 512 bytes */ else burst = 0x2; /* 512 bytes */ /* * Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN, - * RCB_MPS_MODE + * RCB_MPS_MODE, RCB_64B_MODE */ tmp = readl(base + PCIE_MISC_MISC_CTRL); 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, burst, PCIE_MISC_MISC_CTRL_MAX_BURST_SIZE_MASK); - if (pcie->rcb_mps_mode) - u32p_replace_bits(&tmp, 1, PCIE_MISC_MISC_CTRL_PCIE_RCB_MPS_MODE_MASK); + u32p_replace_bits(&tmp, 1, PCIE_MISC_MISC_CTRL_PCIE_RCB_MPS_MODE_MASK); + u32p_replace_bits(&tmp, 1, PCIE_MISC_MISC_CTRL_PCIE_RCB_64B_MODE_MASK); writel(tmp, base + PCIE_MISC_MISC_CTRL); - brcm_pcie_set_tc_qos(pcie); - - ret = brcm_pcie_get_rc_bar2_size_and_offset(pcie, &rc_bar2_size, - &rc_bar2_offset); - if (ret) - return ret; + num_inbound_wins = brcm_pcie_get_inbound_wins(pcie, inbound_wins); + if (num_inbound_wins < 0) + return num_inbound_wins; - 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); + set_inbound_win_registers(pcie, inbound_wins, num_inbound_wins); if (!brcm_pcie_rc_mode(pcie)) { dev_err(pcie->dev, "PCIe RC controller misconfigured as Endpoint\n"); return -EINVAL; } - tmp = readl(base + PCIE_MISC_UBUS_BAR2_CONFIG_REMAP); - u32p_replace_bits(&tmp, 1, PCIE_MISC_UBUS_BAR2_CONFIG_REMAP_ACCESS_ENABLE_MASK); - writel(tmp, base + PCIE_MISC_UBUS_BAR2_CONFIG_REMAP); tmp = readl(base + PCIE_MISC_MISC_CTRL); for (memc = 0; memc < pcie->num_memc; memc++) { u32 scb_size_val = ilog2(pcie->memc_size[memc]) - 15; @@ -1494,29 +1157,6 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie) } writel(tmp, base + PCIE_MISC_MISC_CTRL); - if (pcie->soc_base == BCM2712) { - /* Suppress AXI error responses and return 1s for read failures */ - tmp = readl(base + PCIE_MISC_UBUS_CTRL); - u32p_replace_bits(&tmp, 1, PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_ERR_DIS_MASK); - u32p_replace_bits(&tmp, 1, PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_DECERR_DIS_MASK); - writel(tmp, base + PCIE_MISC_UBUS_CTRL); - writel(0xffffffff, base + PCIE_MISC_AXI_READ_ERROR_DATA); - - /* - * Adjust timeouts. The UBUS timeout also affects CRS - * completion retries, as the request will get terminated if - * either timeout expires, so both have to be a large value - * (in clocks of 750MHz). - * Set UBUS timeout to 250ms, then set RC config retry timeout - * to be ~240ms. - * - * Setting CRSVis=1 will stop the core from blocking on a CRS - * response, but does require the device to be well-behaved... - */ - writel(0xB2D0000, base + PCIE_MISC_UBUS_TIMEOUT); - writel(0xABA0000, base + PCIE_MISC_RC_CONFIG_RETRY_TIMEOUT); - } - /* * We ideally want the MSI target address to be located in the 32bit * addressable memory area. Some devices might depend on it. This is @@ -1524,58 +1164,22 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie) * 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) + if (inbound_wins[2].pci_offset >= SZ_4G || + (inbound_wins[2].size + inbound_wins[2].pci_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; - 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); - /* Always advertise L1 capability */ - aspm_support = BIT(1); - /* Advertise L0s capability unless 'aspm-no-l0s' is set */ + /* Don't advertise L0s capability if 'aspm-no-l0s' */ + aspm_support = PCIE_LINK_STATE_L1; if (!of_property_read_bool(pcie->np, "aspm-no-l0s")) - aspm_support |= BIT(0); + aspm_support |= PCIE_LINK_STATE_L0S; tmp = readl(base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY); u32p_replace_bits(&tmp, aspm_support, PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK); writel(tmp, base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY); - /* program additional inbound windows (RC_BAR4..RC_BAR10) */ - count = (pcie->soc_base == BCM2712) ? 7 : 0; - for (i = 0; i < count; i++) { - u64 bar_cpu, bar_size, bar_pci; - - ret = brcm_pcie_get_rc_bar_n(pcie, 1 + i, &bar_cpu, &bar_size, - &bar_pci); - if (ret) - break; - - tmp = lower_32_bits(bar_pci); - u32p_replace_bits(&tmp, brcm_pcie_encode_ibar_size(bar_size), - PCIE_MISC_RC_BAR_CONFIG_LO_SIZE_MASK); - writel(tmp, base + PCIE_MISC_RC_BAR4_CONFIG_LO + i * 8); - writel(upper_32_bits(bar_pci), - base + PCIE_MISC_RC_BAR4_CONFIG_HI + i * 8); - - tmp = upper_32_bits(bar_cpu) & - PCIE_MISC_UBUS_BAR_CONFIG_REMAP_HI_MASK; - writel(tmp, - base + PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_HI + i * 8); - tmp = lower_32_bits(bar_cpu) & - PCIE_MISC_UBUS_BAR_CONFIG_REMAP_LO_MASK; - writel(tmp | PCIE_MISC_UBUS_BAR_CONFIG_REMAP_ENABLE, - base + PCIE_MISC_UBUS_BAR4_CONFIG_REMAP_LO + i * 8); - } - /* * For config space accesses on the RC, show the right class for * a PCIe-PCIe bridge (the default setting is to be EP mode). @@ -1622,6 +1226,12 @@ static int brcm_pcie_setup(struct brcm_pcie *pcie) PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1_ENDIAN_MODE_BAR2_MASK); writel(tmp, base + PCIE_RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1); + if (pcie->cfg->post_setup) { + ret = pcie->cfg->post_setup(pcie); + if (ret < 0) + return ret; + } + return 0; } @@ -1637,7 +1247,7 @@ static void brcm_extend_rbus_timeout(struct brcm_pcie *pcie) u32 timeout_us = 4000000; /* 4 seconds, our setting for L1SS */ /* 7712 does not have this (RGR1) timer */ - if (pcie->soc_base == BCM7712 || pcie->soc_base == BCM2712) + if (pcie->cfg->soc_base == BCM7712) return; /* Each unit in timeout register is 1/216,000,000 seconds */ @@ -1712,35 +1322,16 @@ static int brcm_pcie_start_link(struct brcm_pcie *pcie) void __iomem *base = pcie->base; u16 nlw, cls, lnksta; bool ssc_good = false; - u32 tmp; - u16 tmp16; int ret, i; + /* Limit the generation if specified */ if (pcie->gen) brcm_pcie_set_gen(pcie, pcie->gen); /* Unassert the fundamental reset */ - if (pcie->tperst_clk_ms) { - /* - * Increase Tperst_clk time by forcing PERST# output low while - * the internal reset is released, so the PLL generates stable - * refclk output further in advance of PERST# deassertion. - */ - tmp = readl(base + HARD_DEBUG(pcie)); - u32p_replace_bits(&tmp, 1, PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK); - writel(tmp, base + HARD_DEBUG(pcie)); - - pcie->perst_set(pcie, 0); - msleep(pcie->tperst_clk_ms); - - tmp = readl(base + HARD_DEBUG(pcie)); - u32p_replace_bits(&tmp, 0, PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK); - writel(tmp, base + HARD_DEBUG(pcie)); - } else { - ret = pcie->perst_set(pcie, 0); - if (ret) - return ret; - } + ret = pcie->cfg->perst_set(pcie, 0); + if (ret) + return ret; /* * Wait for 100ms after PERST# deassertion; see PCIe CEM specification @@ -1778,16 +1369,6 @@ static int brcm_pcie_start_link(struct brcm_pcie *pcie) pci_speed_string(pcie_link_speed[cls]), nlw, ssc_good ? "(SSC)" : "(!SSC)"); - /* - * RootCtl bits are reset by perst_n, which undoes pci_enable_crs() - * called prior to pci_add_new_bus() during probe. Re-enable here. - */ - tmp16 = readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_RTCAP); - if (tmp16 & PCI_EXP_RTCAP_CRSVIS) { - tmp16 = readw(base + BRCM_PCIE_CAP_REGS + PCI_EXP_RTCTL); - u16p_replace_bits(&tmp16, 1, PCI_EXP_RTCTL_CRSSVE); - writew(tmp16, base + BRCM_PCIE_CAP_REGS + PCI_EXP_RTCTL); - } return 0; } @@ -1835,7 +1416,8 @@ static int brcm_pcie_add_bus(struct pci_bus *bus) ret = regulator_bulk_get(dev, sr->num_supplies, sr->supplies); if (ret) { - dev_info(dev, "No regulators for downstream device\n"); + dev_info(dev, "Did not get regulators; err=%d\n", ret); + sr->num_supplies = 0; goto no_regulators; } @@ -1858,7 +1440,7 @@ static void brcm_pcie_remove_bus(struct pci_bus *bus) struct subdev_regulators *sr = pcie->sr; struct device *dev = &bus->dev; - if (!sr) + if (!sr || !bus->parent || !pci_is_root_bus(bus->parent)) return; if (regulator_bulk_disable(sr->num_supplies, sr->supplies)) @@ -1931,12 +1513,12 @@ static int brcm_phy_cntl(struct brcm_pcie *pcie, const int start) static inline int brcm_phy_start(struct brcm_pcie *pcie) { - return pcie->has_phy ? brcm_phy_cntl(pcie, 1) : 0; + return pcie->cfg->has_phy ? brcm_phy_cntl(pcie, 1) : 0; } static inline int brcm_phy_stop(struct brcm_pcie *pcie) { - return pcie->has_phy ? brcm_phy_cntl(pcie, 0) : 0; + return pcie->cfg->has_phy ? brcm_phy_cntl(pcie, 0) : 0; } static int brcm_pcie_turn_off(struct brcm_pcie *pcie) @@ -1947,7 +1529,7 @@ static int brcm_pcie_turn_off(struct brcm_pcie *pcie) if (brcm_pcie_link_up(pcie)) brcm_pcie_enter_l23(pcie); /* Assert fundamental reset */ - ret = pcie->perst_set(pcie, 1); + ret = pcie->cfg->perst_set(pcie, 1); if (ret) return ret; @@ -1961,14 +1543,9 @@ static int brcm_pcie_turn_off(struct brcm_pcie *pcie) u32p_replace_bits(&tmp, 1, PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK); writel(tmp, base + HARD_DEBUG(pcie)); - /* - * Shutting down this bridge on pcie1 means accesses to rescal block - * will hang the chip if another RC wants to assert/deassert rescal. - */ - if (pcie->soc_base == BCM2712) - return 0; - /* Shutdown PCIe bridge */ - ret = pcie->bridge_sw_init_set(pcie, 1); + if (!(pcie->cfg->quirks & CFG_QUIRK_AVOID_BRIDGE_SHUTDOWN)) + /* Shutdown PCIe bridge */ + ret = pcie->cfg->bridge_sw_init_set(pcie, 1); return ret; } @@ -2056,7 +1633,7 @@ static int brcm_pcie_resume_noirq(struct device *dev) goto err_reset; /* Take bridge out of reset so we can access the SERDES reg */ - pcie->bridge_sw_init_set(pcie, 0); + pcie->cfg->bridge_sw_init_set(pcie, 0); /* SERDES_IDDQ = 0 */ tmp = readl(base + HARD_DEBUG(pcie)); @@ -2134,7 +1711,7 @@ static void brcm_pcie_remove(struct platform_device *pdev) static const int pcie_offsets[] = { [RGR1_SW_INIT_1] = 0x9210, [EXT_CFG_INDEX] = 0x9000, - [EXT_CFG_DATA] = 0x9004, + [EXT_CFG_DATA] = 0x8000, [PCIE_HARD_DEBUG] = 0x4204, [PCIE_INTR2_CPU_BASE] = 0x4300, }; @@ -2142,7 +1719,7 @@ static const int pcie_offsets[] = { static const int pcie_offsets_bcm7278[] = { [RGR1_SW_INIT_1] = 0xc010, [EXT_CFG_INDEX] = 0x9000, - [EXT_CFG_DATA] = 0x9004, + [EXT_CFG_DATA] = 0x8000, [PCIE_HARD_DEBUG] = 0x4204, [PCIE_INTR2_CPU_BASE] = 0x4300, }; @@ -2156,15 +1733,9 @@ static const int pcie_offsets_bcm7425[] = { }; static const int pcie_offsets_bcm7712[] = { + [RGR1_SW_INIT_1] = 0x9210, [EXT_CFG_INDEX] = 0x9000, - [EXT_CFG_DATA] = 0x9004, - [PCIE_HARD_DEBUG] = 0x4304, - [PCIE_INTR2_CPU_BASE] = 0x4400, -}; - -static const int pcie_offsets_bcm2712[] = { - [EXT_CFG_INDEX] = 0x9000, - [EXT_CFG_DATA] = 0x9004, + [EXT_CFG_DATA] = 0x8000, [PCIE_HARD_DEBUG] = 0x4304, [PCIE_INTR2_CPU_BASE] = 0x4400, }; @@ -2185,6 +1756,16 @@ static const struct pcie_cfg_data bcm2711_cfg = { .num_inbound_wins = 3, }; +static const struct pcie_cfg_data bcm2712_cfg = { + .offsets = pcie_offsets_bcm7712, + .soc_base = BCM7712, + .perst_set = brcm_pcie_perst_set_7278, + .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_generic, + .post_setup = brcm_pcie_post_setup_bcm2712, + .quirks = CFG_QUIRK_AVOID_BRIDGE_SHUTDOWN, + .num_inbound_wins = 10, +}; + static const struct pcie_cfg_data bcm4908_cfg = { .offsets = pcie_offsets, .soc_base = BCM4908, @@ -2234,15 +1815,9 @@ static const struct pcie_cfg_data bcm7712_cfg = { .num_inbound_wins = 10, }; -static const struct pcie_cfg_data bcm2712_cfg = { - .offsets = pcie_offsets_bcm2712, - .perst_set = brcm_pcie_perst_set_2712, - .bridge_sw_init_set = brcm_pcie_bridge_sw_init_set_2712, - .soc_base = BCM2712, -}; - static const struct of_device_id brcm_pcie_match[] = { { .compatible = "brcm,bcm2711-pcie", .data = &bcm2711_cfg }, + { .compatible = "brcm,bcm2712-pcie", .data = &bcm2712_cfg }, { .compatible = "brcm,bcm4908-pcie", .data = &bcm4908_cfg }, { .compatible = "brcm,bcm7211-pcie", .data = &generic_cfg }, { .compatible = "brcm,bcm7216-pcie", .data = &bcm7216_cfg }, @@ -2251,7 +1826,6 @@ static const struct of_device_id brcm_pcie_match[] = { { .compatible = "brcm,bcm7435-pcie", .data = &bcm7435_cfg }, { .compatible = "brcm,bcm7445-pcie", .data = &generic_cfg }, { .compatible = "brcm,bcm7712-pcie", .data = &bcm7712_cfg }, - { .compatible = "brcm,bcm2712-pcie", .data = &bcm2712_cfg }, {}, }; @@ -2273,7 +1847,8 @@ static struct pci_ops brcm7425_pcie_ops = { static int brcm_pcie_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node, *msi_np; + struct device_node *msi_np __free(device_node) = NULL; + struct device_node *np = pdev->dev.of_node; struct pci_host_bridge *bridge; const struct pcie_cfg_data *data; struct brcm_pcie *pcie; @@ -2292,12 +1867,7 @@ static int brcm_pcie_probe(struct platform_device *pdev) pcie = pci_host_bridge_priv(bridge); pcie->dev = &pdev->dev; pcie->np = np; - pcie->reg_offsets = data->offsets; - pcie->soc_base = data->soc_base; - pcie->perst_set = data->perst_set; - pcie->bridge_sw_init_set = data->bridge_sw_init_set; - pcie->has_phy = data->has_phy; - pcie->num_inbound_wins = data->num_inbound_wins; + pcie->cfg = data; pcie->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(pcie->base)) @@ -2311,9 +1881,6 @@ static int brcm_pcie_probe(struct platform_device *pdev) pcie->gen = (ret < 0) ? 0 : ret; pcie->ssc = of_property_read_bool(np, "brcm,enable-ssc"); - pcie->l1ss = of_property_read_bool(np, "brcm,enable-l1ss"); - pcie->rcb_mps_mode = of_property_read_bool(np, "brcm,enable-mps-rcb"); - of_property_read_u32(np, "brcm,tperst-clk-ms", &pcie->tperst_clk_ms); pcie->rescal = devm_reset_control_get_optional_shared(&pdev->dev, "rescal"); if (IS_ERR(pcie->rescal)) @@ -2335,7 +1902,7 @@ static int brcm_pcie_probe(struct platform_device *pdev) if (ret) return dev_err_probe(&pdev->dev, ret, "could not enable clock\n"); - pcie->bridge_sw_init_set(pcie, 0); + pcie->cfg->bridge_sw_init_set(pcie, 0); if (pcie->swinit_reset) { ret = reset_control_assert(pcie->swinit_reset); @@ -2374,7 +1941,8 @@ static int brcm_pcie_probe(struct platform_device *pdev) goto fail; pcie->hw_rev = readl(pcie->base + PCIE_MISC_REVISION); - if (pcie->soc_base == BCM4908 && pcie->hw_rev >= BRCM_PCIE_HW_REV_3_20) { + if (pcie->cfg->soc_base == BCM4908 && + pcie->hw_rev >= BRCM_PCIE_HW_REV_3_20) { dev_err(pcie->dev, "hardware revision with unsupported PERST# setup\n"); ret = -ENODEV; goto fail; @@ -2387,36 +1955,10 @@ static int brcm_pcie_probe(struct platform_device *pdev) dev_err(pcie->dev, "probe of internal MSI failed"); goto fail; } - } else if (pci_msi_enabled() && msi_np != pcie->np) { - /* Use RC_BAR1 for MIP access */ - u64 msi_pci_addr; - u64 msi_phys_addr; - - if (of_property_read_u64(msi_np, "brcm,msi-pci-addr", &msi_pci_addr)) { - dev_err(pcie->dev, "Unable to find MSI PCI address\n"); - ret = -EINVAL; - goto fail; - } - - if (of_property_read_u64(msi_np, "reg", &msi_phys_addr)) { - dev_err(pcie->dev, "Unable to find MSI physical address\n"); - ret = -EINVAL; - goto fail; - } - - writel(lower_32_bits(msi_pci_addr) | brcm_pcie_encode_ibar_size(0x1000), - pcie->base + PCIE_MISC_RC_BAR1_CONFIG_LO); - writel(upper_32_bits(msi_pci_addr), - pcie->base + PCIE_MISC_RC_BAR1_CONFIG_HI); - - writel(lower_32_bits(msi_phys_addr) | - PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_ACCESS_ENABLE_MASK, - pcie->base + PCIE_MISC_UBUS_BAR1_CONFIG_REMAP); - writel(upper_32_bits(msi_phys_addr), - pcie->base + PCIE_MISC_UBUS_BAR1_CONFIG_REMAP_HI); } - bridge->ops = pcie->soc_base == BCM7425 ? &brcm7425_pcie_ops : &brcm_pcie_ops; + bridge->ops = pcie->cfg->soc_base == BCM7425 ? + &brcm7425_pcie_ops : &brcm_pcie_ops; bridge->sysdata = pcie; platform_set_drvdata(pdev, pcie); @@ -2459,3 +2001,4 @@ module_platform_driver(brcm_pcie_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Broadcom STB PCIe RC driver"); MODULE_AUTHOR("Broadcom"); +MODULE_SOFTDEP("pre: irq_bcm2712_mip");