linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] Add PCIe support for Tesla FSD SoC
       [not found] <CGME20221121104714epcas5p27508b91010c72117dd7116fc387b382f@epcas5p2.samsung.com>
@ 2022-11-21 10:52 ` Shradha Todi
       [not found]   ` <CGME20221121104719epcas5p2f87febfba74a4ca6807b3095acf507d0@epcas5p2.samsung.com>
                     ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: Shradha Todi @ 2022-11-21 10:52 UTC (permalink / raw)
  To: bhelgaas, robh+dt, krzysztof.kozlowski+dt, kishon, vkoul,
	lpieralisi, kw, mani, arnd, gregkh, alim.akhtar, ajaykumar.rs,
	rcsekar, sriranjani.p, bharat.uppal, s.prashar, aswani.reddy,
	pankaj.dubey, p.rajanbabu, niyas.ahmed, chanho61.park
  Cc: linux-pci, devicetree, linux-kernel, linux-phy, Shradha Todi

FSD platform has three instances of DesignWare based PCIe IP,
one is in FSYS0 block and other two in FSYS1 block.
This patch series add required DT binding, DT file modifications,
Controller driver support and PHY driver support for the same.

This series needs following three patches to be merged before
this patchset
[1]: https://www.spinics.net/lists/netdev/msg854161.html
[2]: https://www.spinics.net/lists/netdev/msg854158.html
[3]: https://lore.kernel.org/all/20221013104024.50179-2-p.rajanbabu@samsung.com/


Shradha Todi (6):
  dt-bindings: phy: Add PCIe PHY bindings for FSD
  dt-bindings: PCI: Add PCIe controller bindings for FSD
  PCI: dwc: fsd: Add FSD PCIe Controller driver support
  phy: tesla-pcie: Add PCIe PHY driver support for FSD
  arm64: dts: fsd: Add PCIe support for Tesla FSD SoC
  misc: pci_endpoint_test: Add driver data for FSD PCIe controllers

 .../bindings/pci/tesla,pcie-fsd-ep.yaml       |  107 ++
 .../bindings/pci/tesla,pcie-fsd.yaml          |  117 ++
 .../bindings/phy/phy-tesla-pcie.yaml          |   75 ++
 arch/arm64/boot/dts/tesla/fsd-evb.dts         |   48 +
 arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi    |   65 ++
 arch/arm64/boot/dts/tesla/fsd.dtsi            |  171 +++
 drivers/misc/pci_endpoint_test.c              |    3 +
 drivers/pci/controller/dwc/Kconfig            |   35 +
 drivers/pci/controller/dwc/Makefile           |    1 +
 drivers/pci/controller/dwc/pcie-fsd.c         | 1021 +++++++++++++++++
 drivers/phy/samsung/Kconfig                   |   10 +
 drivers/phy/samsung/Makefile                  |    1 +
 drivers/phy/samsung/phy-tesla-pcie.c          |  397 +++++++
 include/linux/pci_ids.h                       |    2 +
 14 files changed, 2053 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/tesla,pcie-fsd-ep.yaml
 create mode 100644 Documentation/devicetree/bindings/pci/tesla,pcie-fsd.yaml
 create mode 100644 Documentation/devicetree/bindings/phy/phy-tesla-pcie.yaml
 create mode 100644 drivers/pci/controller/dwc/pcie-fsd.c
 create mode 100644 drivers/phy/samsung/phy-tesla-pcie.c

-- 
2.17.1


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

* [PATCH 1/6] dt-bindings: phy: Add PCIe PHY bindings for FSD
       [not found]   ` <CGME20221121104719epcas5p2f87febfba74a4ca6807b3095acf507d0@epcas5p2.samsung.com>
@ 2022-11-21 10:52     ` Shradha Todi
  2022-11-21 11:59       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 14+ messages in thread
From: Shradha Todi @ 2022-11-21 10:52 UTC (permalink / raw)
  To: bhelgaas, robh+dt, krzysztof.kozlowski+dt, kishon, vkoul,
	lpieralisi, kw, mani, arnd, gregkh, alim.akhtar, ajaykumar.rs,
	rcsekar, sriranjani.p, bharat.uppal, s.prashar, aswani.reddy,
	pankaj.dubey, p.rajanbabu, niyas.ahmed, chanho61.park
  Cc: linux-pci, devicetree, linux-kernel, linux-phy, Shradha Todi

Document the PCIe PHY device tree bindings for Tesla
FSD SoC

Signed-off-by: Shradha Todi <shradha.t@samsung.com>
---
 .../bindings/phy/phy-tesla-pcie.yaml          | 75 +++++++++++++++++++
 1 file changed, 75 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/phy-tesla-pcie.yaml

diff --git a/Documentation/devicetree/bindings/phy/phy-tesla-pcie.yaml b/Documentation/devicetree/bindings/phy/phy-tesla-pcie.yaml
new file mode 100644
index 000000000000..8fa9a050af7a
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-tesla-pcie.yaml
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/phy-tesla-pcie.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Tesla FSD SoC PCIe PHY
+
+maintainers:
+  - Shradha Todi <shradha.t@samsung.com>
+
+properties:
+  "#phy-cells":
+    const: 0
+
+  compatible:
+    enum:
+      - tesla,fsd-pcie-phy
+
+  reg:
+    minItems: 2
+    maxItems: 2
+
+  reg-names:
+    minItems: 2
+    maxItems: 2
+    items:
+      enum: [phy, pcs]
+    description: |
+      phy is the register access to PMA layer
+      pcs is the register access to PCS layer
+
+  phy-mode:
+    description: |
+      Defines the bifurcation mode of the PHY
+
+  tesla,pmureg-phandle:
+    $ref: '/schemas/types.yaml#/definitions/phandle'
+    description: phandle for PMU system controller interface used to
+                 control PMU register bits for PCIe PHY
+
+  tesla,pcie-sysreg:
+    $ref: '/schemas/types.yaml#/definitions/phandle'
+    description: phandle for system control registers, used to
+                 control phy signals at system level
+
+required:
+  - "#phy-cells"
+  - compatible
+  - reg
+  - reg-names
+  - phy-mode
+  - tesla,pmureg-phandle
+  - tesla,pcie-sysreg
+
+additionalProperties: false
+
+examples:
+  - |
+    bus {
+      #address-cells = <2>;
+      #size-cells = <2>;
+
+      pcie_phy0: pcie-phy@15080000 {
+        compatible = "tesla,fsd-pcie-phy";
+        #phy-cells = <0>;
+        reg = <0x0 0x15080000 0x0 0x2000>, <0x0 0x150A0000 0x0 0x1000>;
+        reg-names = "phy", "pcs";
+        tesla,pmureg-phandle = <&pmu_system_controller>;
+        tesla,pcie-sysreg = <&sysreg_fsys0>;
+        phy-mode = <0>;
+        status = "disabled";
+      };
+    };
+...
-- 
2.17.1


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

* [PATCH 2/6] dt-bindings: PCI: Add PCIe controller bindings for FSD
       [not found]   ` <CGME20221121104725epcas5p3af00b0c717f2132f5c1ba7fd4e903e26@epcas5p3.samsung.com>
@ 2022-11-21 10:52     ` Shradha Todi
  2022-11-21 12:05       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 14+ messages in thread
From: Shradha Todi @ 2022-11-21 10:52 UTC (permalink / raw)
  To: bhelgaas, robh+dt, krzysztof.kozlowski+dt, kishon, vkoul,
	lpieralisi, kw, mani, arnd, gregkh, alim.akhtar, ajaykumar.rs,
	rcsekar, sriranjani.p, bharat.uppal, s.prashar, aswani.reddy,
	pankaj.dubey, p.rajanbabu, niyas.ahmed, chanho61.park
  Cc: linux-pci, devicetree, linux-kernel, linux-phy, Shradha Todi

Document the PCIe controller device tree bindings for
Tesla FSD SoC for both RC and EP

Signed-off-by: Shradha Todi  <shradha.t@samsung.com>
---
 .../bindings/pci/tesla,pcie-fsd-ep.yaml       | 107 ++++++++++++++++
 .../bindings/pci/tesla,pcie-fsd.yaml          | 117 ++++++++++++++++++
 2 files changed, 224 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/tesla,pcie-fsd-ep.yaml
 create mode 100644 Documentation/devicetree/bindings/pci/tesla,pcie-fsd.yaml

diff --git a/Documentation/devicetree/bindings/pci/tesla,pcie-fsd-ep.yaml b/Documentation/devicetree/bindings/pci/tesla,pcie-fsd-ep.yaml
new file mode 100644
index 000000000000..07308cb9a35c
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/tesla,pcie-fsd-ep.yaml
@@ -0,0 +1,107 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/tesla,pcie-fsd-ep.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Synopsys DesignWare based PCIe EP controller on FSD SoCs
+
+maintainers:
+  - Shradha Todi <shradha.t@samsung.com>
+
+description: |
+  FSD PCIe EP controller is based on Synopsys DesignWare PCIe IP
+  and thus inherits all the common properties defined in
+  snps,dw-pcie-ep.yaml. The controller instance is dual mode and
+  can work in Root port mode or Endpoint mode at a time.
+
+allOf:
+  - $ref: /schemas/pci/snps,dw-pcie-ep.yaml#
+
+properties:
+  compatible:
+    enum:
+      - tesla,fsd-pcie-ep
+
+  reg:
+    items:
+      - description: controller's application logic registers
+      - description: controller's own configuration registers
+                     are available.
+      - description: controller's own configuration shadow registers
+                     are available.
+      - description: Map the remote Root Complex slave address space
+
+  reg-names:
+    items:
+      - const: appl
+      - const: dbi
+      - const: dbi2
+      - const: addr_space
+
+  clocks:
+    items:
+      - description: Auxiliary clock for PCIe
+      - description: AHB clock for PCIe dbi
+      - description: AHB clock for PCIe master
+      - description: AHB clock for PCIe slave
+
+  clock-names:
+    items:
+      - const: aux_clk
+      - const: dbi_clk
+      - const: mstr_clk
+      - const: slv_clk
+
+  interrupts:
+    items:
+      - description: Controller interrupt
+
+  interrupt-names:
+    items:
+      - const: sub_ctrl_intr
+
+  tesla,pcie-sysreg:
+    $ref: '/schemas/types.yaml#/definitions/phandle-array'
+    description: phandle for system control registers, used to
+                 control signals at system level
+
+required:
+
+  - compatible
+  - reg
+  - reg-names
+  - clocks
+  - clock-names
+  - ranges
+  - num-lanes
+  - tesla,pcie-sysreg
+
+additionalProperties: true
+
+examples:
+  - |
+    #include <dt-bindings/clock/fsd-clk.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    pcie4_ep: pcie-ep@15400000 {
+      compatible = "tesla,fsd-pcie-ep";
+      clocks = <&clock_fsys0 PCIE_SUBCTRL_INST0_AUX_CLK_SOC>,
+               <&clock_fsys0 PCIE_SUBCTRL_INST0_DBI_ACLK_SOC>,
+               <&clock_fsys0 PCIE_SUBCTRL_INST0_MSTR_ACLK_SOC>,
+               <&clock_fsys0 PCIE_SUBCTRL_INST0_SLV_ACLK_SOC>;
+      clock-names = "aux_clk", "dbi_clk", "mstr_clk", "slv_clk";
+      interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
+      interrupt-names = "sub_ctrl_intr";
+      reg = <0x15090000 0x1000>,
+            <0x15400000 0x1000>,
+            <0x15401000 0x80>,
+            <0x15800000 0xFF0000>;
+      reg-names = "appl", "dbi", "dbi2", "addr_space";
+      num-lanes = <4>;
+      tesla,pcie-sysreg = <&sysreg_fsys0 0x434>;
+      phys = <&pcie_phy0>;
+      phy-names = "pcie_phy0";
+      status = "disabled";
+    };
+...
diff --git a/Documentation/devicetree/bindings/pci/tesla,pcie-fsd.yaml b/Documentation/devicetree/bindings/pci/tesla,pcie-fsd.yaml
new file mode 100644
index 000000000000..85648e5c7d27
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/tesla,pcie-fsd.yaml
@@ -0,0 +1,117 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/pci/tesla,pcie-fsd.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Synopsys DesignWare based PCIe controller on FSD SoCs
+
+maintainers:
+  - Shradha Todi <shradha.t@samsung.com>
+
+description: |
+  FSD PCIe controller is based on Synopsys DesignWare PCIe IP
+  and thus inherits all the common properties defined in
+  designware-pcie.txt.
+
+allOf:
+  - $ref: /schemas/pci/snps,dw-pcie.yaml#
+
+properties:
+  compatible:
+    const: tesla,fsd-pcie
+
+  reg:
+    items:
+      - description: controller's application logic registers
+      - description: controller's own configuration registers
+                     are available.
+      - description: configuration registers
+
+  reg-names:
+    items:
+      - const: appl
+      - const: dbi
+      - const: config
+
+  clocks:
+    items:
+      - description: Auxiliary clock for PCIe
+      - description: AHB clock for PCIe dbi
+      - description: AHB clock for PCIe master
+      - description: AHB clock for PCIe slave
+
+  clock-names:
+    items:
+      - const: aux_clk
+      - const: dbi_clk
+      - const: mstr_clk
+      - const: slv_clk
+
+  interrupts:
+    minItems: 1
+    items:
+      - description: MSI interrupt
+      - description: Controller interrupt
+
+  interrupt-names:
+    minItems: 1
+    items:
+      - const: msi
+      - const: sub_ctrl_intr
+
+  tesla,pcie-sysreg:
+    $ref: '/schemas/types.yaml#/definitions/phandle-array'
+    description: phandle for system control registers, used to
+                 control signals at system level
+
+required:
+
+  - compatible
+  - reg
+  - reg-names
+  - clocks
+  - clock-names
+  - ranges
+  - num-lanes
+  - tesla,pcie-sysreg
+
+additionalProperties: true
+
+examples:
+  - |
+    #include <dt-bindings/clock/fsd-clk.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    bus {
+      #address-cells = <2>;
+      #size-cells = <2>;
+
+      pcie4_rc: pcie@15400000 {
+        compatible = "tesla,fsd-pcie";
+        clocks = <&clock_fsys0 PCIE_SUBCTRL_INST0_AUX_CLK_SOC>,
+                 <&clock_fsys0 PCIE_SUBCTRL_INST0_DBI_ACLK_SOC>,
+                 <&clock_fsys0 PCIE_SUBCTRL_INST0_MSTR_ACLK_SOC>,
+                 <&clock_fsys0 PCIE_SUBCTRL_INST0_SLV_ACLK_SOC>;
+        clock-names = "aux_clk", "dbi_clk", "mstr_clk", "slv_clk";
+        #address-cells = <3>;
+        #size-cells = <2>;
+        dma-coherent;
+        interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
+        interrupt-names = "msi";
+        num-lanes = <4>;
+        reg = <0x0 0x15090000 0x0 0x1000>,
+              <0x0 0x15400000 0x0 0x1000>,
+              <0x0 0x15800000 0x0 0x1000>;
+        reg-names = "appl", "dbi", "config";
+        ranges =  <0x82000000 0 0x15801000 0 0x15801000 0 0xffefff>;
+        tesla,pcie-sysreg = <&sysreg_fsys0 0x434>;
+        phys = <&pcie_phy0>;
+        phy-names = "pcie_phy0";
+        iommu-map = <0x0 &smmu_fsys0 0x4 0x10000>;
+        iommu-map-mask = <0x0>;
+        status = "disabled";
+      };
+    };
+...
-- 
2.17.1


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

* [PATCH 3/6] PCI: dwc: fsd: Add FSD PCIe Controller driver support
       [not found]   ` <CGME20221121104731epcas5p48f96c92e5bfb4ede56ce74a78887a2f3@epcas5p4.samsung.com>
@ 2022-11-21 10:52     ` Shradha Todi
  2022-11-21 12:07       ` Krzysztof Kozlowski
                         ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Shradha Todi @ 2022-11-21 10:52 UTC (permalink / raw)
  To: bhelgaas, robh+dt, krzysztof.kozlowski+dt, kishon, vkoul,
	lpieralisi, kw, mani, arnd, gregkh, alim.akhtar, ajaykumar.rs,
	rcsekar, sriranjani.p, bharat.uppal, s.prashar, aswani.reddy,
	pankaj.dubey, p.rajanbabu, niyas.ahmed, chanho61.park
  Cc: linux-pci, devicetree, linux-kernel, linux-phy, Shradha Todi

Add PCIe controller driver file for PCIe controller
found in fsd SoC family. This driver adds support for both RC
and EP mode.

Signed-off-by: Niyas Ahmed S T <niyas.ahmed@samsung.com>
Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
Signed-off-by: Padmanabhan Rajanbabu <p.rajanbabu@samsung.com>
Signed-off-by: Shradha Todi <shradha.t@samsung.com>
---
 drivers/pci/controller/dwc/Kconfig    |   35 +
 drivers/pci/controller/dwc/Makefile   |    1 +
 drivers/pci/controller/dwc/pcie-fsd.c | 1021 +++++++++++++++++++++++++
 3 files changed, 1057 insertions(+)
 create mode 100644 drivers/pci/controller/dwc/pcie-fsd.c

diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
index 62ce3abf0f19..9a3d194c979f 100644
--- a/drivers/pci/controller/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
@@ -14,6 +14,41 @@ config PCIE_DW_EP
 	bool
 	select PCIE_DW
 
+config PCIE_FSD
+	bool "Samsung FSD PCIe Controller"
+	default n
+	help
+	  Enables support for the PCIe controller in the FSD SoC. There are
+	  total three instances of PCIe controller in FSD. This controller
+	  can work either in RC or EP mode. In order to enable host-specific
+	  features, PCI_FSD_HOST must be selected and in order to enable
+	  device-specific feature PCI_FSD_EP must be selected.
+
+config PCIE_FSD_HOST
+	bool "PCIe FSD Host Mode"
+	depends on PCI
+	depends on PCI_MSI_IRQ_DOMAIN || PCI_DOMAIN
+	select PCIE_DW_HOST
+	select PCIE_FSD
+	default n
+	help
+	  Enables support for the PCIe controller in the FSD SoC to work in
+	  host (RC) mode. In order to enable host-specific features,
+	  PCIE_DW_HOST must be selected. PCIE_FSD should be selected for
+	  fsd controller specific settings.
+
+config PCIE_FSD_EP
+	bool "PCIe FSD Endpoint Mode"
+	depends on PCI_ENDPOINT
+	select PCIE_DW_EP
+	select PCIE_FSD
+	default n
+	help
+	  Enables support for the PCIe controller in the FSD SoC to work in
+	  endpoint mode. In order to enable device-specific feature
+	  PCI_FSD_EP must be selected. PCIE_FSD should be selected for
+	  fsd controller specific settings.
+
 config PCI_DRA7XX
 	tristate
 
diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
index 8ba7b67f5e50..b76fa6b4e79f 100644
--- a/drivers/pci/controller/dwc/Makefile
+++ b/drivers/pci/controller/dwc/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_PCIE_TEGRA194) += pcie-tegra194.o
 obj-$(CONFIG_PCIE_UNIPHIER) += pcie-uniphier.o
 obj-$(CONFIG_PCIE_UNIPHIER_EP) += pcie-uniphier-ep.o
 obj-$(CONFIG_PCIE_VISCONTI_HOST) += pcie-visconti.o
+obj-$(CONFIG_PCIE_FSD) += pcie-fsd.o
 
 # The following drivers are for devices that use the generic ACPI
 # pci_root.c driver but don't support standard ECAM config access.
diff --git a/drivers/pci/controller/dwc/pcie-fsd.c b/drivers/pci/controller/dwc/pcie-fsd.c
new file mode 100644
index 000000000000..4531efbfc313
--- /dev/null
+++ b/drivers/pci/controller/dwc/pcie-fsd.c
@@ -0,0 +1,1021 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCIe host controller driver for Tesla fsd SoC
+ *
+ * Copyright (C) 2017-2022 Samsung Electronics Co., Ltd. http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pci.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/resource.h>
+#include <linux/mfd/syscon.h>
+#include <linux/types.h>
+
+#include "pcie-designware.h"
+
+#define to_fsd_pcie(x)	dev_get_drvdata((x)->dev)
+
+/* PCIe ELBI registers */
+#define PCIE_APP_LTSSM_ENABLE		0x054
+#define PCIE_ELBI_LTSSM_ENABLE		0x1
+#define PCIE_ELBI_LTSSM_DISABLE		0x0
+#define PCIE_ELBI_CXPL_DEBUG_00_31	0x2C8
+#define LTSSM_STATE_MASK		0x3f
+#define LTSSM_STATE_L0			0x11
+#define PCIE_FSD_DEVICE_TYPE		0x080
+#define DEVICE_TYPE_RC			0x4
+#define DEVICE_TYPE_EP			0x0
+#define IRQ_MSI_ENABLE			BIT(17)
+#define IRQ0_EN				0x10
+#define IRQ1_EN				0x14
+#define IRQ2_EN				0x18
+#define IRQ5_EN				0x1c
+#define IRQ0_STS			0x0
+#define IRQ1_STS			0x4
+#define IRQ2_STS			0x8
+#define IRQ5_STS			0xc
+
+/* Gen3 Control Register */
+#define PCIE_GEN3_RELATED_OFF		0x890
+/* Parameters for equalization feature */
+#define PCIE_GEN3_EQUALIZATION_DISABLE	BIT(16)
+#define PCIE_GEN3_EQ_PHASE_2_3		BIT(9)
+#define PCIE_GEN3_RXEQ_PH01_EN		BIT(12)
+#define PCIE_GEN3_RXEQ_RGRDLESS_RXTS	BIT(13)
+
+/**
+ * struct fsd_pcie - representation of the pci controller
+ * @pci: representation of dwc pcie device structure
+ * @aux_clk: auxiliary clock for the pci block
+ * @dbi_clk: DBI clock
+ * @mstr_clk: master clock
+ * @slv_clk: slave clock
+ * @pdata: private data to determine the oprations supported by device
+ * @appl_base: represent the appl base
+ * @sysreg: represent the system register base
+ * @sysreg_base: represents the offset of the system register required
+ * @phy: represents the phy device associated for the controller
+ */
+struct fsd_pcie {
+	struct dw_pcie *pci;
+	struct clk *aux_clk;
+	struct clk *dbi_clk;
+	struct clk *mstr_clk;
+	struct clk *slv_clk;
+	const struct fsd_pcie_pdata *pdata;
+	void __iomem *appl_base;
+	struct regmap *sysreg;
+	unsigned int sysreg_base;
+	struct phy *phy;
+};
+
+enum fsd_pcie_addr_type {
+	ADDR_TYPE_DBI = 0x0,
+	ADDR_TYPE_DBI2 = 0x32,
+	ADDR_TYPE_ATU = 0x36,
+	ADDR_TYPE_DMA = 0x37,
+};
+
+enum IRQ0_ERR_BITS {
+	APP_PARITY_ERRS_0,
+	APP_PARITY_ERRS_1,
+	APP_PARITY_ERRS_2,
+	CFG_BW_MGT_INT = 4,
+	CFG_LINK_AUTO_BW_INT,
+	CFG_SYS_ERR_RC = 7,
+	DPA_SUBSTATE_UPDATE,
+	FLUSH_DONE,
+	RADM_CORRECTABLE_ERR = 12,
+	RADM_FATAL_ERR,
+	RADM_MSG_CPU_ACTIVE = 22,
+	RADM_MSG_IDLE,
+	RADM_MSG_LTR,
+	RADM_MSG_OBFF,
+	RADM_MSG_UNLOCK,
+	RADM_NONFATAL_ERR,
+	RADM_PM_PME,
+	RADM_PM_TO_ACK,
+	RADM_PM_TURNOFF,
+	RADM_VENDOR_MSG,
+};
+
+enum IRQ1_ERR_BITS {
+	TRGT_CPL_TIMEOUT = 0,
+	VEN_MSG_GRANT,
+	VEN_MSI_GRANT,
+};
+
+enum IRQ2_ERR_BITS {
+	APP_LTR_MSG_GRANT = 0,
+	APP_OBFF_MSG_GRANT,
+	CFG_AER_RC_ERR_INT,
+	CFG_BUS_MASTER_EN,
+	CFG_LINK_EQ_REQ_INT,
+	CFG_PME_INT,
+	EDMA_INT_0,
+	EDMA_INT_1,
+	EDMA_INT_2,
+	EDMA_INT_3,
+	EDMA_INT_4,
+	EDMA_INT_5,
+	EDMA_INT_6,
+	EDMA_INT_7,
+	PM_LINKST_IN_L0S = 18,
+	PM_LINKST_IN_L1,
+	PM_LINKST_IN_L1SUB_0,
+	PM_LINKST_IN_L2,
+	PM_LINKST_L2_EXIT,
+	PM_XTLH_BLOCK_TLP,
+	RADM_CPL_TIMEOUT,
+	RADM_Q_NOT_EMPTY,
+	RDLH_LINK_UP_0,
+	SMLH_LINK_UP = 29,
+	WAKE,
+	COMPARE_END_CHECKER,
+};
+
+enum IRQ5_ERR_BITS {
+	LINK_REQ_RST_NOT,
+	PM_LINKST_IN_L1SUB_1,
+	RDLH_LINK_UP_1,
+	SMLH_REQ_RST_NOT,
+};
+
+struct fsd_pcie_res_ops {
+	int (*get_mem_resources)(struct platform_device *pdev,
+				 struct fsd_pcie *fsd_ctrl);
+	int (*get_clk_resources)(struct platform_device *pdev,
+				 struct fsd_pcie *fsd_ctrl);
+	int (*init_clk_resources)(struct fsd_pcie *fsd_ctrl);
+	void (*deinit_clk_resources)(struct fsd_pcie *fsd_ctrl);
+};
+
+struct fsd_pcie_irq {
+	irqreturn_t (*pcie_msi_irq_handler)(int irq, void *arg);
+	void (*pcie_msi_init)(struct fsd_pcie *fsd_ctrl);
+	irqreturn_t (*pcie_sub_ctrl_handler)(int irq, void *arg);
+};
+
+struct fsd_pcie_pdata {
+	const struct dw_pcie_ops *dwc_ops;
+	struct dw_pcie_host_ops	*host_ops;
+	const struct fsd_pcie_res_ops *res_ops;
+	const struct fsd_pcie_irq *irq_data;
+	unsigned int appl_cxpl_debug_00_31;
+	int op_mode;
+};
+
+static int fsd_pcie_get_mem_resources(struct platform_device *pdev,
+					  struct fsd_pcie *fsd_ctrl)
+{
+	struct resource *res;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	/* External Local Bus interface(ELBI) Register */
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "appl");
+	if (!res)
+		return -EINVAL;
+	fsd_ctrl->appl_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(fsd_ctrl->appl_base)) {
+		dev_err(dev, "Failed to map appl_base\n");
+		return PTR_ERR(fsd_ctrl->appl_base);
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
+	if (!res)
+		return -EINVAL;
+	fsd_ctrl->pci->dbi_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(fsd_ctrl->pci->dbi_base)) {
+		dev_err(dev, "failed to map dbi_base\n");
+		return PTR_ERR(fsd_ctrl->pci->dbi_base);
+	}
+
+	/* sysreg regmap handle */
+	fsd_ctrl->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
+			"tesla,pcie-sysreg");
+	if (IS_ERR(fsd_ctrl->sysreg)) {
+		dev_err(dev, "Sysreg regmap lookup failed.\n");
+		return PTR_ERR(fsd_ctrl->sysreg);
+	}
+
+	ret = of_property_read_u32_index(dev->of_node, "tesla,pcie-sysreg", 1,
+					 &fsd_ctrl->sysreg_base);
+	if (ret) {
+		dev_err(dev, "Couldn't get the register offset for syscon!\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int fsd_pcie_get_clk_resources(struct platform_device *pdev,
+				       struct fsd_pcie *fsd_ctrl)
+{
+	struct device *dev = &pdev->dev;
+
+	fsd_ctrl->aux_clk = devm_clk_get(dev, "aux_clk");
+	if (IS_ERR(fsd_ctrl->aux_clk)) {
+		dev_err(dev, "couldn't get aux clock\n");
+		return -EINVAL;
+	}
+
+	fsd_ctrl->dbi_clk = devm_clk_get(dev, "dbi_clk");
+	if (IS_ERR(fsd_ctrl->dbi_clk)) {
+		dev_err(dev, "couldn't get dbi clk\n");
+		return -EINVAL;
+	}
+
+	fsd_ctrl->slv_clk = devm_clk_get(dev, "slv_clk");
+	if (IS_ERR(fsd_ctrl->slv_clk)) {
+		dev_err(dev, "couldn't get slave clock\n");
+		return -EINVAL;
+	}
+
+	fsd_ctrl->mstr_clk = devm_clk_get(dev, "mstr_clk");
+	if (IS_ERR(fsd_ctrl->mstr_clk)) {
+		dev_err(dev, "couldn't get master clk\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int fsd_pcie_init_clk_resources(struct fsd_pcie *fsd_ctrl)
+{
+	clk_prepare_enable(fsd_ctrl->aux_clk);
+	clk_prepare_enable(fsd_ctrl->dbi_clk);
+	clk_prepare_enable(fsd_ctrl->mstr_clk);
+	clk_prepare_enable(fsd_ctrl->slv_clk);
+
+	return 0;
+}
+
+static void fsd_pcie_deinit_clk_resources(struct fsd_pcie *fsd_ctrl)
+{
+	clk_disable_unprepare(fsd_ctrl->slv_clk);
+	clk_disable_unprepare(fsd_ctrl->mstr_clk);
+	clk_disable_unprepare(fsd_ctrl->dbi_clk);
+	clk_disable_unprepare(fsd_ctrl->aux_clk);
+}
+
+static const struct fsd_pcie_res_ops fsd_pcie_res_ops_data = {
+	.get_mem_resources	= fsd_pcie_get_mem_resources,
+	.get_clk_resources	= fsd_pcie_get_clk_resources,
+	.init_clk_resources	= fsd_pcie_init_clk_resources,
+	.deinit_clk_resources	= fsd_pcie_deinit_clk_resources,
+};
+
+static void fsd_pcie_stop_link(struct dw_pcie *pci)
+{
+	u32 reg;
+	struct fsd_pcie *fsd_ctrl = to_fsd_pcie(pci);
+
+	reg = readl(fsd_ctrl->appl_base + PCIE_APP_LTSSM_ENABLE);
+	reg &= ~PCIE_ELBI_LTSSM_ENABLE;
+	writel(reg, fsd_ctrl->appl_base + PCIE_APP_LTSSM_ENABLE);
+}
+
+static int fsd_pcie_establish_link(struct dw_pcie *pci)
+{
+	struct device *dev = pci->dev;
+	struct fsd_pcie *fsd_ctrl = to_fsd_pcie(pci);
+	struct dw_pcie_ep *ep;
+
+	if (dw_pcie_link_up(pci)) {
+		dev_info(dev, "Link already up\n");
+		return 0;
+	}
+
+	/* assert LTSSM enable */
+	writel(PCIE_ELBI_LTSSM_ENABLE, fsd_ctrl->appl_base +
+			PCIE_APP_LTSSM_ENABLE);
+
+	/* check if the link is up or not */
+	if (!dw_pcie_wait_for_link(pci)) {
+		dev_info(dev, "Link up done successfully\n");
+		if (fsd_ctrl->pdata->op_mode == DEVICE_TYPE_EP) {
+			ep = &pci->ep;
+			dw_pcie_ep_linkup(ep);
+		}
+		return 0;
+	}
+
+	if (fsd_ctrl->pdata->op_mode == DEVICE_TYPE_RC) {
+		/* Return success as link might come up later */
+		return 0;
+	}
+
+	return -ETIMEDOUT;
+}
+
+static void handle_irq0_interrupts(u32 val, u32 is_en)
+{
+	u32 bit_off = 0;
+
+	if (val) {
+		while (bit_off < 32) {
+			if ((val & (0x1 << bit_off)) == 0 || (is_en &
+						(0x1 << bit_off)) == 0) {
+				bit_off++;
+				continue;
+			}
+			switch (bit_off) {
+			case RADM_VENDOR_MSG:
+				pr_info("Interrupt received for\n");
+				break;
+			case RADM_PM_TURNOFF:
+				pr_info("Interrupt received for RADM_PM_TURNOFF\n");
+				break;
+			case RADM_PM_TO_ACK:
+				pr_info("Interrupt received for RADM_PM_TO_ACK\n");
+				break;
+			case RADM_PM_PME:
+				pr_info("Interrupt received for RADM_PM_PME\n");
+				break;
+			case RADM_NONFATAL_ERR:
+				pr_info("Interrupt received for RADM_NONFATAL_ERR\n");
+				break;
+			case RADM_MSG_UNLOCK:
+				pr_info("Interrupt received for RADM_MSG_UNLOCK\n");
+				break;
+			case RADM_MSG_OBFF:
+				pr_info("Interrupt received for RADM_MSG_OBFF\n");
+				break;
+			case RADM_MSG_LTR:
+				pr_info("Interrupt received for RADM_MSG_LTR\n");
+				break;
+			case RADM_MSG_IDLE:
+				pr_info("Interrupt received for RADM_MSG_IDLE\n");
+				break;
+			case RADM_MSG_CPU_ACTIVE:
+				pr_info("Interrupt received for RADM_MSG_CPU_ACTIVE\n");
+				break;
+			case RADM_FATAL_ERR:
+				pr_info("Interrupt received for RADM_FATAL_ERR\n");
+				break;
+			case RADM_CORRECTABLE_ERR:
+				pr_info("Interrupt received for RADM_CORRECTABLE_ERR\n");
+				break;
+			case FLUSH_DONE:
+				pr_info("Interrupt received for FLUSH_DONE\n");
+				break;
+			case DPA_SUBSTATE_UPDATE:
+				pr_info("Interrupt received for DPA_SUBSTATE_UPDATE\n");
+				break;
+			case CFG_SYS_ERR_RC:
+				pr_info("Interrupt received for CFG_SYS_ERR_RC\n");
+				break;
+			case CFG_LINK_AUTO_BW_INT:
+				pr_info("Interrupt received for CFG_LINK_AUTO_BW_INT\n");
+				break;
+			case CFG_BW_MGT_INT:
+				pr_info("Interrupt received for CFG_BW_MGT_INT\n");
+				break;
+			case APP_PARITY_ERRS_2:
+				pr_info("Interrupt received for APP_PARITY_ERRS_2\n");
+				break;
+			case APP_PARITY_ERRS_1:
+				pr_info("Interrupt received for APP_PARITY_ERRS_1\n");
+				break;
+			case APP_PARITY_ERRS_0:
+				pr_info("Interrupt received for APP_PARITY_ERRS_0\n");
+				break;
+			default:
+				pr_info("Unknown Interrupt in IRQ0[%d]\n", bit_off);
+				break;
+			}
+			bit_off++;
+		}
+	}
+}
+
+static void handle_irq1_interrupts(u32 val, u32 is_en)
+{
+	u32 bit_off = 0;
+
+	if (val) {
+		while (bit_off < 32) {
+			if ((val & (0x1 << bit_off)) == 0 || (is_en &
+						(0x1 << bit_off)) == 0) {
+				bit_off++;
+				continue;
+			}
+			switch (bit_off) {
+			case TRGT_CPL_TIMEOUT:
+				pr_info("Interrupt for TRGT_CPL_TIMEOUT\n");
+				break;
+			case VEN_MSG_GRANT:
+				pr_info("Interrupt for VEN_MSG_GRANT\n");
+				break;
+			case VEN_MSI_GRANT:
+				pr_info("Interrupt for VEN_MSI_GRANT\n");
+				break;
+			default:
+				pr_info("Unknown Interrupt in IRQ1[%d]\n", bit_off);
+				break;
+			}
+			bit_off++;
+		}
+	}
+}
+
+static void handle_irq2_interrupts(u32 val, u32 is_en)
+{
+	u32 bit_off = 0;
+
+	if (val) {
+		while (bit_off < 32) {
+			if ((val & (0x1 << bit_off)) == 0 || (is_en &
+						(0x1 << bit_off)) == 0) {
+				bit_off++;
+				continue;
+			}
+			switch (bit_off) {
+			/* To indicate that controller has accepted to send
+			 * Latency Tolerance reporting message
+			 */
+			case APP_LTR_MSG_GRANT:
+				pr_info("Interrupt for APP_LTR_MSG_GRANT\n");
+				break;
+			case APP_OBFF_MSG_GRANT:
+				pr_info("Interrupt for APP_OBFF_MSG_GRANT\n");
+				break;
+			case CFG_AER_RC_ERR_INT:
+				pr_info("Interrupt for CFG_AER_RC_ERR_INT\n");
+				break;
+			/* IRQ when bus master is enabled */
+			case CFG_BUS_MASTER_EN:
+				pr_info("Interrupt for CFG_BUS_MASTER_EN\n");
+				break;
+			/* IRQ to indicate that link Equalization request has been set */
+			case CFG_LINK_EQ_REQ_INT:
+				pr_info("Interrupt for CFG_LINK_EQ_REQ_INT\n");
+				break;
+			case CFG_PME_INT:
+				pr_info("Interrupt for CFG_PME_INIT\n");
+				break;
+			case EDMA_INT_0:
+			case EDMA_INT_1:
+			case EDMA_INT_2:
+			case EDMA_INT_3:
+			case EDMA_INT_4:
+			case EDMA_INT_5:
+			case EDMA_INT_6:
+			case EDMA_INT_7:
+				pr_info("Interrupt for DMA\n");
+				break;
+			/* IRQ when link entres L0s */
+			case PM_LINKST_IN_L0S:
+				pr_info("Interrupt for PM_LINKST_IN_L0S\n");
+				break;
+			/* IRQ when link enters L1 */
+			case PM_LINKST_IN_L1:
+				pr_info("Interrupt for PM_LINKST_IN_L1\n");
+				break;
+			/* IRQ when link enters L1 substate */
+			case PM_LINKST_IN_L1SUB_0:
+				pr_info("Interrupt for PM_LINKST_IN_L1SUB_0\n");
+				break;
+			/* IRQ when link enters L2 */
+			case PM_LINKST_IN_L2:
+				pr_info("Interrupt for PM_LINKST_IN_L2\n");
+				break;
+			/* IRQ when link exits L2 */
+			case PM_LINKST_L2_EXIT:
+				pr_info("Interrupt for PM_LINKST_L2_EXIT\n");
+				break;
+			/* Indicates that application must stop sending new
+			 * outbound TLP requests due to current power state
+			 */
+			case PM_XTLH_BLOCK_TLP:
+				pr_info("Interrupt for PM_XTLH_BLOCK_TLP\n");
+				break;
+			/* Request failed to complete in time */
+			case RADM_CPL_TIMEOUT:
+				pr_info("Interrupt for RADM_CPL_TIMEOUT\n");
+				break;
+			/* Level indicating that receive queues contain TLP header/data */
+			case RADM_Q_NOT_EMPTY:
+				pr_info("Interrupt for RADM_Q_NOT_EMPTY\n");
+				break;
+			/* Data link layer up/down indicator */
+			case RDLH_LINK_UP_0:
+				pr_info("Interrupt for RDLH_LINK_UP_0\n");
+				break;
+			/* Phy link up/down indicator */
+			case SMLH_LINK_UP:
+				pr_info("Interrupt for SMLH_LINK_UP\n");
+				break;
+			case WAKE:
+				pr_info("Interrupt for WAKE\n");
+				break;
+			case COMPARE_END_CHECKER:
+				pr_info("Interrupt for COMPARE_END_CHECKER\n");
+				break;
+			default:
+				pr_info("Unknown Interrupt in IRQ2[%d]\n", bit_off);
+				break;
+			}
+			bit_off++;
+		}
+	}
+}
+
+static void handle_irq5_interrupts(u32 val, u32 is_en)
+{
+	u32 bit_off = 0;
+
+	if (val) {
+		while (bit_off < 32) {
+			if ((val & (0x1 << bit_off)) == 0 || (is_en &
+						(0x1 << bit_off)) == 0) {
+				bit_off++;
+				continue;
+			}
+			switch (bit_off) {
+			case LINK_REQ_RST_NOT:
+				pr_info("Interrupt for LINK_REQ_RST_NOT\n");
+				break;
+			case PM_LINKST_IN_L1SUB_1:
+				pr_info("Interrupt for L1 SUB state Exit\n");
+				break;
+			case RDLH_LINK_UP_1:
+				pr_info("Interrupt for RDLH_LINK_UP_1\n");
+				break;
+			/* Reset request because PHY link went down/ or got hot reset */
+			case SMLH_REQ_RST_NOT:
+				pr_info("Interrupt for SMLH_REQ_RST_NOT\n");
+				break;
+			default:
+				pr_info("Unknown Interrupt in IRQ5[%d]\n", bit_off);
+				break;
+			}
+			bit_off++;
+		}
+	}
+}
+
+/*
+ * fsd_pcie_sub_ctrl_handler : Interrupt handler for all PCIe interrupts.
+ *
+ * These interrupts trigger on different events happening in the PCIe
+ * controller like link status, link entering and exiting low power
+ * states like L0s, L1, DMA completion/abort interrupts, wake being
+ * triggered and other information.
+ *
+ * IRQ_0: (offset 0x0): IRQ for pulse output 1
+ *	Enable these interrupts at offset 0x10
+ * IRQ_1: (offset 0x4): IRQ for pulse output 2
+ *	Enable these interrupts at offset 0x14
+ * IRQ_2: (offset 0x8): IRQ for level output, rising edge
+ *	Enable these interrupts at offset 0x18
+ * IRQ_5: (offset 0xC): IRQ for level output, falling edge
+ *	Enable these interrupts at offset 0x1C
+ */
+
+static irqreturn_t fsd_pcie_sub_ctrl_handler(int irq, void *arg)
+{
+	u32 irq0, irq1, irq2, irq5;
+	struct fsd_pcie *fsd_ctrl = arg;
+	u32 irq0_en, irq1_en, irq2_en, irq5_en;
+
+	/* Read IRQ0 status */
+	irq0 = readl(fsd_ctrl->appl_base + IRQ0_STS);
+	/* Clear IRQ0 status after storing status value */
+	writel(irq0, fsd_ctrl->appl_base + IRQ0_STS);
+
+	/* Read IRQ1 status */
+	irq1 = readl(fsd_ctrl->appl_base + IRQ1_STS);
+	/* Clear IRQ1 status after storing status value */
+	writel(irq1, fsd_ctrl->appl_base + IRQ1_STS);
+
+	/* Read IRQ2 status */
+	irq2 = readl(fsd_ctrl->appl_base + IRQ2_STS);
+	/* Clear IRQ2 status after storing status value */
+	writel(irq2, fsd_ctrl->appl_base + IRQ2_STS);
+
+	/* Read IRQ5 status */
+	irq5 = readl(fsd_ctrl->appl_base + IRQ5_STS);
+	/* Clear IRQ5 status after storing status value */
+	writel(irq5, fsd_ctrl->appl_base + IRQ5_STS);
+
+	irq0_en = readl(fsd_ctrl->appl_base + IRQ0_EN);
+	irq1_en = readl(fsd_ctrl->appl_base + IRQ1_EN);
+	irq2_en = readl(fsd_ctrl->appl_base + IRQ2_EN);
+	irq5_en = readl(fsd_ctrl->appl_base + IRQ5_EN);
+	/* Handle all interrupts */
+	handle_irq0_interrupts(irq0, irq0_en);
+	handle_irq1_interrupts(irq1, irq1_en);
+	handle_irq2_interrupts(irq2, irq2_en);
+	handle_irq5_interrupts(irq5, irq5_en);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t fsd_pcie_msi_irq_handler(int irq, void *arg)
+{
+	u32 val;
+	struct fsd_pcie *fsd_ctrl = arg;
+	struct dw_pcie *pci = fsd_ctrl->pci;
+	struct dw_pcie_rp *pp = &pci->pp;
+
+	val = readl(fsd_ctrl->appl_base + IRQ2_STS);
+
+	if ((val & IRQ_MSI_ENABLE) == IRQ_MSI_ENABLE) {
+		val &= IRQ_MSI_ENABLE;
+		writel(val, fsd_ctrl->appl_base + IRQ2_STS);
+		dw_handle_msi_irq(pp);
+	} else {
+		fsd_pcie_sub_ctrl_handler(irq, arg);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void fsd_pcie_msi_init(struct fsd_pcie *fsd_ctrl)
+{
+	int val;
+
+	/* enable MSI interrupt */
+	val = readl(fsd_ctrl->appl_base + IRQ2_EN);
+	val |= IRQ_MSI_ENABLE;
+	writel(val, fsd_ctrl->appl_base + IRQ2_EN);
+}
+
+static void fsd_pcie_enable_interrupts(struct fsd_pcie *fsd_ctrl)
+{
+	if (IS_ENABLED(CONFIG_PCI_MSI))
+		fsd_ctrl->pdata->irq_data->pcie_msi_init(fsd_ctrl);
+}
+
+static u32 fsd_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base,
+				u32 reg, size_t size)
+{
+	bool is_atu = false;
+	struct fsd_pcie *fsd_ctrl = to_fsd_pcie(pci);
+	u32 val;
+
+	if (pci->atu_base) {
+		if (base >= pci->atu_base) {
+
+			is_atu = true;
+			regmap_write(fsd_ctrl->sysreg, fsd_ctrl->sysreg_base,
+					ADDR_TYPE_ATU);
+			base = base - DEFAULT_DBI_ATU_OFFSET;
+		}
+	}
+
+	dw_pcie_read(base + reg, size, &val);
+
+	if (is_atu)
+		regmap_write(fsd_ctrl->sysreg, fsd_ctrl->sysreg_base, ADDR_TYPE_DBI);
+
+	return val;
+}
+
+static void fsd_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base,
+				u32 reg, size_t size, u32 val)
+{
+	struct fsd_pcie *fsd_ctrl = to_fsd_pcie(pci);
+	bool is_atu = false;
+
+	if (pci->atu_base) {
+		if (base >= pci->atu_base) {
+			is_atu = true;
+			regmap_write(fsd_ctrl->sysreg, fsd_ctrl->sysreg_base,
+					ADDR_TYPE_ATU);
+			base = base - DEFAULT_DBI_ATU_OFFSET;
+		}
+	}
+
+	dw_pcie_write(base + reg, size, val);
+
+	if (is_atu)
+		regmap_write(fsd_ctrl->sysreg, fsd_ctrl->sysreg_base, ADDR_TYPE_DBI);
+}
+
+static void fsd_pcie_write_dbi2(struct dw_pcie *pci, void __iomem *base,
+				u32 reg, size_t size, u32 val)
+{
+	struct fsd_pcie *fsd_ctrl = to_fsd_pcie(pci);
+
+	regmap_write(fsd_ctrl->sysreg, fsd_ctrl->sysreg_base, ADDR_TYPE_DBI2);
+	dw_pcie_write(pci->dbi_base + reg, size, val);
+	regmap_write(fsd_ctrl->sysreg, fsd_ctrl->sysreg_base, ADDR_TYPE_DBI);
+}
+
+static int fsd_pcie_link_up(struct dw_pcie *pci)
+{
+	u32 val;
+	struct fsd_pcie *fsd_ctrl = to_fsd_pcie(pci);
+
+	val = readl(fsd_ctrl->appl_base +
+			fsd_ctrl->pdata->appl_cxpl_debug_00_31);
+
+	return (val & LTSSM_STATE_MASK) == LTSSM_STATE_L0;
+}
+
+static int fsd_pcie_host_init(struct dw_pcie_rp *pp)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+	struct fsd_pcie *fsd_ctrl = to_fsd_pcie(pci);
+
+	dw_pcie_writel_dbi(pci, PCIE_GEN3_RELATED_OFF,
+				(PCIE_GEN3_EQ_PHASE_2_3 |
+				 PCIE_GEN3_RXEQ_PH01_EN |
+				 PCIE_GEN3_RXEQ_RGRDLESS_RXTS));
+
+	fsd_pcie_enable_interrupts(fsd_ctrl);
+
+	return 0;
+}
+
+static struct dw_pcie_host_ops fsd_pcie_host_ops = {
+	.host_init = fsd_pcie_host_init,
+};
+
+static int fsd_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
+				 enum pci_epc_irq_type type, u16 interrupt_num)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+
+	switch (type) {
+	case PCI_EPC_IRQ_LEGACY:
+		dev_err(pci->dev, "EP does not support legacy IRQs\n");
+		return -EINVAL;
+	case PCI_EPC_IRQ_MSI:
+		return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num);
+	default:
+		dev_err(pci->dev, "UNKNOWN IRQ type\n");
+	}
+
+	return 0;
+}
+
+static const struct pci_epc_features fsd_pcie_epc_features = {
+	.linkup_notifier = false,
+	.msi_capable = true,
+	.msix_capable = false,
+};
+
+static const struct pci_epc_features*
+	fsd_pcie_get_features(struct dw_pcie_ep *ep)
+{
+	return &fsd_pcie_epc_features;
+}
+
+static struct dw_pcie_ep_ops fsd_dw_pcie_ep_ops = {
+	.raise_irq	= fsd_pcie_raise_irq,
+	.get_features	= fsd_pcie_get_features,
+};
+
+static const struct fsd_pcie_irq fsd_pcie_irq_data = {
+	.pcie_msi_irq_handler	= fsd_pcie_msi_irq_handler,
+	.pcie_msi_init		= fsd_pcie_msi_init,
+	.pcie_sub_ctrl_handler	= fsd_pcie_sub_ctrl_handler,
+};
+
+static int __init fsd_add_pcie_ep(struct fsd_pcie *fsd_ctrl,
+		struct platform_device *pdev)
+{
+	struct dw_pcie_ep *ep;
+	struct dw_pcie *pci = fsd_ctrl->pci;
+	int ret;
+	struct device *dev = &pdev->dev;
+
+	ep = &pci->ep;
+	ep->ops = &fsd_dw_pcie_ep_ops;
+
+	dw_pcie_writel_dbi(pci, PCIE_GEN3_RELATED_OFF,
+				(PCIE_GEN3_EQUALIZATION_DISABLE |
+				 PCIE_GEN3_RXEQ_PH01_EN |
+				 PCIE_GEN3_RXEQ_RGRDLESS_RXTS));
+
+	ret = dw_pcie_ep_init(ep);
+	if (ret)
+		dev_err(dev, "failed to initialize endpoint\n");
+
+	return ret;
+}
+
+static int __init fsd_add_pcie_port(struct fsd_pcie *fsd_ctrl,
+					struct platform_device *pdev)
+{
+	int irq;
+	struct device *dev = &pdev->dev;
+	int irq_flags;
+	int ret;
+	struct dw_pcie *pci = fsd_ctrl->pci;
+	struct dw_pcie_rp *pp = &pci->pp;
+
+	if (IS_ENABLED(CONFIG_PCI_MSI)) {
+		irq = platform_get_irq_byname(pdev, "msi");
+		if (!irq) {
+			dev_err(dev, "failed to get msi irq\n");
+			return -ENODEV;
+		}
+
+		irq_flags = IRQF_TRIGGER_RISING | IRQF_SHARED | IRQF_NO_THREAD;
+
+		ret = devm_request_irq(dev, irq,
+					fsd_ctrl->pdata->irq_data->pcie_msi_irq_handler,
+					irq_flags, "fsd-pcie", fsd_ctrl);
+		if (ret) {
+			dev_err(dev, "failed to request msi irq\n");
+			return ret;
+		}
+		pp->msi_irq[0] = -ENODEV;
+	}
+
+	ret = dw_pcie_host_init(pp);
+	if (ret)
+		dev_err(dev, "failed to initialize host\n");
+
+	return ret;
+}
+
+static const struct dw_pcie_ops fsd_dw_pcie_ops = {
+	.read_dbi	= fsd_pcie_read_dbi,
+	.write_dbi	= fsd_pcie_write_dbi,
+	.write_dbi2	= fsd_pcie_write_dbi2,
+	.start_link	= fsd_pcie_establish_link,
+	.stop_link	= fsd_pcie_stop_link,
+	.link_up	= fsd_pcie_link_up,
+};
+
+static int fsd_pcie_probe(struct platform_device *pdev)
+{
+	int ret;
+	int irq, irq_flags;
+	struct dw_pcie *pci;
+	struct dw_pcie_rp *pp;
+	struct fsd_pcie *fsd_ctrl;
+	struct device *dev = &pdev->dev;
+	const struct fsd_pcie_pdata *pdata;
+	struct device_node *np = dev->of_node;
+
+	fsd_ctrl = devm_kzalloc(dev, sizeof(*fsd_ctrl), GFP_KERNEL);
+	if (!fsd_ctrl)
+		return -ENOMEM;
+
+	pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
+	if (!pci)
+		return -ENOMEM;
+
+	pdata = (const struct fsd_pcie_pdata *) of_device_get_match_data(dev);
+
+	fsd_ctrl->pci = pci;
+	fsd_ctrl->pdata = pdata;
+
+	pci->dev = dev;
+	pci->ops = pdata->dwc_ops;
+	pci->dbi_base2 = NULL;
+	pci->dbi_base = NULL;
+	pci->atu_base = NULL;
+	pp = &pci->pp;
+	pp->ops = fsd_ctrl->pdata->host_ops;
+
+	fsd_ctrl->phy = devm_of_phy_get(dev, np, NULL);
+	if (IS_ERR(fsd_ctrl->phy)) {
+		if (PTR_ERR(fsd_ctrl->phy) == -EPROBE_DEFER)
+			return PTR_ERR(fsd_ctrl->phy);
+	}
+
+	phy_init(fsd_ctrl->phy);
+
+	if (pdata->res_ops && pdata->res_ops->get_mem_resources) {
+		ret = pdata->res_ops->get_mem_resources(pdev, fsd_ctrl);
+		if (ret)
+			return ret;
+	}
+
+	if (pdata->res_ops && pdata->res_ops->get_clk_resources) {
+		ret = pdata->res_ops->get_clk_resources(pdev, fsd_ctrl);
+		if (ret)
+			return ret;
+		ret = pdata->res_ops->init_clk_resources(fsd_ctrl);
+		if (ret)
+			return ret;
+	}
+
+	platform_set_drvdata(pdev, fsd_ctrl);
+
+	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(36));
+	if (ret)
+		goto fail_dma_set;
+
+	switch (fsd_ctrl->pdata->op_mode) {
+	case DEVICE_TYPE_RC:
+		writel(DEVICE_TYPE_RC, fsd_ctrl->appl_base +
+					PCIE_FSD_DEVICE_TYPE);
+		ret = fsd_add_pcie_port(fsd_ctrl, pdev);
+		if (ret)
+			goto fail_add_pcie_port;
+		break;
+	case DEVICE_TYPE_EP:
+		writel(DEVICE_TYPE_EP, fsd_ctrl->appl_base +
+				PCIE_FSD_DEVICE_TYPE);
+
+		ret = fsd_add_pcie_ep(fsd_ctrl, pdev);
+		if (ret)
+			goto fail_add_pcie_ep;
+		break;
+	}
+
+	irq = platform_get_irq_byname(pdev, "sub_ctrl_intr");
+	if (irq > 0) {
+
+		irq_flags = IRQF_TRIGGER_RISING | IRQF_SHARED | IRQF_NO_THREAD;
+
+		ret = devm_request_irq(dev, irq,
+				fsd_ctrl->pdata->irq_data->pcie_sub_ctrl_handler,
+				irq_flags, "fsd-sub-ctrl-pcie", fsd_ctrl);
+		if (ret)
+			dev_err(dev, "failed to request sub ctrl irq\n");
+	}
+
+	dev_info(dev, "FSD PCIe probe completed successfully\n");
+
+	return 0;
+
+fail_dma_set:
+	dev_err(dev, "PCIe Failed to set 36 bit dma mask\n");
+fail_add_pcie_port:
+	phy_exit(fsd_ctrl->phy);
+fail_add_pcie_ep:
+	if (pdata->res_ops && pdata->res_ops->deinit_clk_resources)
+		pdata->res_ops->deinit_clk_resources(fsd_ctrl);
+	return ret;
+}
+
+static int __exit fsd_pcie_remove(struct platform_device *pdev)
+{
+	struct fsd_pcie *fsd_ctrl = platform_get_drvdata(pdev);
+	const struct fsd_pcie_pdata *pdata = fsd_ctrl->pdata;
+
+	if (pdata->res_ops && pdata->res_ops->deinit_clk_resources)
+		pdata->res_ops->deinit_clk_resources(fsd_ctrl);
+
+	return 0;
+}
+
+static const struct fsd_pcie_pdata fsd_pcie_rc_pdata = {
+	.dwc_ops		= &fsd_dw_pcie_ops,
+	.host_ops		= &fsd_pcie_host_ops,
+	.res_ops		= &fsd_pcie_res_ops_data,
+	.irq_data		= &fsd_pcie_irq_data,
+	.appl_cxpl_debug_00_31	= PCIE_ELBI_CXPL_DEBUG_00_31,
+	.op_mode		= DEVICE_TYPE_RC,
+};
+
+static const struct fsd_pcie_pdata fsd_pcie_ep_pdata = {
+	.dwc_ops		= &fsd_dw_pcie_ops,
+	.host_ops		= &fsd_pcie_host_ops,
+	.res_ops		= &fsd_pcie_res_ops_data,
+	.irq_data		= &fsd_pcie_irq_data,
+	.appl_cxpl_debug_00_31	= PCIE_ELBI_CXPL_DEBUG_00_31,
+	.op_mode		= DEVICE_TYPE_EP,
+};
+
+static const struct of_device_id fsd_pcie_of_match[] = {
+	{
+		.compatible = "tesla,fsd-pcie",
+		.data = (void *) &fsd_pcie_rc_pdata,
+	},
+	{
+		.compatible = "tesla,fsd-pcie-ep",
+		.data = (void *) &fsd_pcie_ep_pdata,
+	},
+
+	{},
+};
+
+static struct platform_driver fsd_pcie_driver = {
+	.probe		= fsd_pcie_probe,
+	.remove		= __exit_p(fsd_pcie_remove),
+	.driver		= {
+		.name	= "fsd-pcie",
+		.of_match_table = fsd_pcie_of_match,
+	},
+};
+
+static int __init fsd_pcie_init(void)
+{
+	return platform_driver_register(&fsd_pcie_driver);
+}
+module_init(fsd_pcie_init);
-- 
2.17.1


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

* [PATCH 4/6] phy: tesla-pcie: Add PCIe PHY driver support for FSD
       [not found]   ` <CGME20221121104736epcas5p36c12ff0b575af77f8cf99811b055b339@epcas5p3.samsung.com>
@ 2022-11-21 10:52     ` Shradha Todi
  2022-11-21 12:08       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 14+ messages in thread
From: Shradha Todi @ 2022-11-21 10:52 UTC (permalink / raw)
  To: bhelgaas, robh+dt, krzysztof.kozlowski+dt, kishon, vkoul,
	lpieralisi, kw, mani, arnd, gregkh, alim.akhtar, ajaykumar.rs,
	rcsekar, sriranjani.p, bharat.uppal, s.prashar, aswani.reddy,
	pankaj.dubey, p.rajanbabu, niyas.ahmed, chanho61.park
  Cc: linux-pci, devicetree, linux-kernel, linux-phy, Shradha Todi

This patch adds PHY driver support for PCIe controller
found in Tesla FSD SoC.

Signed-off-by: Niyas Ahmed S T <niyas.ahmed@samsung.com>
Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
Signed-off-by: Shradha Todi <shradha.t@samsung.com>
Signed-off-by: Padmanabhan Rajanbabu <p.rajanbabu@samsung.com>
---
 drivers/phy/samsung/Kconfig          |  10 +
 drivers/phy/samsung/Makefile         |   1 +
 drivers/phy/samsung/phy-tesla-pcie.c | 397 +++++++++++++++++++++++++++
 3 files changed, 408 insertions(+)
 create mode 100644 drivers/phy/samsung/phy-tesla-pcie.c

diff --git a/drivers/phy/samsung/Kconfig b/drivers/phy/samsung/Kconfig
index 3ccaabf2850a..8c108b974c09 100644
--- a/drivers/phy/samsung/Kconfig
+++ b/drivers/phy/samsung/Kconfig
@@ -38,6 +38,16 @@ config PHY_SAMSUNG_UFS
 	  Samsung Exynos SoCs. This driver provides the interface for UFS host
 	  controller to do PHY related programming.
 
+config PHY_TESLA_FSD_PCIE
+	bool "TESLA FSD PCIe PHY driver"
+	depends on OF && (ARCH_TESLA_FSD || COMPILE_TEST)
+	select GENERIC_PHY
+	help
+	  Enable PCIe PHY support for TESLA FSD SoC series.
+	  This driver provides PHY interface for TESLA FSD PCIe controller.
+	  It will do basic initialisation of the PHY and make it available
+	  for use.
+
 config PHY_SAMSUNG_USB2
 	tristate "S5P/Exynos SoC series USB 2.0 PHY driver"
 	depends on HAS_IOMEM
diff --git a/drivers/phy/samsung/Makefile b/drivers/phy/samsung/Makefile
index afb34a153e34..f1fc0db84eab 100644
--- a/drivers/phy/samsung/Makefile
+++ b/drivers/phy/samsung/Makefile
@@ -15,3 +15,4 @@ phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2)	+= phy-exynos5250-usb2.o
 phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2)	+= phy-s5pv210-usb2.o
 obj-$(CONFIG_PHY_EXYNOS5_USBDRD)	+= phy-exynos5-usbdrd.o
 obj-$(CONFIG_PHY_EXYNOS5250_SATA)	+= phy-exynos5250-sata.o
+obj-$(CONFIG_PHY_TESLA_FSD_PCIE)		+= phy-tesla-pcie.o
diff --git a/drivers/phy/samsung/phy-tesla-pcie.c b/drivers/phy/samsung/phy-tesla-pcie.c
new file mode 100644
index 000000000000..448579f53840
--- /dev/null
+++ b/drivers/phy/samsung/phy-tesla-pcie.c
@@ -0,0 +1,397 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TESLA FSD SoC series PCIe PHY driver
+ *
+ * Phy provider for PCIe controller on TESLA FSD SoC series
+ *
+ * Copyright (C) 2018-2021 Samsung Electronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/init.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+
+#define FSD_LANE_OFFSET			0x400
+#define BRF_NONE			0
+#define BRF_L4				1
+#define BRF_L2				2
+
+/* TESLA FSD: PCIe PHY registers */
+#define PCIE_PHY_AGG_BIF_RESET		0x0200
+#define PCIE_PHY_AGG_BIF_CLOCK		0x0208
+
+#define FSD_PCIE_PHY_TRSV_REG01_LN_N	0x5EC
+#define FSD_PCIE_PHY_TRSV_REG02_LN_N	0x548
+#define FSD_PCIE_PHY_TRSV_REG03_LN_N	0x4E4
+#define FSD_PCIE_PHY_TRSV_REG04_LN_N	0x4EC
+#define FSD_PCIE_PHY_TRSV_REG05_LN_N	0x4F0
+#define FSD_PCIE_PHY_TRSV_REG06_LN_N	0x4F8
+#define FSD_PCIE_PHY_TRSV_REG07_LN_N	0x4FC
+#define FSD_PCIE_PHY_TRSV_REG08_LN_N	0x50C
+#define FSD_PCIE_PHY_TRSV_REG09_LN_N	0x520
+#define FSD_PCIE_PHY_TRSV_REG10_LN_N	0x5AC
+#define FSD_PCIE_PHY_TRSV_REG11_LN_N	0x60C
+#define FSD_PCIE_PHY_TRSV_REG12_LN_N	0x618
+#define FSD_PCIE_PHY_TRSV_REG13_LN_N	0x61C
+#define FSD_PCIE_PHY_TRSV_REG14_LN_N	0x678
+#define FSD_PCIE_PHY_TRSV_REG15_LN_N	0x67C
+#define FSD_PCIE_PHY_TRSV_REG16_LN_N	0x404
+#define FSD_PCIE_PHY_TRSV_REG17_LN_N	0x408
+#define FSD_PCIE_PHY_TRSV_REG18_LN_N	0x414
+#define FSD_PCIE_PHY_TRSV_REG19_LN_N	0x418
+#define FSD_PCIE_PHY_TRSV_REG20_LN_N	0x41C
+#define FSD_PCIE_PHY_TRSV_REG21_LN_N	0x424
+#define FSD_PCIE_PHY_TRSV_REG22_LN_N	0x428
+#define FSD_PCIE_PHY_TRSV_REG23_LN_N	0x430
+#define FSD_PCIE_PHY_TRSV_REG24_LN_N	0x448
+#define FSD_PCIE_PHY_TRSV_REG25_LN_N	0x44C
+#define FSD_PCIE_PHY_TRSV_REG26_LN_N	0x450
+#define FSD_PCIE_PHY_TRSV_REG27_LN_N	0x454
+#define FSD_PCIE_PHY_TRSV_REG28_LN_N	0x458
+#define FSD_PCIE_PHY_TRSV_REG29_LN_N	0x7F0
+#define FSD_PCIE_PHY_TRSV_REG30_LN_N	0x7F4
+
+/* TESLA FSD PCIe PCS registers */
+#define PCIE_PCS_BRF_0			0x0004
+#define PCIE_PCS_BRF_1			0x0804
+#define PCIE_PCS_CLK			0x0180
+
+/* TESLA FSD SYS REG registers */
+#define PCIE_PHY_0_CON			0x042C
+#define PCIE_PHY_1_CON			0x0500
+
+#define PHY_0_CON_MASK			0x3FF
+#define PHY_0_REF_SEL_MASK		0x3
+#define PHY_0_REF_SEL			(0x2 << 0)
+#define PHY_0_SSC_EN_MASK		0x8
+#define PHY_0_SSC_EN			BIT(3)
+#define PHY_0_AUX_EN_MASK		0x10
+#define PHY_0_AUX_EN			BIT(4)
+#define PHY_0_CMN_RSTN_MASK		0x100
+#define PHY_0_CMN_RSTN			BIT(8)
+#define PHY_0_INIT_RSTN_MASK		0x200
+#define PHY_0_INIT_RSTN			BIT(9)
+
+#define PHY_1_CON_MASK			0x1FF
+#define PHY_1_AUX_EN_MASK		0x1
+#define PHY_1_AUX_EN			BIT(0)
+#define PHY_1_CMN_RSTN_MASK		0x2
+#define PHY_1_CMN_RSTN			BIT(1)
+#define PHY_1_INIT_RSTN_MASK		0x8
+#define PHY_1_INIT_RSTN			BIT(3)
+#define PHY_1_REF_SEL_MASK		0x30
+#define PHY_1_REF_SEL			(0x2 << 4)
+#define PHY_1_SSC_EN_MASK		0x80
+#define PHY_1_SSC_EN			BIT(7)
+
+struct fsd_pcie_phy_n_pdata {
+	u32 phy_con;
+	u32 phy_con_mask;
+	u32 phy_ref_sel_mask;
+	u32 phy_ref_sel;
+	u32 phy_ssc_en_mask;
+	u32 phy_ssc_en;
+	u32 phy_aux_en_mask;
+	u32 phy_aux_en;
+	u32 phy_cmn_rstn_mask;
+	u32 phy_cmn_rstn;
+	u32 phy_init_rstn_mask;
+	u32 phy_init_rstn;
+	u32 phy_trsv_reg19_val;
+	u32 phy_trsv_reg29_val;
+	u32 num_lanes;
+	u32 lane_offset;
+};
+
+struct fsd_pcie_phy_data {
+	const struct phy_ops	*ops;
+	struct fsd_pcie_phy_n_pdata *phy0_pdata;
+	struct fsd_pcie_phy_n_pdata *phy1_pdata;
+};
+
+struct fsd_pcie_phy {
+	void __iomem *phy_base;
+	void __iomem *pcs_base;
+
+	struct regmap *sysreg;
+	const struct fsd_pcie_phy_data *drv_data;
+	struct fsd_pcie_phy_n_pdata *pdata;
+
+	u32 lane_sel;
+	u32 bifurcation_mode;
+	int phy_id;
+};
+
+struct fsd_pcie_phy_n_pdata fsd_phy0_con = {
+	.num_lanes		= 0x4,
+	.lane_offset		= FSD_LANE_OFFSET,
+	.phy_con		= PCIE_PHY_0_CON,
+	.phy_con_mask		= PHY_0_CON_MASK,
+	.phy_ref_sel_mask	= PHY_0_REF_SEL_MASK,
+	.phy_ref_sel		= PHY_0_REF_SEL,
+	.phy_ssc_en_mask	= PHY_0_SSC_EN_MASK,
+	.phy_ssc_en		= PHY_0_SSC_EN,
+	.phy_aux_en_mask	= PHY_0_AUX_EN_MASK,
+	.phy_aux_en		= PHY_0_AUX_EN,
+	.phy_cmn_rstn_mask	= PHY_0_CMN_RSTN_MASK,
+	.phy_cmn_rstn		= PHY_0_CMN_RSTN,
+	.phy_init_rstn_mask	= PHY_0_INIT_RSTN_MASK,
+	.phy_init_rstn		= PHY_0_INIT_RSTN,
+	.phy_trsv_reg19_val	= 0x0,
+	.phy_trsv_reg29_val	= 0x7,
+};
+
+struct fsd_pcie_phy_n_pdata fsd_phy1_con = {
+	.num_lanes		= 0x4,
+	.lane_offset		= FSD_LANE_OFFSET,
+	.phy_con		= PCIE_PHY_1_CON,
+	.phy_con_mask		= PHY_1_CON_MASK,
+	.phy_ref_sel_mask	= PHY_1_REF_SEL_MASK,
+	.phy_ref_sel		= PHY_1_REF_SEL,
+	.phy_ssc_en_mask	= PHY_1_SSC_EN_MASK,
+	.phy_ssc_en		= PHY_1_SSC_EN,
+	.phy_aux_en_mask	= PHY_1_AUX_EN_MASK,
+	.phy_aux_en		= PHY_1_AUX_EN,
+	.phy_cmn_rstn_mask	= PHY_1_CMN_RSTN_MASK,
+	.phy_cmn_rstn		= PHY_1_CMN_RSTN,
+	.phy_init_rstn_mask	= PHY_1_INIT_RSTN_MASK,
+	.phy_init_rstn		= PHY_1_INIT_RSTN,
+	.phy_trsv_reg19_val	= 0x3,
+	.phy_trsv_reg29_val	= 0x80,
+};
+
+static void fsd_pcie_phy_writel(struct fsd_pcie_phy *phy_ctrl,
+							u32 val, u32 offset)
+{
+	u32 i;
+	void __iomem *phy_base = phy_ctrl->phy_base;
+	struct fsd_pcie_phy_n_pdata *pdata = phy_ctrl->pdata;
+
+	for (i = 0; i < pdata->num_lanes; i++)
+		writel(val, phy_base + (offset + i * pdata->lane_offset));
+}
+
+static int fsd_pcie_phy_init(struct phy *phy)
+{
+	struct fsd_pcie_phy *phy_ctrl = phy_get_drvdata(phy);
+	void __iomem *phy_base = phy_ctrl->phy_base;
+	struct fsd_pcie_phy_n_pdata *pdata = phy_ctrl->pdata;
+
+	if (phy_ctrl->bifurcation_mode == BRF_NONE) {
+		writel(0x00, phy_ctrl->pcs_base + PCIE_PCS_BRF_0);
+		writel(0x00, phy_ctrl->pcs_base + PCIE_PCS_BRF_1);
+		writel(0x00, phy_base + PCIE_PHY_AGG_BIF_RESET);
+		writel(0x00, phy_base + PCIE_PHY_AGG_BIF_CLOCK);
+	} else if (phy_ctrl->bifurcation_mode == BRF_L4) {
+		writel(0xF, phy_ctrl->pcs_base + PCIE_PCS_BRF_0);
+		writel(0xF, phy_ctrl->pcs_base + PCIE_PCS_BRF_1);
+		writel(0x55, phy_base + PCIE_PHY_AGG_BIF_RESET);
+		writel(0x00, phy_base + PCIE_PHY_AGG_BIF_CLOCK);
+	} else if (phy_ctrl->bifurcation_mode == BRF_L2) {
+		writel(0xC, phy_ctrl->pcs_base + PCIE_PCS_BRF_0);
+		writel(0xC, phy_ctrl->pcs_base + PCIE_PCS_BRF_1);
+		writel(0x50, phy_base + PCIE_PHY_AGG_BIF_RESET);
+		writel(0xA0, phy_base + PCIE_PHY_AGG_BIF_CLOCK);
+	}
+
+	fsd_pcie_phy_writel(phy_ctrl, 0x20, FSD_PCIE_PHY_TRSV_REG01_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x01, FSD_PCIE_PHY_TRSV_REG02_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0xF, FSD_PCIE_PHY_TRSV_REG03_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x13, FSD_PCIE_PHY_TRSV_REG04_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0xFB, FSD_PCIE_PHY_TRSV_REG05_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x10, FSD_PCIE_PHY_TRSV_REG06_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x4, FSD_PCIE_PHY_TRSV_REG07_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x11, FSD_PCIE_PHY_TRSV_REG08_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x11, FSD_PCIE_PHY_TRSV_REG09_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x78, FSD_PCIE_PHY_TRSV_REG10_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x8, FSD_PCIE_PHY_TRSV_REG11_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0xFF, FSD_PCIE_PHY_TRSV_REG12_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x3D, FSD_PCIE_PHY_TRSV_REG13_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x33, FSD_PCIE_PHY_TRSV_REG14_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x33, FSD_PCIE_PHY_TRSV_REG15_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x3F, FSD_PCIE_PHY_TRSV_REG16_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x1C, FSD_PCIE_PHY_TRSV_REG17_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x2B, FSD_PCIE_PHY_TRSV_REG18_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, pdata->phy_trsv_reg19_val,
+			FSD_PCIE_PHY_TRSV_REG19_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x9, FSD_PCIE_PHY_TRSV_REG20_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x10, FSD_PCIE_PHY_TRSV_REG21_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x0, FSD_PCIE_PHY_TRSV_REG22_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x93, FSD_PCIE_PHY_TRSV_REG23_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x1, FSD_PCIE_PHY_TRSV_REG24_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x0, FSD_PCIE_PHY_TRSV_REG25_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x0, FSD_PCIE_PHY_TRSV_REG26_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x0, FSD_PCIE_PHY_TRSV_REG27_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x0, FSD_PCIE_PHY_TRSV_REG28_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, pdata->phy_trsv_reg29_val,
+			FSD_PCIE_PHY_TRSV_REG29_LN_N);
+	fsd_pcie_phy_writel(phy_ctrl, 0x0, FSD_PCIE_PHY_TRSV_REG30_LN_N);
+
+	regmap_update_bits(phy_ctrl->sysreg, pdata->phy_con,
+			pdata->phy_cmn_rstn_mask, pdata->phy_cmn_rstn);
+
+	return 0;
+}
+
+static int fsd_pcie_phy_reset(struct phy *phy)
+{
+	struct fsd_pcie_phy *phy_ctrl = phy_get_drvdata(phy);
+	struct fsd_pcie_phy_n_pdata *pdata = phy_ctrl->pdata;
+
+	writel(0x1, phy_ctrl->pcs_base + PCIE_PCS_CLK);
+
+	regmap_update_bits(phy_ctrl->sysreg, pdata->phy_con, pdata->phy_con_mask,
+			   0x0);
+	regmap_update_bits(phy_ctrl->sysreg, pdata->phy_con, pdata->phy_aux_en_mask,
+			   pdata->phy_aux_en);
+	regmap_update_bits(phy_ctrl->sysreg, pdata->phy_con, pdata->phy_ref_sel_mask,
+			   pdata->phy_ref_sel);
+
+	/* Perform Init Reset Release */
+	regmap_update_bits(phy_ctrl->sysreg, pdata->phy_con,
+			pdata->phy_init_rstn_mask, pdata->phy_init_rstn);
+	return 0;
+}
+
+static const struct phy_ops fsd_phy_ops = {
+	.init		= fsd_pcie_phy_init,
+	.reset		= fsd_pcie_phy_reset,
+	.owner		= THIS_MODULE,
+};
+
+static const struct fsd_pcie_phy_data fsd_pcie_phy = {
+	.ops		= &fsd_phy_ops,
+	.phy0_pdata	= &fsd_phy0_con,
+	.phy1_pdata	= &fsd_phy1_con,
+};
+
+static const struct of_device_id fsd_pcie_phy_match[] = {
+	{
+		.compatible = "tesla,fsd-pcie-phy",
+		.data = &fsd_pcie_phy,
+	},
+	{},
+};
+
+static int fsd_pcie_phy_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct device *dev = &pdev->dev;
+	struct fsd_pcie_phy *fsd_phy;
+	struct phy *generic_phy;
+	struct phy_provider *phy_provider;
+	struct resource *res;
+	const struct fsd_pcie_phy_data *drv_data;
+	struct regmap *sysreg;
+	struct fsd_pcie_phy_n_pdata *pdata;
+
+	drv_data = of_device_get_match_data(dev);
+	if (!drv_data)
+		return -ENODEV;
+
+	fsd_phy = devm_kzalloc(dev, sizeof(*fsd_phy), GFP_KERNEL);
+	if (!fsd_phy)
+		return -ENOMEM;
+
+	fsd_phy->phy_id = of_alias_get_id(dev->of_node, "pciephy");
+	if (fsd_phy->phy_id == 0)
+		fsd_phy->pdata = drv_data->phy0_pdata;
+	else
+		fsd_phy->pdata = drv_data->phy1_pdata;
+	pdata = fsd_phy->pdata;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	fsd_phy->phy_base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(fsd_phy->phy_base)) {
+		dev_err(dev, "Failed to get phy_base resource\n");
+		ret = PTR_ERR(fsd_phy->phy_base);
+		goto fail_get_resource;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	fsd_phy->pcs_base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(fsd_phy->pcs_base)) {
+		dev_err(dev, "Failed to get pcs_base resource\n");
+		ret = PTR_ERR(fsd_phy->pcs_base);
+		goto fail_get_resource;
+	}
+
+	/* sysreg regmap handle */
+	fsd_phy->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
+			"tesla,pcie-sysreg");
+	if (IS_ERR(fsd_phy->sysreg)) {
+		dev_err(dev, "pcie sysreg regmap lookup failed.\n");
+		ret = PTR_ERR(fsd_phy->sysreg);
+		goto fail_get_resource;
+	}
+
+	/* Bifurcation/Aggregation configuration */
+	if (of_property_read_u32(dev->of_node, "phy-mode",
+				&fsd_phy->bifurcation_mode)) {
+		dev_err(dev, "Failed selecting the phy-mode\n");
+		ret = -EINVAL;
+		goto fail_get_resource;
+	}
+	dev_info(dev, "property phy-mode from u32 : %x\n", fsd_phy->bifurcation_mode);
+
+	sysreg = fsd_phy->sysreg;
+	fsd_phy->drv_data = drv_data;
+
+	generic_phy = devm_phy_create(dev, dev->of_node, drv_data->ops);
+	if (IS_ERR(generic_phy)) {
+		dev_err(dev, "Failed to create PHY\n");
+		ret = PTR_ERR(generic_phy);
+		goto fail_get_resource;
+	}
+
+	phy_set_drvdata(generic_phy, fsd_phy);
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(phy_provider)) {
+		dev_err(dev, "Failed to register phy provider\n");
+		ret = PTR_ERR_OR_ZERO(phy_provider);
+		goto fail_phy_provider;
+	}
+
+	writel(0x1, fsd_phy->pcs_base + PCIE_PCS_CLK);
+
+	regmap_update_bits(sysreg, pdata->phy_con, pdata->phy_con_mask,
+			   0x0);
+	regmap_update_bits(sysreg, pdata->phy_con, pdata->phy_aux_en_mask,
+			   pdata->phy_aux_en);
+	regmap_update_bits(sysreg, pdata->phy_con, pdata->phy_ref_sel_mask,
+			   pdata->phy_ref_sel);
+
+	/* Perform Init Reset Release */
+	regmap_update_bits(sysreg, pdata->phy_con, pdata->phy_init_rstn_mask,
+			   pdata->phy_init_rstn);
+
+	dev_info(dev, "PCIe PHY%d Probe Successful\n", fsd_phy->phy_id);
+
+	return 0;
+fail_phy_provider:
+	devm_phy_destroy(dev, generic_phy);
+fail_get_resource:
+	return ret;
+}
+
+static struct platform_driver fsd_pcie_phy_driver = {
+	.probe	= fsd_pcie_phy_probe,
+	.driver = {
+		.of_match_table	= fsd_pcie_phy_match,
+		.name		= "fsd_pcie_phy",
+	}
+};
+
+builtin_platform_driver(fsd_pcie_phy_driver);
-- 
2.17.1


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

* [PATCH 5/6] arm64: dts: fsd: Add PCIe support for Tesla FSD SoC
       [not found]   ` <CGME20221121104741epcas5p31e1320bc4c0912485c1fabe52ea19988@epcas5p3.samsung.com>
@ 2022-11-21 10:52     ` Shradha Todi
  2022-11-21 12:11       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 14+ messages in thread
From: Shradha Todi @ 2022-11-21 10:52 UTC (permalink / raw)
  To: bhelgaas, robh+dt, krzysztof.kozlowski+dt, kishon, vkoul,
	lpieralisi, kw, mani, arnd, gregkh, alim.akhtar, ajaykumar.rs,
	rcsekar, sriranjani.p, bharat.uppal, s.prashar, aswani.reddy,
	pankaj.dubey, p.rajanbabu, niyas.ahmed, chanho61.park
  Cc: linux-pci, devicetree, linux-kernel, linux-phy, Shradha Todi

Add the support for PCIe controller driver and phy driver
for Tesla FSD. It includes support for both RC and EP.

Signed-off-by: Niyas Ahmed S T <niyas.ahmed@samsung.com>
Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
Signed-off-by: Shradha Todi <shradha.t@samsung.com>
---
 arch/arm64/boot/dts/tesla/fsd-evb.dts      |  48 ++++++
 arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi |  65 ++++++++
 arch/arm64/boot/dts/tesla/fsd.dtsi         | 171 +++++++++++++++++++++
 3 files changed, 284 insertions(+)

diff --git a/arch/arm64/boot/dts/tesla/fsd-evb.dts b/arch/arm64/boot/dts/tesla/fsd-evb.dts
index 1db6ddf03f01..cda72b0f76f8 100644
--- a/arch/arm64/boot/dts/tesla/fsd-evb.dts
+++ b/arch/arm64/boot/dts/tesla/fsd-evb.dts
@@ -41,3 +41,51 @@
 &ufs {
 	status = "okay";
 };
+
+&pcie_phy0 {
+	status = "disabled";
+};
+
+&pcie_phy1 {
+	status = "disabled";
+};
+
+&pcie4_rc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_clkreq>, <&pcie1_wake>, <&pcie1_preset>,
+			<&pcie0_slot1>;
+	status = "disabled";
+};
+
+&pcie4_ep {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_clkreq>, <&pcie1_wake>, <&pcie1_preset>,
+			<&pcie0_slot1>;
+	status = "disabled";
+};
+
+&pcie0_rc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_clkreq>, <&pcie0_wake0>, <&pcie0_preset0>,
+			 <&pcie0_slot0>;
+	status = "disabled";
+};
+
+&pcie0_ep {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_clkreq>, <&pcie0_wake0>, <&pcie0_preset0>,
+			 <&pcie0_slot0>;
+	status = "disabled";
+};
+
+&pcie1_rc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_clkreq>, <&pcie0_wake1>, <&pcie0_preset0>;
+	status = "disabled";
+};
+
+&pcie1_ep {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_clkreq>, <&pcie0_wake1>, <&pcie0_preset0>;
+	status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi b/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi
index d0abb9aa0e9e..edae62dfa987 100644
--- a/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi
@@ -64,6 +64,27 @@
 		samsung,pin-pud = <FSD_PIN_PULL_NONE>;
 		samsung,pin-drv = <FSD_PIN_DRV_LV2>;
 	};
+
+	pcie1_clkreq: pcie1-clkreq {
+		samsung,pins = "gpf6-0";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV4>;
+	};
+
+	pcie1_wake: pcie1-wake {
+		samsung,pins = "gpf6-1";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV4>;
+	};
+
+	pcie1_preset: pcie1-preset {
+		samsung,pins = "gpf6-2";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV4>;
+	};
 };
 
 &pinctrl_peric {
@@ -339,6 +360,50 @@
 		samsung,pin-pud = <FSD_PIN_PULL_UP>;
 		samsung,pin-drv = <FSD_PIN_DRV_LV1>;
 	};
+
+	pcie0_clkreq: pcie0-clkreq {
+		samsung,pins = "gpc8-0";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV4>;
+	};
+
+	pcie0_wake1: pcie0-wake1 {
+		samsung,pins = "gpc8-3";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV4>;
+	};
+
+	pcie0_wake0: pcie0-wake0 {
+		samsung,pins = "gpc8-1";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV4>;
+	};
+
+	pcie0_preset0: pcie0-preset0 {
+		samsung,pins = "gpc8-2";
+		samsung,pin-function = <FSD_PIN_FUNC_2>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV4>;
+	};
+
+	pcie0_slot0: pcie0-gpio22 {
+		samsung,pins = "gpg2-6";
+		samsung,pin-function = <FSD_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV4>;
+		samsung,pin-val = <1>;
+	};
+
+	pcie0_slot1: pcie0-gpio23 {
+		samsung,pins = "gpg2-7";
+		samsung,pin-function = <FSD_PIN_FUNC_OUTPUT>;
+		samsung,pin-pud = <FSD_PIN_PULL_UP>;
+		samsung,pin-drv = <FSD_PIN_DRV_LV4>;
+		samsung,pin-val = <1>;
+	};
 };
 
 &pinctrl_pmu {
diff --git a/arch/arm64/boot/dts/tesla/fsd.dtsi b/arch/arm64/boot/dts/tesla/fsd.dtsi
index f35bc5a288c2..2177f6964553 100644
--- a/arch/arm64/boot/dts/tesla/fsd.dtsi
+++ b/arch/arm64/boot/dts/tesla/fsd.dtsi
@@ -32,6 +32,14 @@
 		spi0 = &spi_0;
 		spi1 = &spi_1;
 		spi2 = &spi_2;
+		pciephy0 = &pcie_phy0;
+		pciephy1 = &pcie_phy1;
+		pcierc0 = &pcie0_rc;
+		pcieep0 = &pcie0_ep;
+		pcierc1 = &pcie1_rc;
+		pcieep1 = &pcie1_ep;
+		pcierc2 = &pcie4_rc;
+		pcieep2 = &pcie4_ep;
 	};
 
 	cpus {
@@ -860,6 +868,169 @@
 			clocks = <&clock_fsys0 UFS0_MPHY_REFCLK_IXTAL26>;
 			clock-names = "ref_clk";
 		};
+
+		pcie_phy0: pcie-phy@15080000 {
+			compatible = "tesla,fsd-pcie-phy";
+			#phy-cells = <0>;
+			reg = <0x0 0x15080000 0x0 0x2000>,
+			      <0x0 0x150A0000 0x0 0x1000>;
+			reg-names = "phy", "pcs";
+			samsung,pmureg-phandle = <&pmu_system_controller>;
+			tesla,pcie-sysreg = <&sysreg_fsys0>;
+			phy-mode = <0>;
+			status = "disabled";
+		};
+
+		pcie_phy1: pcie-phy@16880000 {
+			compatible = "tesla,fsd-pcie-phy";
+			#phy-cells = <0>;
+			reg = <0x0 0x16880000 0x0 0x2000>,
+			      <0x0 0x16860000 0x0 0x1000>;
+			reg-names = "phy", "pcs";
+			samsung,pmureg-phandle = <&pmu_system_controller>;
+			tesla,pcie-sysreg = <&sysreg_fsys1>;
+			phy-mode = <0>;
+			status = "disabled";
+		};
+
+		pcie4_rc: pcie@15400000 {
+			compatible = "tesla,fsd-pcie";
+			clocks = <&clock_fsys0 PCIE_SUBCTRL_INST0_AUX_CLK_SOC>,
+				 <&clock_fsys0 PCIE_SUBCTRL_INST0_DBI_ACLK_SOC>,
+				 <&clock_fsys0 PCIE_SUBCTRL_INST0_MSTR_ACLK_SOC>,
+				 <&clock_fsys0 PCIE_SUBCTRL_INST0_SLV_ACLK_SOC>;
+			clock-names = "aux_clk", "dbi_clk", "mstr_clk", "slv_clk";
+			#address-cells = <3>;
+			#size-cells = <2>;
+			dma-coherent;
+			interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "msi";
+			num-lanes = <4>;
+			reg = <0x0 0x15090000 0x0 0x1000>,
+			      <0x0 0x15400000 0x0 0x1000>,
+			      <0x0 0x15800000 0x0 0x1000>;
+			reg-names = "appl", "dbi", "config";
+			ranges =  <0x82000000 0 0x15801000 0 0x15801000 0 0xffefff>;
+			tesla,pcie-sysreg = <&sysreg_fsys0 0x434>;
+			phys = <&pcie_phy0>;
+			phy-names = "pcie_phy0";
+			iommu-map = <0x0 &smmu_fsys0 0x4 0x10000>;
+			iommu-map-mask = <0x0>;
+			status = "disabled";
+		};
+
+		pcie4_ep: pcie-ep@15400000 {
+			compatible = "tesla,fsd-pcie-ep";
+			clocks = <&clock_fsys0 PCIE_SUBCTRL_INST0_AUX_CLK_SOC>,
+				 <&clock_fsys0 PCIE_SUBCTRL_INST0_DBI_ACLK_SOC>,
+				 <&clock_fsys0 PCIE_SUBCTRL_INST0_MSTR_ACLK_SOC>,
+				 <&clock_fsys0 PCIE_SUBCTRL_INST0_SLV_ACLK_SOC>;
+			clock-names = "aux_clk", "dbi_clk", "mstr_clk", "slv_clk";
+			interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "sub_ctrl_intr";
+			reg = <0x0 0x15090000 0x0 0x1000>,
+			      <0x0 0x15400000 0x0 0x1000>,
+			      <0x0 0x15401000 0x0 0x80>,
+			      <0x0 0x15800000 0x0 0xFF0000>;
+			reg-names = "appl", "dbi", "dbi2", "addr_space";
+			num-lanes = <4>;
+			tesla,pcie-sysreg = <&sysreg_fsys0 0x434>;
+			phys = <&pcie_phy0>;
+			phy-names = "pcie_phy0";
+			status = "disabled";
+		};
+
+		pcie0_rc: pcie@16A00000 {
+			compatible = "tesla,fsd-pcie";
+			clocks = <&clock_fsys1 PCIE_LINK0_IPCLKPORT_AUX_ACLK>,
+				 <&clock_fsys1 PCIE_LINK0_IPCLKPORT_DBI_ACLK>,
+				 <&clock_fsys1 PCIE_LINK0_IPCLKPORT_MSTR_ACLK>,
+				 <&clock_fsys1 PCIE_LINK0_IPCLKPORT_SLV_ACLK>;
+			clock-names = "aux_clk", "dbi_clk", "mstr_clk", "slv_clk";
+			#address-cells = <3>;
+			#size-cells = <2>;
+			dma-coherent;
+			interrupts = <GIC_SPI 115 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "msi";
+			num-lanes = <4>;
+			reg = <0x0 0x168B0000 0x0 0x1000>,
+			      <0x0 0x16A00000 0x0 0x2000>,
+			      <0x0 0x17000000 0x0 0x1000>;
+			reg-names = "appl", "dbi", "config";
+			ranges =  <0x82000000 0 0x17001000 0 0x17001000 0 0xffefff>;
+			tesla,pcie-sysreg = <&sysreg_fsys1 0x50C>;
+			phys = <&pcie_phy1>;
+			phy-names = "pcie_phy1";
+			iommu-map = <0x0 &smmu_imem 0x0 0x10000>;
+			iommu-map-mask = <0x0>;
+			status = "disabled";
+		};
+
+		pcie0_ep: pcie-ep@16A00000 {
+			compatible = "tesla,fsd-pcie-ep";
+			clocks = <&clock_fsys1 PCIE_LINK0_IPCLKPORT_AUX_ACLK>,
+				 <&clock_fsys1 PCIE_LINK0_IPCLKPORT_DBI_ACLK>,
+				 <&clock_fsys1 PCIE_LINK0_IPCLKPORT_MSTR_ACLK>,
+				 <&clock_fsys1 PCIE_LINK0_IPCLKPORT_SLV_ACLK>;
+			clock-names = "aux_clk", "dbi_clk", "mstr_clk", "slv_clk";
+			interrupts = <GIC_SPI 115 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "sub_ctrl_intr";
+			reg = <0x0 0x168B0000 0x0 0x1000>,
+			      <0x0 0x16A00000 0x0 0x1000>,
+			      <0x0 0x16A01000 0x0 0x80>,
+			      <0x0 0x17000000 0x0 0xFF0000>;
+			reg-names = "appl", "dbi", "dbi2", "addr_space";
+			num-lanes = <4>;
+			tesla,pcie-sysreg = <&sysreg_fsys1 0x50C>;
+			phys = <&pcie_phy1>;
+			phy-names = "pcie_phy1";
+			status = "disabled";
+		};
+
+		pcie1_rc: pcie-rc@16B00000 {
+			compatible = "tesla,fsd-pcie";
+			clocks = <&clock_fsys1 PCIE_LINK1_IPCLKPORT_AUX_ACLK>,
+				 <&clock_fsys1 PCIE_LINK1_IPCLKPORT_DBI_ACLK>,
+				 <&clock_fsys1 PCIE_LINK1_IPCLKPORT_MSTR_ACLK>,
+				 <&clock_fsys1 PCIE_LINK1_IPCLKPORT_SLV_ACLK>;
+			clock-names = "aux_clk", "dbi_clk", "mstr_clk", "slv_clk";
+			#address-cells = <3>;
+			#size-cells = <2>;
+			dma-coherent;
+			interrupts = <GIC_SPI 117 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "msi";
+			num-lanes = <4>;
+			reg = <0x0 0x168C0000 0x0 0x1000>,
+			      <0x0 0x16B00000 0x0 0x1000>,
+			      <0x0 0x18000000 0x0 0x1000>;
+			reg-names = "appl", "dbi", "config";
+			ranges =  <0x82000000 0 0x18001000 0 0x18001000 0 0xffefff>;
+			tesla,pcie-sysreg = <&sysreg_fsys1 0x510>;
+			phys = <&pcie_phy1>;
+			phy-names = "pcie_phy1";
+			status = "disabled";
+		};
+
+		pcie1_ep: pcie-ep@16B00000 {
+			compatible = "tesla,fsd-pcie";
+			clocks = <&clock_fsys1 PCIE_LINK1_IPCLKPORT_AUX_ACLK>,
+				 <&clock_fsys1 PCIE_LINK1_IPCLKPORT_DBI_ACLK>,
+				 <&clock_fsys1 PCIE_LINK1_IPCLKPORT_MSTR_ACLK>,
+				 <&clock_fsys1 PCIE_LINK1_IPCLKPORT_SLV_ACLK>;
+			clock-names = "aux_clk", "dbi_clk", "mstr_clk", "slv_clk";
+			interrupts = <GIC_SPI 117 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "intr";
+			reg = <0x0 0x168C0000 0x0 0x1000>,
+			      <0x0 0x16B00000 0x0 0x1000>,
+			      <0x0 0x16B01000 0x0 0x80>,
+			      <0x0 0x18000000 0x0 0xFF0000>;
+			reg-names = "appl", "dbi", "dbi2", "addr_space";
+			num-lanes = <4>;
+			tesla,pcie-sysreg = <&sysreg_fsys1 0x510>;
+			phys = <&pcie_phy1>;
+			phy-names = "pcie_phy1";
+			status = "disabled";
+		};
 	};
 };
 
-- 
2.17.1


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

* [PATCH 6/6] misc: pci_endpoint_test: Add driver data for FSD PCIe controllers
       [not found]   ` <CGME20221121104746epcas5p109c7bb299cf19070a9237c00c162ed8f@epcas5p1.samsung.com>
@ 2022-11-21 10:52     ` Shradha Todi
  0 siblings, 0 replies; 14+ messages in thread
From: Shradha Todi @ 2022-11-21 10:52 UTC (permalink / raw)
  To: bhelgaas, robh+dt, krzysztof.kozlowski+dt, kishon, vkoul,
	lpieralisi, kw, mani, arnd, gregkh, alim.akhtar, ajaykumar.rs,
	rcsekar, sriranjani.p, bharat.uppal, s.prashar, aswani.reddy,
	pankaj.dubey, p.rajanbabu, niyas.ahmed, chanho61.park
  Cc: linux-pci, devicetree, linux-kernel, linux-phy, Shradha Todi

dma_map_single() might not return a 4KB aligned address, so add the
default_data as driver data for FSD PCIe controllers to make it
4KB aligned.

Signed-off-by: Shradha Todi <shradha.t@samsung.com>
---
 drivers/misc/pci_endpoint_test.c | 3 +++
 include/linux/pci_ids.h          | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
index 11530b4ec389..2cd1aaa87966 100644
--- a/drivers/misc/pci_endpoint_test.c
+++ b/drivers/misc/pci_endpoint_test.c
@@ -983,6 +983,9 @@ static const struct pci_device_id pci_endpoint_test_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_LS1088A),
 	  .driver_data = (kernel_ulong_t)&default_data,
 	},
+	{ PCI_DEVICE(PCI_VENDOR_ID_TESLA, 0x7777),
+	  .driver_data = (kernel_ulong_t)&default_data,
+	},
 	{ PCI_DEVICE_DATA(SYNOPSYS, EDDA, NULL) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM654),
 	  .driver_data = (kernel_ulong_t)&am654_data
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index b362d90eb9b0..a29b69e908aa 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -158,6 +158,8 @@
 
 #define PCI_VENDOR_ID_LOONGSON		0x0014
 
+#define PCI_VENDOR_ID_TESLA		0x014a
+
 #define PCI_VENDOR_ID_TTTECH		0x0357
 #define PCI_DEVICE_ID_TTTECH_MC322	0x000a
 
-- 
2.17.1


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

* Re: [PATCH 1/6] dt-bindings: phy: Add PCIe PHY bindings for FSD
  2022-11-21 10:52     ` [PATCH 1/6] dt-bindings: phy: Add PCIe PHY bindings for FSD Shradha Todi
@ 2022-11-21 11:59       ` Krzysztof Kozlowski
  0 siblings, 0 replies; 14+ messages in thread
From: Krzysztof Kozlowski @ 2022-11-21 11:59 UTC (permalink / raw)
  To: Shradha Todi, bhelgaas, robh+dt, krzysztof.kozlowski+dt, kishon,
	vkoul, lpieralisi, kw, mani, arnd, gregkh, alim.akhtar,
	ajaykumar.rs, rcsekar, sriranjani.p, bharat.uppal, s.prashar,
	aswani.reddy, pankaj.dubey, p.rajanbabu, niyas.ahmed,
	chanho61.park
  Cc: linux-pci, devicetree, linux-kernel, linux-phy

On 21/11/2022 11:52, Shradha Todi wrote:
> Document the PCIe PHY device tree bindings for Tesla
> FSD SoC

Subject: drop second, redundant "bindings".

> 
> Signed-off-by: Shradha Todi <shradha.t@samsung.com>
> ---
>  .../bindings/phy/phy-tesla-pcie.yaml          | 75 +++++++++++++++++++
>  1 file changed, 75 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/phy/phy-tesla-pcie.yaml
> 
> diff --git a/Documentation/devicetree/bindings/phy/phy-tesla-pcie.yaml b/Documentation/devicetree/bindings/phy/phy-tesla-pcie.yaml
> new file mode 100644
> index 000000000000..8fa9a050af7a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/phy-tesla-pcie.yaml

Filename based on compatible.

> @@ -0,0 +1,75 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/phy/phy-tesla-pcie.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Tesla FSD SoC PCIe PHY
> +
> +maintainers:
> +  - Shradha Todi <shradha.t@samsung.com>
> +
> +properties:
> +  "#phy-cells":
> +    const: 0

Put compatible as first.

> +
> +  compatible:
> +    enum:
> +      - tesla,fsd-pcie-phy
> +
> +  reg:
> +    minItems: 2

Drop minItems

> +    maxItems: 2
> +
> +  reg-names:
> +    minItems: 2
> +    maxItems: 2

Drop both.

> +    items:
> +      enum: [phy, pcs]

Instead list items one after another.

> +    description: |
> +      phy is the register access to PMA layer
> +      pcs is the register access to PCS layer

These go to describing items in 'reg:'

> +
> +  phy-mode:
> +    description: |
> +      Defines the bifurcation mode of the PHY

enum, probably type as well... phy-mode is usually a string. Is it here?

> +
> +  tesla,pmureg-phandle:

Drop phandle, so tesla,pmu-syscon

> +    $ref: '/schemas/types.yaml#/definitions/phandle'

Drop quotes

> +    description: phandle for PMU system controller interface used to
> +                 control PMU register bits for PCIe PHY
> +
> +  tesla,pcie-sysreg:
> +    $ref: '/schemas/types.yaml#/definitions/phandle'

Drop quotes

> +    description: phandle for system control registers, used to
> +                 control phy signals at system level
> +
> +required:
> +  - "#phy-cells"
> +  - compatible

compatible first.

> +  - reg
> +  - reg-names
> +  - phy-mode
> +  - tesla,pmureg-phandle
> +  - tesla,pcie-sysreg
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    bus {
> +      #address-cells = <2>;
> +      #size-cells = <2>;
> +
> +      pcie_phy0: pcie-phy@15080000 {
> +        compatible = "tesla,fsd-pcie-phy";
> +        #phy-cells = <0>;
> +        reg = <0x0 0x15080000 0x0 0x2000>, <0x0 0x150A0000 0x0 0x1000>;
> +        reg-names = "phy", "pcs";
> +        tesla,pmureg-phandle = <&pmu_system_controller>;
> +        tesla,pcie-sysreg = <&sysreg_fsys0>;
> +        phy-mode = <0>;
> +        status = "disabled";

Drop status

> +      };
> +    };
> +...

Best regards,
Krzysztof


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

* Re: [PATCH 2/6] dt-bindings: PCI: Add PCIe controller bindings for FSD
  2022-11-21 10:52     ` [PATCH 2/6] dt-bindings: PCI: Add PCIe controller " Shradha Todi
@ 2022-11-21 12:05       ` Krzysztof Kozlowski
  0 siblings, 0 replies; 14+ messages in thread
From: Krzysztof Kozlowski @ 2022-11-21 12:05 UTC (permalink / raw)
  To: Shradha Todi, bhelgaas, robh+dt, krzysztof.kozlowski+dt, kishon,
	vkoul, lpieralisi, kw, mani, arnd, gregkh, alim.akhtar,
	ajaykumar.rs, rcsekar, sriranjani.p, bharat.uppal, s.prashar,
	aswani.reddy, pankaj.dubey, p.rajanbabu, niyas.ahmed,
	chanho61.park
  Cc: linux-pci, devicetree, linux-kernel, linux-phy

On 21/11/2022 11:52, Shradha Todi wrote:
> Document the PCIe controller device tree bindings for

Subject: drop second, redundant "bindings".

> Tesla FSD SoC for both RC and EP

Full stop.

> 
> Signed-off-by: Shradha Todi  <shradha.t@samsung.com>
> ---
>  .../bindings/pci/tesla,pcie-fsd-ep.yaml       | 107 ++++++++++++++++
>  .../bindings/pci/tesla,pcie-fsd.yaml          | 117 ++++++++++++++++++
>  2 files changed, 224 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pci/tesla,pcie-fsd-ep.yaml
>  create mode 100644 Documentation/devicetree/bindings/pci/tesla,pcie-fsd.yaml
> 
> diff --git a/Documentation/devicetree/bindings/pci/tesla,pcie-fsd-ep.yaml b/Documentation/devicetree/bindings/pci/tesla,pcie-fsd-ep.yaml
> new file mode 100644
> index 000000000000..07308cb9a35c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pci/tesla,pcie-fsd-ep.yaml

Filename based on compatible.

> @@ -0,0 +1,107 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/pci/tesla,pcie-fsd-ep.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Synopsys DesignWare based PCIe EP controller on FSD SoCs
> +
> +maintainers:
> +  - Shradha Todi <shradha.t@samsung.com>
> +
> +description: |
> +  FSD PCIe EP controller is based on Synopsys DesignWare PCIe IP
> +  and thus inherits all the common properties defined in
> +  snps,dw-pcie-ep.yaml. The controller instance is dual mode and
> +  can work in Root port mode or Endpoint mode at a time.
> +
> +allOf:
> +  - $ref: /schemas/pci/snps,dw-pcie-ep.yaml#
> +
> +properties:
> +  compatible:
> +    enum:
> +      - tesla,fsd-pcie-ep
> +
> +  reg:
> +    items:
> +      - description: controller's application logic registers
> +      - description: controller's own configuration registers
> +                     are available.
> +      - description: controller's own configuration shadow registers
> +                     are available.
> +      - description: Map the remote Root Complex slave address space
> +
> +  reg-names:
> +    items:
> +      - const: appl
> +      - const: dbi
> +      - const: dbi2
> +      - const: addr_space
> +
> +  clocks:
> +    items:
> +      - description: Auxiliary clock for PCIe
> +      - description: AHB clock for PCIe dbi
> +      - description: AHB clock for PCIe master
> +      - description: AHB clock for PCIe slave
> +
> +  clock-names:
> +    items:
> +      - const: aux_clk
> +      - const: dbi_clk
> +      - const: mstr_clk
> +      - const: slv_clk

Drop "_clk" everywhere.

> +
> +  interrupts:
> +    items:
> +      - description: Controller interrupt
> +
> +  interrupt-names:
> +    items:
> +      - const: sub_ctrl_intr

Drop entire property.

> +
> +  tesla,pcie-sysreg:
> +    $ref: '/schemas/types.yaml#/definitions/phandle-array'

Drop quotes.

In the PHY patch you said it is one phandle. Here it is an array. If it
is an array, then define it  properly:
https://elixir.bootlin.com/linux/v5.18-rc1/source/Documentation/devicetree/bindings/soc/samsung/exynos-usi.yaml#L42

> +    description: phandle for system control registers, used to
> +                 control signals at system level
> +
> +required:
> +

Drop blank line.

> +  - compatible
> +  - reg
> +  - reg-names
> +  - clocks
> +  - clock-names
> +  - ranges
> +  - num-lanes
> +  - tesla,pcie-sysreg
> +
> +additionalProperties: true

This must be false. Did you see such code anywhere in existing bindings?
Maybe you meant unevaluatedProperties?

> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/fsd-clk.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +    pcie4_ep: pcie-ep@15400000 {
> +      compatible = "tesla,fsd-pcie-ep";
> +      clocks = <&clock_fsys0 PCIE_SUBCTRL_INST0_AUX_CLK_SOC>,
> +               <&clock_fsys0 PCIE_SUBCTRL_INST0_DBI_ACLK_SOC>,
> +               <&clock_fsys0 PCIE_SUBCTRL_INST0_MSTR_ACLK_SOC>,
> +               <&clock_fsys0 PCIE_SUBCTRL_INST0_SLV_ACLK_SOC>;
> +      clock-names = "aux_clk", "dbi_clk", "mstr_clk", "slv_clk";
> +      interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
> +      interrupt-names = "sub_ctrl_intr";
> +      reg = <0x15090000 0x1000>,

reg is a second property.

> +            <0x15400000 0x1000>,
> +            <0x15401000 0x80>,
> +            <0x15800000 0xFF0000>;

Lowercase hex.

> +      reg-names = "appl", "dbi", "dbi2", "addr_space";
> +      num-lanes = <4>;
> +      tesla,pcie-sysreg = <&sysreg_fsys0 0x434>;
> +      phys = <&pcie_phy0>;
> +      phy-names = "pcie_phy0";
> +      status = "disabled";

No status.

> +    };
> +...
> diff --git a/Documentation/devicetree/bindings/pci/tesla,pcie-fsd.yaml b/Documentation/devicetree/bindings/pci/tesla,pcie-fsd.yaml
> new file mode 100644
> index 000000000000..85648e5c7d27
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pci/tesla,pcie-fsd.yaml

All comments apply here as well.

> @@ -0,0 +1,117 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +
> +$id: http://devicetree.org/schemas/pci/tesla,pcie-fsd.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Synopsys DesignWare based PCIe controller on FSD SoCs
> +
> +maintainers:
> +  - Shradha Todi <shradha.t@samsung.com>
> +
> +description: |
> +  FSD PCIe controller is based on Synopsys DesignWare PCIe IP
> +  and thus inherits all the common properties defined in
> +  designware-pcie.txt.
> +
> +allOf:
> +  - $ref: /schemas/pci/snps,dw-pcie.yaml#
> +
> +properties:
> +  compatible:
> +    const: tesla,fsd-pcie
> +
> +  reg:
> +    items:
> +      - description: controller's application logic registers
> +      - description: controller's own configuration registers
> +                     are available.
> +      - description: configuration registers
> +
> +  reg-names:
> +    items:
> +      - const: appl
> +      - const: dbi
> +      - const: config
> +
> +  clocks:
> +    items:
> +      - description: Auxiliary clock for PCIe
> +      - description: AHB clock for PCIe dbi
> +      - description: AHB clock for PCIe master
> +      - description: AHB clock for PCIe slave
> +
> +  clock-names:
> +    items:
> +      - const: aux_clk
> +      - const: dbi_clk
> +      - const: mstr_clk
> +      - const: slv_clk
> +
> +  interrupts:
> +    minItems: 1
> +    items:
> +      - description: MSI interrupt
> +      - description: Controller interrupt
> +
> +  interrupt-names:
> +    minItems: 1
> +    items:
> +      - const: msi
> +      - const: sub_ctrl_intr

Drop "_intr"

> +
> +  tesla,pcie-sysreg:
> +    $ref: '/schemas/types.yaml#/definitions/phandle-array'
> +    description: phandle for system control registers, used to
> +                 control signals at system level
> +
> +required:
> +

?

> +  - compatible
> +  - reg
> +  - reg-names
> +  - clocks
> +  - clock-names
> +  - ranges
> +  - num-lanes
> +  - tesla,pcie-sysreg
> +
> +additionalProperties: true

false

> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/fsd-clk.h>
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +    bus {
> +      #address-cells = <2>;
> +      #size-cells = <2>;
> +
> +      pcie4_rc: pcie@15400000 {
> +        compatible = "tesla,fsd-pcie";
> +        clocks = <&clock_fsys0 PCIE_SUBCTRL_INST0_AUX_CLK_SOC>,
> +                 <&clock_fsys0 PCIE_SUBCTRL_INST0_DBI_ACLK_SOC>,
> +                 <&clock_fsys0 PCIE_SUBCTRL_INST0_MSTR_ACLK_SOC>,
> +                 <&clock_fsys0 PCIE_SUBCTRL_INST0_SLV_ACLK_SOC>;
> +        clock-names = "aux_clk", "dbi_clk", "mstr_clk", "slv_clk";
> +        #address-cells = <3>;
> +        #size-cells = <2>;
> +        dma-coherent;
> +        interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
> +        interrupt-names = "msi";
> +        num-lanes = <4>;
> +        reg = <0x0 0x15090000 0x0 0x1000>,
> +              <0x0 0x15400000 0x0 0x1000>,
> +              <0x0 0x15800000 0x0 0x1000>;

reg is always second. reg-names in such case third. ranges fourth.

> +        reg-names = "appl", "dbi", "config";


Best regards,
Krzysztof


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

* Re: [PATCH 3/6] PCI: dwc: fsd: Add FSD PCIe Controller driver support
  2022-11-21 10:52     ` [PATCH 3/6] PCI: dwc: fsd: Add FSD PCIe Controller driver support Shradha Todi
@ 2022-11-21 12:07       ` Krzysztof Kozlowski
  2022-11-21 23:18       ` Bjorn Helgaas
  2022-11-30 18:44       ` Rob Herring
  2 siblings, 0 replies; 14+ messages in thread
From: Krzysztof Kozlowski @ 2022-11-21 12:07 UTC (permalink / raw)
  To: Shradha Todi, bhelgaas, robh+dt, krzysztof.kozlowski+dt, kishon,
	vkoul, lpieralisi, kw, mani, arnd, gregkh, alim.akhtar,
	ajaykumar.rs, rcsekar, sriranjani.p, bharat.uppal, s.prashar,
	aswani.reddy, pankaj.dubey, p.rajanbabu, niyas.ahmed,
	chanho61.park
  Cc: linux-pci, devicetree, linux-kernel, linux-phy

On 21/11/2022 11:52, Shradha Todi wrote:
> Add PCIe controller driver file for PCIe controller
> found in fsd SoC family. This driver adds support for both RC
> and EP mode.
> 
> Signed-off-by: Niyas Ahmed S T <niyas.ahmed@samsung.com>
> Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
> Signed-off-by: Padmanabhan Rajanbabu <p.rajanbabu@samsung.com>
> Signed-off-by: Shradha Todi <shradha.t@samsung.com>
> ---
>  drivers/pci/controller/dwc/Kconfig    |   35 +
>  drivers/pci/controller/dwc/Makefile   |    1 +
>  drivers/pci/controller/dwc/pcie-fsd.c | 1021 +++++++++++++++++++++++++
>  3 files changed, 1057 insertions(+)
>  create mode 100644 drivers/pci/controller/dwc/pcie-fsd.c
> 

Yeah, when Samsung started upstreaming Artpec-8 PCI and said "it is
entirely different, cannot be merged with anything else", I had a
feeling it will bite us.

So now we see one more.

Then in some days there will be separate PCI for Exynos in Google
products. Then in company X, then Y.

No, work on unified approach not 3 different drivers.

Best regards,
Krzysztof


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

* Re: [PATCH 4/6] phy: tesla-pcie: Add PCIe PHY driver support for FSD
  2022-11-21 10:52     ` [PATCH 4/6] phy: tesla-pcie: Add PCIe PHY driver support for FSD Shradha Todi
@ 2022-11-21 12:08       ` Krzysztof Kozlowski
  0 siblings, 0 replies; 14+ messages in thread
From: Krzysztof Kozlowski @ 2022-11-21 12:08 UTC (permalink / raw)
  To: Shradha Todi, bhelgaas, robh+dt, krzysztof.kozlowski+dt, kishon,
	vkoul, lpieralisi, kw, mani, arnd, gregkh, alim.akhtar,
	ajaykumar.rs, rcsekar, sriranjani.p, bharat.uppal, s.prashar,
	aswani.reddy, pankaj.dubey, p.rajanbabu, niyas.ahmed,
	chanho61.park
  Cc: linux-pci, devicetree, linux-kernel, linux-phy

On 21/11/2022 11:52, Shradha Todi wrote:
> This patch adds PHY driver support for PCIe controller
> found in Tesla FSD SoC.
> 
> Signed-off-by: Niyas Ahmed S T <niyas.ahmed@samsung.com>
> Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
> Signed-off-by: Shradha Todi <shradha.t@samsung.com>
> Signed-off-by: Padmanabhan Rajanbabu <p.rajanbabu@samsung.com>
> ---
>  drivers/phy/samsung/Kconfig          |  10 +
>  drivers/phy/samsung/Makefile         |   1 +
>  drivers/phy/samsung/phy-tesla-pcie.c | 397 +++++++++++++++++++++++++++
>  3 files changed, 408 insertions(+)
>  create mode 100644 drivers/phy/samsung/phy-tesla-pcie.c
> 

Same comment as for PCI. It's the third driver for Samsung Exynos PCIe
PHY and every time you will say "but it is different".

No, work on unified approach not 3 different drivers.

Best regards,
Krzysztof


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

* Re: [PATCH 5/6] arm64: dts: fsd: Add PCIe support for Tesla FSD SoC
  2022-11-21 10:52     ` [PATCH 5/6] arm64: dts: fsd: Add PCIe support for Tesla FSD SoC Shradha Todi
@ 2022-11-21 12:11       ` Krzysztof Kozlowski
  0 siblings, 0 replies; 14+ messages in thread
From: Krzysztof Kozlowski @ 2022-11-21 12:11 UTC (permalink / raw)
  To: Shradha Todi, bhelgaas, robh+dt, krzysztof.kozlowski+dt, kishon,
	vkoul, lpieralisi, kw, mani, arnd, gregkh, alim.akhtar,
	ajaykumar.rs, rcsekar, sriranjani.p, bharat.uppal, s.prashar,
	aswani.reddy, pankaj.dubey, p.rajanbabu, niyas.ahmed,
	chanho61.park
  Cc: linux-pci, devicetree, linux-kernel, linux-phy

On 21/11/2022 11:52, Shradha Todi wrote:
> Add the support for PCIe controller driver and phy driver
> for Tesla FSD. It includes support for both RC and EP.
> 
> Signed-off-by: Niyas Ahmed S T <niyas.ahmed@samsung.com>
> Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
> Signed-off-by: Shradha Todi <shradha.t@samsung.com>
> ---
>  arch/arm64/boot/dts/tesla/fsd-evb.dts      |  48 ++++++
>  arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi |  65 ++++++++
>  arch/arm64/boot/dts/tesla/fsd.dtsi         | 171 +++++++++++++++++++++
>  3 files changed, 284 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/tesla/fsd-evb.dts b/arch/arm64/boot/dts/tesla/fsd-evb.dts
> index 1db6ddf03f01..cda72b0f76f8 100644
> --- a/arch/arm64/boot/dts/tesla/fsd-evb.dts
> +++ b/arch/arm64/boot/dts/tesla/fsd-evb.dts
> @@ -41,3 +41,51 @@
>  &ufs {
>  	status = "okay";
>  };
> +
> +&pcie_phy0 {
> +	status = "disabled";

It's a double disable, isn't it?

> +};
> +
> +&pcie_phy1 {
> +	status = "disabled";
> +};
> +
> +&pcie4_rc {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pcie1_clkreq>, <&pcie1_wake>, <&pcie1_preset>,
> +			<&pcie0_slot1>;
> +	status = "disabled";

???

> +};
> +
> +&pcie4_ep {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pcie1_clkreq>, <&pcie1_wake>, <&pcie1_preset>,
> +			<&pcie0_slot1>;
> +	status = "disabled";
> +};
> +
> +&pcie0_rc {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pcie0_clkreq>, <&pcie0_wake0>, <&pcie0_preset0>,
> +			 <&pcie0_slot0>;
> +	status = "disabled";
> +};
> +
> +&pcie0_ep {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pcie0_clkreq>, <&pcie0_wake0>, <&pcie0_preset0>,
> +			 <&pcie0_slot0>;
> +	status = "disabled";
> +};
> +
> +&pcie1_rc {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pcie0_clkreq>, <&pcie0_wake1>, <&pcie0_preset0>;
> +	status = "disabled";
> +};
> +
> +&pcie1_ep {
> +	pinctrl-names = "default";
> +	pinctrl-0 = <&pcie0_clkreq>, <&pcie0_wake1>, <&pcie0_preset0>;
> +	status = "disabled";

Ordering is broken. All overrides/extends are ordered by label name.

> +};
> diff --git a/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi b/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi
> index d0abb9aa0e9e..edae62dfa987 100644
> --- a/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi
> +++ b/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi
> @@ -64,6 +64,27 @@
>  		samsung,pin-pud = <FSD_PIN_PULL_NONE>;
>  		samsung,pin-drv = <FSD_PIN_DRV_LV2>;
>  	};
> +
> +	pcie1_clkreq: pcie1-clkreq {

Does not look like you tested the DTS against bindings. Please run `make
dtbs_check` (see Documentation/devicetree/bindings/writing-schema.rst
for instructions).

(...)

>  
>  &pinctrl_pmu {
> diff --git a/arch/arm64/boot/dts/tesla/fsd.dtsi b/arch/arm64/boot/dts/tesla/fsd.dtsi
> index f35bc5a288c2..2177f6964553 100644
> --- a/arch/arm64/boot/dts/tesla/fsd.dtsi
> +++ b/arch/arm64/boot/dts/tesla/fsd.dtsi
> @@ -32,6 +32,14 @@
>  		spi0 = &spi_0;
>  		spi1 = &spi_1;
>  		spi2 = &spi_2;
> +		pciephy0 = &pcie_phy0;
> +		pciephy1 = &pcie_phy1;
> +		pcierc0 = &pcie0_rc;
> +		pcieep0 = &pcie0_ep;
> +		pcierc1 = &pcie1_rc;
> +		pcieep1 = &pcie1_ep;
> +		pcierc2 = &pcie4_rc;
> +		pcieep2 = &pcie4_ep;

Since these are disabled, aliases do not belong to DTSI, but to board.

Also, explain why do you need them.

>  	};
>  
>  	cpus {
> @@ -860,6 +868,169 @@
>  			clocks = <&clock_fsys0 UFS0_MPHY_REFCLK_IXTAL26>;
>  			clock-names = "ref_clk";
>  		};
> +
> +		pcie_phy0: pcie-phy@15080000 {
> +			compatible = "tesla,fsd-pcie-phy";
> +			#phy-cells = <0>;
> +			reg = <0x0 0x15080000 0x0 0x2000>,
> +			      <0x0 0x150A0000 0x0 0x1000>;
> +			reg-names = "phy", "pcs";
> +			samsung,pmureg-phandle = <&pmu_system_controller>;
> +			tesla,pcie-sysreg = <&sysreg_fsys0>;
> +			phy-mode = <0>;
> +			status = "disabled";
> +		};
> +
> +		pcie_phy1: pcie-phy@16880000 {
> +			compatible = "tesla,fsd-pcie-phy";
> +			#phy-cells = <0>;
> +			reg = <0x0 0x16880000 0x0 0x2000>,
> +			      <0x0 0x16860000 0x0 0x1000>;
> +			reg-names = "phy", "pcs";
> +			samsung,pmureg-phandle = <&pmu_system_controller>;
> +			tesla,pcie-sysreg = <&sysreg_fsys1>;
> +			phy-mode = <0>;
> +			status = "disabled";
> +		};
> +
> +		pcie4_rc: pcie@15400000 {

Not ordered. Keep nodes sorted by unit address, at least within the
group of devices you add.

> +			compatible = "tesla,fsd-pcie";

reg is second property. reg-names and ranges follow.

> +			clocks = <&clock_fsys0 PCIE_SUBCTRL_INST0_AUX_CLK_SOC>,
> +				 <&clock_fsys0 PCIE_SUBCTRL_INST0_DBI_ACLK_SOC>,
> +				 <&clock_fsys0 PCIE_SUBCTRL_INST0_MSTR_ACLK_SOC>,
> +				 <&clock_fsys0 PCIE_SUBCTRL_INST0_SLV_ACLK_SOC>;
> +			clock-names = "aux_clk", "dbi_clk", "mstr_clk", "slv_clk";
> +			#address-cells = <3>;
> +			#size-cells = <2>;

Best regards,
Krzysztof


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

* Re: [PATCH 3/6] PCI: dwc: fsd: Add FSD PCIe Controller driver support
  2022-11-21 10:52     ` [PATCH 3/6] PCI: dwc: fsd: Add FSD PCIe Controller driver support Shradha Todi
  2022-11-21 12:07       ` Krzysztof Kozlowski
@ 2022-11-21 23:18       ` Bjorn Helgaas
  2022-11-30 18:44       ` Rob Herring
  2 siblings, 0 replies; 14+ messages in thread
From: Bjorn Helgaas @ 2022-11-21 23:18 UTC (permalink / raw)
  To: Shradha Todi
  Cc: bhelgaas, robh+dt, krzysztof.kozlowski+dt, kishon, vkoul,
	lpieralisi, kw, mani, arnd, gregkh, alim.akhtar, ajaykumar.rs,
	rcsekar, sriranjani.p, bharat.uppal, s.prashar, aswani.reddy,
	pankaj.dubey, p.rajanbabu, niyas.ahmed, chanho61.park, linux-pci,
	devicetree, linux-kernel, linux-phy

On Mon, Nov 21, 2022 at 04:22:07PM +0530, Shradha Todi wrote:
> Add PCIe controller driver file for PCIe controller
> found in fsd SoC family. This driver adds support for both RC
> and EP mode.
> 
> Signed-off-by: Niyas Ahmed S T <niyas.ahmed@samsung.com>
> Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
> Signed-off-by: Padmanabhan Rajanbabu <p.rajanbabu@samsung.com>
> Signed-off-by: Shradha Todi <shradha.t@samsung.com>

Would be much, much better if drivers can be combined as Krzysztof
suggests.  Superficial comments below if not.

> +config PCIE_FSD
> +	bool "Samsung FSD PCIe Controller"
> +	default n

Unnecessary since "default n" is the default.  Please read and learn
from the existing Kconfig for other drivers.

> +config PCIE_FSD_HOST
> +	bool "PCIe FSD Host Mode"
> +	depends on PCI

Shouldn't be necessary because the entire menu depends on PCI:

  menu "DesignWare PCI Core Support"
	  depends on PCI

> +	depends on PCI_MSI_IRQ_DOMAIN || PCI_DOMAIN
> +	select PCIE_DW_HOST
> +	select PCIE_FSD
> +	default n

Unnecessary.

> +config PCIE_FSD_EP
> +	bool "PCIe FSD Endpoint Mode"
> +	depends on PCI_ENDPOINT
> +	select PCIE_DW_EP
> +	select PCIE_FSD
> +	default n

Unnecessary.

> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * PCIe host controller driver for Tesla fsd SoC
> + *
> + * Copyright (C) 2017-2022 Samsung Electronics Co., Ltd. http://www.samsung.com
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.

Unnecessary copyright text since you have SPDX at the top.

> + * struct fsd_pcie - representation of the pci controller

s/pci/PCI/ in English text (you do it inconsistently)
s/pcie/PCIe/ same

> + * @pci: representation of dwc pcie device structure
> + * @pdata: private data to determine the oprations supported by device

s/oprations/operations/

> + * @appl_base: represent the appl base
> + * @sysreg: represent the system register base
> + * @sysreg_base: represents the offset of the system register required

"representation", "represent", "represents"?  Pick one.

> + * @phy: represents the phy device associated for the controller

s/phy/PHY/ in English text

> +	/* External Local Bus interface(ELBI) Register */

Space before "(" in English text.

> +		dev_err(dev, "failed to map dbi_base\n");
> +		dev_err(dev, "Sysreg regmap lookup failed.\n");
> +		dev_err(dev, "Couldn't get the register offset for syscon!\n");
> +		dev_err(dev, "couldn't get aux clock\n");

Random capitalization of driver messages.  Pick one.

> +	/* assert LTSSM enable */
> +		/* Return success as link might come up later */

Random capitalization of comments.  Pick one.

> +			case RADM_VENDOR_MSG:
> +				pr_info("Interrupt received for\n");

Must include device identification.  This one also looks incomplete
("for ..."?)

> +			/* To indicate that controller has accepted to send
> +			 * Latency Tolerance reporting message

Use standard multi-line comment format.

> +			dev_err(dev, "failed to get msi irq\n");

s/msi/MSI/ in English text.
s/irq/IRQ/ also

> +	.start_link	= fsd_pcie_establish_link,

fsd_pcie_start_link() to match function pointer name.

> +	pci->dbi_base2 = NULL;
> +	pci->dbi_base = NULL;
> +	pci->atu_base = NULL;

Unnecessary since you used kzalloc().

> +	dev_info(dev, "FSD PCIe probe completed successfully\n");

Questionable utility.  Most drivers don't emit this, or if they do,
they include some useful information like address, IRQ, etc.

> +	dev_err(dev, "PCIe Failed to set 36 bit dma mask\n");

s/dma/DMA/ in English text.

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

* Re: [PATCH 3/6] PCI: dwc: fsd: Add FSD PCIe Controller driver support
  2022-11-21 10:52     ` [PATCH 3/6] PCI: dwc: fsd: Add FSD PCIe Controller driver support Shradha Todi
  2022-11-21 12:07       ` Krzysztof Kozlowski
  2022-11-21 23:18       ` Bjorn Helgaas
@ 2022-11-30 18:44       ` Rob Herring
  2 siblings, 0 replies; 14+ messages in thread
From: Rob Herring @ 2022-11-30 18:44 UTC (permalink / raw)
  To: Shradha Todi
  Cc: bhelgaas, krzysztof.kozlowski+dt, kishon, vkoul, lpieralisi, kw,
	mani, arnd, gregkh, alim.akhtar, ajaykumar.rs, rcsekar,
	sriranjani.p, bharat.uppal, s.prashar, aswani.reddy,
	pankaj.dubey, p.rajanbabu, niyas.ahmed, chanho61.park, linux-pci,
	devicetree, linux-kernel, linux-phy

On Mon, Nov 21, 2022 at 04:22:07PM +0530, Shradha Todi wrote:
> Add PCIe controller driver file for PCIe controller
> found in fsd SoC family. This driver adds support for both RC
> and EP mode.
> 
> Signed-off-by: Niyas Ahmed S T <niyas.ahmed@samsung.com>
> Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
> Signed-off-by: Padmanabhan Rajanbabu <p.rajanbabu@samsung.com>
> Signed-off-by: Shradha Todi <shradha.t@samsung.com>
> ---
>  drivers/pci/controller/dwc/Kconfig    |   35 +
>  drivers/pci/controller/dwc/Makefile   |    1 +
>  drivers/pci/controller/dwc/pcie-fsd.c | 1021 +++++++++++++++++++++++++
>  3 files changed, 1057 insertions(+)
>  create mode 100644 drivers/pci/controller/dwc/pcie-fsd.c
> 
> diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
> index 62ce3abf0f19..9a3d194c979f 100644
> --- a/drivers/pci/controller/dwc/Kconfig
> +++ b/drivers/pci/controller/dwc/Kconfig
> @@ -14,6 +14,41 @@ config PCIE_DW_EP
>  	bool
>  	select PCIE_DW
>  
> +config PCIE_FSD
> +	bool "Samsung FSD PCIe Controller"
> +	default n
> +	help
> +	  Enables support for the PCIe controller in the FSD SoC. There are
> +	  total three instances of PCIe controller in FSD. This controller
> +	  can work either in RC or EP mode. In order to enable host-specific
> +	  features, PCI_FSD_HOST must be selected and in order to enable
> +	  device-specific feature PCI_FSD_EP must be selected.
> +
> +config PCIE_FSD_HOST
> +	bool "PCIe FSD Host Mode"
> +	depends on PCI
> +	depends on PCI_MSI_IRQ_DOMAIN || PCI_DOMAIN
> +	select PCIE_DW_HOST
> +	select PCIE_FSD
> +	default n
> +	help
> +	  Enables support for the PCIe controller in the FSD SoC to work in
> +	  host (RC) mode. In order to enable host-specific features,
> +	  PCIE_DW_HOST must be selected. PCIE_FSD should be selected for
> +	  fsd controller specific settings.
> +
> +config PCIE_FSD_EP
> +	bool "PCIe FSD Endpoint Mode"
> +	depends on PCI_ENDPOINT
> +	select PCIE_DW_EP
> +	select PCIE_FSD
> +	default n
> +	help
> +	  Enables support for the PCIe controller in the FSD SoC to work in
> +	  endpoint mode. In order to enable device-specific feature
> +	  PCI_FSD_EP must be selected. PCIE_FSD should be selected for
> +	  fsd controller specific settings.
> +
>  config PCI_DRA7XX
>  	tristate
>  
> diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
> index 8ba7b67f5e50..b76fa6b4e79f 100644
> --- a/drivers/pci/controller/dwc/Makefile
> +++ b/drivers/pci/controller/dwc/Makefile
> @@ -25,6 +25,7 @@ obj-$(CONFIG_PCIE_TEGRA194) += pcie-tegra194.o
>  obj-$(CONFIG_PCIE_UNIPHIER) += pcie-uniphier.o
>  obj-$(CONFIG_PCIE_UNIPHIER_EP) += pcie-uniphier-ep.o
>  obj-$(CONFIG_PCIE_VISCONTI_HOST) += pcie-visconti.o
> +obj-$(CONFIG_PCIE_FSD) += pcie-fsd.o
>  
>  # The following drivers are for devices that use the generic ACPI
>  # pci_root.c driver but don't support standard ECAM config access.
> diff --git a/drivers/pci/controller/dwc/pcie-fsd.c b/drivers/pci/controller/dwc/pcie-fsd.c
> new file mode 100644
> index 000000000000..4531efbfc313
> --- /dev/null
> +++ b/drivers/pci/controller/dwc/pcie-fsd.c
> @@ -0,0 +1,1021 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * PCIe host controller driver for Tesla fsd SoC
> + *
> + * Copyright (C) 2017-2022 Samsung Electronics Co., Ltd. http://www.samsung.com
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>

You shouldn't need this header.

> +#include <linux/of_device.h>
> +#include <linux/of_gpio.h>

You shouldn't need this header.

> +#include <linux/pci.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/resource.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/types.h>
> +
> +#include "pcie-designware.h"
> +
> +#define to_fsd_pcie(x)	dev_get_drvdata((x)->dev)
> +
> +/* PCIe ELBI registers */
> +#define PCIE_APP_LTSSM_ENABLE		0x054
> +#define PCIE_ELBI_LTSSM_ENABLE		0x1
> +#define PCIE_ELBI_LTSSM_DISABLE		0x0
> +#define PCIE_ELBI_CXPL_DEBUG_00_31	0x2C8
> +#define LTSSM_STATE_MASK		0x3f
> +#define LTSSM_STATE_L0			0x11
> +#define PCIE_FSD_DEVICE_TYPE		0x080
> +#define DEVICE_TYPE_RC			0x4
> +#define DEVICE_TYPE_EP			0x0
> +#define IRQ_MSI_ENABLE			BIT(17)
> +#define IRQ0_EN				0x10
> +#define IRQ1_EN				0x14
> +#define IRQ2_EN				0x18
> +#define IRQ5_EN				0x1c
> +#define IRQ0_STS			0x0
> +#define IRQ1_STS			0x4
> +#define IRQ2_STS			0x8
> +#define IRQ5_STS			0xc
> +
> +/* Gen3 Control Register */
> +#define PCIE_GEN3_RELATED_OFF		0x890
> +/* Parameters for equalization feature */
> +#define PCIE_GEN3_EQUALIZATION_DISABLE	BIT(16)
> +#define PCIE_GEN3_EQ_PHASE_2_3		BIT(9)
> +#define PCIE_GEN3_RXEQ_PH01_EN		BIT(12)
> +#define PCIE_GEN3_RXEQ_RGRDLESS_RXTS	BIT(13)
> +
> +/**
> + * struct fsd_pcie - representation of the pci controller
> + * @pci: representation of dwc pcie device structure
> + * @aux_clk: auxiliary clock for the pci block
> + * @dbi_clk: DBI clock
> + * @mstr_clk: master clock
> + * @slv_clk: slave clock
> + * @pdata: private data to determine the oprations supported by device
> + * @appl_base: represent the appl base
> + * @sysreg: represent the system register base
> + * @sysreg_base: represents the offset of the system register required
> + * @phy: represents the phy device associated for the controller
> + */
> +struct fsd_pcie {
> +	struct dw_pcie *pci;
> +	struct clk *aux_clk;
> +	struct clk *dbi_clk;
> +	struct clk *mstr_clk;
> +	struct clk *slv_clk;
> +	const struct fsd_pcie_pdata *pdata;
> +	void __iomem *appl_base;
> +	struct regmap *sysreg;
> +	unsigned int sysreg_base;
> +	struct phy *phy;
> +};
> +
> +enum fsd_pcie_addr_type {
> +	ADDR_TYPE_DBI = 0x0,
> +	ADDR_TYPE_DBI2 = 0x32,
> +	ADDR_TYPE_ATU = 0x36,
> +	ADDR_TYPE_DMA = 0x37,
> +};
> +
> +enum IRQ0_ERR_BITS {
> +	APP_PARITY_ERRS_0,
> +	APP_PARITY_ERRS_1,
> +	APP_PARITY_ERRS_2,
> +	CFG_BW_MGT_INT = 4,
> +	CFG_LINK_AUTO_BW_INT,
> +	CFG_SYS_ERR_RC = 7,
> +	DPA_SUBSTATE_UPDATE,
> +	FLUSH_DONE,
> +	RADM_CORRECTABLE_ERR = 12,
> +	RADM_FATAL_ERR,
> +	RADM_MSG_CPU_ACTIVE = 22,
> +	RADM_MSG_IDLE,
> +	RADM_MSG_LTR,
> +	RADM_MSG_OBFF,
> +	RADM_MSG_UNLOCK,
> +	RADM_NONFATAL_ERR,
> +	RADM_PM_PME,
> +	RADM_PM_TO_ACK,
> +	RADM_PM_TURNOFF,
> +	RADM_VENDOR_MSG,
> +};
> +
> +enum IRQ1_ERR_BITS {
> +	TRGT_CPL_TIMEOUT = 0,
> +	VEN_MSG_GRANT,
> +	VEN_MSI_GRANT,
> +};
> +
> +enum IRQ2_ERR_BITS {
> +	APP_LTR_MSG_GRANT = 0,
> +	APP_OBFF_MSG_GRANT,
> +	CFG_AER_RC_ERR_INT,
> +	CFG_BUS_MASTER_EN,
> +	CFG_LINK_EQ_REQ_INT,
> +	CFG_PME_INT,
> +	EDMA_INT_0,
> +	EDMA_INT_1,
> +	EDMA_INT_2,
> +	EDMA_INT_3,
> +	EDMA_INT_4,
> +	EDMA_INT_5,
> +	EDMA_INT_6,
> +	EDMA_INT_7,
> +	PM_LINKST_IN_L0S = 18,
> +	PM_LINKST_IN_L1,
> +	PM_LINKST_IN_L1SUB_0,
> +	PM_LINKST_IN_L2,
> +	PM_LINKST_L2_EXIT,
> +	PM_XTLH_BLOCK_TLP,
> +	RADM_CPL_TIMEOUT,
> +	RADM_Q_NOT_EMPTY,
> +	RDLH_LINK_UP_0,
> +	SMLH_LINK_UP = 29,
> +	WAKE,
> +	COMPARE_END_CHECKER,
> +};
> +
> +enum IRQ5_ERR_BITS {
> +	LINK_REQ_RST_NOT,
> +	PM_LINKST_IN_L1SUB_1,
> +	RDLH_LINK_UP_1,
> +	SMLH_REQ_RST_NOT,
> +};
> +
> +struct fsd_pcie_res_ops {
> +	int (*get_mem_resources)(struct platform_device *pdev,
> +				 struct fsd_pcie *fsd_ctrl);
> +	int (*get_clk_resources)(struct platform_device *pdev,
> +				 struct fsd_pcie *fsd_ctrl);
> +	int (*init_clk_resources)(struct fsd_pcie *fsd_ctrl);
> +	void (*deinit_clk_resources)(struct fsd_pcie *fsd_ctrl);
> +};
> +
> +struct fsd_pcie_irq {
> +	irqreturn_t (*pcie_msi_irq_handler)(int irq, void *arg);
> +	void (*pcie_msi_init)(struct fsd_pcie *fsd_ctrl);
> +	irqreturn_t (*pcie_sub_ctrl_handler)(int irq, void *arg);
> +};

Why the indirection? You only have 1 version of all these functions.

> +
> +struct fsd_pcie_pdata {
> +	const struct dw_pcie_ops *dwc_ops;
> +	struct dw_pcie_host_ops	*host_ops;
> +	const struct fsd_pcie_res_ops *res_ops;
> +	const struct fsd_pcie_irq *irq_data;
> +	unsigned int appl_cxpl_debug_00_31;
> +	int op_mode;
> +};
> +
> +static int fsd_pcie_get_mem_resources(struct platform_device *pdev,
> +					  struct fsd_pcie *fsd_ctrl)
> +{
> +	struct resource *res;
> +	struct device *dev = &pdev->dev;
> +	int ret;
> +
> +	/* External Local Bus interface(ELBI) Register */
> +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "appl");
> +	if (!res)
> +		return -EINVAL;
> +	fsd_ctrl->appl_base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(fsd_ctrl->appl_base)) {
> +		dev_err(dev, "Failed to map appl_base\n");
> +		return PTR_ERR(fsd_ctrl->appl_base);
> +	}
> +
> +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");

The DW core code takes care of this.

> +	if (!res)
> +		return -EINVAL;
> +	fsd_ctrl->pci->dbi_base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(fsd_ctrl->pci->dbi_base)) {
> +		dev_err(dev, "failed to map dbi_base\n");
> +		return PTR_ERR(fsd_ctrl->pci->dbi_base);
> +	}
> +
> +	/* sysreg regmap handle */
> +	fsd_ctrl->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
> +			"tesla,pcie-sysreg");
> +	if (IS_ERR(fsd_ctrl->sysreg)) {
> +		dev_err(dev, "Sysreg regmap lookup failed.\n");
> +		return PTR_ERR(fsd_ctrl->sysreg);
> +	}
> +
> +	ret = of_property_read_u32_index(dev->of_node, "tesla,pcie-sysreg", 1,
> +					 &fsd_ctrl->sysreg_base);
> +	if (ret) {
> +		dev_err(dev, "Couldn't get the register offset for syscon!\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int fsd_pcie_get_clk_resources(struct platform_device *pdev,
> +				       struct fsd_pcie *fsd_ctrl)
> +{
> +	struct device *dev = &pdev->dev;
> +
> +	fsd_ctrl->aux_clk = devm_clk_get(dev, "aux_clk");
> +	if (IS_ERR(fsd_ctrl->aux_clk)) {
> +		dev_err(dev, "couldn't get aux clock\n");
> +		return -EINVAL;
> +	}
> +
> +	fsd_ctrl->dbi_clk = devm_clk_get(dev, "dbi_clk");
> +	if (IS_ERR(fsd_ctrl->dbi_clk)) {
> +		dev_err(dev, "couldn't get dbi clk\n");
> +		return -EINVAL;
> +	}
> +
> +	fsd_ctrl->slv_clk = devm_clk_get(dev, "slv_clk");
> +	if (IS_ERR(fsd_ctrl->slv_clk)) {
> +		dev_err(dev, "couldn't get slave clock\n");
> +		return -EINVAL;
> +	}
> +
> +	fsd_ctrl->mstr_clk = devm_clk_get(dev, "mstr_clk");
> +	if (IS_ERR(fsd_ctrl->mstr_clk)) {
> +		dev_err(dev, "couldn't get master clk\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int fsd_pcie_init_clk_resources(struct fsd_pcie *fsd_ctrl)
> +{
> +	clk_prepare_enable(fsd_ctrl->aux_clk);
> +	clk_prepare_enable(fsd_ctrl->dbi_clk);
> +	clk_prepare_enable(fsd_ctrl->mstr_clk);
> +	clk_prepare_enable(fsd_ctrl->slv_clk);
> +
> +	return 0;
> +}
> +
> +static void fsd_pcie_deinit_clk_resources(struct fsd_pcie *fsd_ctrl)
> +{
> +	clk_disable_unprepare(fsd_ctrl->slv_clk);
> +	clk_disable_unprepare(fsd_ctrl->mstr_clk);
> +	clk_disable_unprepare(fsd_ctrl->dbi_clk);
> +	clk_disable_unprepare(fsd_ctrl->aux_clk);
> +}
> +
> +static const struct fsd_pcie_res_ops fsd_pcie_res_ops_data = {
> +	.get_mem_resources	= fsd_pcie_get_mem_resources,
> +	.get_clk_resources	= fsd_pcie_get_clk_resources,
> +	.init_clk_resources	= fsd_pcie_init_clk_resources,
> +	.deinit_clk_resources	= fsd_pcie_deinit_clk_resources,
> +};
> +
> +static void fsd_pcie_stop_link(struct dw_pcie *pci)
> +{
> +	u32 reg;
> +	struct fsd_pcie *fsd_ctrl = to_fsd_pcie(pci);
> +
> +	reg = readl(fsd_ctrl->appl_base + PCIE_APP_LTSSM_ENABLE);
> +	reg &= ~PCIE_ELBI_LTSSM_ENABLE;
> +	writel(reg, fsd_ctrl->appl_base + PCIE_APP_LTSSM_ENABLE);
> +}
> +
> +static int fsd_pcie_establish_link(struct dw_pcie *pci)
> +{
> +	struct device *dev = pci->dev;
> +	struct fsd_pcie *fsd_ctrl = to_fsd_pcie(pci);
> +	struct dw_pcie_ep *ep;
> +
> +	if (dw_pcie_link_up(pci)) {
> +		dev_info(dev, "Link already up\n");

Print messages on failure, not normal operation.

> +		return 0;
> +	}
> +
> +	/* assert LTSSM enable */
> +	writel(PCIE_ELBI_LTSSM_ENABLE, fsd_ctrl->appl_base +
> +			PCIE_APP_LTSSM_ENABLE);
> +
> +	/* check if the link is up or not */
> +	if (!dw_pcie_wait_for_link(pci)) {

IIRC, the DW core will do the wait for you.

> +		dev_info(dev, "Link up done successfully\n");
> +		if (fsd_ctrl->pdata->op_mode == DEVICE_TYPE_EP) {
> +			ep = &pci->ep;
> +			dw_pcie_ep_linkup(ep);
> +		}
> +		return 0;
> +	}
> +
> +	if (fsd_ctrl->pdata->op_mode == DEVICE_TYPE_RC) {
> +		/* Return success as link might come up later */
> +		return 0;
> +	}
> +
> +	return -ETIMEDOUT;
> +}
> +
> +static void handle_irq0_interrupts(u32 val, u32 is_en)
> +{
> +	u32 bit_off = 0;
> +
> +	if (val) {
> +		while (bit_off < 32) {
> +			if ((val & (0x1 << bit_off)) == 0 || (is_en &
> +						(0x1 << bit_off)) == 0) {
> +				bit_off++;
> +				continue;
> +			}
> +			switch (bit_off) {
> +			case RADM_VENDOR_MSG:
> +				pr_info("Interrupt received for\n");

Printing messages is not handling an interrupt. Remove all these.

> +				break;
> +			case RADM_PM_TURNOFF:
> +				pr_info("Interrupt received for RADM_PM_TURNOFF\n");
> +				break;
> +			case RADM_PM_TO_ACK:
> +				pr_info("Interrupt received for RADM_PM_TO_ACK\n");
> +				break;
> +			case RADM_PM_PME:
> +				pr_info("Interrupt received for RADM_PM_PME\n");
> +				break;
> +			case RADM_NONFATAL_ERR:
> +				pr_info("Interrupt received for RADM_NONFATAL_ERR\n");
> +				break;
> +			case RADM_MSG_UNLOCK:
> +				pr_info("Interrupt received for RADM_MSG_UNLOCK\n");
> +				break;
> +			case RADM_MSG_OBFF:
> +				pr_info("Interrupt received for RADM_MSG_OBFF\n");
> +				break;
> +			case RADM_MSG_LTR:
> +				pr_info("Interrupt received for RADM_MSG_LTR\n");
> +				break;
> +			case RADM_MSG_IDLE:
> +				pr_info("Interrupt received for RADM_MSG_IDLE\n");
> +				break;
> +			case RADM_MSG_CPU_ACTIVE:
> +				pr_info("Interrupt received for RADM_MSG_CPU_ACTIVE\n");
> +				break;
> +			case RADM_FATAL_ERR:
> +				pr_info("Interrupt received for RADM_FATAL_ERR\n");
> +				break;
> +			case RADM_CORRECTABLE_ERR:
> +				pr_info("Interrupt received for RADM_CORRECTABLE_ERR\n");
> +				break;
> +			case FLUSH_DONE:
> +				pr_info("Interrupt received for FLUSH_DONE\n");
> +				break;
> +			case DPA_SUBSTATE_UPDATE:
> +				pr_info("Interrupt received for DPA_SUBSTATE_UPDATE\n");
> +				break;
> +			case CFG_SYS_ERR_RC:
> +				pr_info("Interrupt received for CFG_SYS_ERR_RC\n");
> +				break;
> +			case CFG_LINK_AUTO_BW_INT:
> +				pr_info("Interrupt received for CFG_LINK_AUTO_BW_INT\n");
> +				break;
> +			case CFG_BW_MGT_INT:
> +				pr_info("Interrupt received for CFG_BW_MGT_INT\n");
> +				break;
> +			case APP_PARITY_ERRS_2:
> +				pr_info("Interrupt received for APP_PARITY_ERRS_2\n");
> +				break;
> +			case APP_PARITY_ERRS_1:
> +				pr_info("Interrupt received for APP_PARITY_ERRS_1\n");
> +				break;
> +			case APP_PARITY_ERRS_0:
> +				pr_info("Interrupt received for APP_PARITY_ERRS_0\n");
> +				break;
> +			default:
> +				pr_info("Unknown Interrupt in IRQ0[%d]\n", bit_off);
> +				break;
> +			}
> +			bit_off++;
> +		}
> +	}
> +}
> +
> +static void handle_irq1_interrupts(u32 val, u32 is_en)
> +{
> +	u32 bit_off = 0;
> +
> +	if (val) {
> +		while (bit_off < 32) {
> +			if ((val & (0x1 << bit_off)) == 0 || (is_en &
> +						(0x1 << bit_off)) == 0) {
> +				bit_off++;
> +				continue;
> +			}
> +			switch (bit_off) {
> +			case TRGT_CPL_TIMEOUT:
> +				pr_info("Interrupt for TRGT_CPL_TIMEOUT\n");
> +				break;
> +			case VEN_MSG_GRANT:
> +				pr_info("Interrupt for VEN_MSG_GRANT\n");
> +				break;
> +			case VEN_MSI_GRANT:
> +				pr_info("Interrupt for VEN_MSI_GRANT\n");
> +				break;
> +			default:
> +				pr_info("Unknown Interrupt in IRQ1[%d]\n", bit_off);
> +				break;
> +			}
> +			bit_off++;
> +		}
> +	}
> +}
> +
> +static void handle_irq2_interrupts(u32 val, u32 is_en)
> +{
> +	u32 bit_off = 0;
> +
> +	if (val) {
> +		while (bit_off < 32) {
> +			if ((val & (0x1 << bit_off)) == 0 || (is_en &
> +						(0x1 << bit_off)) == 0) {
> +				bit_off++;
> +				continue;
> +			}
> +			switch (bit_off) {
> +			/* To indicate that controller has accepted to send
> +			 * Latency Tolerance reporting message
> +			 */
> +			case APP_LTR_MSG_GRANT:
> +				pr_info("Interrupt for APP_LTR_MSG_GRANT\n");
> +				break;
> +			case APP_OBFF_MSG_GRANT:
> +				pr_info("Interrupt for APP_OBFF_MSG_GRANT\n");
> +				break;
> +			case CFG_AER_RC_ERR_INT:
> +				pr_info("Interrupt for CFG_AER_RC_ERR_INT\n");
> +				break;
> +			/* IRQ when bus master is enabled */
> +			case CFG_BUS_MASTER_EN:
> +				pr_info("Interrupt for CFG_BUS_MASTER_EN\n");
> +				break;
> +			/* IRQ to indicate that link Equalization request has been set */
> +			case CFG_LINK_EQ_REQ_INT:
> +				pr_info("Interrupt for CFG_LINK_EQ_REQ_INT\n");
> +				break;
> +			case CFG_PME_INT:
> +				pr_info("Interrupt for CFG_PME_INIT\n");
> +				break;
> +			case EDMA_INT_0:
> +			case EDMA_INT_1:
> +			case EDMA_INT_2:
> +			case EDMA_INT_3:
> +			case EDMA_INT_4:
> +			case EDMA_INT_5:
> +			case EDMA_INT_6:
> +			case EDMA_INT_7:
> +				pr_info("Interrupt for DMA\n");
> +				break;
> +			/* IRQ when link entres L0s */
> +			case PM_LINKST_IN_L0S:
> +				pr_info("Interrupt for PM_LINKST_IN_L0S\n");
> +				break;
> +			/* IRQ when link enters L1 */
> +			case PM_LINKST_IN_L1:
> +				pr_info("Interrupt for PM_LINKST_IN_L1\n");
> +				break;
> +			/* IRQ when link enters L1 substate */
> +			case PM_LINKST_IN_L1SUB_0:
> +				pr_info("Interrupt for PM_LINKST_IN_L1SUB_0\n");
> +				break;
> +			/* IRQ when link enters L2 */
> +			case PM_LINKST_IN_L2:
> +				pr_info("Interrupt for PM_LINKST_IN_L2\n");
> +				break;
> +			/* IRQ when link exits L2 */
> +			case PM_LINKST_L2_EXIT:
> +				pr_info("Interrupt for PM_LINKST_L2_EXIT\n");
> +				break;
> +			/* Indicates that application must stop sending new
> +			 * outbound TLP requests due to current power state
> +			 */
> +			case PM_XTLH_BLOCK_TLP:
> +				pr_info("Interrupt for PM_XTLH_BLOCK_TLP\n");
> +				break;
> +			/* Request failed to complete in time */
> +			case RADM_CPL_TIMEOUT:
> +				pr_info("Interrupt for RADM_CPL_TIMEOUT\n");
> +				break;
> +			/* Level indicating that receive queues contain TLP header/data */
> +			case RADM_Q_NOT_EMPTY:
> +				pr_info("Interrupt for RADM_Q_NOT_EMPTY\n");
> +				break;
> +			/* Data link layer up/down indicator */
> +			case RDLH_LINK_UP_0:
> +				pr_info("Interrupt for RDLH_LINK_UP_0\n");
> +				break;
> +			/* Phy link up/down indicator */
> +			case SMLH_LINK_UP:
> +				pr_info("Interrupt for SMLH_LINK_UP\n");
> +				break;
> +			case WAKE:
> +				pr_info("Interrupt for WAKE\n");
> +				break;
> +			case COMPARE_END_CHECKER:
> +				pr_info("Interrupt for COMPARE_END_CHECKER\n");
> +				break;
> +			default:
> +				pr_info("Unknown Interrupt in IRQ2[%d]\n", bit_off);
> +				break;
> +			}
> +			bit_off++;
> +		}
> +	}
> +}
> +
> +static void handle_irq5_interrupts(u32 val, u32 is_en)
> +{
> +	u32 bit_off = 0;
> +
> +	if (val) {
> +		while (bit_off < 32) {
> +			if ((val & (0x1 << bit_off)) == 0 || (is_en &
> +						(0x1 << bit_off)) == 0) {
> +				bit_off++;
> +				continue;
> +			}
> +			switch (bit_off) {
> +			case LINK_REQ_RST_NOT:
> +				pr_info("Interrupt for LINK_REQ_RST_NOT\n");
> +				break;
> +			case PM_LINKST_IN_L1SUB_1:
> +				pr_info("Interrupt for L1 SUB state Exit\n");
> +				break;
> +			case RDLH_LINK_UP_1:
> +				pr_info("Interrupt for RDLH_LINK_UP_1\n");
> +				break;
> +			/* Reset request because PHY link went down/ or got hot reset */
> +			case SMLH_REQ_RST_NOT:
> +				pr_info("Interrupt for SMLH_REQ_RST_NOT\n");
> +				break;
> +			default:
> +				pr_info("Unknown Interrupt in IRQ5[%d]\n", bit_off);
> +				break;
> +			}
> +			bit_off++;
> +		}
> +	}
> +}
> +
> +/*
> + * fsd_pcie_sub_ctrl_handler : Interrupt handler for all PCIe interrupts.
> + *
> + * These interrupts trigger on different events happening in the PCIe
> + * controller like link status, link entering and exiting low power
> + * states like L0s, L1, DMA completion/abort interrupts, wake being
> + * triggered and other information.
> + *
> + * IRQ_0: (offset 0x0): IRQ for pulse output 1
> + *	Enable these interrupts at offset 0x10
> + * IRQ_1: (offset 0x4): IRQ for pulse output 2
> + *	Enable these interrupts at offset 0x14
> + * IRQ_2: (offset 0x8): IRQ for level output, rising edge
> + *	Enable these interrupts at offset 0x18
> + * IRQ_5: (offset 0xC): IRQ for level output, falling edge
> + *	Enable these interrupts at offset 0x1C
> + */
> +
> +static irqreturn_t fsd_pcie_sub_ctrl_handler(int irq, void *arg)
> +{
> +	u32 irq0, irq1, irq2, irq5;
> +	struct fsd_pcie *fsd_ctrl = arg;
> +	u32 irq0_en, irq1_en, irq2_en, irq5_en;
> +
> +	/* Read IRQ0 status */
> +	irq0 = readl(fsd_ctrl->appl_base + IRQ0_STS);
> +	/* Clear IRQ0 status after storing status value */
> +	writel(irq0, fsd_ctrl->appl_base + IRQ0_STS);
> +
> +	/* Read IRQ1 status */
> +	irq1 = readl(fsd_ctrl->appl_base + IRQ1_STS);
> +	/* Clear IRQ1 status after storing status value */
> +	writel(irq1, fsd_ctrl->appl_base + IRQ1_STS);
> +
> +	/* Read IRQ2 status */
> +	irq2 = readl(fsd_ctrl->appl_base + IRQ2_STS);
> +	/* Clear IRQ2 status after storing status value */
> +	writel(irq2, fsd_ctrl->appl_base + IRQ2_STS);
> +
> +	/* Read IRQ5 status */
> +	irq5 = readl(fsd_ctrl->appl_base + IRQ5_STS);
> +	/* Clear IRQ5 status after storing status value */
> +	writel(irq5, fsd_ctrl->appl_base + IRQ5_STS);
> +
> +	irq0_en = readl(fsd_ctrl->appl_base + IRQ0_EN);
> +	irq1_en = readl(fsd_ctrl->appl_base + IRQ1_EN);
> +	irq2_en = readl(fsd_ctrl->appl_base + IRQ2_EN);
> +	irq5_en = readl(fsd_ctrl->appl_base + IRQ5_EN);
> +	/* Handle all interrupts */
> +	handle_irq0_interrupts(irq0, irq0_en);
> +	handle_irq1_interrupts(irq1, irq1_en);
> +	handle_irq2_interrupts(irq2, irq2_en);
> +	handle_irq5_interrupts(irq5, irq5_en);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t fsd_pcie_msi_irq_handler(int irq, void *arg)
> +{
> +	u32 val;
> +	struct fsd_pcie *fsd_ctrl = arg;
> +	struct dw_pcie *pci = fsd_ctrl->pci;
> +	struct dw_pcie_rp *pp = &pci->pp;
> +
> +	val = readl(fsd_ctrl->appl_base + IRQ2_STS);
> +
> +	if ((val & IRQ_MSI_ENABLE) == IRQ_MSI_ENABLE) {
> +		val &= IRQ_MSI_ENABLE;
> +		writel(val, fsd_ctrl->appl_base + IRQ2_STS);
> +		dw_handle_msi_irq(pp);
> +	} else {
> +		fsd_pcie_sub_ctrl_handler(irq, arg);
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static void fsd_pcie_msi_init(struct fsd_pcie *fsd_ctrl)
> +{
> +	int val;
> +
> +	/* enable MSI interrupt */
> +	val = readl(fsd_ctrl->appl_base + IRQ2_EN);
> +	val |= IRQ_MSI_ENABLE;
> +	writel(val, fsd_ctrl->appl_base + IRQ2_EN);
> +}
> +
> +static void fsd_pcie_enable_interrupts(struct fsd_pcie *fsd_ctrl)
> +{
> +	if (IS_ENABLED(CONFIG_PCI_MSI))
> +		fsd_ctrl->pdata->irq_data->pcie_msi_init(fsd_ctrl);
> +}
> +
> +static u32 fsd_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base,
> +				u32 reg, size_t size)
> +{
> +	bool is_atu = false;
> +	struct fsd_pcie *fsd_ctrl = to_fsd_pcie(pci);
> +	u32 val;
> +
> +	if (pci->atu_base) {
> +		if (base >= pci->atu_base) {
> +
> +			is_atu = true;
> +			regmap_write(fsd_ctrl->sysreg, fsd_ctrl->sysreg_base,
> +					ADDR_TYPE_ATU);
> +			base = base - DEFAULT_DBI_ATU_OFFSET;
> +		}
> +	}
> +
> +	dw_pcie_read(base + reg, size, &val);
> +
> +	if (is_atu)
> +		regmap_write(fsd_ctrl->sysreg, fsd_ctrl->sysreg_base, ADDR_TYPE_DBI);

You've got the same code twice. Rework this to be a common function 
that does just:

if (ATU)
    regmap_write(fsd_ctrl->sysreg, fsd_ctrl->sysreg_base, ADDR_TYPE_ATU);
else
    regmap_write(fsd_ctrl->sysreg, fsd_ctrl->sysreg_base, ADDR_TYPE_DBI);

Then you just call it followed by dw_pcie_read or dw_pcie_write.

> +
> +	return val;
> +}
> +
> +static void fsd_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base,
> +				u32 reg, size_t size, u32 val)
> +{
> +	struct fsd_pcie *fsd_ctrl = to_fsd_pcie(pci);
> +	bool is_atu = false;
> +
> +	if (pci->atu_base) {
> +		if (base >= pci->atu_base) {
> +			is_atu = true;
> +			regmap_write(fsd_ctrl->sysreg, fsd_ctrl->sysreg_base,
> +					ADDR_TYPE_ATU);
> +			base = base - DEFAULT_DBI_ATU_OFFSET;
> +		}
> +	}
> +
> +	dw_pcie_write(base + reg, size, val);
> +
> +	if (is_atu)
> +		regmap_write(fsd_ctrl->sysreg, fsd_ctrl->sysreg_base, ADDR_TYPE_DBI);
> +}
> +
> +static void fsd_pcie_write_dbi2(struct dw_pcie *pci, void __iomem *base,
> +				u32 reg, size_t size, u32 val)
> +{
> +	struct fsd_pcie *fsd_ctrl = to_fsd_pcie(pci);
> +
> +	regmap_write(fsd_ctrl->sysreg, fsd_ctrl->sysreg_base, ADDR_TYPE_DBI2);
> +	dw_pcie_write(pci->dbi_base + reg, size, val);
> +	regmap_write(fsd_ctrl->sysreg, fsd_ctrl->sysreg_base, ADDR_TYPE_DBI);
> +}
> +
> +static int fsd_pcie_link_up(struct dw_pcie *pci)
> +{
> +	u32 val;
> +	struct fsd_pcie *fsd_ctrl = to_fsd_pcie(pci);
> +
> +	val = readl(fsd_ctrl->appl_base +
> +			fsd_ctrl->pdata->appl_cxpl_debug_00_31);
> +
> +	return (val & LTSSM_STATE_MASK) == LTSSM_STATE_L0;
> +}
> +
> +static int fsd_pcie_host_init(struct dw_pcie_rp *pp)
> +{
> +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> +	struct fsd_pcie *fsd_ctrl = to_fsd_pcie(pci);
> +
> +	dw_pcie_writel_dbi(pci, PCIE_GEN3_RELATED_OFF,
> +				(PCIE_GEN3_EQ_PHASE_2_3 |
> +				 PCIE_GEN3_RXEQ_PH01_EN |
> +				 PCIE_GEN3_RXEQ_RGRDLESS_RXTS));
> +
> +	fsd_pcie_enable_interrupts(fsd_ctrl);
> +
> +	return 0;
> +}
> +
> +static struct dw_pcie_host_ops fsd_pcie_host_ops = {
> +	.host_init = fsd_pcie_host_init,
> +};
> +
> +static int fsd_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
> +				 enum pci_epc_irq_type type, u16 interrupt_num)
> +{
> +	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> +
> +	switch (type) {
> +	case PCI_EPC_IRQ_LEGACY:
> +		dev_err(pci->dev, "EP does not support legacy IRQs\n");
> +		return -EINVAL;
> +	case PCI_EPC_IRQ_MSI:
> +		return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num);
> +	default:
> +		dev_err(pci->dev, "UNKNOWN IRQ type\n");
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct pci_epc_features fsd_pcie_epc_features = {
> +	.linkup_notifier = false,
> +	.msi_capable = true,
> +	.msix_capable = false,
> +};
> +
> +static const struct pci_epc_features*
> +	fsd_pcie_get_features(struct dw_pcie_ep *ep)
> +{
> +	return &fsd_pcie_epc_features;
> +}
> +
> +static struct dw_pcie_ep_ops fsd_dw_pcie_ep_ops = {
> +	.raise_irq	= fsd_pcie_raise_irq,
> +	.get_features	= fsd_pcie_get_features,
> +};
> +
> +static const struct fsd_pcie_irq fsd_pcie_irq_data = {
> +	.pcie_msi_irq_handler	= fsd_pcie_msi_irq_handler,
> +	.pcie_msi_init		= fsd_pcie_msi_init,
> +	.pcie_sub_ctrl_handler	= fsd_pcie_sub_ctrl_handler,
> +};
> +
> +static int __init fsd_add_pcie_ep(struct fsd_pcie *fsd_ctrl,
> +		struct platform_device *pdev)
> +{
> +	struct dw_pcie_ep *ep;
> +	struct dw_pcie *pci = fsd_ctrl->pci;
> +	int ret;
> +	struct device *dev = &pdev->dev;
> +
> +	ep = &pci->ep;
> +	ep->ops = &fsd_dw_pcie_ep_ops;
> +
> +	dw_pcie_writel_dbi(pci, PCIE_GEN3_RELATED_OFF,
> +				(PCIE_GEN3_EQUALIZATION_DISABLE |
> +				 PCIE_GEN3_RXEQ_PH01_EN |
> +				 PCIE_GEN3_RXEQ_RGRDLESS_RXTS));
> +
> +	ret = dw_pcie_ep_init(ep);
> +	if (ret)
> +		dev_err(dev, "failed to initialize endpoint\n");
> +
> +	return ret;
> +}
> +
> +static int __init fsd_add_pcie_port(struct fsd_pcie *fsd_ctrl,
> +					struct platform_device *pdev)
> +{
> +	int irq;
> +	struct device *dev = &pdev->dev;
> +	int irq_flags;
> +	int ret;
> +	struct dw_pcie *pci = fsd_ctrl->pci;
> +	struct dw_pcie_rp *pp = &pci->pp;
> +
> +	if (IS_ENABLED(CONFIG_PCI_MSI)) {
> +		irq = platform_get_irq_byname(pdev, "msi");

Wasn't in the binding. And the DWC core does this for you.

> +		if (!irq) {
> +			dev_err(dev, "failed to get msi irq\n");
> +			return -ENODEV;
> +		}
> +
> +		irq_flags = IRQF_TRIGGER_RISING | IRQF_SHARED | IRQF_NO_THREAD;
> +
> +		ret = devm_request_irq(dev, irq,
> +					fsd_ctrl->pdata->irq_data->pcie_msi_irq_handler,
> +					irq_flags, "fsd-pcie", fsd_ctrl);
> +		if (ret) {
> +			dev_err(dev, "failed to request msi irq\n");
> +			return ret;
> +		}
> +		pp->msi_irq[0] = -ENODEV;
> +	}
> +
> +	ret = dw_pcie_host_init(pp);
> +	if (ret)
> +		dev_err(dev, "failed to initialize host\n");
> +
> +	return ret;
> +}
> +
> +static const struct dw_pcie_ops fsd_dw_pcie_ops = {
> +	.read_dbi	= fsd_pcie_read_dbi,
> +	.write_dbi	= fsd_pcie_write_dbi,
> +	.write_dbi2	= fsd_pcie_write_dbi2,
> +	.start_link	= fsd_pcie_establish_link,
> +	.stop_link	= fsd_pcie_stop_link,
> +	.link_up	= fsd_pcie_link_up,
> +};
> +
> +static int fsd_pcie_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +	int irq, irq_flags;
> +	struct dw_pcie *pci;
> +	struct dw_pcie_rp *pp;
> +	struct fsd_pcie *fsd_ctrl;
> +	struct device *dev = &pdev->dev;
> +	const struct fsd_pcie_pdata *pdata;
> +	struct device_node *np = dev->of_node;
> +
> +	fsd_ctrl = devm_kzalloc(dev, sizeof(*fsd_ctrl), GFP_KERNEL);
> +	if (!fsd_ctrl)
> +		return -ENOMEM;
> +
> +	pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
> +	if (!pci)
> +		return -ENOMEM;
> +
> +	pdata = (const struct fsd_pcie_pdata *) of_device_get_match_data(dev);
> +
> +	fsd_ctrl->pci = pci;
> +	fsd_ctrl->pdata = pdata;
> +
> +	pci->dev = dev;
> +	pci->ops = pdata->dwc_ops;
> +	pci->dbi_base2 = NULL;
> +	pci->dbi_base = NULL;
> +	pci->atu_base = NULL;
> +	pp = &pci->pp;
> +	pp->ops = fsd_ctrl->pdata->host_ops;
> +
> +	fsd_ctrl->phy = devm_of_phy_get(dev, np, NULL);

Use the non-DT version.

> +	if (IS_ERR(fsd_ctrl->phy)) {
> +		if (PTR_ERR(fsd_ctrl->phy) == -EPROBE_DEFER)
> +			return PTR_ERR(fsd_ctrl->phy);
> +	}
> +
> +	phy_init(fsd_ctrl->phy);
> +
> +	if (pdata->res_ops && pdata->res_ops->get_mem_resources) {
> +		ret = pdata->res_ops->get_mem_resources(pdev, fsd_ctrl);

Again, get rid of the indirection. If it does vary, don't invent your 
own ops. We only need 1 level of abstraction.

> +		if (ret)
> +			return ret;
> +	}
> +
> +	if (pdata->res_ops && pdata->res_ops->get_clk_resources) {
> +		ret = pdata->res_ops->get_clk_resources(pdev, fsd_ctrl);
> +		if (ret)
> +			return ret;
> +		ret = pdata->res_ops->init_clk_resources(fsd_ctrl);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	platform_set_drvdata(pdev, fsd_ctrl);
> +
> +	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(36));
> +	if (ret)
> +		goto fail_dma_set;
> +
> +	switch (fsd_ctrl->pdata->op_mode) {
> +	case DEVICE_TYPE_RC:
> +		writel(DEVICE_TYPE_RC, fsd_ctrl->appl_base +
> +					PCIE_FSD_DEVICE_TYPE);
> +		ret = fsd_add_pcie_port(fsd_ctrl, pdev);
> +		if (ret)
> +			goto fail_add_pcie_port;
> +		break;
> +	case DEVICE_TYPE_EP:
> +		writel(DEVICE_TYPE_EP, fsd_ctrl->appl_base +
> +				PCIE_FSD_DEVICE_TYPE);
> +
> +		ret = fsd_add_pcie_ep(fsd_ctrl, pdev);
> +		if (ret)
> +			goto fail_add_pcie_ep;
> +		break;
> +	}
> +
> +	irq = platform_get_irq_byname(pdev, "sub_ctrl_intr");
> +	if (irq > 0) {
> +
> +		irq_flags = IRQF_TRIGGER_RISING | IRQF_SHARED | IRQF_NO_THREAD;
> +
> +		ret = devm_request_irq(dev, irq,
> +				fsd_ctrl->pdata->irq_data->pcie_sub_ctrl_handler,
> +				irq_flags, "fsd-sub-ctrl-pcie", fsd_ctrl);
> +		if (ret)
> +			dev_err(dev, "failed to request sub ctrl irq\n");
> +	}
> +
> +	dev_info(dev, "FSD PCIe probe completed successfully\n");
> +
> +	return 0;
> +
> +fail_dma_set:
> +	dev_err(dev, "PCIe Failed to set 36 bit dma mask\n");
> +fail_add_pcie_port:
> +	phy_exit(fsd_ctrl->phy);
> +fail_add_pcie_ep:
> +	if (pdata->res_ops && pdata->res_ops->deinit_clk_resources)
> +		pdata->res_ops->deinit_clk_resources(fsd_ctrl);
> +	return ret;
> +}
> +
> +static int __exit fsd_pcie_remove(struct platform_device *pdev)
> +{
> +	struct fsd_pcie *fsd_ctrl = platform_get_drvdata(pdev);
> +	const struct fsd_pcie_pdata *pdata = fsd_ctrl->pdata;
> +
> +	if (pdata->res_ops && pdata->res_ops->deinit_clk_resources)
> +		pdata->res_ops->deinit_clk_resources(fsd_ctrl);
> +
> +	return 0;
> +}
> +
> +static const struct fsd_pcie_pdata fsd_pcie_rc_pdata = {
> +	.dwc_ops		= &fsd_dw_pcie_ops,
> +	.host_ops		= &fsd_pcie_host_ops,
> +	.res_ops		= &fsd_pcie_res_ops_data,
> +	.irq_data		= &fsd_pcie_irq_data,
> +	.appl_cxpl_debug_00_31	= PCIE_ELBI_CXPL_DEBUG_00_31,
> +	.op_mode		= DEVICE_TYPE_RC,
> +};
> +
> +static const struct fsd_pcie_pdata fsd_pcie_ep_pdata = {
> +	.dwc_ops		= &fsd_dw_pcie_ops,
> +	.host_ops		= &fsd_pcie_host_ops,
> +	.res_ops		= &fsd_pcie_res_ops_data,
> +	.irq_data		= &fsd_pcie_irq_data,
> +	.appl_cxpl_debug_00_31	= PCIE_ELBI_CXPL_DEBUG_00_31,
> +	.op_mode		= DEVICE_TYPE_EP,
> +};
> +
> +static const struct of_device_id fsd_pcie_of_match[] = {
> +	{
> +		.compatible = "tesla,fsd-pcie",
> +		.data = (void *) &fsd_pcie_rc_pdata,
> +	},
> +	{
> +		.compatible = "tesla,fsd-pcie-ep",
> +		.data = (void *) &fsd_pcie_ep_pdata,
> +	},
> +
> +	{},
> +};
> +
> +static struct platform_driver fsd_pcie_driver = {
> +	.probe		= fsd_pcie_probe,
> +	.remove		= __exit_p(fsd_pcie_remove),
> +	.driver		= {
> +		.name	= "fsd-pcie",
> +		.of_match_table = fsd_pcie_of_match,
> +	},
> +};
> +
> +static int __init fsd_pcie_init(void)
> +{
> +	return platform_driver_register(&fsd_pcie_driver);
> +}
> +module_init(fsd_pcie_init);
> -- 
> 2.17.1
> 
> 

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

end of thread, other threads:[~2022-11-30 18:44 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20221121104714epcas5p27508b91010c72117dd7116fc387b382f@epcas5p2.samsung.com>
2022-11-21 10:52 ` [PATCH 0/6] Add PCIe support for Tesla FSD SoC Shradha Todi
     [not found]   ` <CGME20221121104719epcas5p2f87febfba74a4ca6807b3095acf507d0@epcas5p2.samsung.com>
2022-11-21 10:52     ` [PATCH 1/6] dt-bindings: phy: Add PCIe PHY bindings for FSD Shradha Todi
2022-11-21 11:59       ` Krzysztof Kozlowski
     [not found]   ` <CGME20221121104725epcas5p3af00b0c717f2132f5c1ba7fd4e903e26@epcas5p3.samsung.com>
2022-11-21 10:52     ` [PATCH 2/6] dt-bindings: PCI: Add PCIe controller " Shradha Todi
2022-11-21 12:05       ` Krzysztof Kozlowski
     [not found]   ` <CGME20221121104731epcas5p48f96c92e5bfb4ede56ce74a78887a2f3@epcas5p4.samsung.com>
2022-11-21 10:52     ` [PATCH 3/6] PCI: dwc: fsd: Add FSD PCIe Controller driver support Shradha Todi
2022-11-21 12:07       ` Krzysztof Kozlowski
2022-11-21 23:18       ` Bjorn Helgaas
2022-11-30 18:44       ` Rob Herring
     [not found]   ` <CGME20221121104736epcas5p36c12ff0b575af77f8cf99811b055b339@epcas5p3.samsung.com>
2022-11-21 10:52     ` [PATCH 4/6] phy: tesla-pcie: Add PCIe PHY driver support for FSD Shradha Todi
2022-11-21 12:08       ` Krzysztof Kozlowski
     [not found]   ` <CGME20221121104741epcas5p31e1320bc4c0912485c1fabe52ea19988@epcas5p3.samsung.com>
2022-11-21 10:52     ` [PATCH 5/6] arm64: dts: fsd: Add PCIe support for Tesla FSD SoC Shradha Todi
2022-11-21 12:11       ` Krzysztof Kozlowski
     [not found]   ` <CGME20221121104746epcas5p109c7bb299cf19070a9237c00c162ed8f@epcas5p1.samsung.com>
2022-11-21 10:52     ` [PATCH 6/6] misc: pci_endpoint_test: Add driver data for FSD PCIe controllers Shradha Todi

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).