linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/6] Add PCI driver for the Apple M1
@ 2021-08-16  3:16 Alyssa Rosenzweig
  2021-08-16  3:16 ` [PATCH v2 1/6] dt-bindings: pci: Add DT bindings for apple,pcie Alyssa Rosenzweig
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Alyssa Rosenzweig @ 2021-08-16  3:16 UTC (permalink / raw)
  To: linux-pci
  Cc: Bjorn Helgaas, Rob Herring, Lorenzo Pieralisi,
	Krzysztof Wilczyński, Alyssa Rosenzweig, Stan Skowronek,
	Marc Zyngier, Mark Kettenis, Sven Peter, Hector Martin,
	devicetree, linux-kernel

This adds a PCIe driver for the internal bus on the Apple M1 (and
presumably other Apple system-on-chips). It's based on the work of Marc
Zyngier, Mark Kettenis, and Stan Skowronek (Corellium). In conjunction
with a pinctrl driver, this enables the USB type-A ports and the
Ethernet port. It also paves the way for Wi-Fi and Bluetooth, but that
requires further work.

For the largest change since v1 of the series-- this now uses Mark
Kettenis's device tree bindings for PCIe. This series contains Mark's
patches (currently under discussion on the LKML) adding the device tree
nodes required for PCIe. I have made minor modifications to Mark's
original patches to get everything working under Linux:

* In the bindings themselves, I've increased the maximum number of
  interrupts to accommodate the full set.
* In the PCIe node, I've added the full set of interrupts.
* I've added the PCIe DART nodes (IOMMUs) and the corresponding
  iommu-map(-mask) properties already covered in the bindings.
* I've tweaked the sizes of the `reg` blocks. Otherwise I got a page
  fault early on.

I've collected the patches required to test on this branch:

	https://github.com/mu-one/linux/commits/pcie-v2

This branch is based on linux-next and contains a GPIO (pinctrl) driver,
a clock gate driver, additional device tree nodes, and this series.  The
type-A ports and Ethernet should work out-of-the-box on that tree,
provided the kernel is booted through m1n1. This improves on Maz's
initial PCIe driver, which required U-Boot to function.

I've started using Linux on M1 as my workstation for Panfrost
development, so this should have 40 hours of testing by this time next
week.

== Project Blurb ==

Asahi Linux is an open community project dedicated to developing and
maintaining mainline support for Apple Silicon on Linux. Feel free to
drop by #asahi and #asahi-dev on OFTC to chat with us, or check
our website for more information on the project:

== Changes ==

Changes for v2:
- Cherrypicked Mark's device tree bindings and switched to using them.
- Split up the PCI driver patch into 3.
- Large numbers of minor changes to the driver better match upstream
  quality standards (using more helper functions, etc.)

Alyssa Rosenzweig (3):
  PCI: apple: Add initial hardware bring-up
  PCI: apple: Set up reference clocks when probing
  PCI: apple: Add MSI handling

Mark Kettenis (3):
  dt-bindings: pci: Add DT bindings for apple,pcie
  arm64: apple: Add pinctrl nodes
  arm64: apple: Add PCIe node

 .../devicetree/bindings/pci/apple,pcie.yaml   | 166 +++++++
 MAINTAINERS                                   |   7 +
 arch/arm64/boot/dts/apple/t8103.dtsi          | 207 ++++++++
 drivers/pci/controller/Kconfig                |  12 +
 drivers/pci/controller/Makefile               |   1 +
 drivers/pci/controller/pcie-apple.c           | 448 ++++++++++++++++++
 6 files changed, 841 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/apple,pcie.yaml
 create mode 100644 drivers/pci/controller/pcie-apple.c

-- 
2.30.2


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/6] dt-bindings: pci: Add DT bindings for apple,pcie
  2021-08-16  3:16 [PATCH v2 0/6] Add PCI driver for the Apple M1 Alyssa Rosenzweig
@ 2021-08-16  3:16 ` Alyssa Rosenzweig
  2021-08-16  3:16 ` [PATCH v2 2/6] PCI: apple: Add initial hardware bring-up Alyssa Rosenzweig
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Alyssa Rosenzweig @ 2021-08-16  3:16 UTC (permalink / raw)
  To: linux-pci
  Cc: Bjorn Helgaas, Rob Herring, Lorenzo Pieralisi,
	Krzysztof Wilczyński, Alyssa Rosenzweig, Stan Skowronek,
	Marc Zyngier, Mark Kettenis, Sven Peter, Hector Martin,
	devicetree, linux-kernel

From: Mark Kettenis <kettenis@openbsd.org>

The Apple PCIe host controller is a PCIe host controller with
multiple root ports present in Apple ARM SoC platforms, including
various iPhone and iPad devices and the "Apple Silicon" Macs.

Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
---
 .../devicetree/bindings/pci/apple,pcie.yaml   | 166 ++++++++++++++++++
 MAINTAINERS                                   |   1 +
 2 files changed, 167 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/apple,pcie.yaml

diff --git a/Documentation/devicetree/bindings/pci/apple,pcie.yaml b/Documentation/devicetree/bindings/pci/apple,pcie.yaml
new file mode 100644
index 000000000000..054f6f069833
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/apple,pcie.yaml
@@ -0,0 +1,166 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/apple,pcie.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Apple PCIe host controller
+
+maintainers:
+  - Mark Kettenis <kettenis@openbsd.org>
+
+description: |
+  The Apple PCIe host controller is a PCIe host controller with
+  multiple root ports present in Apple ARM SoC platforms, including
+  various iPhone and iPad devices and the "Apple Silicon" Macs.
+  The controller incorporates Synopsys DesigWare PCIe logic to
+  implements its root ports.  But the ATU found on most DesignWare
+  PCIe host bridges is absent.
+  All root ports share a single ECAM space, but separate GPIOs are
+  used to take the PCI devices on those ports out of reset.  Therefore
+  the standard "reset-gpio" and "max-link-speed" properties appear on
+  the child nodes that represent the PCI bridges that correspond to
+  the individual root ports.
+  MSIs are handled by the PCIe controller and translated into regular
+  interrupts.  A range of 32 MSIs is provided.  These 32 MSIs can be
+  distributed over the root ports as the OS sees fit by programming
+  the PCIe controller's port registers.
+
+allOf:
+  - $ref: /schemas/pci/pci-bus.yaml#
+
+properties:
+  compatible:
+    items:
+      - const: apple,t8103-pcie
+      - const: apple,pcie
+
+  reg:
+    minItems: 3
+    maxItems: 5
+
+  reg-names:
+    minItems: 3
+    maxItems: 5
+    items:
+      - const: config
+      - const: rc
+      - const: port0
+      - const: port1
+      - const: port2
+
+  ranges:
+    minItems: 2
+    maxItems: 2
+
+  interrupts:
+    description:
+      Interrupt specifiers.
+    minItems: 1
+    maxItems: 35
+
+  msi-controller: true
+  msi-parent: true
+
+  msi-ranges:
+    description:
+      A list of pairs <intid span>, where "intid" is the first
+      interrupt number that can be used as an MSI, and "span" the size
+      of that range.
+    $ref: /schemas/types.yaml#/definitions/uint32-matrix
+    items:
+      minItems: 2
+      maxItems: 2
+
+  iommu-map: true
+  iommu-map-mask: true
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - bus-range
+  - interrupts
+  - msi-controller
+  - msi-parent
+  - msi-ranges
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/apple-aic.h>
+
+    soc {
+      #address-cells = <2>;
+      #size-cells = <2>;
+
+      pcie0: pcie@690000000 {
+        compatible = "apple,t8103-pcie", "apple,pcie";
+        device_type = "pci";
+
+        reg = <0x6 0x90000000 0x0 0x1000000>,
+              <0x6 0x80000000 0x0 0x4000>,
+              <0x6 0x81000000 0x0 0x8000>,
+              <0x6 0x82000000 0x0 0x8000>,
+              <0x6 0x83000000 0x0 0x8000>;
+        reg-names = "config", "rc", "port0", "port1", "port2";
+
+        interrupt-parent = <&aic>;
+        interrupts = <AIC_IRQ 695 IRQ_TYPE_LEVEL_HIGH>,
+                     <AIC_IRQ 698 IRQ_TYPE_LEVEL_HIGH>,
+                     <AIC_IRQ 701 IRQ_TYPE_LEVEL_HIGH>;
+
+        msi-controller;
+        msi-parent = <&pcie0>;
+        msi-ranges = <704 32>;
+
+        iommu-map = <0x100 &dart0 1 1>,
+                    <0x200 &dart1 1 1>,
+                    <0x300 &dart2 1 1>;
+        iommu-map-mask = <0xff00>;
+
+        bus-range = <0 3>;
+        #address-cells = <3>;
+        #size-cells = <2>;
+        ranges = <0x43000000 0x6 0xa0000000 0x6 0xa0000000 0x0 0x20000000>,
+                 <0x02000000 0x0 0xc0000000 0x6 0xc0000000 0x0 0x40000000>;
+
+        clocks = <&pcie_core_clk>, <&pcie_aux_clk>, <&pcie_ref_clk>;
+        pinctrl-0 = <&pcie_pins>;
+        pinctrl-names = "default";
+
+        pci@0,0 {
+          device_type = "pci";
+          reg = <0x0 0x0 0x0 0x0 0x0>;
+          reset-gpios = <&pinctrl_ap 152 0>;
+          max-link-speed = <2>;
+
+          #address-cells = <3>;
+          #size-cells = <2>;
+          ranges;
+        };
+
+        pci@1,0 {
+          device_type = "pci";
+          reg = <0x800 0x0 0x0 0x0 0x0>;
+          reset-gpios = <&pinctrl_ap 153 0>;
+          max-link-speed = <2>;
+
+          #address-cells = <3>;
+          #size-cells = <2>;
+          ranges;
+        };
+
+        pci@2,0 {
+          device_type = "pci";
+          reg = <0x1000 0x0 0x0 0x0 0x0>;
+          reset-gpios = <&pinctrl_ap 33 0>;
+          max-link-speed = <1>;
+
+          #address-cells = <3>;
+          #size-cells = <2>;
+          ranges;
+        };
+      };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index b63403793c81..a5687cf6f925 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1701,6 +1701,7 @@ C:	irc://irc.oftc.net/asahi-dev
 T:	git https://github.com/AsahiLinux/linux.git
 F:	Documentation/devicetree/bindings/arm/apple.yaml
 F:	Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
+F:	Documentation/devicetree/bindings/pci/apple,pcie.yaml
 F:	Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
 F:	arch/arm64/boot/dts/apple/
 F:	drivers/irqchip/irq-apple-aic.c
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/6] PCI: apple: Add initial hardware bring-up
  2021-08-16  3:16 [PATCH v2 0/6] Add PCI driver for the Apple M1 Alyssa Rosenzweig
  2021-08-16  3:16 ` [PATCH v2 1/6] dt-bindings: pci: Add DT bindings for apple,pcie Alyssa Rosenzweig
@ 2021-08-16  3:16 ` Alyssa Rosenzweig
  2021-08-22 18:42   ` Mark Kettenis
  2021-08-16  3:16 ` [PATCH v2 3/6] PCI: apple: Set up reference clocks when probing Alyssa Rosenzweig
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 9+ messages in thread
From: Alyssa Rosenzweig @ 2021-08-16  3:16 UTC (permalink / raw)
  To: linux-pci
  Cc: Bjorn Helgaas, Rob Herring, Lorenzo Pieralisi,
	Krzysztof Wilczyński, Alyssa Rosenzweig, Stan Skowronek,
	Marc Zyngier, Mark Kettenis, Sven Peter, Hector Martin,
	devicetree, linux-kernel

Add a minimal driver to bring up the PCIe bus on Apple system-on-chips,
particularly the Apple M1. This driver exposes the internal bus used for
the USB type-A ports, Ethernet, Wi-Fi, and Bluetooth. Bringing up the
radios requires additional drivers beyond what's necessary for PCIe
itself.

In this patch, a minimal driver is added that brings up the PCIe bus on
probe. This logic is derived from Corellium's driver via Mark Kettenis's
U-Boot patches.

Co-developed-by: Stan Skowronek <stan@corellium.com>
Signed-off-by: Stan Skowronek <stan@corellium.com>
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
---
 MAINTAINERS                         |   6 +
 drivers/pci/controller/Kconfig      |  12 ++
 drivers/pci/controller/Makefile     |   1 +
 drivers/pci/controller/pcie-apple.c | 251 ++++++++++++++++++++++++++++
 4 files changed, 270 insertions(+)
 create mode 100644 drivers/pci/controller/pcie-apple.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a5687cf6f925..47cb3d320c56 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1269,6 +1269,12 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/iommu/apple,dart.yaml
 F:	drivers/iommu/apple-dart.c
 
+APPLE PCIE CONTROLLER DRIVER
+M:	Alyssa Rosenzweig <alyssa@rosenzweig.io>
+L:	linux-pci@vger.kernel.org
+S:	Maintained
+F:	drivers/pci/controller/pcie-apple.c
+
 APPLE SMC DRIVER
 M:	Henrik Rydberg <rydberg@bitmath.org>
 L:	linux-hwmon@vger.kernel.org
diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
index 326f7d13024f..814833a8120d 100644
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -312,6 +312,18 @@ config PCIE_HISI_ERR
 	  Say Y here if you want error handling support
 	  for the PCIe controller's errors on HiSilicon HIP SoCs
 
+config PCIE_APPLE
+	tristate "Apple PCIe controller"
+	depends on ARCH_APPLE || COMPILE_TEST
+	depends on OF
+	depends on PCI_MSI_IRQ_DOMAIN
+	help
+	  Say Y here if you want to enable PCIe controller support on Apple
+	  system-on-chips, like the Apple M1. This is required for the USB
+	  type-A ports, Ethernet, Wi-Fi, and Bluetooth.
+
+	  If unsure, say Y if you have an Apple Silicon system.
+
 source "drivers/pci/controller/dwc/Kconfig"
 source "drivers/pci/controller/mobiveil/Kconfig"
 source "drivers/pci/controller/cadence/Kconfig"
diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
index aaf30b3dcc14..f9d40bad932c 100644
--- a/drivers/pci/controller/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_VMD) += vmd.o
 obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
 obj-$(CONFIG_PCI_LOONGSON) += pci-loongson.o
 obj-$(CONFIG_PCIE_HISI_ERR) += pcie-hisi-error.o
+obj-$(CONFIG_PCIE_APPLE) += pcie-apple.o
 # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
 obj-y				+= dwc/
 obj-y				+= mobiveil/
diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
new file mode 100644
index 000000000000..a1efcc3373ea
--- /dev/null
+++ b/drivers/pci/controller/pcie-apple.c
@@ -0,0 +1,251 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCIe host bridge driver for Apple system-on-chips.
+ *
+ * The HW is ECAM compliant, so once the controller is initialized, the driver
+ * mostly only needs MSI handling. Initialization requires enabling power and
+ * clocks, along with a number of register pokes.
+ *
+ * Copyright (C) 2021 Alyssa Rosenzweig <alyssa@rosenzweig.io>
+ * Copyright (C) 2021 Google LLC
+ * Copyright (C) 2021 Corellium LLC
+ * Copyright (C) 2021 Mark Kettenis <kettenis@openbsd.org>
+ *
+ * Author: Alyssa Rosenzweig <alyssa@rosenzweig.io>
+ * Author: Marc Zyngier <maz@kernel.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/msi.h>
+#include <linux/of_irq.h>
+#include <linux/pci-ecam.h>
+#include <linux/iopoll.h>
+#include <linux/gpio/consumer.h>
+
+#define CORE_RC_PHYIF_CTL		0x00024
+#define   CORE_RC_PHYIF_CTL_RUN		BIT(0)
+#define CORE_RC_PHYIF_STAT		0x00028
+#define   CORE_RC_PHYIF_STAT_REFCLK	BIT(4)
+#define CORE_RC_CTL			0x00050
+#define   CORE_RC_CTL_RUN		BIT(0)
+#define CORE_RC_STAT			0x00058
+#define   CORE_RC_STAT_READY		BIT(0)
+#define CORE_FABRIC_STAT		0x04000
+#define   CORE_FABRIC_STAT_MASK		0x001F001F
+#define CORE_LANE_CFG(port)		(0x84000 + 0x4000 * (port))
+#define   CORE_LANE_CFG_REFCLK0REQ	BIT(0)
+#define   CORE_LANE_CFG_REFCLK1		BIT(1)
+#define   CORE_LANE_CFG_REFCLK0ACK	BIT(2)
+#define   CORE_LANE_CFG_REFCLKEN	(BIT(9) | BIT(10))
+#define CORE_LANE_CTL(port)		(0x84004 + 0x4000 * (port))
+#define   CORE_LANE_CTL_CFGACC		BIT(15)
+
+#define PORT_LTSSMCTL			0x00080
+#define   PORT_LTSSMCTL_START		BIT(0)
+#define PORT_INTSTAT			0x00100
+#define   PORT_INT_TUNNEL_ERR		BIT(31)
+#define   PORT_INT_CPL_TIMEOUT		BIT(23)
+#define   PORT_INT_RID2SID_MAPERR	BIT(22)
+#define   PORT_INT_CPL_ABORT		BIT(21)
+#define   PORT_INT_MSI_BAD_DATA		BIT(19)
+#define   PORT_INT_MSI_ERR		BIT(18)
+#define   PORT_INT_REQADDR_GT32		BIT(17)
+#define   PORT_INT_AF_TIMEOUT		BIT(15)
+#define   PORT_INT_LINK_DOWN		BIT(14)
+#define   PORT_INT_LINK_UP		BIT(12)
+#define   PORT_INT_LINK_BWMGMT		BIT(11)
+#define   PORT_INT_AER_MASK		(15 << 4)
+#define   PORT_INT_PORT_ERR		BIT(4)
+#define   PORT_INT_INTx(i)		BIT(i)
+#define   PORT_INT_INTxALL		15
+#define PORT_INTMSK			0x00104
+#define PORT_INTMSKSET			0x00108
+#define PORT_INTMSKCLR			0x0010c
+#define PORT_MSICFG			0x00124
+#define   PORT_MSICFG_EN		BIT(0)
+#define   PORT_MSICFG_L2MSINUM_SHIFT	4
+#define PORT_MSIBASE			0x00128
+#define   PORT_MSIBASE_1_SHIFT		16
+#define PORT_MSIADDR			0x00168
+#define PORT_LINKSTS			0x00208
+#define   PORT_LINKSTS_UP		BIT(0)
+#define   PORT_LINKSTS_BUSY		BIT(2)
+#define PORT_LINKCMDSTS			0x00210
+#define PORT_OUTS_NPREQS		0x00284
+#define   PORT_OUTS_NPREQS_REQ		BIT(24)
+#define   PORT_OUTS_NPREQS_CPL		BIT(16)
+#define PORT_RXWR_FIFO			0x00288
+#define   PORT_RXWR_FIFO_HDR		GENMASK(15, 10)
+#define   PORT_RXWR_FIFO_DATA		GENMASK(9, 0)
+#define PORT_RXRD_FIFO			0x0028C
+#define   PORT_RXRD_FIFO_REQ		GENMASK(6, 0)
+#define PORT_OUTS_CPLS			0x00290
+#define   PORT_OUTS_CPLS_SHRD		GENMASK(14, 8)
+#define   PORT_OUTS_CPLS_WAIT		GENMASK(6, 0)
+#define PORT_APPCLK			0x00800
+#define   PORT_APPCLK_EN		BIT(0)
+#define   PORT_APPCLK_CGDIS		BIT(8)
+#define PORT_STATUS			0x00804
+#define   PORT_STATUS_READY		BIT(0)
+#define PORT_REFCLK			0x00810
+#define   PORT_REFCLK_EN		BIT(0)
+#define   PORT_REFCLK_CGDIS		BIT(8)
+#define PORT_PERST			0x00814
+#define   PORT_PERST_OFF		BIT(0)
+#define PORT_RID2SID(i16)		(0x00828 + 4 * (i16))
+#define   PORT_RID2SID_VALID		BIT(31)
+#define   PORT_RID2SID_SID_SHIFT	16
+#define   PORT_RID2SID_BUS_SHIFT	8
+#define   PORT_RID2SID_DEV_SHIFT	3
+#define   PORT_RID2SID_FUNC_SHIFT	0
+#define PORT_OUTS_PREQS_HDR		0x00980
+#define   PORT_OUTS_PREQS_HDR_MASK	GENMASK(9, 0)
+#define PORT_OUTS_PREQS_DATA		0x00984
+#define   PORT_OUTS_PREQS_DATA_MASK	GENMASK(15, 0)
+#define PORT_TUNCTRL			0x00988
+#define   PORT_TUNCTRL_PERST_ON		BIT(0)
+#define   PORT_TUNCTRL_PERST_ACK_REQ	BIT(1)
+#define PORT_TUNSTAT			0x0098c
+#define   PORT_TUNSTAT_PERST_ON		BIT(0)
+#define   PORT_TUNSTAT_PERST_ACK_PEND	BIT(1)
+#define PORT_PREFMEM_ENABLE		0x00994
+
+/* The doorbell address is "well known" */
+#define DOORBELL_ADDR			0xfffff000
+
+struct apple_pcie {
+	struct mutex		lock;
+	struct device		*dev;
+	void __iomem            *rc;
+};
+
+static inline void rmwl(u32 clr, u32 set, void __iomem *addr)
+{
+	writel_relaxed((readl_relaxed(addr) & ~clr) | set, addr);
+}
+
+static int apple_pcie_setup_port(struct apple_pcie *pcie,
+				 struct gpio_desc *reset,
+				 unsigned int i)
+{
+	struct platform_device *platform = to_platform_device(pcie->dev);
+	void __iomem *port;
+	uint32_t stat;
+	int ret;
+
+	port = devm_platform_ioremap_resource(platform, i + 2);
+
+	if (IS_ERR(port))
+		return -ENODEV;
+
+	/* Skip setup if the link was already enabled by the bootloader */
+	if (readl_relaxed(port + PORT_LINKSTS) & PORT_LINKSTS_UP)
+		return 0;
+
+	rmwl(0, PORT_PERST_OFF, port + PORT_PERST);
+	gpiod_set_value(reset, 1);
+
+	ret = readl_relaxed_poll_timeout(port + PORT_STATUS, stat,
+					 stat & PORT_STATUS_READY, 100, 250000);
+	if (ret < 0) {
+		dev_err(pcie->dev, "port %u ready wait timeout\n", i);
+		return ret;
+	}
+
+	/* Configure MSIs */
+	writel_relaxed(DOORBELL_ADDR, port + PORT_MSIADDR);
+	writel_relaxed(0, port + PORT_MSIBASE);
+
+	/* Enable 32 MSIs */
+	writel_relaxed((5 << PORT_MSICFG_L2MSINUM_SHIFT) | PORT_MSICFG_EN,
+		       port + PORT_MSICFG);
+
+	/* Enable link interrupts */
+	writel_relaxed(0xfb512fff, port + PORT_INTMSKSET);
+
+	writel_relaxed(PORT_INT_LINK_UP | PORT_INT_LINK_DOWN |
+		       PORT_INT_AF_TIMEOUT | PORT_INT_REQADDR_GT32 |
+		       PORT_INT_MSI_ERR | PORT_INT_MSI_BAD_DATA |
+		       PORT_INT_CPL_ABORT | PORT_INT_CPL_TIMEOUT | (1 << 26),
+		       port + PORT_INTSTAT);
+
+	/* Flush writes and enable the link */
+	dma_wmb();
+	writel_relaxed(PORT_LTSSMCTL_START, port + PORT_LTSSMCTL);
+
+	return 0;
+}
+
+static int apple_m1_pci_init(struct pci_config_window *cfg)
+{
+	struct device *dev = cfg->parent;
+	struct platform_device *platform = to_platform_device(dev);
+
+	struct apple_pcie *pcie;
+	struct device_node *of_port;
+	int ret, i;
+
+	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
+	if (!pcie)
+		return -ENOMEM;
+
+	pcie->dev = dev;
+
+	mutex_init(&pcie->lock);
+
+	pcie->rc = devm_platform_ioremap_resource(platform, 1);
+
+	if (IS_ERR(pcie->rc))
+		return -ENODEV;
+
+	i = 0;
+
+	for_each_child_of_node(dev->of_node, of_port) {
+		struct gpio_desc *reset;
+
+		reset = gpiod_get_from_of_node(of_port, "reset-gpios", 0,
+					       GPIOD_OUT_LOW, "#PERST");
+		if (IS_ERR(reset))
+			return PTR_ERR(reset);
+
+		ret = apple_pcie_setup_port(pcie, reset, i);
+
+		if (ret) {
+			dev_err(pcie->dev, "Port %u setup fail: %d\n", i, ret);
+			return ret;
+		}
+
+		++i;
+	}
+
+	return 0;
+}
+
+static const struct pci_ecam_ops apple_m1_cfg_ecam_ops = {
+	.init		= apple_m1_pci_init,
+	.pci_ops	= {
+		.map_bus	= pci_ecam_map_bus,
+		.read		= pci_generic_config_read,
+		.write		= pci_generic_config_write,
+	}
+};
+
+static const struct of_device_id apple_pci_of_match[] = {
+	{ .compatible = "apple,pcie", .data = &apple_m1_cfg_ecam_ops },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, apple_pci_of_match);
+
+static struct platform_driver apple_pci_driver = {
+	.driver = {
+		.name = "pcie-apple",
+		.of_match_table = apple_pci_of_match,
+	},
+	.probe = pci_host_common_probe,
+	.remove = pci_host_common_remove,
+};
+module_platform_driver(apple_pci_driver);
+
+MODULE_LICENSE("GPL v2");
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 3/6] PCI: apple: Set up reference clocks when probing
  2021-08-16  3:16 [PATCH v2 0/6] Add PCI driver for the Apple M1 Alyssa Rosenzweig
  2021-08-16  3:16 ` [PATCH v2 1/6] dt-bindings: pci: Add DT bindings for apple,pcie Alyssa Rosenzweig
  2021-08-16  3:16 ` [PATCH v2 2/6] PCI: apple: Add initial hardware bring-up Alyssa Rosenzweig
@ 2021-08-16  3:16 ` Alyssa Rosenzweig
  2021-08-16  3:16 ` [PATCH v2 4/6] PCI: apple: Add MSI handling Alyssa Rosenzweig
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Alyssa Rosenzweig @ 2021-08-16  3:16 UTC (permalink / raw)
  To: linux-pci
  Cc: Bjorn Helgaas, Rob Herring, Lorenzo Pieralisi,
	Krzysztof Wilczyński, Alyssa Rosenzweig, Stan Skowronek,
	Marc Zyngier, Mark Kettenis, Sven Peter, Hector Martin,
	devicetree, linux-kernel

Apple's PCIe controller requires clocks to be configured in order to
bring up the hardware. Add the register pokes required to do so. Adapted
from Corellium's driver via Mark Kettenis's U-Boot patches.

Co-developed-by: Stan Skowronek <stan@corellium.com>
Signed-off-by: Stan Skowronek <stan@corellium.com>
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
---
 drivers/pci/controller/pcie-apple.c | 47 +++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
index a1efcc3373ea..4ab767cf841b 100644
--- a/drivers/pci/controller/pcie-apple.c
+++ b/drivers/pci/controller/pcie-apple.c
@@ -126,6 +126,47 @@ static inline void rmwl(u32 clr, u32 set, void __iomem *addr)
 	writel_relaxed((readl_relaxed(addr) & ~clr) | set, addr);
 }
 
+static int apple_pcie_setup_refclk(void __iomem *rc,
+				   void __iomem *port,
+				   unsigned int idx)
+{
+	u32 stat;
+	int res;
+
+	res = readl_relaxed_poll_timeout(rc + CORE_RC_PHYIF_STAT, stat,
+					 stat & CORE_RC_PHYIF_STAT_REFCLK,
+					 100, 50000);
+	if (res < 0)
+		return res;
+
+	rmwl(0, CORE_LANE_CTL_CFGACC, rc + CORE_LANE_CTL(idx));
+	rmwl(0, CORE_LANE_CFG_REFCLK0REQ, rc + CORE_LANE_CFG(idx));
+
+	res = readl_relaxed_poll_timeout(rc + CORE_LANE_CFG(idx), stat,
+					 stat & CORE_LANE_CFG_REFCLK0ACK,
+					 100, 50000);
+	if (res < 0)
+		return res;
+
+	rmwl(0, CORE_LANE_CFG_REFCLK1, rc + CORE_LANE_CFG(idx));
+	res = readl_relaxed_poll_timeout(rc + CORE_LANE_CFG(idx), stat,
+					 stat & CORE_LANE_CFG_REFCLK1,
+					 100, 50000);
+
+	if (res < 0)
+		return res;
+
+	rmwl(CORE_LANE_CTL_CFGACC, 0, rc + CORE_LANE_CTL(idx));
+
+	/* Flush writes before enabling the clocks */
+	dma_wmb();
+
+	rmwl(0, CORE_LANE_CFG_REFCLKEN, rc + CORE_LANE_CFG(idx));
+	rmwl(0, PORT_REFCLK_EN, port + PORT_REFCLK);
+
+	return 0;
+}
+
 static int apple_pcie_setup_port(struct apple_pcie *pcie,
 				 struct gpio_desc *reset,
 				 unsigned int i)
@@ -144,6 +185,12 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
 	if (readl_relaxed(port + PORT_LINKSTS) & PORT_LINKSTS_UP)
 		return 0;
 
+	rmwl(0, PORT_APPCLK_EN, port + PORT_APPCLK);
+
+	ret = apple_pcie_setup_refclk(pcie->rc, port, i);
+	if (ret < 0)
+		return ret;
+
 	rmwl(0, PORT_PERST_OFF, port + PORT_PERST);
 	gpiod_set_value(reset, 1);
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 4/6] PCI: apple: Add MSI handling
  2021-08-16  3:16 [PATCH v2 0/6] Add PCI driver for the Apple M1 Alyssa Rosenzweig
                   ` (2 preceding siblings ...)
  2021-08-16  3:16 ` [PATCH v2 3/6] PCI: apple: Set up reference clocks when probing Alyssa Rosenzweig
@ 2021-08-16  3:16 ` Alyssa Rosenzweig
  2021-08-16  3:16 ` [PATCH v2 5/6] arm64: apple: Add pinctrl nodes Alyssa Rosenzweig
  2021-08-16  3:16 ` [PATCH v2 6/6] arm64: apple: Add PCIe node Alyssa Rosenzweig
  5 siblings, 0 replies; 9+ messages in thread
From: Alyssa Rosenzweig @ 2021-08-16  3:16 UTC (permalink / raw)
  To: linux-pci
  Cc: Bjorn Helgaas, Rob Herring, Lorenzo Pieralisi,
	Krzysztof Wilczyński, Alyssa Rosenzweig, Stan Skowronek,
	Marc Zyngier, Mark Kettenis, Sven Peter, Hector Martin,
	devicetree, linux-kernel

Add MSI handling to the Apple PCIe driver. As the hardware is ECAM
compliant, this code is the only hardware-specific piece required
after probing. This is sufficient to bring up Ethernet and the USB type
A ports.

Co-developed-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
---
 drivers/pci/controller/pcie-apple.c | 152 +++++++++++++++++++++++++++-
 1 file changed, 151 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
index 4ab767cf841b..04ebb9b956ae 100644
--- a/drivers/pci/controller/pcie-apple.c
+++ b/drivers/pci/controller/pcie-apple.c
@@ -119,6 +119,10 @@ struct apple_pcie {
 	struct mutex		lock;
 	struct device		*dev;
 	void __iomem            *rc;
+	struct irq_domain	*domain;
+	unsigned long		*bitmap;
+	u32			msi_base;
+	u32			nvecs;
 };
 
 static inline void rmwl(u32 clr, u32 set, void __iomem *addr)
@@ -126,6 +130,105 @@ static inline void rmwl(u32 clr, u32 set, void __iomem *addr)
 	writel_relaxed((readl_relaxed(addr) & ~clr) | set, addr);
 }
 
+static void apple_msi_top_irq_mask(struct irq_data *d)
+{
+	pci_msi_mask_irq(d);
+	irq_chip_mask_parent(d);
+}
+
+static void apple_msi_top_irq_unmask(struct irq_data *d)
+{
+	pci_msi_unmask_irq(d);
+	irq_chip_unmask_parent(d);
+}
+
+static struct irq_chip apple_msi_top_chip = {
+	.name			= "PCIe MSI",
+	.irq_mask		= apple_msi_top_irq_mask,
+	.irq_unmask		= apple_msi_top_irq_unmask,
+	.irq_eoi		= irq_chip_eoi_parent,
+	.irq_set_affinity	= irq_chip_set_affinity_parent,
+	.irq_set_type		= irq_chip_set_type_parent,
+};
+
+static void apple_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
+{
+	msg->address_hi = upper_32_bits(DOORBELL_ADDR);
+	msg->address_lo = lower_32_bits(DOORBELL_ADDR);
+	msg->data = data->hwirq;
+}
+
+static struct irq_chip apple_msi_bottom_chip = {
+	.name			= "MSI",
+	.irq_mask		= irq_chip_mask_parent,
+	.irq_unmask		= irq_chip_unmask_parent,
+	.irq_eoi		= irq_chip_eoi_parent,
+	.irq_set_affinity	= irq_chip_set_affinity_parent,
+	.irq_set_type		= irq_chip_set_type_parent,
+	.irq_compose_msi_msg	= apple_msi_compose_msg,
+};
+
+static int apple_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
+				  unsigned int nr_irqs, void *args)
+{
+	struct apple_pcie *pcie = domain->host_data;
+	struct irq_fwspec fwspec;
+	unsigned int i;
+	int ret, hwirq;
+
+	mutex_lock(&pcie->lock);
+
+	hwirq = bitmap_find_free_region(pcie->bitmap, pcie->nvecs,
+					order_base_2(nr_irqs));
+
+	mutex_unlock(&pcie->lock);
+
+	if (hwirq < 0)
+		return -ENOSPC;
+
+	fwspec.fwnode = domain->parent->fwnode;
+	fwspec.param_count = 3;
+	fwspec.param[0] = 0;
+	fwspec.param[1] = hwirq + pcie->msi_base;
+	fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+
+	ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &fwspec);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < nr_irqs; i++) {
+		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+					      &apple_msi_bottom_chip,
+					      domain->host_data);
+	}
+
+	return 0;
+}
+
+static void apple_msi_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 apple_pcie *pcie = domain->host_data;
+
+	mutex_lock(&pcie->lock);
+
+	bitmap_release_region(pcie->bitmap, d->hwirq, order_base_2(nr_irqs));
+
+	mutex_unlock(&pcie->lock);
+}
+
+static const struct irq_domain_ops apple_msi_domain_ops = {
+	.alloc	= apple_msi_domain_alloc,
+	.free	= apple_msi_domain_free,
+};
+
+static struct msi_domain_info apple_msi_info = {
+	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+		   MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX),
+	.chip	= &apple_msi_top_chip,
+};
+
 static int apple_pcie_setup_refclk(void __iomem *rc,
 				   void __iomem *port,
 				   unsigned int idx)
@@ -225,6 +328,53 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
 	return 0;
 }
 
+static int apple_msi_init(struct apple_pcie *pcie)
+{
+	struct fwnode_handle *fwnode = dev_fwnode(pcie->dev);
+	struct device_node *parent_intc;
+	struct irq_domain *parent;
+	int ret;
+
+	ret = of_property_read_u32_index(to_of_node(fwnode), "msi-ranges",
+					 0, &pcie->msi_base);
+	if (ret)
+		return ret;
+
+	ret = of_property_read_u32_index(to_of_node(fwnode), "msi-ranges",
+					 1, &pcie->nvecs);
+	if (ret)
+		return ret;
+
+	pcie->bitmap = devm_bitmap_zalloc(pcie->dev, pcie->nvecs, GFP_KERNEL);
+	if (!pcie->bitmap)
+		return -ENOMEM;
+
+	parent_intc = of_irq_find_parent(to_of_node(fwnode));
+	parent = irq_find_host(parent_intc);
+	if (!parent_intc || !parent) {
+		dev_err(pcie->dev, "failed to find parent domain\n");
+		return -ENXIO;
+	}
+
+	parent = irq_domain_create_hierarchy(parent, 0, pcie->nvecs, fwnode,
+					     &apple_msi_domain_ops, pcie);
+	if (!parent) {
+		dev_err(pcie->dev, "failed to create IRQ domain\n");
+		return -ENOMEM;
+	}
+	irq_domain_update_bus_token(parent, DOMAIN_BUS_NEXUS);
+
+	pcie->domain = pci_msi_create_irq_domain(fwnode, &apple_msi_info,
+						 parent);
+	if (!pcie->domain) {
+		dev_err(pcie->dev, "failed to create MSI domain\n");
+		irq_domain_remove(parent);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
 static int apple_m1_pci_init(struct pci_config_window *cfg)
 {
 	struct device *dev = cfg->parent;
@@ -267,7 +417,7 @@ static int apple_m1_pci_init(struct pci_config_window *cfg)
 		++i;
 	}
 
-	return 0;
+	return apple_msi_init(pcie);
 }
 
 static const struct pci_ecam_ops apple_m1_cfg_ecam_ops = {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 5/6] arm64: apple: Add pinctrl nodes
  2021-08-16  3:16 [PATCH v2 0/6] Add PCI driver for the Apple M1 Alyssa Rosenzweig
                   ` (3 preceding siblings ...)
  2021-08-16  3:16 ` [PATCH v2 4/6] PCI: apple: Add MSI handling Alyssa Rosenzweig
@ 2021-08-16  3:16 ` Alyssa Rosenzweig
  2021-08-16  3:16 ` [PATCH v2 6/6] arm64: apple: Add PCIe node Alyssa Rosenzweig
  5 siblings, 0 replies; 9+ messages in thread
From: Alyssa Rosenzweig @ 2021-08-16  3:16 UTC (permalink / raw)
  To: linux-pci
  Cc: Bjorn Helgaas, Rob Herring, Lorenzo Pieralisi,
	Krzysztof Wilczyński, Alyssa Rosenzweig, Stan Skowronek,
	Marc Zyngier, Mark Kettenis, Sven Peter, Hector Martin,
	devicetree, linux-kernel

From: Mark Kettenis <kettenis@openbsd.org>

Add pinctrl nodes corresponding to the gpio,t8101 nodes in the
Apple device tree for the Mac mini (M1, 2020).

Clock references are left out at the moment and will be added once
the appropriate bindings have been settled upon.

Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
---
 arch/arm64/boot/dts/apple/t8103.dtsi | 83 ++++++++++++++++++++++++++++
 1 file changed, 83 insertions(+)

diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index a1e22a2ea2e5..342e01c6098e 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -9,6 +9,7 @@
 
 #include <dt-bindings/interrupt-controller/apple-aic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/apple.h>
 
 / {
 	compatible = "apple,t8103", "apple,arm-platform";
@@ -131,5 +132,87 @@ aic: interrupt-controller@23b100000 {
 			interrupt-controller;
 			reg = <0x2 0x3b100000 0x0 0x8000>;
 		};
+
+		pinctrl_ap: pinctrl@23c100000 {
+			compatible = "apple,t8103-pinctrl", "apple,pinctrl";
+			reg = <0x2 0x3c100000 0x0 0x100000>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pinctrl_ap 0 0 212>;
+
+			interrupt-controller;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 190 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 191 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 192 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 193 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 194 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 195 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 196 IRQ_TYPE_LEVEL_HIGH>;
+
+			pcie_pins: pcie-pins {
+				pinmux = <APPLE_PINMUX(150, 1)>,
+					 <APPLE_PINMUX(151, 1)>,
+					 <APPLE_PINMUX(32, 1)>;
+			};
+		};
+
+		pinctrl_nub: pinctrl@23d1f0000 {
+			compatible = "apple,t8103-pinctrl", "apple,pinctrl";
+			reg = <0x2 0x3d1f0000 0x0 0x4000>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pinctrl_nub 0 0 23>;
+
+			interrupt-controller;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 330 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 331 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 332 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 333 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 334 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 335 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 336 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pinctrl_smc: pinctrl@23e820000 {
+			compatible = "apple,t8103-pinctrl", "apple,pinctrl";
+			reg = <0x2 0x3e820000 0x0 0x4000>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pinctrl_smc 0 0 16>;
+
+			interrupt-controller;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 391 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 392 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 393 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 394 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 395 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 396 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 397 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pinctrl_aop: pinctrl@24a820000 {
+			compatible = "apple,t8103-pinctrl", "apple,pinctrl";
+			reg = <0x2 0x4a820000 0x0 0x4000>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pinctrl_aop 0 0 42>;
+
+			interrupt-controller;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 268 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 269 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 270 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 271 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 272 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 273 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 274 IRQ_TYPE_LEVEL_HIGH>;
+		};
 	};
 };
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 6/6] arm64: apple: Add PCIe node
  2021-08-16  3:16 [PATCH v2 0/6] Add PCI driver for the Apple M1 Alyssa Rosenzweig
                   ` (4 preceding siblings ...)
  2021-08-16  3:16 ` [PATCH v2 5/6] arm64: apple: Add pinctrl nodes Alyssa Rosenzweig
@ 2021-08-16  3:16 ` Alyssa Rosenzweig
  2021-08-22 18:28   ` Mark Kettenis
  5 siblings, 1 reply; 9+ messages in thread
From: Alyssa Rosenzweig @ 2021-08-16  3:16 UTC (permalink / raw)
  To: linux-pci
  Cc: Bjorn Helgaas, Rob Herring, Lorenzo Pieralisi,
	Krzysztof Wilczyński, Alyssa Rosenzweig, Stan Skowronek,
	Marc Zyngier, Mark Kettenis, Sven Peter, Hector Martin,
	devicetree, linux-kernel

From: Mark Kettenis <kettenis@openbsd.org>

Add node corresponding to the apcie,t8103 node in the Apple device tree
for the Mac mini (M1, 2020).

Clock references are left out at the moment and will be added once the
appropriate bindings have been settled on.

Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
---
 arch/arm64/boot/dts/apple/t8103.dtsi | 124 +++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index 342e01c6098e..c0d3b2fb0366 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -214,5 +214,129 @@ pinctrl_aop: pinctrl@24a820000 {
 				     <AIC_IRQ 273 IRQ_TYPE_LEVEL_HIGH>,
 				     <AIC_IRQ 274 IRQ_TYPE_LEVEL_HIGH>;
 		};
+
+		pcie0_dart_0: dart@681008000 {
+			compatible = "apple,t8103-dart";
+			reg = <0x6 0x81008000 0x0 0x4000>;
+			#iommu-cells = <1>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 696 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pcie0_dart_1: dart@682008000 {
+			compatible = "apple,t8103-dart";
+			reg = <0x6 0x82008000 0x0 0x4000>;
+			#iommu-cells = <1>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 699 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pcie0_dart_2: dart@683008000 {
+			compatible = "apple,t8103-dart";
+			reg = <0x6 0x83008000 0x0 0x4000>;
+			#iommu-cells = <1>;
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 702 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pcie0: pcie@690000000 {
+			compatible = "apple,t8103-pcie", "apple,pcie";
+			device_type = "pci";
+
+			reg = <0x6 0x90000000 0x0 0x1000000>,
+			      <0x6 0x80000000 0x0 0x100000>,
+			      <0x6 0x81000000 0x0 0x4000>,
+			      <0x6 0x82000000 0x0 0x4000>,
+			      <0x6 0x83000000 0x0 0x4000>;
+			reg-names = "config", "rc", "port0", "port1", "port2";
+
+			interrupt-parent = <&aic>;
+			interrupts = <AIC_IRQ 695 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 698 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 701 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 704 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 705 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 706 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 707 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 708 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 709 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 710 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 711 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 712 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 713 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 714 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 715 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 716 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 717 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 718 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 719 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 720 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 721 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 722 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 723 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 724 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 725 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 726 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 727 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 728 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 729 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 730 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 731 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 732 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 733 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 734 IRQ_TYPE_LEVEL_HIGH>,
+				     <AIC_IRQ 735 IRQ_TYPE_LEVEL_HIGH>;
+
+			msi-controller;
+			msi-parent = <&pcie0>;
+			msi-ranges = <704 32>;
+
+			iommu-map = <0x100 &pcie0_dart_0 0 1>,
+				    <0x200 &pcie0_dart_1 0 1>,
+				    <0x300 &pcie0_dart_2 0 1>;
+			iommu-map-mask = <0xff00>;
+
+			bus-range = <0 3>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges = <0x43000000 0x6 0xa0000000 0x6 0xa0000000 0x0 0x20000000>,
+				 <0x02000000 0x0 0xc0000000 0x6 0xc0000000 0x0 0x40000000>;
+
+			pinctrl-0 = <&pcie_pins>;
+			pinctrl-names = "default";
+
+			pci@0,0 {
+				device_type = "pci";
+				reg = <0x0 0x0 0x0 0x0 0x0>;
+				reset-gpios = <&pinctrl_ap 152 0>;
+				max-link-speed = <2>;
+
+				#address-cells = <3>;
+				#size-cells = <2>;
+				ranges;
+			};
+
+			pci@1,0 {
+				device_type = "pci";
+				reg = <0x800 0x0 0x0 0x0 0x0>;
+				reset-gpios = <&pinctrl_ap 153 0>;
+				max-link-speed = <2>;
+
+				#address-cells = <3>;
+				#size-cells = <2>;
+				ranges;
+			};
+
+			pci@2,0 {
+				device_type = "pci";
+				reg = <0x1000 0x0 0x0 0x0 0x0>;
+				reset-gpios = <&pinctrl_ap 33 0>;
+				max-link-speed = <1>;
+
+				#address-cells = <3>;
+				#size-cells = <2>;
+				ranges;
+			};
+		};
 	};
 };
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 6/6] arm64: apple: Add PCIe node
  2021-08-16  3:16 ` [PATCH v2 6/6] arm64: apple: Add PCIe node Alyssa Rosenzweig
@ 2021-08-22 18:28   ` Mark Kettenis
  0 siblings, 0 replies; 9+ messages in thread
From: Mark Kettenis @ 2021-08-22 18:28 UTC (permalink / raw)
  To: Alyssa Rosenzweig
  Cc: linux-pci, bhelgaas, robh+dt, lorenzo.pieralisi, kw, alyssa,
	stan, maz, kettenis, sven, marcan, devicetree, linux-kernel

> From: Alyssa Rosenzweig <alyssa@rosenzweig.io>
> Date: Sun, 15 Aug 2021 23:16:21 -0400
> 
> From: Mark Kettenis <kettenis@openbsd.org>
> 
> Add node corresponding to the apcie,t8103 node in the Apple device tree
> for the Mac mini (M1, 2020).
> 
> Clock references are left out at the moment and will be added once the
> appropriate bindings have been settled on.
> 
> Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
> Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
> ---
>  arch/arm64/boot/dts/apple/t8103.dtsi | 124 +++++++++++++++++++++++++++
>  1 file changed, 124 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
> index 342e01c6098e..c0d3b2fb0366 100644
> --- a/arch/arm64/boot/dts/apple/t8103.dtsi
> +++ b/arch/arm64/boot/dts/apple/t8103.dtsi
> @@ -214,5 +214,129 @@ pinctrl_aop: pinctrl@24a820000 {
>  				     <AIC_IRQ 273 IRQ_TYPE_LEVEL_HIGH>,
>  				     <AIC_IRQ 274 IRQ_TYPE_LEVEL_HIGH>;
>  		};
> +
> +		pcie0_dart_0: dart@681008000 {
> +			compatible = "apple,t8103-dart";
> +			reg = <0x6 0x81008000 0x0 0x4000>;
> +			#iommu-cells = <1>;
> +			interrupt-parent = <&aic>;
> +			interrupts = <AIC_IRQ 696 IRQ_TYPE_LEVEL_HIGH>;
> +		};
> +
> +		pcie0_dart_1: dart@682008000 {
> +			compatible = "apple,t8103-dart";
> +			reg = <0x6 0x82008000 0x0 0x4000>;
> +			#iommu-cells = <1>;
> +			interrupt-parent = <&aic>;
> +			interrupts = <AIC_IRQ 699 IRQ_TYPE_LEVEL_HIGH>;
> +		};
> +
> +		pcie0_dart_2: dart@683008000 {
> +			compatible = "apple,t8103-dart";
> +			reg = <0x6 0x83008000 0x0 0x4000>;
> +			#iommu-cells = <1>;
> +			interrupt-parent = <&aic>;
> +			interrupts = <AIC_IRQ 702 IRQ_TYPE_LEVEL_HIGH>;
> +		};
> +
> +		pcie0: pcie@690000000 {
> +			compatible = "apple,t8103-pcie", "apple,pcie";
> +			device_type = "pci";
> +
> +			reg = <0x6 0x90000000 0x0 0x1000000>,
> +			      <0x6 0x80000000 0x0 0x100000>,
> +			      <0x6 0x81000000 0x0 0x4000>,
> +			      <0x6 0x82000000 0x0 0x4000>,
> +			      <0x6 0x83000000 0x0 0x4000>;
> +			reg-names = "config", "rc", "port0", "port1", "port2";
> +
> +			interrupt-parent = <&aic>;
> +			interrupts = <AIC_IRQ 695 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 698 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 701 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 704 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 705 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 706 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 707 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 708 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 709 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 710 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 711 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 712 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 713 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 714 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 715 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 716 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 717 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 718 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 719 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 720 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 721 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 722 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 723 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 724 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 725 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 726 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 727 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 728 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 729 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 730 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 731 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 732 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 733 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 734 IRQ_TYPE_LEVEL_HIGH>,
> +				     <AIC_IRQ 735 IRQ_TYPE_LEVEL_HIGH>;
> +
> +			msi-controller;
> +			msi-parent = <&pcie0>;
> +			msi-ranges = <704 32>;
> +
> +			iommu-map = <0x100 &pcie0_dart_0 0 1>,
> +				    <0x200 &pcie0_dart_1 0 1>,
> +				    <0x300 &pcie0_dart_2 0 1>;
> +			iommu-map-mask = <0xff00>;

So this will need a little bit more thought.

The PCIe bridge hardware has logic to map a PCIe Requester ID (RID) to
an IOMMU Stream ID (SID).  The RID is basically just the PCI
bus/device/function number of the PCI device that initiates the DMA.
As far as I can tell if the RID isn't matched by the PCIe bridge
RID-to-SID mapping hardware it will be mapped to SID 0.  Your driver
doesn't program the RID-to-SID hardware so using 0 as the SID in your
device tree makes some sense.

However, since SID 0 is the default used when there is no match for an
RID, we should probably avoid it if we can.  That's why in my
apple,pcie DT binding series I used SID 1.  But this would require
additional code in the driver to parse the iommu-map property and
program the RID-to-SID hardware accordingly.

Now until we support the Tunderbolt ports, this isn't all that
important and we can go with your current driver and DT.  I can adjust
the U-Boot DT accordingly.

> +
> +			bus-range = <0 3>;
> +			#address-cells = <3>;
> +			#size-cells = <2>;
> +			ranges = <0x43000000 0x6 0xa0000000 0x6 0xa0000000 0x0 0x20000000>,
> +				 <0x02000000 0x0 0xc0000000 0x6 0xc0000000 0x0 0x40000000>;
> +
> +			pinctrl-0 = <&pcie_pins>;
> +			pinctrl-names = "default";
> +
> +			pci@0,0 {
> +				device_type = "pci";
> +				reg = <0x0 0x0 0x0 0x0 0x0>;
> +				reset-gpios = <&pinctrl_ap 152 0>;
> +				max-link-speed = <2>;
> +
> +				#address-cells = <3>;
> +				#size-cells = <2>;
> +				ranges;
> +			};
> +
> +			pci@1,0 {
> +				device_type = "pci";
> +				reg = <0x800 0x0 0x0 0x0 0x0>;
> +				reset-gpios = <&pinctrl_ap 153 0>;
> +				max-link-speed = <2>;
> +
> +				#address-cells = <3>;
> +				#size-cells = <2>;
> +				ranges;
> +			};
> +
> +			pci@2,0 {
> +				device_type = "pci";
> +				reg = <0x1000 0x0 0x0 0x0 0x0>;
> +				reset-gpios = <&pinctrl_ap 33 0>;
> +				max-link-speed = <1>;
> +
> +				#address-cells = <3>;
> +				#size-cells = <2>;
> +				ranges;
> +			};
> +		};
>  	};
>  };
> -- 
> 2.30.2
> 
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/6] PCI: apple: Add initial hardware bring-up
  2021-08-16  3:16 ` [PATCH v2 2/6] PCI: apple: Add initial hardware bring-up Alyssa Rosenzweig
@ 2021-08-22 18:42   ` Mark Kettenis
  0 siblings, 0 replies; 9+ messages in thread
From: Mark Kettenis @ 2021-08-22 18:42 UTC (permalink / raw)
  To: Alyssa Rosenzweig
  Cc: linux-pci, bhelgaas, robh+dt, lorenzo.pieralisi, kw, alyssa,
	stan, maz, kettenis, sven, marcan, devicetree, linux-kernel

> From: Alyssa Rosenzweig <alyssa@rosenzweig.io>
> Date: Sun, 15 Aug 2021 23:16:17 -0400
> 
> Add a minimal driver to bring up the PCIe bus on Apple system-on-chips,
> particularly the Apple M1. This driver exposes the internal bus used for
> the USB type-A ports, Ethernet, Wi-Fi, and Bluetooth. Bringing up the
> radios requires additional drivers beyond what's necessary for PCIe
> itself.
> 
> In this patch, a minimal driver is added that brings up the PCIe bus on
> probe. This logic is derived from Corellium's driver via Mark Kettenis's
> U-Boot patches.
> 
> Co-developed-by: Stan Skowronek <stan@corellium.com>
> Signed-off-by: Stan Skowronek <stan@corellium.com>
> Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
> ---
>  MAINTAINERS                         |   6 +
>  drivers/pci/controller/Kconfig      |  12 ++
>  drivers/pci/controller/Makefile     |   1 +
>  drivers/pci/controller/pcie-apple.c | 251 ++++++++++++++++++++++++++++
>  4 files changed, 270 insertions(+)
>  create mode 100644 drivers/pci/controller/pcie-apple.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a5687cf6f925..47cb3d320c56 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1269,6 +1269,12 @@ S:	Maintained
>  F:	Documentation/devicetree/bindings/iommu/apple,dart.yaml
>  F:	drivers/iommu/apple-dart.c
>  
> +APPLE PCIE CONTROLLER DRIVER
> +M:	Alyssa Rosenzweig <alyssa@rosenzweig.io>
> +L:	linux-pci@vger.kernel.org
> +S:	Maintained
> +F:	drivers/pci/controller/pcie-apple.c
> +
>  APPLE SMC DRIVER
>  M:	Henrik Rydberg <rydberg@bitmath.org>
>  L:	linux-hwmon@vger.kernel.org
> diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
> index 326f7d13024f..814833a8120d 100644
> --- a/drivers/pci/controller/Kconfig
> +++ b/drivers/pci/controller/Kconfig
> @@ -312,6 +312,18 @@ config PCIE_HISI_ERR
>  	  Say Y here if you want error handling support
>  	  for the PCIe controller's errors on HiSilicon HIP SoCs
>  
> +config PCIE_APPLE
> +	tristate "Apple PCIe controller"
> +	depends on ARCH_APPLE || COMPILE_TEST
> +	depends on OF
> +	depends on PCI_MSI_IRQ_DOMAIN
> +	help
> +	  Say Y here if you want to enable PCIe controller support on Apple
> +	  system-on-chips, like the Apple M1. This is required for the USB
> +	  type-A ports, Ethernet, Wi-Fi, and Bluetooth.
> +
> +	  If unsure, say Y if you have an Apple Silicon system.
> +
>  source "drivers/pci/controller/dwc/Kconfig"
>  source "drivers/pci/controller/mobiveil/Kconfig"
>  source "drivers/pci/controller/cadence/Kconfig"
> diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
> index aaf30b3dcc14..f9d40bad932c 100644
> --- a/drivers/pci/controller/Makefile
> +++ b/drivers/pci/controller/Makefile
> @@ -37,6 +37,7 @@ obj-$(CONFIG_VMD) += vmd.o
>  obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
>  obj-$(CONFIG_PCI_LOONGSON) += pci-loongson.o
>  obj-$(CONFIG_PCIE_HISI_ERR) += pcie-hisi-error.o
> +obj-$(CONFIG_PCIE_APPLE) += pcie-apple.o
>  # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
>  obj-y				+= dwc/
>  obj-y				+= mobiveil/
> diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
> new file mode 100644
> index 000000000000..a1efcc3373ea
> --- /dev/null
> +++ b/drivers/pci/controller/pcie-apple.c
> @@ -0,0 +1,251 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * PCIe host bridge driver for Apple system-on-chips.
> + *
> + * The HW is ECAM compliant, so once the controller is initialized, the driver
> + * mostly only needs MSI handling. Initialization requires enabling power and
> + * clocks, along with a number of register pokes.
> + *
> + * Copyright (C) 2021 Alyssa Rosenzweig <alyssa@rosenzweig.io>
> + * Copyright (C) 2021 Google LLC
> + * Copyright (C) 2021 Corellium LLC
> + * Copyright (C) 2021 Mark Kettenis <kettenis@openbsd.org>
> + *
> + * Author: Alyssa Rosenzweig <alyssa@rosenzweig.io>
> + * Author: Marc Zyngier <maz@kernel.org>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/irqdomain.h>
> +#include <linux/module.h>
> +#include <linux/msi.h>
> +#include <linux/of_irq.h>
> +#include <linux/pci-ecam.h>
> +#include <linux/iopoll.h>
> +#include <linux/gpio/consumer.h>
> +
> +#define CORE_RC_PHYIF_CTL		0x00024
> +#define   CORE_RC_PHYIF_CTL_RUN		BIT(0)
> +#define CORE_RC_PHYIF_STAT		0x00028
> +#define   CORE_RC_PHYIF_STAT_REFCLK	BIT(4)
> +#define CORE_RC_CTL			0x00050
> +#define   CORE_RC_CTL_RUN		BIT(0)
> +#define CORE_RC_STAT			0x00058
> +#define   CORE_RC_STAT_READY		BIT(0)
> +#define CORE_FABRIC_STAT		0x04000
> +#define   CORE_FABRIC_STAT_MASK		0x001F001F
> +#define CORE_LANE_CFG(port)		(0x84000 + 0x4000 * (port))
> +#define   CORE_LANE_CFG_REFCLK0REQ	BIT(0)
> +#define   CORE_LANE_CFG_REFCLK1		BIT(1)
> +#define   CORE_LANE_CFG_REFCLK0ACK	BIT(2)
> +#define   CORE_LANE_CFG_REFCLKEN	(BIT(9) | BIT(10))
> +#define CORE_LANE_CTL(port)		(0x84004 + 0x4000 * (port))
> +#define   CORE_LANE_CTL_CFGACC		BIT(15)
> +
> +#define PORT_LTSSMCTL			0x00080
> +#define   PORT_LTSSMCTL_START		BIT(0)
> +#define PORT_INTSTAT			0x00100
> +#define   PORT_INT_TUNNEL_ERR		BIT(31)
> +#define   PORT_INT_CPL_TIMEOUT		BIT(23)
> +#define   PORT_INT_RID2SID_MAPERR	BIT(22)
> +#define   PORT_INT_CPL_ABORT		BIT(21)
> +#define   PORT_INT_MSI_BAD_DATA		BIT(19)
> +#define   PORT_INT_MSI_ERR		BIT(18)
> +#define   PORT_INT_REQADDR_GT32		BIT(17)
> +#define   PORT_INT_AF_TIMEOUT		BIT(15)
> +#define   PORT_INT_LINK_DOWN		BIT(14)
> +#define   PORT_INT_LINK_UP		BIT(12)
> +#define   PORT_INT_LINK_BWMGMT		BIT(11)
> +#define   PORT_INT_AER_MASK		(15 << 4)
> +#define   PORT_INT_PORT_ERR		BIT(4)
> +#define   PORT_INT_INTx(i)		BIT(i)
> +#define   PORT_INT_INTxALL		15
> +#define PORT_INTMSK			0x00104
> +#define PORT_INTMSKSET			0x00108
> +#define PORT_INTMSKCLR			0x0010c
> +#define PORT_MSICFG			0x00124
> +#define   PORT_MSICFG_EN		BIT(0)
> +#define   PORT_MSICFG_L2MSINUM_SHIFT	4
> +#define PORT_MSIBASE			0x00128
> +#define   PORT_MSIBASE_1_SHIFT		16
> +#define PORT_MSIADDR			0x00168
> +#define PORT_LINKSTS			0x00208
> +#define   PORT_LINKSTS_UP		BIT(0)
> +#define   PORT_LINKSTS_BUSY		BIT(2)
> +#define PORT_LINKCMDSTS			0x00210
> +#define PORT_OUTS_NPREQS		0x00284
> +#define   PORT_OUTS_NPREQS_REQ		BIT(24)
> +#define   PORT_OUTS_NPREQS_CPL		BIT(16)
> +#define PORT_RXWR_FIFO			0x00288
> +#define   PORT_RXWR_FIFO_HDR		GENMASK(15, 10)
> +#define   PORT_RXWR_FIFO_DATA		GENMASK(9, 0)
> +#define PORT_RXRD_FIFO			0x0028C
> +#define   PORT_RXRD_FIFO_REQ		GENMASK(6, 0)
> +#define PORT_OUTS_CPLS			0x00290
> +#define   PORT_OUTS_CPLS_SHRD		GENMASK(14, 8)
> +#define   PORT_OUTS_CPLS_WAIT		GENMASK(6, 0)
> +#define PORT_APPCLK			0x00800
> +#define   PORT_APPCLK_EN		BIT(0)
> +#define   PORT_APPCLK_CGDIS		BIT(8)
> +#define PORT_STATUS			0x00804
> +#define   PORT_STATUS_READY		BIT(0)
> +#define PORT_REFCLK			0x00810
> +#define   PORT_REFCLK_EN		BIT(0)
> +#define   PORT_REFCLK_CGDIS		BIT(8)
> +#define PORT_PERST			0x00814
> +#define   PORT_PERST_OFF		BIT(0)
> +#define PORT_RID2SID(i16)		(0x00828 + 4 * (i16))
> +#define   PORT_RID2SID_VALID		BIT(31)
> +#define   PORT_RID2SID_SID_SHIFT	16
> +#define   PORT_RID2SID_BUS_SHIFT	8
> +#define   PORT_RID2SID_DEV_SHIFT	3
> +#define   PORT_RID2SID_FUNC_SHIFT	0
> +#define PORT_OUTS_PREQS_HDR		0x00980
> +#define   PORT_OUTS_PREQS_HDR_MASK	GENMASK(9, 0)
> +#define PORT_OUTS_PREQS_DATA		0x00984
> +#define   PORT_OUTS_PREQS_DATA_MASK	GENMASK(15, 0)
> +#define PORT_TUNCTRL			0x00988
> +#define   PORT_TUNCTRL_PERST_ON		BIT(0)
> +#define   PORT_TUNCTRL_PERST_ACK_REQ	BIT(1)
> +#define PORT_TUNSTAT			0x0098c
> +#define   PORT_TUNSTAT_PERST_ON		BIT(0)
> +#define   PORT_TUNSTAT_PERST_ACK_PEND	BIT(1)
> +#define PORT_PREFMEM_ENABLE		0x00994
> +
> +/* The doorbell address is "well known" */
> +#define DOORBELL_ADDR			0xfffff000
> +
> +struct apple_pcie {
> +	struct mutex		lock;
> +	struct device		*dev;
> +	void __iomem            *rc;
> +};
> +
> +static inline void rmwl(u32 clr, u32 set, void __iomem *addr)
> +{
> +	writel_relaxed((readl_relaxed(addr) & ~clr) | set, addr);
> +}
> +
> +static int apple_pcie_setup_port(struct apple_pcie *pcie,
> +				 struct gpio_desc *reset,
> +				 unsigned int i)
> +{
> +	struct platform_device *platform = to_platform_device(pcie->dev);
> +	void __iomem *port;
> +	uint32_t stat;
> +	int ret;
> +
> +	port = devm_platform_ioremap_resource(platform, i + 2);
> +
> +	if (IS_ERR(port))
> +		return -ENODEV;
> +
> +	/* Skip setup if the link was already enabled by the bootloader */
> +	if (readl_relaxed(port + PORT_LINKSTS) & PORT_LINKSTS_UP)
> +		return 0;
> +
> +	rmwl(0, PORT_PERST_OFF, port + PORT_PERST);
> +	gpiod_set_value(reset, 1);
> +
> +	ret = readl_relaxed_poll_timeout(port + PORT_STATUS, stat,
> +					 stat & PORT_STATUS_READY, 100, 250000);
> +	if (ret < 0) {
> +		dev_err(pcie->dev, "port %u ready wait timeout\n", i);
> +		return ret;
> +	}
> +
> +	/* Configure MSIs */
> +	writel_relaxed(DOORBELL_ADDR, port + PORT_MSIADDR);
> +	writel_relaxed(0, port + PORT_MSIBASE);
> +
> +	/* Enable 32 MSIs */
> +	writel_relaxed((5 << PORT_MSICFG_L2MSINUM_SHIFT) | PORT_MSICFG_EN,
> +		       port + PORT_MSICFG);

The MSI configuration writes should probably be part of patch 4/6.

> +
> +	/* Enable link interrupts */
> +	writel_relaxed(0xfb512fff, port + PORT_INTMSKSET);

So this magic number should probably be the bitwise inverse of the
value used below:

> +
> +	writel_relaxed(PORT_INT_LINK_UP | PORT_INT_LINK_DOWN |
> +		       PORT_INT_AF_TIMEOUT | PORT_INT_REQADDR_GT32 |
> +		       PORT_INT_MSI_ERR | PORT_INT_MSI_BAD_DATA |
> +		       PORT_INT_CPL_ABORT | PORT_INT_CPL_TIMEOUT | (1 << 26),
> +		       port + PORT_INTSTAT);

My suggestion would be to introduce a #define PORT_INT_DEFAULT for
that collection of bits and use ~PORT_INT_DEFAULT in the first write
and PORT_INT_DEFAULT in the latter.

Wonder if we can figure out what bit 26 means.  Or maybe we don't
really need to enable that interrupt and can forget about it?  The
Corellium code doesn't handle that bit in its interrupt handler, so
unless there is some magic going on we should be able to simply ignore
it.

> +
> +	/* Flush writes and enable the link */
> +	dma_wmb();
> +	writel_relaxed(PORT_LTSSMCTL_START, port + PORT_LTSSMCTL);
> +
> +	return 0;
> +}
> +
> +static int apple_m1_pci_init(struct pci_config_window *cfg)
> +{
> +	struct device *dev = cfg->parent;
> +	struct platform_device *platform = to_platform_device(dev);
> +
> +	struct apple_pcie *pcie;
> +	struct device_node *of_port;
> +	int ret, i;
> +
> +	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
> +	if (!pcie)
> +		return -ENOMEM;
> +
> +	pcie->dev = dev;
> +
> +	mutex_init(&pcie->lock);
> +
> +	pcie->rc = devm_platform_ioremap_resource(platform, 1);
> +
> +	if (IS_ERR(pcie->rc))
> +		return -ENODEV;
> +
> +	i = 0;
> +
> +	for_each_child_of_node(dev->of_node, of_port) {
> +		struct gpio_desc *reset;
> +
> +		reset = gpiod_get_from_of_node(of_port, "reset-gpios", 0,
> +					       GPIOD_OUT_LOW, "#PERST");
> +		if (IS_ERR(reset))
> +			return PTR_ERR(reset);
> +
> +		ret = apple_pcie_setup_port(pcie, reset, i);
> +
> +		if (ret) {
> +			dev_err(pcie->dev, "Port %u setup fail: %d\n", i, ret);
> +			return ret;
> +		}
> +
> +		++i;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct pci_ecam_ops apple_m1_cfg_ecam_ops = {
> +	.init		= apple_m1_pci_init,
> +	.pci_ops	= {
> +		.map_bus	= pci_ecam_map_bus,
> +		.read		= pci_generic_config_read,
> +		.write		= pci_generic_config_write,
> +	}
> +};
> +
> +static const struct of_device_id apple_pci_of_match[] = {
> +	{ .compatible = "apple,pcie", .data = &apple_m1_cfg_ecam_ops },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, apple_pci_of_match);
> +
> +static struct platform_driver apple_pci_driver = {
> +	.driver = {
> +		.name = "pcie-apple",
> +		.of_match_table = apple_pci_of_match,
> +	},
> +	.probe = pci_host_common_probe,
> +	.remove = pci_host_common_remove,
> +};
> +module_platform_driver(apple_pci_driver);
> +
> +MODULE_LICENSE("GPL v2");
> -- 
> 2.30.2
> 
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-08-22 18:42 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-16  3:16 [PATCH v2 0/6] Add PCI driver for the Apple M1 Alyssa Rosenzweig
2021-08-16  3:16 ` [PATCH v2 1/6] dt-bindings: pci: Add DT bindings for apple,pcie Alyssa Rosenzweig
2021-08-16  3:16 ` [PATCH v2 2/6] PCI: apple: Add initial hardware bring-up Alyssa Rosenzweig
2021-08-22 18:42   ` Mark Kettenis
2021-08-16  3:16 ` [PATCH v2 3/6] PCI: apple: Set up reference clocks when probing Alyssa Rosenzweig
2021-08-16  3:16 ` [PATCH v2 4/6] PCI: apple: Add MSI handling Alyssa Rosenzweig
2021-08-16  3:16 ` [PATCH v2 5/6] arm64: apple: Add pinctrl nodes Alyssa Rosenzweig
2021-08-16  3:16 ` [PATCH v2 6/6] arm64: apple: Add PCIe node Alyssa Rosenzweig
2021-08-22 18:28   ` Mark Kettenis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).