public inbox for devicetree@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller
@ 2026-01-29  9:26 zhangsenchuan
  2026-01-29  9:28 ` [PATCH v10 1/2] dt-bindings: PCI: eic7700: Add Eswin PCIe host controller zhangsenchuan
                   ` (4 more replies)
  0 siblings, 5 replies; 17+ messages in thread
From: zhangsenchuan @ 2026-01-29  9:26 UTC (permalink / raw)
  To: bhelgaas, mani, krzk+dt, conor+dt, lpieralisi, kwilczynski, robh,
	p.zabel, linux-pci, devicetree, linux-kernel, christian.bruel,
	shradha.t, krishna.chundru, thippeswamy.havalige, inochiama,
	Frank.li
  Cc: ningyu, linmin, pinkesh.vaghela, ouyanghui, Senchuan Zhang

From: Senchuan Zhang <zhangsenchuan@eswincomputing.com>

Changes in v10:
- Updates: eswin,eic7700-pcie.yaml
  - None

- Updates: pcie-eic7700.c
  - Remove devm_clk_bulk_get_all_enabled API, use devm_clk_bulk_get_all
    and clk_bulk_prepare_enable. Add resource release codes and add
    eic7700_pcie_host_deinit API.
  - Update PCI_DEVICE_ID_ESWIN_EIC7700.
  - Add reset_control_put release resources in "goto err_port:".
  - Delete trailing comma after a terminator in eic7700_pcie_of_match.
- Link to V9: https://lore.kernel.org/all/20251229113021.1859-1-zhangsenchuan@eswincomputing.com/

Changes in v9:
- Updates: eswin,eic7700-pcie.yaml
  - None

- Updates: pcie-eic7700.c
  - Update comment, s/Rort/Port/.
- Link to V8: https://lore.kernel.org/all/20251215095928.1712-1-zhangsenchuan@eswincomputing.com/

Changes in v8:
- Updates: eswin,eic7700-pcie.yaml
  - None

- Updates: pcie-eic7700.c
  - Remove dw_pcie_suspend_noirq/dw_pcie_resume_noirq API and add a
    comment, and remove .deinit.
  - Remove no_pme_handshake flag.
  - Add dw_pcie_dbi_ro_wr_en/dw_pcie_dbi_ro_wr_dis API.
  - Add eic7700_pcie_assert helper function.
  - Update NOIRQ_SYSTEM_SLEEP_PM_OPS to DEFINE_NOIRQ_DEV_PM_OPS.
- Link to V7: https://lore.kernel.org/all/20251202090225.1602-1-zhangsenchuan@eswincomputing.com/

Changes in v7:
- Updates: eswin,eic7700-pcie.yaml
  - None

- Updates: pcie-eic7700.c
  - Update "config PCIE_EIC7700" bool to tristate.
  - Remove fix MSI-X code, depend on new commit [1].
  - Add set no_pme_handshake flag.
  - Update -EINVAL to -ENODATA and add PM runtime function.
  - Add ".probe_type = PROBE_PREFER_ASYNCHRONOUS,".
  - Update eic7700_pcie_perst_deassert function name to
    eic7700_pcie_perst_reset.
  - Update readw to dw_pcie_readw_dbi function.
  - Add comments above reset_control_bulk_deassert function.

- Updates: pcie-designware.h pcie-designware-host.c
 -  The ESWIN EIC7700 SoC lacks hardware support for the L2/L3 low-power
    link states. It cannot enter the L2/L3 ready state through the
    PME_Turn_Off/PME_To_Ack handshake protocol. To address this, add a
    no_pme_handshake flag skip PME_Turn_Off broadcast and link state check
    code, other driver can reuse this flag if meet the similar situation.
- Link to V6: https://lore.kernel.org/linux-pci/20251120101018.1477-1-zhangsenchuan@eswincomputing.com/
- Link to: https://lore.kernel.org/linux-pci/20251109-remove_cap-v1-3-2208f46f4dc2@oss.qualcomm.com/ [1]

Changes in v6:
- Updates: eswin,eic7700-pcie.yaml
  - Add Reviewed-by: Rob Herring (Arm) <robh@kernel.org>.

- Updates: pcie-eic7700.c
  - Remove pci_root_ports_have_device function judgment during suspend.
  - Remove eic7700_pcie_pme_turn_off and eic7700_pcie_get_ltssm function.
  - Add set no_suspport_L2 flag.

- Updates: pcie-designware.h pcie-designware-host.c
 - The ESWIN EIC7700 soc does not support enter L2 link state. Therefore
   add no_suspport_L2 flag skip PME_Turn_Off broadcast and link state
   check code, other driver can reuse this flag if meet the similar
   situation.
- Link to V5: https://lore.kernel.org/all/20251110090716.1392-1-zhangsenchuan@eswincomputing.com/
- Link to: https://lore.kernel.org/all/e7plmtwtkkd4ymrt2hkztcqdx4ugfjk64oksjyf6lpi2oui53d@vhuo5occyref/

Changes in v5:
- Updates: eswin,eic7700-pcie.yaml
  - Modify reg-names: update mgmt to elbi.
  - Modify clock-names: update pclk to phy_reg.
  - Modify reset-names: update powerup to pwr.
  - Remove powerup modify in "snps,dw-pcie-common.yaml" file.

- Updates: pcie-eic7700.c
  - Update the driver submission comment, mention EIC7700 in the
    "config PCIE_EIC7700" and in the driver title.
  - Update some comments, for examples: "s/PME_TURN_OFF/PME_Turn_Off/",
    "s/INTX/INTx/", "s/PERST/PERST#/", "s/perst/PERST#/", "s/id/ID/".
  - Update "struct *_pcie" name and function name, add the eic7700 prefix.
  - Use PCIEELBI_CTRL0_DEV_TYPE macro and update comment, use FIELD_PREP.
  - Add eic7700_pcie_data pointer in struct eic7700_pcie.
  - Update .deinit callback function name and removed the dw_pcie_link_up
    judgment, add pci_root_ports_have_device function judgment.
  - Remove devm_platform_ioremap_resource_byname function get mgmt, use
    platform_get_resource_byname function get elbi in "pcie-designware.c".
  - Update of_reset_control_get to of_reset_control_get_exclusive, use
    devm_reset_control_bulk_get_exclusive function get resets, update use
    reset_control_bulk_assert/reset_control_bulk_deassert function.
- Link to V4: https://lore.kernel.org/all/20251030082900.1304-1-zhangsenchuan@eswincomputing.com/
- Link to https://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/tree/?h=controller/dwc

Changes in v4:
- Updates: eswin,eic7700-pcie.yaml
  - Use snps,dw-pcie.yaml instead pci-host-bridge.yaml.

- Updates: snps,dw-pcie-common.yaml
  - Add powerup reset property, our powerup property is somewhat different
    from the general attributes defined by Synopsys DWC binding.

- Updates: pcie-eic7700.c
  - Update the driver submission comment.
  - Alphabetize so the menuconfig entries remain sorted by vendor.
  - Update use PCI_CAP_LIST_NEXT_MASK macro.
  - Use readl_poll_timeout function.
  - Update eswin_pcie_suspend/eswin_pcie_resume name to
    eswin_pcie_suspend_noirq/eswin_pcie_resume_noirq.
  - PM use dw_pcie_suspend_noirq and dw_pcie_resume_noirq function and add
    eswin_pcie_get_ltssm, eswin_pcie_pme_turn_off, eswin_pcie_host_exit
    function adapt to PM.
- Link to V3: https://lore.kernel.org/linux-pci/20250923120946.1218-1-zhangsenchuan@eswincomputing.com/

Changes in v3:
- Updates: eswin,eic7700-pcie.yaml
  - Based on the last patch yaml file, devicetree separates the root port
    node, changing it significantly. Therefore, "Reviewed-by: Krzysztof
    Kozlowski <krzysztof.kozlowski@linaro.org>" is not added.
  - Clock and reset drivers are under review. In yaml, macro definitions
    used in clock and reset can only be replaced by constant values.
  - Move the num-lanes and perst resets to the PCIe Root Port node, make
    it easier to support multiple Root Ports in future versions of the
    hardware.
  - Update the num-lanes attribute and modify define num-lanes as decimal.
  - Optimize the ranges attribute and clear the relocatable flag (bit 31)
    for any regions.
  - Update comment: inte~inth are actual interrupts and these names align
    with the interrupt names in the hardware IP, inte~inth interrupts
    corresponds to Deassert_INTA~Deassert_INTD.
  - Add Signed-off-by: Yanghui Ou <ouyanghui@eswincomputing.com>.

- Updates: pcie-eic7700.c
  - Update the submission comment and add DWC IP revision, data rate, lane
    information.
  - Optimize the "config PCIE_EIC7700" configuration.
  - Optimize the macro definition, add bitfield definition for the mask,
    and remove redundant comments. optimize comments, make use of 80
    columns for comments.
  - Use the dw_pcie_find_capability function to obtain the offset by
    traversing the function list.
  - Remove the sets MPS code and configure it by PCI core.
  - Alphabetize so the menuconfig entries remain sorted by vendor.
  - Configure ESWIN VID:DID for Root Port as the default values are
	invalid,and remove the redundant lane config.
  - Use reverse Xmas order for all local variables in this driver
  - Hardware doesn't support MSI-X but it advertises MSI-X capability, set
    a flag and clear it conditionally.
  - Resets are all necessary, Update the interface function for resets.
  - Since driver does not depend on any parent to power on any resource,
    the pm runtime related functions are removed.
  - Remove "eswin_pcie_shutdown" function, our comment on the shutdown
    function is incorrect. Moreover, when the host powers reboots,it will
    enter the shutdown function, we are using host reset and do not need
    to assert perst. Therefore, the shutdown function is not necessary.
  - remove "eswin_pcie_remove", because it is not safe to remove it during
    runtime, and this driver has been modified to builtin_platform_driver
    and does not support hot plugging, therefore, the remove function is
    not needed.
  - The Suspend function adds link state judgment, and for controllers
    with active devices, resources cannot be turned off.
  - Add Signed-off-by: Yanghui Ou <ouyanghui@eswincomputing.com>.
- Link to V2: https://lore.kernel.org/linux-pci/20250829082021.49-1-zhangsenchuan@eswincomputing.com/

Changes in v2:
- Updates: eswin,eic7700-pcie.yaml
  - Optimize the naming of "clock-names" and "reset-names".
  - Add a reference to "$ref: /schemas/pci/pci-host-bridge.yaml#".
    (The name of the reset attribute in the "snps,dw-pcie-common.yaml"
    file is different from our reset attribute and "snps,dw-pcie.yaml"
    file cannot be directly referenced)
  - Follow DTS coding style to optimize yaml attributes.
  - Remove status = "disabled" from yaml.

- Updates: pcie-eic7700.c
  - Remove unnecessary imported header files.
  - Use dev_err instead of pr_err and remove the WARN_ON function.
  - The eswin_evb_socket_power_on function is removed and not supported.
  - The eswin_pcie_remove function is placed after the probe function.
  - Optimize function alignment.
  - Manage the clock using the devm_clk_bulk_get_all_enabled function.
  - Handle the release of resources after the dw_pcie_host_init function
    call fails.
  - Remove the dev_dbg function and remove __exit_p.
  - Add support for the system pm function.
- Link to V1: https://lore.kernel.org/all/20250516094057.1300-1-zhangsenchuan@eswincomputing.com/

Senchuan Zhang (2):
  dt-bindings: PCI: eic7700: Add Eswin PCIe host controller
  PCI: eic7700: Add Eswin PCIe host controller driver

 .../bindings/pci/eswin,eic7700-pcie.yaml      | 167 +++++++
 drivers/pci/controller/dwc/Kconfig            |  11 +
 drivers/pci/controller/dwc/Makefile           |   1 +
 drivers/pci/controller/dwc/pcie-eic7700.c     | 410 ++++++++++++++++++
 4 files changed, 589 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/eswin,eic7700-pcie.yaml
 create mode 100644 drivers/pci/controller/dwc/pcie-eic7700.c

--
2.25.1


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

* [PATCH v10 1/2] dt-bindings: PCI: eic7700: Add Eswin PCIe host controller
  2026-01-29  9:26 [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller zhangsenchuan
@ 2026-01-29  9:28 ` zhangsenchuan
  2026-01-29  9:29 ` [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver zhangsenchuan
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 17+ messages in thread
From: zhangsenchuan @ 2026-01-29  9:28 UTC (permalink / raw)
  To: bhelgaas, mani, krzk+dt, conor+dt, lpieralisi, kwilczynski, robh,
	p.zabel, linux-pci, devicetree, linux-kernel, christian.bruel,
	shradha.t, krishna.chundru, thippeswamy.havalige, inochiama,
	Frank.li
  Cc: ningyu, linmin, pinkesh.vaghela, ouyanghui, Senchuan Zhang

From: Senchuan Zhang <zhangsenchuan@eswincomputing.com>

Add Device Tree binding documentation for the Eswin EIC7700 PCIe
controller module, the PCIe controller enables the core to correctly
initialize and manage the PCIe bus and connected devices.

Signed-off-by: Yu Ning <ningyu@eswincomputing.com>
Signed-off-by: Yanghui Ou <ouyanghui@eswincomputing.com>
Signed-off-by: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
---
 .../bindings/pci/eswin,eic7700-pcie.yaml      | 167 ++++++++++++++++++
 1 file changed, 167 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/eswin,eic7700-pcie.yaml

diff --git a/Documentation/devicetree/bindings/pci/eswin,eic7700-pcie.yaml b/Documentation/devicetree/bindings/pci/eswin,eic7700-pcie.yaml
new file mode 100644
index 000000000000..9c0150834e6d
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/eswin,eic7700-pcie.yaml
@@ -0,0 +1,167 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/eswin,eic7700-pcie.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Eswin EIC7700 PCIe host controller
+
+maintainers:
+  - Yu Ning <ningyu@eswincomputing.com>
+  - Senchuan Zhang <zhangsenchuan@eswincomputing.com>
+  - Yanghui Ou <ouyanghui@eswincomputing.com>
+
+description:
+  Eswin EIC7700 SoC PCIe root complex controller is based on the Synopsys
+  DesignWare PCIe IP.
+
+properties:
+  compatible:
+    const: eswin,eic7700-pcie
+
+  reg:
+    maxItems: 3
+
+  reg-names:
+    items:
+      - const: dbi
+      - const: config
+      - const: elbi
+
+  ranges:
+    maxItems: 3
+
+  '#interrupt-cells':
+    const: 1
+
+  interrupt-names:
+    items:
+      - const: msi
+      - const: inta
+      - const: intb
+      - const: intc
+      - const: intd
+
+  interrupt-map:
+    maxItems: 4
+
+  interrupt-map-mask:
+    items:
+      - const: 0
+      - const: 0
+      - const: 0
+      - const: 7
+
+  clocks:
+    maxItems: 4
+
+  clock-names:
+    items:
+      - const: mstr
+      - const: dbi
+      - const: phy_reg
+      - const: aux
+
+  resets:
+    maxItems: 2
+
+  reset-names:
+    items:
+      - const: dbi
+      - const: pwr
+
+patternProperties:
+  "^pcie@":
+    type: object
+    $ref: /schemas/pci/pci-pci-bridge.yaml#
+
+    properties:
+      reg:
+        maxItems: 1
+
+      num-lanes:
+        maximum: 4
+
+      resets:
+        maxItems: 1
+
+      reset-names:
+        items:
+          - const: perst
+
+    required:
+      - reg
+      - ranges
+      - num-lanes
+      - resets
+      - reset-names
+
+    unevaluatedProperties: false
+
+required:
+  - compatible
+  - reg
+  - ranges
+  - interrupts
+  - interrupt-names
+  - interrupt-map-mask
+  - interrupt-map
+  - '#interrupt-cells'
+  - clocks
+  - clock-names
+  - resets
+  - reset-names
+
+allOf:
+  - $ref: /schemas/pci/snps,dw-pcie.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        pcie@54000000 {
+            compatible = "eswin,eic7700-pcie";
+            reg = <0x0 0x54000000 0x0 0x4000000>,
+                  <0x0 0x40000000 0x0 0x800000>,
+                  <0x0 0x50000000 0x0 0x100000>;
+            reg-names = "dbi", "config", "elbi";
+            #address-cells = <3>;
+            #size-cells = <2>;
+            #interrupt-cells = <1>;
+            ranges = <0x01000000 0x0 0x40800000 0x0 0x40800000 0x0 0x800000>,
+                     <0x02000000 0x0 0x41000000 0x0 0x41000000 0x0 0xf000000>,
+                     <0x43000000 0x80 0x00000000 0x80 0x00000000 0x2 0x00000000>;
+            bus-range = <0x00 0xff>;
+            clocks = <&clock 144>,
+                     <&clock 145>,
+                     <&clock 146>,
+                     <&clock 147>;
+            clock-names = "mstr", "dbi", "phy_reg", "aux";
+            resets = <&reset 97>,
+                     <&reset 98>;
+            reset-names = "dbi", "pwr";
+            interrupts = <220>, <179>, <180>, <181>, <182>, <183>, <184>, <185>, <186>;
+            interrupt-names = "msi", "inta", "intb", "intc", "intd";
+            interrupt-parent = <&plic>;
+            interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+            interrupt-map = <0x0 0x0 0x0 0x1 &plic 179>,
+                            <0x0 0x0 0x0 0x2 &plic 180>,
+                            <0x0 0x0 0x0 0x3 &plic 181>,
+                            <0x0 0x0 0x0 0x4 &plic 182>;
+            device_type = "pci";
+            pcie@0 {
+                reg = <0x0 0x0 0x0 0x0 0x0>;
+                #address-cells = <3>;
+                #size-cells = <2>;
+                ranges;
+                device_type = "pci";
+                num-lanes = <4>;
+                resets = <&reset 99>;
+                reset-names = "perst";
+            };
+        };
+    };
-- 
2.25.1


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

* [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver
  2026-01-29  9:26 [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller zhangsenchuan
  2026-01-29  9:28 ` [PATCH v10 1/2] dt-bindings: PCI: eic7700: Add Eswin PCIe host controller zhangsenchuan
@ 2026-01-29  9:29 ` zhangsenchuan
  2026-02-18 12:47   ` Manivannan Sadhasivam
  2026-02-01 12:24 ` [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller Leon Romanovsky
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 17+ messages in thread
From: zhangsenchuan @ 2026-01-29  9:29 UTC (permalink / raw)
  To: bhelgaas, mani, krzk+dt, conor+dt, lpieralisi, kwilczynski, robh,
	p.zabel, linux-pci, devicetree, linux-kernel, christian.bruel,
	shradha.t, krishna.chundru, thippeswamy.havalige, inochiama,
	Frank.li
  Cc: ningyu, linmin, pinkesh.vaghela, ouyanghui, Senchuan Zhang

From: Senchuan Zhang <zhangsenchuan@eswincomputing.com>

Add driver for the Eswin EIC7700 PCIe host controller, which is based on
the DesignWare PCIe core, IP revision 5.96a. The PCIe Gen.3 controller
supports a data rate of 8 GT/s and 4 channels, support INTx and MSI
interrupts.

Signed-off-by: Yu Ning <ningyu@eswincomputing.com>
Signed-off-by: Yanghui Ou <ouyanghui@eswincomputing.com>
Signed-off-by: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
---
 drivers/pci/controller/dwc/Kconfig        |  11 +
 drivers/pci/controller/dwc/Makefile       |   1 +
 drivers/pci/controller/dwc/pcie-eic7700.c | 410 ++++++++++++++++++++++
 3 files changed, 422 insertions(+)
 create mode 100644 drivers/pci/controller/dwc/pcie-eic7700.c

diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
index 519b59422b47..c837cb5947b6 100644
--- a/drivers/pci/controller/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
@@ -93,6 +93,17 @@ config PCIE_BT1
 	  Enables support for the PCIe controller in the Baikal-T1 SoC to work
 	  in host mode. It's based on the Synopsys DWC PCIe v4.60a IP-core.
 
+config PCIE_EIC7700
+	tristate "Eswin EIC7700 PCIe controller"
+	depends on ARCH_ESWIN || COMPILE_TEST
+	depends on PCI_MSI
+	select PCIE_DW_HOST
+	help
+	  Say Y here if you want PCIe controller support for the Eswin EIC7700.
+	  The PCIe controller on EIC7700 is based on DesignWare hardware,
+	  enables support for the PCIe controller in the EIC7700 SoC to work in
+	  host mode.
+
 config PCI_IMX6
 	bool
 
diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
index 67ba59c02038..7c5a5186ea83 100644
--- a/drivers/pci/controller/dwc/Makefile
+++ b/drivers/pci/controller/dwc/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_PCIE_DW_EP) += pcie-designware-ep.o
 obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o
 obj-$(CONFIG_PCIE_AMD_MDB) += pcie-amd-mdb.o
 obj-$(CONFIG_PCIE_BT1) += pcie-bt1.o
+obj-$(CONFIG_PCIE_EIC7700) += pcie-eic7700.o
 obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
 obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
 obj-$(CONFIG_PCIE_FU740) += pcie-fu740.o
diff --git a/drivers/pci/controller/dwc/pcie-eic7700.c b/drivers/pci/controller/dwc/pcie-eic7700.c
new file mode 100644
index 000000000000..dab8e3b98810
--- /dev/null
+++ b/drivers/pci/controller/dwc/pcie-eic7700.c
@@ -0,0 +1,410 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ESWIN EIC7700 PCIe root complex driver
+ *
+ * Copyright 2026, Beijing ESWIN Computing Technology Co., Ltd.
+ *
+ * Authors: Yu Ning <ningyu@eswincomputing.com>
+ *          Senchuan Zhang <zhangsenchuan@eswincomputing.com>
+ *          Yanghui Ou <ouyanghui@eswincomputing.com>
+ */
+
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/resource.h>
+#include <linux/reset.h>
+#include <linux/types.h>
+
+#include "pcie-designware.h"
+
+/* ELBI registers */
+#define PCIEELBI_CTRL0_OFFSET		0x0
+#define PCIEELBI_STATUS0_OFFSET		0x100
+
+/* LTSSM register fields */
+#define PCIEELBI_APP_LTSSM_ENABLE	BIT(5)
+
+/* APP_HOLD_PHY_RST register fields */
+#define PCIEELBI_APP_HOLD_PHY_RST	BIT(6)
+
+/* PM_SEL_AUX_CLK register fields */
+#define PCIEELBI_PM_SEL_AUX_CLK		BIT(16)
+
+/* DEV_TYPE register fields */
+#define PCIEELBI_CTRL0_DEV_TYPE		GENMASK(3, 0)
+
+/* Vendor and device ID value */
+#define PCI_VENDOR_ID_ESWIN		0x1fe1
+#define PCI_DEVICE_ID_ESWIN_EIC7700	0x2030
+
+#define EIC7700_NUM_RSTS		ARRAY_SIZE(eic7700_pcie_rsts)
+
+static const char * const eic7700_pcie_rsts[] = {
+	"pwr",
+	"dbi",
+};
+
+struct eic7700_pcie_port {
+	struct list_head list;
+	struct reset_control *perst;
+	int num_lanes;
+};
+
+struct eic7700_pcie {
+	struct dw_pcie pci;
+	struct clk_bulk_data *clks;
+	struct reset_control_bulk_data resets[EIC7700_NUM_RSTS];
+	struct list_head ports;
+	int num_clks;
+};
+
+#define to_eic7700_pcie(x) dev_get_drvdata((x)->dev)
+
+static int eic7700_pcie_start_link(struct dw_pcie *pci)
+{
+	u32 val;
+
+	/* Enable LTSSM */
+	val = readl_relaxed(pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
+	val |= PCIEELBI_APP_LTSSM_ENABLE;
+	writel_relaxed(val, pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
+
+	return 0;
+}
+
+static bool eic7700_pcie_link_up(struct dw_pcie *pci)
+{
+	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+	u16 val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
+
+	return val & PCI_EXP_LNKSTA_DLLLA;
+}
+
+static int eic7700_pcie_perst_reset(struct eic7700_pcie_port *port,
+				    struct eic7700_pcie *pcie)
+{
+	int ret;
+
+	ret = reset_control_assert(port->perst);
+	if (ret) {
+		dev_err(pcie->pci.dev, "Failed to assert PERST#\n");
+		return ret;
+	}
+
+	/* Ensure that PERST# has been asserted for at least 100 ms */
+	msleep(PCIE_T_PVPERL_MS);
+
+	ret = reset_control_deassert(port->perst);
+	if (ret) {
+		dev_err(pcie->pci.dev, "Failed to deassert PERST#\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void eic7700_pcie_assert(struct eic7700_pcie *pcie)
+{
+	struct eic7700_pcie_port *port;
+
+	list_for_each_entry(port, &pcie->ports, list)
+		reset_control_assert(port->perst);
+	reset_control_bulk_assert(EIC7700_NUM_RSTS, pcie->resets);
+}
+
+static int eic7700_pcie_parse_port(struct eic7700_pcie *pcie,
+				   struct device_node *node)
+{
+	struct device *dev = pcie->pci.dev;
+	struct eic7700_pcie_port *port;
+
+	port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
+	if (!port)
+		return -ENOMEM;
+
+	port->perst = of_reset_control_get_exclusive(node, "perst");
+	if (IS_ERR(port->perst)) {
+		dev_err(dev, "Failed to get PERST# reset\n");
+		return PTR_ERR(port->perst);
+	}
+
+	/*
+	 * TODO: Since the Root Port node is separated out by pcie devicetree,
+	 * the DWC core initialization code can't parse the num-lanes attribute
+	 * in the Root Port. Before entering the DWC core initialization code,
+	 * the platform driver code parses the Root Port node. The EIC7700 only
+	 * supports one Root Port node, and the num-lanes attribute is suitable
+	 * for the case of one Root Port.
+	 */
+	if (!of_property_read_u32(node, "num-lanes", &port->num_lanes))
+		pcie->pci.num_lanes = port->num_lanes;
+
+	INIT_LIST_HEAD(&port->list);
+	list_add_tail(&port->list, &pcie->ports);
+
+	return 0;
+}
+
+static int eic7700_pcie_parse_ports(struct eic7700_pcie *pcie)
+{
+	struct eic7700_pcie_port *port, *tmp;
+	struct device *dev = pcie->pci.dev;
+	int ret;
+
+	for_each_available_child_of_node_scoped(dev->of_node, of_port) {
+		ret = eic7700_pcie_parse_port(pcie, of_port);
+		if (ret)
+			goto err_port;
+	}
+
+	return 0;
+
+err_port:
+	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
+		reset_control_put(port->perst);
+		list_del(&port->list);
+	}
+
+	return ret;
+}
+
+static int eic7700_pcie_host_init(struct dw_pcie_rp *pp)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+	struct eic7700_pcie *pcie = to_eic7700_pcie(pci);
+	struct eic7700_pcie_port *port;
+	u32 val;
+	int ret;
+
+	ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks);
+	if (ret)
+		return ret;
+
+	/*
+	 * The PWR and DBI reset signals are respectively used to reset the
+	 * PCIe controller and the DBI register.
+	 *
+	 * The PERST# signal is a reset signal that simultaneously controls the
+	 * PCIe controller, PHY, and Endpoint. Before configuring the PHY, the
+	 * PERST# signal must first be deasserted.
+	 *
+	 * The external reference clock is supplied simultaneously to the PHY
+	 * and EP. When the PHY is configurable, the entire chip already has
+	 * stable power and reference clock. The PHY will be ready within 20ms
+	 * after writing app_hold_phy_rst register bit of ELBI register space.
+	 */
+	ret = reset_control_bulk_deassert(EIC7700_NUM_RSTS, pcie->resets);
+	if (ret) {
+		dev_err(pcie->pci.dev, "Failed to deassert resets\n");
+		goto err_deassert;
+	}
+
+	/* Configure Root Port type */
+	val = readl_relaxed(pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
+	val &= ~PCIEELBI_CTRL0_DEV_TYPE;
+	val |= FIELD_PREP(PCIEELBI_CTRL0_DEV_TYPE, PCI_EXP_TYPE_ROOT_PORT);
+	writel_relaxed(val, pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
+
+	list_for_each_entry(port, &pcie->ports, list) {
+		ret = eic7700_pcie_perst_reset(port, pcie);
+		if (ret)
+			goto err_perst;
+	}
+
+	/* Configure app_hold_phy_rst */
+	val = readl_relaxed(pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
+	val &= ~PCIEELBI_APP_HOLD_PHY_RST;
+	writel_relaxed(val, pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
+
+	/* The maximum waiting time for the clock switch lock is 20ms */
+	ret = readl_poll_timeout(pci->elbi_base + PCIEELBI_STATUS0_OFFSET, val,
+				 !(val & PCIEELBI_PM_SEL_AUX_CLK), 1000,
+				 20000);
+	if (ret) {
+		dev_err(pci->dev, "Timeout waiting for PM_SEL_AUX_CLK ready\n");
+		goto err_phy_init;
+	}
+
+	/*
+	 * Configure ESWIN VID:DID for Root Port as the default values are
+	 * invalid.
+	 */
+	dw_pcie_dbi_ro_wr_en(pci);
+	dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, PCI_VENDOR_ID_ESWIN);
+	dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, PCI_DEVICE_ID_ESWIN_EIC7700);
+	dw_pcie_dbi_ro_wr_dis(pci);
+
+	return 0;
+
+err_phy_init:
+	list_for_each_entry(port, &pcie->ports, list)
+		reset_control_assert(port->perst);
+err_perst:
+	reset_control_bulk_assert(EIC7700_NUM_RSTS, pcie->resets);
+err_deassert:
+	clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
+
+	return ret;
+}
+
+static void eic7700_pcie_host_deinit(struct dw_pcie_rp *pp)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+	struct eic7700_pcie *pcie = to_eic7700_pcie(pci);
+
+	eic7700_pcie_assert(pcie);
+	clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
+}
+
+static const struct dw_pcie_host_ops eic7700_pcie_host_ops = {
+	.init = eic7700_pcie_host_init,
+	.deinit = eic7700_pcie_host_deinit,
+};
+
+static const struct dw_pcie_ops dw_pcie_ops = {
+	.start_link = eic7700_pcie_start_link,
+	.link_up = eic7700_pcie_link_up,
+};
+
+static int eic7700_pcie_probe(struct platform_device *pdev)
+{
+	struct eic7700_pcie_port *port, *tmp;
+	struct device *dev = &pdev->dev;
+	struct eic7700_pcie *pcie;
+	struct dw_pcie *pci;
+	int ret, i;
+
+	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
+	if (!pcie)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&pcie->ports);
+
+	pci = &pcie->pci;
+	pci->dev = dev;
+	pci->ops = &dw_pcie_ops;
+	pci->pp.ops = &eic7700_pcie_host_ops;
+
+	pcie->num_clks = devm_clk_bulk_get_all(dev, &pcie->clks);
+	if (pcie->num_clks < 0)
+		return dev_err_probe(dev, pcie->num_clks,
+				     "Failed to get pcie clocks\n");
+
+	for (i = 0; i < EIC7700_NUM_RSTS; i++)
+		pcie->resets[i].id = eic7700_pcie_rsts[i];
+
+	ret = devm_reset_control_bulk_get_exclusive(dev, EIC7700_NUM_RSTS,
+						    pcie->resets);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get resets\n");
+
+	ret = eic7700_pcie_parse_ports(pcie);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to parse Root Port\n");
+
+	platform_set_drvdata(pdev, pcie);
+
+	pm_runtime_no_callbacks(dev);
+	devm_pm_runtime_enable(dev);
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0)
+		goto err_pm_runtime_put;
+
+	ret = dw_pcie_host_init(&pci->pp);
+	if (ret) {
+		dev_err(dev, "Failed to init host\n");
+		goto err_pm_runtime_put;
+	}
+
+	return 0;
+
+err_pm_runtime_put:
+	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
+		reset_control_put(port->perst);
+		list_del(&port->list);
+	}
+	pm_runtime_put(dev);
+
+	return ret;
+}
+
+static int eic7700_pcie_suspend_noirq(struct device *dev)
+{
+	struct eic7700_pcie *pcie = dev_get_drvdata(dev);
+
+	/*
+	 * The ESWIN EIC7700 SoC lacks hardware support for the L2/L3 low-power
+	 * link states. It cannot enter the L2/L3 Ready state through the
+	 * PME_Turn_Off/PME_To_Ack handshake protocol. To avoid this problem,
+	 * the dw_pcie_suspend_noirq API is not used.
+	 */
+	eic7700_pcie_host_deinit(&pcie->pci.pp);
+
+	return 0;
+}
+
+static int eic7700_pcie_resume_noirq(struct device *dev)
+{
+	struct eic7700_pcie *pcie = dev_get_drvdata(dev);
+	struct eic7700_pcie_port *port, *tmp;
+	int ret;
+
+	ret = eic7700_pcie_host_init(&pcie->pci.pp);
+	if (ret) {
+		dev_err(dev, "Host init failed: %d\n", ret);
+		goto err_init;
+	}
+
+	ret = dw_pcie_setup_rc(&pcie->pci.pp);
+	if (ret)
+		goto err_setup_rc;
+
+	ret = eic7700_pcie_start_link(&pcie->pci);
+	if (ret)
+		goto err_setup_rc;
+
+	dw_pcie_wait_for_link(&pcie->pci);
+
+	return 0;
+
+err_setup_rc:
+	eic7700_pcie_host_deinit(&pcie->pci.pp);
+err_init:
+	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
+		reset_control_put(port->perst);
+		list_del(&port->list);
+	}
+
+	return ret;
+}
+
+DEFINE_NOIRQ_DEV_PM_OPS(eic7700_pcie_pm, eic7700_pcie_suspend_noirq,
+			eic7700_pcie_resume_noirq);
+
+static const struct of_device_id eic7700_pcie_of_match[] = {
+	{ .compatible = "eswin,eic7700-pcie" },
+	{}
+};
+
+static struct platform_driver eic7700_pcie_driver = {
+	.probe = eic7700_pcie_probe,
+	.driver = {
+		.name = "eic7700-pcie",
+		.of_match_table = eic7700_pcie_of_match,
+		.suppress_bind_attrs = true,
+		.pm = &eic7700_pcie_pm,
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+	},
+};
+builtin_platform_driver(eic7700_pcie_driver);
+
+MODULE_DESCRIPTION("Eswin EIC7700 PCIe host controller driver");
+MODULE_AUTHOR("Yu Ning <ningyu@eswincomputing.com>");
+MODULE_AUTHOR("Senchuan Zhang <zhangsenchuan@eswincomputing.com>");
+MODULE_AUTHOR("Yanghui Ou <ouyanghui@eswincomputing.com>");
+MODULE_LICENSE("GPL");
-- 
2.25.1


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

* Re: [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller
  2026-01-29  9:26 [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller zhangsenchuan
  2026-01-29  9:28 ` [PATCH v10 1/2] dt-bindings: PCI: eic7700: Add Eswin PCIe host controller zhangsenchuan
  2026-01-29  9:29 ` [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver zhangsenchuan
@ 2026-02-01 12:24 ` Leon Romanovsky
  2026-02-01 12:28   ` Leon Romanovsky
  2026-02-01 12:25 ` Leon Romanovsky
  2026-02-02 10:59 ` Manivannan Sadhasivam
  4 siblings, 1 reply; 17+ messages in thread
From: Leon Romanovsky @ 2026-02-01 12:24 UTC (permalink / raw)
  To: bhelgaas, mani, krzk+dt, conor+dt, lpieralisi, kwilczynski, robh,
	p.zabel, linux-pci, devicetree, linux-kernel, christian.bruel,
	shradha.t, krishna.chundru, thippeswamy.havalige, inochiama,
	Frank.li, zhangsenchuan
  Cc: ningyu, linmin, pinkesh.vaghela, ouyanghui


On Thu, 29 Jan 2026 17:26:28 +0800, zhangsenchuan@eswincomputing.com wrote:
> Changes in v10:
> - Updates: eswin,eic7700-pcie.yaml
>   - None
> 
> - Updates: pcie-eic7700.c
>   - Remove devm_clk_bulk_get_all_enabled API, use devm_clk_bulk_get_all
>     and clk_bulk_prepare_enable. Add resource release codes and add
>     eic7700_pcie_host_deinit API.
>   - Update PCI_DEVICE_ID_ESWIN_EIC7700.
>   - Add reset_control_put release resources in "goto err_port:".
>   - Delete trailing comma after a terminator in eic7700_pcie_of_match.
> - Link to V9: https://lore.kernel.org/all/20251229113021.1859-1-zhangsenchuan@eswincomputing.com/
> 
> [...]

Applied, thanks!

[1/2] dt-bindings: PCI: eic7700: Add Eswin PCIe host controller
      (no commit info)
[2/2] PCI: eic7700: Add Eswin PCIe host controller driver
      (no commit info)

Best regards,
-- 
Leon Romanovsky <leon@kernel.org>


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

* Re: [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller
  2026-01-29  9:26 [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller zhangsenchuan
                   ` (2 preceding siblings ...)
  2026-02-01 12:24 ` [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller Leon Romanovsky
@ 2026-02-01 12:25 ` Leon Romanovsky
  2026-02-02 10:59 ` Manivannan Sadhasivam
  4 siblings, 0 replies; 17+ messages in thread
From: Leon Romanovsky @ 2026-02-01 12:25 UTC (permalink / raw)
  To: bhelgaas, mani, krzk+dt, conor+dt, lpieralisi, kwilczynski, robh,
	p.zabel, linux-pci, devicetree, linux-kernel, christian.bruel,
	shradha.t, krishna.chundru, thippeswamy.havalige, inochiama,
	Frank.li, zhangsenchuan
  Cc: ningyu, linmin, pinkesh.vaghela, ouyanghui


On Thu, 29 Jan 2026 17:26:28 +0800, zhangsenchuan@eswincomputing.com wrote:
> Changes in v10:
> - Updates: eswin,eic7700-pcie.yaml
>   - None
> 
> - Updates: pcie-eic7700.c
>   - Remove devm_clk_bulk_get_all_enabled API, use devm_clk_bulk_get_all
>     and clk_bulk_prepare_enable. Add resource release codes and add
>     eic7700_pcie_host_deinit API.
>   - Update PCI_DEVICE_ID_ESWIN_EIC7700.
>   - Add reset_control_put release resources in "goto err_port:".
>   - Delete trailing comma after a terminator in eic7700_pcie_of_match.
> - Link to V9: https://lore.kernel.org/all/20251229113021.1859-1-zhangsenchuan@eswincomputing.com/
> 
> [...]

Applied, thanks!

[1/2] dt-bindings: PCI: eic7700: Add Eswin PCIe host controller
      (no commit info)
[2/2] PCI: eic7700: Add Eswin PCIe host controller driver
      (no commit info)

Best regards,
-- 
Leon Romanovsky <leon@kernel.org>


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

* Re: [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller
  2026-02-01 12:24 ` [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller Leon Romanovsky
@ 2026-02-01 12:28   ` Leon Romanovsky
  2026-02-02 10:57     ` Manivannan Sadhasivam
  0 siblings, 1 reply; 17+ messages in thread
From: Leon Romanovsky @ 2026-02-01 12:28 UTC (permalink / raw)
  To: bhelgaas, mani, krzk+dt, conor+dt, lpieralisi, kwilczynski, robh,
	p.zabel, linux-pci, devicetree, linux-kernel, christian.bruel,
	shradha.t, krishna.chundru, thippeswamy.havalige, inochiama,
	Frank.li, zhangsenchuan
  Cc: ningyu, linmin, pinkesh.vaghela, ouyanghui

On Sun, Feb 01, 2026 at 07:24:54AM -0500, Leon Romanovsky wrote:
> 
> On Thu, 29 Jan 2026 17:26:28 +0800, zhangsenchuan@eswincomputing.com wrote:
> > Changes in v10:
> > - Updates: eswin,eic7700-pcie.yaml
> >   - None
> > 
> > - Updates: pcie-eic7700.c
> >   - Remove devm_clk_bulk_get_all_enabled API, use devm_clk_bulk_get_all
> >     and clk_bulk_prepare_enable. Add resource release codes and add
> >     eic7700_pcie_host_deinit API.
> >   - Update PCI_DEVICE_ID_ESWIN_EIC7700.
> >   - Add reset_control_put release resources in "goto err_port:".
> >   - Delete trailing comma after a terminator in eic7700_pcie_of_match.
> > - Link to V9: https://lore.kernel.org/all/20251229113021.1859-1-zhangsenchuan@eswincomputing.com/
> > 
> > [...]
> 
> Applied, thanks!
> 
> [1/2] dt-bindings: PCI: eic7700: Add Eswin PCIe host controller
>       (no commit info)
> [2/2] PCI: eic7700: Add Eswin PCIe host controller driver
>       (no commit info)


Sorry for the noise. The issue was caused by a mistake in my scripts.  
Of course, it was never applied.

Thanks

> 
> Best regards,
> -- 
> Leon Romanovsky <leon@kernel.org>
> 
> 

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

* Re: [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller
  2026-02-01 12:28   ` Leon Romanovsky
@ 2026-02-02 10:57     ` Manivannan Sadhasivam
  0 siblings, 0 replies; 17+ messages in thread
From: Manivannan Sadhasivam @ 2026-02-02 10:57 UTC (permalink / raw)
  To: Leon Romanovsky
  Cc: bhelgaas, krzk+dt, conor+dt, lpieralisi, kwilczynski, robh,
	p.zabel, linux-pci, devicetree, linux-kernel, christian.bruel,
	shradha.t, krishna.chundru, thippeswamy.havalige, inochiama,
	Frank.li, zhangsenchuan, ningyu, linmin, pinkesh.vaghela,
	ouyanghui

On Sun, Feb 01, 2026 at 02:28:10PM +0200, Leon Romanovsky wrote:
> On Sun, Feb 01, 2026 at 07:24:54AM -0500, Leon Romanovsky wrote:
> > 
> > On Thu, 29 Jan 2026 17:26:28 +0800, zhangsenchuan@eswincomputing.com wrote:
> > > Changes in v10:
> > > - Updates: eswin,eic7700-pcie.yaml
> > >   - None
> > > 
> > > - Updates: pcie-eic7700.c
> > >   - Remove devm_clk_bulk_get_all_enabled API, use devm_clk_bulk_get_all
> > >     and clk_bulk_prepare_enable. Add resource release codes and add
> > >     eic7700_pcie_host_deinit API.
> > >   - Update PCI_DEVICE_ID_ESWIN_EIC7700.
> > >   - Add reset_control_put release resources in "goto err_port:".
> > >   - Delete trailing comma after a terminator in eic7700_pcie_of_match.
> > > - Link to V9: https://lore.kernel.org/all/20251229113021.1859-1-zhangsenchuan@eswincomputing.com/
> > > 
> > > [...]
> > 
> > Applied, thanks!
> > 
> > [1/2] dt-bindings: PCI: eic7700: Add Eswin PCIe host controller
> >       (no commit info)
> > [2/2] PCI: eic7700: Add Eswin PCIe host controller driver
> >       (no commit info)
> 
> 
> Sorry for the noise. The issue was caused by a mistake in my scripts.  
> Of course, it was never applied.
> 

I was about to scream, but glad that this didn't happen.

- Mani

-- 
மணிவண்ணன் சதாசிவம்

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

* Re: [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller
  2026-01-29  9:26 [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller zhangsenchuan
                   ` (3 preceding siblings ...)
  2026-02-01 12:25 ` Leon Romanovsky
@ 2026-02-02 10:59 ` Manivannan Sadhasivam
  2026-02-06 22:20   ` Bjorn Helgaas
  4 siblings, 1 reply; 17+ messages in thread
From: Manivannan Sadhasivam @ 2026-02-02 10:59 UTC (permalink / raw)
  To: zhangsenchuan
  Cc: bhelgaas, krzk+dt, conor+dt, lpieralisi, kwilczynski, robh,
	p.zabel, linux-pci, devicetree, linux-kernel, christian.bruel,
	shradha.t, krishna.chundru, thippeswamy.havalige, inochiama,
	Frank.li, ningyu, linmin, pinkesh.vaghela, ouyanghui

On Thu, Jan 29, 2026 at 05:26:28PM +0800, zhangsenchuan@eswincomputing.com wrote:
> From: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
> 
> Changes in v10:
> - Updates: eswin,eic7700-pcie.yaml
>   - None
> 

This version looks good to me, but it'd be good if Bjorn could give an Ack since
there were previous reviews from him. Also, this week is -rc8, so it is too late
for 7.0. I hope we can merge this series early, once v7.0-rc1 is released.

- Mani

> - Updates: pcie-eic7700.c
>   - Remove devm_clk_bulk_get_all_enabled API, use devm_clk_bulk_get_all
>     and clk_bulk_prepare_enable. Add resource release codes and add
>     eic7700_pcie_host_deinit API.
>   - Update PCI_DEVICE_ID_ESWIN_EIC7700.
>   - Add reset_control_put release resources in "goto err_port:".
>   - Delete trailing comma after a terminator in eic7700_pcie_of_match.
> - Link to V9: https://lore.kernel.org/all/20251229113021.1859-1-zhangsenchuan@eswincomputing.com/
> 
> Changes in v9:
> - Updates: eswin,eic7700-pcie.yaml
>   - None
> 
> - Updates: pcie-eic7700.c
>   - Update comment, s/Rort/Port/.
> - Link to V8: https://lore.kernel.org/all/20251215095928.1712-1-zhangsenchuan@eswincomputing.com/
> 
> Changes in v8:
> - Updates: eswin,eic7700-pcie.yaml
>   - None
> 
> - Updates: pcie-eic7700.c
>   - Remove dw_pcie_suspend_noirq/dw_pcie_resume_noirq API and add a
>     comment, and remove .deinit.
>   - Remove no_pme_handshake flag.
>   - Add dw_pcie_dbi_ro_wr_en/dw_pcie_dbi_ro_wr_dis API.
>   - Add eic7700_pcie_assert helper function.
>   - Update NOIRQ_SYSTEM_SLEEP_PM_OPS to DEFINE_NOIRQ_DEV_PM_OPS.
> - Link to V7: https://lore.kernel.org/all/20251202090225.1602-1-zhangsenchuan@eswincomputing.com/
> 
> Changes in v7:
> - Updates: eswin,eic7700-pcie.yaml
>   - None
> 
> - Updates: pcie-eic7700.c
>   - Update "config PCIE_EIC7700" bool to tristate.
>   - Remove fix MSI-X code, depend on new commit [1].
>   - Add set no_pme_handshake flag.
>   - Update -EINVAL to -ENODATA and add PM runtime function.
>   - Add ".probe_type = PROBE_PREFER_ASYNCHRONOUS,".
>   - Update eic7700_pcie_perst_deassert function name to
>     eic7700_pcie_perst_reset.
>   - Update readw to dw_pcie_readw_dbi function.
>   - Add comments above reset_control_bulk_deassert function.
> 
> - Updates: pcie-designware.h pcie-designware-host.c
>  -  The ESWIN EIC7700 SoC lacks hardware support for the L2/L3 low-power
>     link states. It cannot enter the L2/L3 ready state through the
>     PME_Turn_Off/PME_To_Ack handshake protocol. To address this, add a
>     no_pme_handshake flag skip PME_Turn_Off broadcast and link state check
>     code, other driver can reuse this flag if meet the similar situation.
> - Link to V6: https://lore.kernel.org/linux-pci/20251120101018.1477-1-zhangsenchuan@eswincomputing.com/
> - Link to: https://lore.kernel.org/linux-pci/20251109-remove_cap-v1-3-2208f46f4dc2@oss.qualcomm.com/ [1]
> 
> Changes in v6:
> - Updates: eswin,eic7700-pcie.yaml
>   - Add Reviewed-by: Rob Herring (Arm) <robh@kernel.org>.
> 
> - Updates: pcie-eic7700.c
>   - Remove pci_root_ports_have_device function judgment during suspend.
>   - Remove eic7700_pcie_pme_turn_off and eic7700_pcie_get_ltssm function.
>   - Add set no_suspport_L2 flag.
> 
> - Updates: pcie-designware.h pcie-designware-host.c
>  - The ESWIN EIC7700 soc does not support enter L2 link state. Therefore
>    add no_suspport_L2 flag skip PME_Turn_Off broadcast and link state
>    check code, other driver can reuse this flag if meet the similar
>    situation.
> - Link to V5: https://lore.kernel.org/all/20251110090716.1392-1-zhangsenchuan@eswincomputing.com/
> - Link to: https://lore.kernel.org/all/e7plmtwtkkd4ymrt2hkztcqdx4ugfjk64oksjyf6lpi2oui53d@vhuo5occyref/
> 
> Changes in v5:
> - Updates: eswin,eic7700-pcie.yaml
>   - Modify reg-names: update mgmt to elbi.
>   - Modify clock-names: update pclk to phy_reg.
>   - Modify reset-names: update powerup to pwr.
>   - Remove powerup modify in "snps,dw-pcie-common.yaml" file.
> 
> - Updates: pcie-eic7700.c
>   - Update the driver submission comment, mention EIC7700 in the
>     "config PCIE_EIC7700" and in the driver title.
>   - Update some comments, for examples: "s/PME_TURN_OFF/PME_Turn_Off/",
>     "s/INTX/INTx/", "s/PERST/PERST#/", "s/perst/PERST#/", "s/id/ID/".
>   - Update "struct *_pcie" name and function name, add the eic7700 prefix.
>   - Use PCIEELBI_CTRL0_DEV_TYPE macro and update comment, use FIELD_PREP.
>   - Add eic7700_pcie_data pointer in struct eic7700_pcie.
>   - Update .deinit callback function name and removed the dw_pcie_link_up
>     judgment, add pci_root_ports_have_device function judgment.
>   - Remove devm_platform_ioremap_resource_byname function get mgmt, use
>     platform_get_resource_byname function get elbi in "pcie-designware.c".
>   - Update of_reset_control_get to of_reset_control_get_exclusive, use
>     devm_reset_control_bulk_get_exclusive function get resets, update use
>     reset_control_bulk_assert/reset_control_bulk_deassert function.
> - Link to V4: https://lore.kernel.org/all/20251030082900.1304-1-zhangsenchuan@eswincomputing.com/
> - Link to https://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/tree/?h=controller/dwc
> 
> Changes in v4:
> - Updates: eswin,eic7700-pcie.yaml
>   - Use snps,dw-pcie.yaml instead pci-host-bridge.yaml.
> 
> - Updates: snps,dw-pcie-common.yaml
>   - Add powerup reset property, our powerup property is somewhat different
>     from the general attributes defined by Synopsys DWC binding.
> 
> - Updates: pcie-eic7700.c
>   - Update the driver submission comment.
>   - Alphabetize so the menuconfig entries remain sorted by vendor.
>   - Update use PCI_CAP_LIST_NEXT_MASK macro.
>   - Use readl_poll_timeout function.
>   - Update eswin_pcie_suspend/eswin_pcie_resume name to
>     eswin_pcie_suspend_noirq/eswin_pcie_resume_noirq.
>   - PM use dw_pcie_suspend_noirq and dw_pcie_resume_noirq function and add
>     eswin_pcie_get_ltssm, eswin_pcie_pme_turn_off, eswin_pcie_host_exit
>     function adapt to PM.
> - Link to V3: https://lore.kernel.org/linux-pci/20250923120946.1218-1-zhangsenchuan@eswincomputing.com/
> 
> Changes in v3:
> - Updates: eswin,eic7700-pcie.yaml
>   - Based on the last patch yaml file, devicetree separates the root port
>     node, changing it significantly. Therefore, "Reviewed-by: Krzysztof
>     Kozlowski <krzysztof.kozlowski@linaro.org>" is not added.
>   - Clock and reset drivers are under review. In yaml, macro definitions
>     used in clock and reset can only be replaced by constant values.
>   - Move the num-lanes and perst resets to the PCIe Root Port node, make
>     it easier to support multiple Root Ports in future versions of the
>     hardware.
>   - Update the num-lanes attribute and modify define num-lanes as decimal.
>   - Optimize the ranges attribute and clear the relocatable flag (bit 31)
>     for any regions.
>   - Update comment: inte~inth are actual interrupts and these names align
>     with the interrupt names in the hardware IP, inte~inth interrupts
>     corresponds to Deassert_INTA~Deassert_INTD.
>   - Add Signed-off-by: Yanghui Ou <ouyanghui@eswincomputing.com>.
> 
> - Updates: pcie-eic7700.c
>   - Update the submission comment and add DWC IP revision, data rate, lane
>     information.
>   - Optimize the "config PCIE_EIC7700" configuration.
>   - Optimize the macro definition, add bitfield definition for the mask,
>     and remove redundant comments. optimize comments, make use of 80
>     columns for comments.
>   - Use the dw_pcie_find_capability function to obtain the offset by
>     traversing the function list.
>   - Remove the sets MPS code and configure it by PCI core.
>   - Alphabetize so the menuconfig entries remain sorted by vendor.
>   - Configure ESWIN VID:DID for Root Port as the default values are
> 	invalid,and remove the redundant lane config.
>   - Use reverse Xmas order for all local variables in this driver
>   - Hardware doesn't support MSI-X but it advertises MSI-X capability, set
>     a flag and clear it conditionally.
>   - Resets are all necessary, Update the interface function for resets.
>   - Since driver does not depend on any parent to power on any resource,
>     the pm runtime related functions are removed.
>   - Remove "eswin_pcie_shutdown" function, our comment on the shutdown
>     function is incorrect. Moreover, when the host powers reboots,it will
>     enter the shutdown function, we are using host reset and do not need
>     to assert perst. Therefore, the shutdown function is not necessary.
>   - remove "eswin_pcie_remove", because it is not safe to remove it during
>     runtime, and this driver has been modified to builtin_platform_driver
>     and does not support hot plugging, therefore, the remove function is
>     not needed.
>   - The Suspend function adds link state judgment, and for controllers
>     with active devices, resources cannot be turned off.
>   - Add Signed-off-by: Yanghui Ou <ouyanghui@eswincomputing.com>.
> - Link to V2: https://lore.kernel.org/linux-pci/20250829082021.49-1-zhangsenchuan@eswincomputing.com/
> 
> Changes in v2:
> - Updates: eswin,eic7700-pcie.yaml
>   - Optimize the naming of "clock-names" and "reset-names".
>   - Add a reference to "$ref: /schemas/pci/pci-host-bridge.yaml#".
>     (The name of the reset attribute in the "snps,dw-pcie-common.yaml"
>     file is different from our reset attribute and "snps,dw-pcie.yaml"
>     file cannot be directly referenced)
>   - Follow DTS coding style to optimize yaml attributes.
>   - Remove status = "disabled" from yaml.
> 
> - Updates: pcie-eic7700.c
>   - Remove unnecessary imported header files.
>   - Use dev_err instead of pr_err and remove the WARN_ON function.
>   - The eswin_evb_socket_power_on function is removed and not supported.
>   - The eswin_pcie_remove function is placed after the probe function.
>   - Optimize function alignment.
>   - Manage the clock using the devm_clk_bulk_get_all_enabled function.
>   - Handle the release of resources after the dw_pcie_host_init function
>     call fails.
>   - Remove the dev_dbg function and remove __exit_p.
>   - Add support for the system pm function.
> - Link to V1: https://lore.kernel.org/all/20250516094057.1300-1-zhangsenchuan@eswincomputing.com/
> 
> Senchuan Zhang (2):
>   dt-bindings: PCI: eic7700: Add Eswin PCIe host controller
>   PCI: eic7700: Add Eswin PCIe host controller driver
> 
>  .../bindings/pci/eswin,eic7700-pcie.yaml      | 167 +++++++
>  drivers/pci/controller/dwc/Kconfig            |  11 +
>  drivers/pci/controller/dwc/Makefile           |   1 +
>  drivers/pci/controller/dwc/pcie-eic7700.c     | 410 ++++++++++++++++++
>  4 files changed, 589 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pci/eswin,eic7700-pcie.yaml
>  create mode 100644 drivers/pci/controller/dwc/pcie-eic7700.c
> 
> --
> 2.25.1
> 

-- 
மணிவண்ணன் சதாசிவம்

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

* Re: [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller
  2026-02-02 10:59 ` Manivannan Sadhasivam
@ 2026-02-06 22:20   ` Bjorn Helgaas
  0 siblings, 0 replies; 17+ messages in thread
From: Bjorn Helgaas @ 2026-02-06 22:20 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: zhangsenchuan, bhelgaas, krzk+dt, conor+dt, lpieralisi,
	kwilczynski, robh, p.zabel, linux-pci, devicetree, linux-kernel,
	christian.bruel, shradha.t, krishna.chundru, thippeswamy.havalige,
	inochiama, Frank.li, ningyu, linmin, pinkesh.vaghela, ouyanghui

On Mon, Feb 02, 2026 at 04:29:51PM +0530, Manivannan Sadhasivam wrote:
> On Thu, Jan 29, 2026 at 05:26:28PM +0800, zhangsenchuan@eswincomputing.com wrote:
> > From: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
> > 
> > Changes in v10:
> > - Updates: eswin,eic7700-pcie.yaml
> >   - None
> > 
> 
> This version looks good to me, but it'd be good if Bjorn could give
> an Ack since there were previous reviews from him. Also, this week
> is -rc8, so it is too late for 7.0. I hope we can merge this series
> early, once v7.0-rc1 is released.

Will do, ping me after v7.0-rc1 to remind me.

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

* Re: [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver
  2026-01-29  9:29 ` [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver zhangsenchuan
@ 2026-02-18 12:47   ` Manivannan Sadhasivam
  2026-02-24  8:14     ` zhangsenchuan
  0 siblings, 1 reply; 17+ messages in thread
From: Manivannan Sadhasivam @ 2026-02-18 12:47 UTC (permalink / raw)
  To: zhangsenchuan
  Cc: bhelgaas, krzk+dt, conor+dt, lpieralisi, kwilczynski, robh,
	p.zabel, linux-pci, devicetree, linux-kernel, christian.bruel,
	shradha.t, krishna.chundru, thippeswamy.havalige, inochiama,
	Frank.li, ningyu, linmin, pinkesh.vaghela, ouyanghui

On Thu, Jan 29, 2026 at 05:29:00PM +0800, zhangsenchuan@eswincomputing.com wrote:
> From: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
> 
> Add driver for the Eswin EIC7700 PCIe host controller, which is based on
> the DesignWare PCIe core, IP revision 5.96a. The PCIe Gen.3 controller
> supports a data rate of 8 GT/s and 4 channels, support INTx and MSI
> interrupts.
> 
> Signed-off-by: Yu Ning <ningyu@eswincomputing.com>
> Signed-off-by: Yanghui Ou <ouyanghui@eswincomputing.com>
> Signed-off-by: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
> ---
>  drivers/pci/controller/dwc/Kconfig        |  11 +
>  drivers/pci/controller/dwc/Makefile       |   1 +
>  drivers/pci/controller/dwc/pcie-eic7700.c | 410 ++++++++++++++++++++++
>  3 files changed, 422 insertions(+)
>  create mode 100644 drivers/pci/controller/dwc/pcie-eic7700.c
> 
> diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
> index 519b59422b47..c837cb5947b6 100644
> --- a/drivers/pci/controller/dwc/Kconfig
> +++ b/drivers/pci/controller/dwc/Kconfig
> @@ -93,6 +93,17 @@ config PCIE_BT1
>  	  Enables support for the PCIe controller in the Baikal-T1 SoC to work
>  	  in host mode. It's based on the Synopsys DWC PCIe v4.60a IP-core.
>  
> +config PCIE_EIC7700
> +	tristate "Eswin EIC7700 PCIe controller"
> +	depends on ARCH_ESWIN || COMPILE_TEST
> +	depends on PCI_MSI
> +	select PCIE_DW_HOST
> +	help
> +	  Say Y here if you want PCIe controller support for the Eswin EIC7700.
> +	  The PCIe controller on EIC7700 is based on DesignWare hardware,
> +	  enables support for the PCIe controller in the EIC7700 SoC to work in
> +	  host mode.
> +
>  config PCI_IMX6
>  	bool
>  
> diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
> index 67ba59c02038..7c5a5186ea83 100644
> --- a/drivers/pci/controller/dwc/Makefile
> +++ b/drivers/pci/controller/dwc/Makefile
> @@ -6,6 +6,7 @@ obj-$(CONFIG_PCIE_DW_EP) += pcie-designware-ep.o
>  obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o
>  obj-$(CONFIG_PCIE_AMD_MDB) += pcie-amd-mdb.o
>  obj-$(CONFIG_PCIE_BT1) += pcie-bt1.o
> +obj-$(CONFIG_PCIE_EIC7700) += pcie-eic7700.o
>  obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
>  obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
>  obj-$(CONFIG_PCIE_FU740) += pcie-fu740.o
> diff --git a/drivers/pci/controller/dwc/pcie-eic7700.c b/drivers/pci/controller/dwc/pcie-eic7700.c
> new file mode 100644
> index 000000000000..dab8e3b98810
> --- /dev/null
> +++ b/drivers/pci/controller/dwc/pcie-eic7700.c
> @@ -0,0 +1,410 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * ESWIN EIC7700 PCIe root complex driver
> + *
> + * Copyright 2026, Beijing ESWIN Computing Technology Co., Ltd.
> + *
> + * Authors: Yu Ning <ningyu@eswincomputing.com>
> + *          Senchuan Zhang <zhangsenchuan@eswincomputing.com>
> + *          Yanghui Ou <ouyanghui@eswincomputing.com>
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/iopoll.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/pci.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/resource.h>
> +#include <linux/reset.h>
> +#include <linux/types.h>
> +
> +#include "pcie-designware.h"
> +
> +/* ELBI registers */
> +#define PCIEELBI_CTRL0_OFFSET		0x0
> +#define PCIEELBI_STATUS0_OFFSET		0x100
> +
> +/* LTSSM register fields */
> +#define PCIEELBI_APP_LTSSM_ENABLE	BIT(5)
> +
> +/* APP_HOLD_PHY_RST register fields */
> +#define PCIEELBI_APP_HOLD_PHY_RST	BIT(6)
> +
> +/* PM_SEL_AUX_CLK register fields */
> +#define PCIEELBI_PM_SEL_AUX_CLK		BIT(16)
> +
> +/* DEV_TYPE register fields */
> +#define PCIEELBI_CTRL0_DEV_TYPE		GENMASK(3, 0)
> +
> +/* Vendor and device ID value */
> +#define PCI_VENDOR_ID_ESWIN		0x1fe1
> +#define PCI_DEVICE_ID_ESWIN_EIC7700	0x2030
> +
> +#define EIC7700_NUM_RSTS		ARRAY_SIZE(eic7700_pcie_rsts)
> +
> +static const char * const eic7700_pcie_rsts[] = {
> +	"pwr",
> +	"dbi",
> +};
> +
> +struct eic7700_pcie_port {
> +	struct list_head list;
> +	struct reset_control *perst;
> +	int num_lanes;
> +};
> +
> +struct eic7700_pcie {
> +	struct dw_pcie pci;
> +	struct clk_bulk_data *clks;
> +	struct reset_control_bulk_data resets[EIC7700_NUM_RSTS];
> +	struct list_head ports;
> +	int num_clks;
> +};
> +
> +#define to_eic7700_pcie(x) dev_get_drvdata((x)->dev)
> +
> +static int eic7700_pcie_start_link(struct dw_pcie *pci)
> +{
> +	u32 val;
> +
> +	/* Enable LTSSM */
> +	val = readl_relaxed(pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> +	val |= PCIEELBI_APP_LTSSM_ENABLE;
> +	writel_relaxed(val, pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> +
> +	return 0;
> +}
> +
> +static bool eic7700_pcie_link_up(struct dw_pcie *pci)
> +{
> +	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
> +	u16 val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
> +
> +	return val & PCI_EXP_LNKSTA_DLLLA;
> +}
> +
> +static int eic7700_pcie_perst_reset(struct eic7700_pcie_port *port,
> +				    struct eic7700_pcie *pcie)
> +{
> +	int ret;
> +
> +	ret = reset_control_assert(port->perst);
> +	if (ret) {
> +		dev_err(pcie->pci.dev, "Failed to assert PERST#\n");
> +		return ret;
> +	}
> +
> +	/* Ensure that PERST# has been asserted for at least 100 ms */
> +	msleep(PCIE_T_PVPERL_MS);
> +
> +	ret = reset_control_deassert(port->perst);
> +	if (ret) {
> +		dev_err(pcie->pci.dev, "Failed to deassert PERST#\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static void eic7700_pcie_assert(struct eic7700_pcie *pcie)
> +{
> +	struct eic7700_pcie_port *port;
> +
> +	list_for_each_entry(port, &pcie->ports, list)
> +		reset_control_assert(port->perst);
> +	reset_control_bulk_assert(EIC7700_NUM_RSTS, pcie->resets);
> +}
> +
> +static int eic7700_pcie_parse_port(struct eic7700_pcie *pcie,
> +				   struct device_node *node)
> +{
> +	struct device *dev = pcie->pci.dev;
> +	struct eic7700_pcie_port *port;
> +
> +	port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
> +	if (!port)
> +		return -ENOMEM;
> +
> +	port->perst = of_reset_control_get_exclusive(node, "perst");
> +	if (IS_ERR(port->perst)) {
> +		dev_err(dev, "Failed to get PERST# reset\n");
> +		return PTR_ERR(port->perst);
> +	}
> +
> +	/*
> +	 * TODO: Since the Root Port node is separated out by pcie devicetree,
> +	 * the DWC core initialization code can't parse the num-lanes attribute
> +	 * in the Root Port. Before entering the DWC core initialization code,
> +	 * the platform driver code parses the Root Port node. The EIC7700 only
> +	 * supports one Root Port node, and the num-lanes attribute is suitable
> +	 * for the case of one Root Port.
> +	 */
> +	if (!of_property_read_u32(node, "num-lanes", &port->num_lanes))
> +		pcie->pci.num_lanes = port->num_lanes;
> +
> +	INIT_LIST_HEAD(&port->list);
> +	list_add_tail(&port->list, &pcie->ports);
> +
> +	return 0;
> +}
> +
> +static int eic7700_pcie_parse_ports(struct eic7700_pcie *pcie)
> +{
> +	struct eic7700_pcie_port *port, *tmp;
> +	struct device *dev = pcie->pci.dev;
> +	int ret;
> +
> +	for_each_available_child_of_node_scoped(dev->of_node, of_port) {
> +		ret = eic7700_pcie_parse_port(pcie, of_port);
> +		if (ret)
> +			goto err_port;
> +	}
> +
> +	return 0;
> +
> +err_port:
> +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> +		reset_control_put(port->perst);
> +		list_del(&port->list);
> +	}
> +
> +	return ret;
> +}
> +
> +static int eic7700_pcie_host_init(struct dw_pcie_rp *pp)
> +{
> +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> +	struct eic7700_pcie *pcie = to_eic7700_pcie(pci);
> +	struct eic7700_pcie_port *port;
> +	u32 val;
> +	int ret;
> +
> +	ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks);
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * The PWR and DBI reset signals are respectively used to reset the
> +	 * PCIe controller and the DBI register.
> +	 *
> +	 * The PERST# signal is a reset signal that simultaneously controls the
> +	 * PCIe controller, PHY, and Endpoint. Before configuring the PHY, the
> +	 * PERST# signal must first be deasserted.
> +	 *
> +	 * The external reference clock is supplied simultaneously to the PHY
> +	 * and EP. When the PHY is configurable, the entire chip already has
> +	 * stable power and reference clock. The PHY will be ready within 20ms
> +	 * after writing app_hold_phy_rst register bit of ELBI register space.
> +	 */
> +	ret = reset_control_bulk_deassert(EIC7700_NUM_RSTS, pcie->resets);
> +	if (ret) {
> +		dev_err(pcie->pci.dev, "Failed to deassert resets\n");
> +		goto err_deassert;
> +	}
> +
> +	/* Configure Root Port type */
> +	val = readl_relaxed(pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> +	val &= ~PCIEELBI_CTRL0_DEV_TYPE;
> +	val |= FIELD_PREP(PCIEELBI_CTRL0_DEV_TYPE, PCI_EXP_TYPE_ROOT_PORT);
> +	writel_relaxed(val, pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> +
> +	list_for_each_entry(port, &pcie->ports, list) {
> +		ret = eic7700_pcie_perst_reset(port, pcie);
> +		if (ret)
> +			goto err_perst;
> +	}
> +
> +	/* Configure app_hold_phy_rst */
> +	val = readl_relaxed(pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> +	val &= ~PCIEELBI_APP_HOLD_PHY_RST;
> +	writel_relaxed(val, pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> +
> +	/* The maximum waiting time for the clock switch lock is 20ms */
> +	ret = readl_poll_timeout(pci->elbi_base + PCIEELBI_STATUS0_OFFSET, val,
> +				 !(val & PCIEELBI_PM_SEL_AUX_CLK), 1000,
> +				 20000);
> +	if (ret) {
> +		dev_err(pci->dev, "Timeout waiting for PM_SEL_AUX_CLK ready\n");
> +		goto err_phy_init;
> +	}
> +
> +	/*
> +	 * Configure ESWIN VID:DID for Root Port as the default values are
> +	 * invalid.
> +	 */
> +	dw_pcie_dbi_ro_wr_en(pci);
> +	dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, PCI_VENDOR_ID_ESWIN);
> +	dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, PCI_DEVICE_ID_ESWIN_EIC7700);
> +	dw_pcie_dbi_ro_wr_dis(pci);
> +
> +	return 0;
> +
> +err_phy_init:
> +	list_for_each_entry(port, &pcie->ports, list)
> +		reset_control_assert(port->perst);
> +err_perst:
> +	reset_control_bulk_assert(EIC7700_NUM_RSTS, pcie->resets);
> +err_deassert:
> +	clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
> +
> +	return ret;
> +}
> +
> +static void eic7700_pcie_host_deinit(struct dw_pcie_rp *pp)
> +{
> +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> +	struct eic7700_pcie *pcie = to_eic7700_pcie(pci);
> +
> +	eic7700_pcie_assert(pcie);
> +	clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
> +}
> +
> +static const struct dw_pcie_host_ops eic7700_pcie_host_ops = {
> +	.init = eic7700_pcie_host_init,
> +	.deinit = eic7700_pcie_host_deinit,
> +};
> +
> +static const struct dw_pcie_ops dw_pcie_ops = {
> +	.start_link = eic7700_pcie_start_link,
> +	.link_up = eic7700_pcie_link_up,
> +};
> +
> +static int eic7700_pcie_probe(struct platform_device *pdev)
> +{
> +	struct eic7700_pcie_port *port, *tmp;
> +	struct device *dev = &pdev->dev;
> +	struct eic7700_pcie *pcie;
> +	struct dw_pcie *pci;
> +	int ret, i;
> +
> +	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
> +	if (!pcie)
> +		return -ENOMEM;
> +
> +	INIT_LIST_HEAD(&pcie->ports);
> +
> +	pci = &pcie->pci;
> +	pci->dev = dev;
> +	pci->ops = &dw_pcie_ops;
> +	pci->pp.ops = &eic7700_pcie_host_ops;
> +
> +	pcie->num_clks = devm_clk_bulk_get_all(dev, &pcie->clks);
> +	if (pcie->num_clks < 0)
> +		return dev_err_probe(dev, pcie->num_clks,
> +				     "Failed to get pcie clocks\n");
> +
> +	for (i = 0; i < EIC7700_NUM_RSTS; i++)
> +		pcie->resets[i].id = eic7700_pcie_rsts[i];
> +
> +	ret = devm_reset_control_bulk_get_exclusive(dev, EIC7700_NUM_RSTS,
> +						    pcie->resets);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "Failed to get resets\n");
> +
> +	ret = eic7700_pcie_parse_ports(pcie);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "Failed to parse Root Port\n");
> +
> +	platform_set_drvdata(pdev, pcie);
> +
> +	pm_runtime_no_callbacks(dev);
> +	devm_pm_runtime_enable(dev);
> +	ret = pm_runtime_get_sync(dev);
> +	if (ret < 0)
> +		goto err_pm_runtime_put;
> +
> +	ret = dw_pcie_host_init(&pci->pp);
> +	if (ret) {
> +		dev_err(dev, "Failed to init host\n");
> +		goto err_pm_runtime_put;
> +	}
> +
> +	return 0;
> +
> +err_pm_runtime_put:
> +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> +		reset_control_put(port->perst);
> +		list_del(&port->list);
> +	}
> +	pm_runtime_put(dev);
> +
> +	return ret;
> +}
> +
> +static int eic7700_pcie_suspend_noirq(struct device *dev)
> +{
> +	struct eic7700_pcie *pcie = dev_get_drvdata(dev);
> +
> +	/*
> +	 * The ESWIN EIC7700 SoC lacks hardware support for the L2/L3 low-power
> +	 * link states. It cannot enter the L2/L3 Ready state through the
> +	 * PME_Turn_Off/PME_To_Ack handshake protocol. To avoid this problem,
> +	 * the dw_pcie_suspend_noirq API is not used.
> +	 */

With 7.0, you can provide a dummy pme_turn_off() API and set
'pci->pp.skip_l23_ready' to reuse the dw_pcie_{suspend/resume}_noirq APIs.

- Mani

> +	eic7700_pcie_host_deinit(&pcie->pci.pp);
> +
> +	return 0;
> +}
> +
> +static int eic7700_pcie_resume_noirq(struct device *dev)
> +{
> +	struct eic7700_pcie *pcie = dev_get_drvdata(dev);
> +	struct eic7700_pcie_port *port, *tmp;
> +	int ret;
> +
> +	ret = eic7700_pcie_host_init(&pcie->pci.pp);
> +	if (ret) {
> +		dev_err(dev, "Host init failed: %d\n", ret);
> +		goto err_init;
> +	}
> +
> +	ret = dw_pcie_setup_rc(&pcie->pci.pp);
> +	if (ret)
> +		goto err_setup_rc;
> +
> +	ret = eic7700_pcie_start_link(&pcie->pci);
> +	if (ret)
> +		goto err_setup_rc;
> +
> +	dw_pcie_wait_for_link(&pcie->pci);
> +
> +	return 0;
> +
> +err_setup_rc:
> +	eic7700_pcie_host_deinit(&pcie->pci.pp);
> +err_init:
> +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> +		reset_control_put(port->perst);
> +		list_del(&port->list);
> +	}
> +
> +	return ret;
> +}
> +
> +DEFINE_NOIRQ_DEV_PM_OPS(eic7700_pcie_pm, eic7700_pcie_suspend_noirq,
> +			eic7700_pcie_resume_noirq);
> +
> +static const struct of_device_id eic7700_pcie_of_match[] = {
> +	{ .compatible = "eswin,eic7700-pcie" },
> +	{}
> +};
> +
> +static struct platform_driver eic7700_pcie_driver = {
> +	.probe = eic7700_pcie_probe,
> +	.driver = {
> +		.name = "eic7700-pcie",
> +		.of_match_table = eic7700_pcie_of_match,
> +		.suppress_bind_attrs = true,
> +		.pm = &eic7700_pcie_pm,
> +		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
> +	},
> +};
> +builtin_platform_driver(eic7700_pcie_driver);
> +
> +MODULE_DESCRIPTION("Eswin EIC7700 PCIe host controller driver");
> +MODULE_AUTHOR("Yu Ning <ningyu@eswincomputing.com>");
> +MODULE_AUTHOR("Senchuan Zhang <zhangsenchuan@eswincomputing.com>");
> +MODULE_AUTHOR("Yanghui Ou <ouyanghui@eswincomputing.com>");
> +MODULE_LICENSE("GPL");
> -- 
> 2.25.1
> 

-- 
மணிவண்ணன் சதாசிவம்

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

* Re: Re: [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver
  2026-02-18 12:47   ` Manivannan Sadhasivam
@ 2026-02-24  8:14     ` zhangsenchuan
  2026-02-25 13:37       ` Manivannan Sadhasivam
  0 siblings, 1 reply; 17+ messages in thread
From: zhangsenchuan @ 2026-02-24  8:14 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: bhelgaas, krzk+dt, conor+dt, lpieralisi, kwilczynski, robh,
	p.zabel, linux-pci, devicetree, linux-kernel, christian.bruel,
	shradha.t, krishna.chundru, thippeswamy.havalige, inochiama,
	Frank.li, ningyu, linmin, pinkesh.vaghela, ouyanghui




> -----Original Messages-----
> From: "Manivannan Sadhasivam" <mani@kernel.org>
> Send time:Wednesday, 18/02/2026 20:47:14
> To: zhangsenchuan@eswincomputing.com
> Cc: bhelgaas@google.com, krzk+dt@kernel.org, conor+dt@kernel.org, lpieralisi@kernel.org, kwilczynski@kernel.org, robh@kernel.org, p.zabel@pengutronix.de, linux-pci@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, christian.bruel@foss.st.com, shradha.t@samsung.com, krishna.chundru@oss.qualcomm.com, thippeswamy.havalige@amd.com, inochiama@gmail.com, Frank.li@nxp.com, ningyu@eswincomputing.com, linmin@eswincomputing.com, pinkesh.vaghela@einfochips.com, ouyanghui@eswincomputing.com
> Subject: Re: [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver
> 
> On Thu, Jan 29, 2026 at 05:29:00PM +0800, zhangsenchuan@eswincomputing.com wrote:
> > From: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
> > 
> > Add driver for the Eswin EIC7700 PCIe host controller, which is based on
> > the DesignWare PCIe core, IP revision 5.96a. The PCIe Gen.3 controller
> > supports a data rate of 8 GT/s and 4 channels, support INTx and MSI
> > interrupts.
> > 
> > Signed-off-by: Yu Ning <ningyu@eswincomputing.com>
> > Signed-off-by: Yanghui Ou <ouyanghui@eswincomputing.com>
> > Signed-off-by: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
> > ---
> >  drivers/pci/controller/dwc/Kconfig        |  11 +
> >  drivers/pci/controller/dwc/Makefile       |   1 +
> >  drivers/pci/controller/dwc/pcie-eic7700.c | 410 ++++++++++++++++++++++
> >  3 files changed, 422 insertions(+)
> >  create mode 100644 drivers/pci/controller/dwc/pcie-eic7700.c
> > 
> > diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
> > index 519b59422b47..c837cb5947b6 100644
> > --- a/drivers/pci/controller/dwc/Kconfig
> > +++ b/drivers/pci/controller/dwc/Kconfig
> > @@ -93,6 +93,17 @@ config PCIE_BT1
> >  	  Enables support for the PCIe controller in the Baikal-T1 SoC to work
> >  	  in host mode. It's based on the Synopsys DWC PCIe v4.60a IP-core.
> >  
> > +config PCIE_EIC7700
> > +	tristate "Eswin EIC7700 PCIe controller"
> > +	depends on ARCH_ESWIN || COMPILE_TEST
> > +	depends on PCI_MSI
> > +	select PCIE_DW_HOST
> > +	help
> > +	  Say Y here if you want PCIe controller support for the Eswin EIC7700.
> > +	  The PCIe controller on EIC7700 is based on DesignWare hardware,
> > +	  enables support for the PCIe controller in the EIC7700 SoC to work in
> > +	  host mode.
> > +
> >  config PCI_IMX6
> >  	bool
> >  
> > diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
> > index 67ba59c02038..7c5a5186ea83 100644
> > --- a/drivers/pci/controller/dwc/Makefile
> > +++ b/drivers/pci/controller/dwc/Makefile
> > @@ -6,6 +6,7 @@ obj-$(CONFIG_PCIE_DW_EP) += pcie-designware-ep.o
> >  obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o
> >  obj-$(CONFIG_PCIE_AMD_MDB) += pcie-amd-mdb.o
> >  obj-$(CONFIG_PCIE_BT1) += pcie-bt1.o
> > +obj-$(CONFIG_PCIE_EIC7700) += pcie-eic7700.o
> >  obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
> >  obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
> >  obj-$(CONFIG_PCIE_FU740) += pcie-fu740.o
> > diff --git a/drivers/pci/controller/dwc/pcie-eic7700.c b/drivers/pci/controller/dwc/pcie-eic7700.c
> > new file mode 100644
> > index 000000000000..dab8e3b98810
> > --- /dev/null
> > +++ b/drivers/pci/controller/dwc/pcie-eic7700.c
> > @@ -0,0 +1,410 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * ESWIN EIC7700 PCIe root complex driver
> > + *
> > + * Copyright 2026, Beijing ESWIN Computing Technology Co., Ltd.
> > + *
> > + * Authors: Yu Ning <ningyu@eswincomputing.com>
> > + *          Senchuan Zhang <zhangsenchuan@eswincomputing.com>
> > + *          Yanghui Ou <ouyanghui@eswincomputing.com>
> > + */
> > +
> > +#include <linux/interrupt.h>
> > +#include <linux/iopoll.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/pci.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/pm_runtime.h>
> > +#include <linux/resource.h>
> > +#include <linux/reset.h>
> > +#include <linux/types.h>
> > +
> > +#include "pcie-designware.h"
> > +
> > +/* ELBI registers */
> > +#define PCIEELBI_CTRL0_OFFSET		0x0
> > +#define PCIEELBI_STATUS0_OFFSET		0x100
> > +
> > +/* LTSSM register fields */
> > +#define PCIEELBI_APP_LTSSM_ENABLE	BIT(5)
> > +
> > +/* APP_HOLD_PHY_RST register fields */
> > +#define PCIEELBI_APP_HOLD_PHY_RST	BIT(6)
> > +
> > +/* PM_SEL_AUX_CLK register fields */
> > +#define PCIEELBI_PM_SEL_AUX_CLK		BIT(16)
> > +
> > +/* DEV_TYPE register fields */
> > +#define PCIEELBI_CTRL0_DEV_TYPE		GENMASK(3, 0)
> > +
> > +/* Vendor and device ID value */
> > +#define PCI_VENDOR_ID_ESWIN		0x1fe1
> > +#define PCI_DEVICE_ID_ESWIN_EIC7700	0x2030
> > +
> > +#define EIC7700_NUM_RSTS		ARRAY_SIZE(eic7700_pcie_rsts)
> > +
> > +static const char * const eic7700_pcie_rsts[] = {
> > +	"pwr",
> > +	"dbi",
> > +};
> > +
> > +struct eic7700_pcie_port {
> > +	struct list_head list;
> > +	struct reset_control *perst;
> > +	int num_lanes;
> > +};
> > +
> > +struct eic7700_pcie {
> > +	struct dw_pcie pci;
> > +	struct clk_bulk_data *clks;
> > +	struct reset_control_bulk_data resets[EIC7700_NUM_RSTS];
> > +	struct list_head ports;
> > +	int num_clks;
> > +};
> > +
> > +#define to_eic7700_pcie(x) dev_get_drvdata((x)->dev)
> > +
> > +static int eic7700_pcie_start_link(struct dw_pcie *pci)
> > +{
> > +	u32 val;
> > +
> > +	/* Enable LTSSM */
> > +	val = readl_relaxed(pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> > +	val |= PCIEELBI_APP_LTSSM_ENABLE;
> > +	writel_relaxed(val, pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> > +
> > +	return 0;
> > +}
> > +
> > +static bool eic7700_pcie_link_up(struct dw_pcie *pci)
> > +{
> > +	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
> > +	u16 val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
> > +
> > +	return val & PCI_EXP_LNKSTA_DLLLA;
> > +}
> > +
> > +static int eic7700_pcie_perst_reset(struct eic7700_pcie_port *port,
> > +				    struct eic7700_pcie *pcie)
> > +{
> > +	int ret;
> > +
> > +	ret = reset_control_assert(port->perst);
> > +	if (ret) {
> > +		dev_err(pcie->pci.dev, "Failed to assert PERST#\n");
> > +		return ret;
> > +	}
> > +
> > +	/* Ensure that PERST# has been asserted for at least 100 ms */
> > +	msleep(PCIE_T_PVPERL_MS);
> > +
> > +	ret = reset_control_deassert(port->perst);
> > +	if (ret) {
> > +		dev_err(pcie->pci.dev, "Failed to deassert PERST#\n");
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static void eic7700_pcie_assert(struct eic7700_pcie *pcie)
> > +{
> > +	struct eic7700_pcie_port *port;
> > +
> > +	list_for_each_entry(port, &pcie->ports, list)
> > +		reset_control_assert(port->perst);
> > +	reset_control_bulk_assert(EIC7700_NUM_RSTS, pcie->resets);
> > +}
> > +
> > +static int eic7700_pcie_parse_port(struct eic7700_pcie *pcie,
> > +				   struct device_node *node)
> > +{
> > +	struct device *dev = pcie->pci.dev;
> > +	struct eic7700_pcie_port *port;
> > +
> > +	port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
> > +	if (!port)
> > +		return -ENOMEM;
> > +
> > +	port->perst = of_reset_control_get_exclusive(node, "perst");
> > +	if (IS_ERR(port->perst)) {
> > +		dev_err(dev, "Failed to get PERST# reset\n");
> > +		return PTR_ERR(port->perst);
> > +	}
> > +
> > +	/*
> > +	 * TODO: Since the Root Port node is separated out by pcie devicetree,
> > +	 * the DWC core initialization code can't parse the num-lanes attribute
> > +	 * in the Root Port. Before entering the DWC core initialization code,
> > +	 * the platform driver code parses the Root Port node. The EIC7700 only
> > +	 * supports one Root Port node, and the num-lanes attribute is suitable
> > +	 * for the case of one Root Port.
> > +	 */
> > +	if (!of_property_read_u32(node, "num-lanes", &port->num_lanes))
> > +		pcie->pci.num_lanes = port->num_lanes;
> > +
> > +	INIT_LIST_HEAD(&port->list);
> > +	list_add_tail(&port->list, &pcie->ports);
> > +
> > +	return 0;
> > +}
> > +
> > +static int eic7700_pcie_parse_ports(struct eic7700_pcie *pcie)
> > +{
> > +	struct eic7700_pcie_port *port, *tmp;
> > +	struct device *dev = pcie->pci.dev;
> > +	int ret;
> > +
> > +	for_each_available_child_of_node_scoped(dev->of_node, of_port) {
> > +		ret = eic7700_pcie_parse_port(pcie, of_port);
> > +		if (ret)
> > +			goto err_port;
> > +	}
> > +
> > +	return 0;
> > +
> > +err_port:
> > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > +		reset_control_put(port->perst);
> > +		list_del(&port->list);
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +static int eic7700_pcie_host_init(struct dw_pcie_rp *pp)
> > +{
> > +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > +	struct eic7700_pcie *pcie = to_eic7700_pcie(pci);
> > +	struct eic7700_pcie_port *port;
> > +	u32 val;
> > +	int ret;
> > +
> > +	ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks);
> > +	if (ret)
> > +		return ret;
> > +
> > +	/*
> > +	 * The PWR and DBI reset signals are respectively used to reset the
> > +	 * PCIe controller and the DBI register.
> > +	 *
> > +	 * The PERST# signal is a reset signal that simultaneously controls the
> > +	 * PCIe controller, PHY, and Endpoint. Before configuring the PHY, the
> > +	 * PERST# signal must first be deasserted.
> > +	 *
> > +	 * The external reference clock is supplied simultaneously to the PHY
> > +	 * and EP. When the PHY is configurable, the entire chip already has
> > +	 * stable power and reference clock. The PHY will be ready within 20ms
> > +	 * after writing app_hold_phy_rst register bit of ELBI register space.
> > +	 */
> > +	ret = reset_control_bulk_deassert(EIC7700_NUM_RSTS, pcie->resets);
> > +	if (ret) {
> > +		dev_err(pcie->pci.dev, "Failed to deassert resets\n");
> > +		goto err_deassert;
> > +	}
> > +
> > +	/* Configure Root Port type */
> > +	val = readl_relaxed(pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> > +	val &= ~PCIEELBI_CTRL0_DEV_TYPE;
> > +	val |= FIELD_PREP(PCIEELBI_CTRL0_DEV_TYPE, PCI_EXP_TYPE_ROOT_PORT);
> > +	writel_relaxed(val, pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> > +
> > +	list_for_each_entry(port, &pcie->ports, list) {
> > +		ret = eic7700_pcie_perst_reset(port, pcie);
> > +		if (ret)
> > +			goto err_perst;
> > +	}
> > +
> > +	/* Configure app_hold_phy_rst */
> > +	val = readl_relaxed(pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> > +	val &= ~PCIEELBI_APP_HOLD_PHY_RST;
> > +	writel_relaxed(val, pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> > +
> > +	/* The maximum waiting time for the clock switch lock is 20ms */
> > +	ret = readl_poll_timeout(pci->elbi_base + PCIEELBI_STATUS0_OFFSET, val,
> > +				 !(val & PCIEELBI_PM_SEL_AUX_CLK), 1000,
> > +				 20000);
> > +	if (ret) {
> > +		dev_err(pci->dev, "Timeout waiting for PM_SEL_AUX_CLK ready\n");
> > +		goto err_phy_init;
> > +	}
> > +
> > +	/*
> > +	 * Configure ESWIN VID:DID for Root Port as the default values are
> > +	 * invalid.
> > +	 */
> > +	dw_pcie_dbi_ro_wr_en(pci);
> > +	dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, PCI_VENDOR_ID_ESWIN);
> > +	dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, PCI_DEVICE_ID_ESWIN_EIC7700);
> > +	dw_pcie_dbi_ro_wr_dis(pci);
> > +
> > +	return 0;
> > +
> > +err_phy_init:
> > +	list_for_each_entry(port, &pcie->ports, list)
> > +		reset_control_assert(port->perst);
> > +err_perst:
> > +	reset_control_bulk_assert(EIC7700_NUM_RSTS, pcie->resets);
> > +err_deassert:
> > +	clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
> > +
> > +	return ret;
> > +}
> > +
> > +static void eic7700_pcie_host_deinit(struct dw_pcie_rp *pp)
> > +{
> > +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > +	struct eic7700_pcie *pcie = to_eic7700_pcie(pci);
> > +
> > +	eic7700_pcie_assert(pcie);
> > +	clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
> > +}
> > +
> > +static const struct dw_pcie_host_ops eic7700_pcie_host_ops = {
> > +	.init = eic7700_pcie_host_init,
> > +	.deinit = eic7700_pcie_host_deinit,
> > +};
> > +
> > +static const struct dw_pcie_ops dw_pcie_ops = {
> > +	.start_link = eic7700_pcie_start_link,
> > +	.link_up = eic7700_pcie_link_up,
> > +};
> > +
> > +static int eic7700_pcie_probe(struct platform_device *pdev)
> > +{
> > +	struct eic7700_pcie_port *port, *tmp;
> > +	struct device *dev = &pdev->dev;
> > +	struct eic7700_pcie *pcie;
> > +	struct dw_pcie *pci;
> > +	int ret, i;
> > +
> > +	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
> > +	if (!pcie)
> > +		return -ENOMEM;
> > +
> > +	INIT_LIST_HEAD(&pcie->ports);
> > +
> > +	pci = &pcie->pci;
> > +	pci->dev = dev;
> > +	pci->ops = &dw_pcie_ops;
> > +	pci->pp.ops = &eic7700_pcie_host_ops;
> > +
> > +	pcie->num_clks = devm_clk_bulk_get_all(dev, &pcie->clks);
> > +	if (pcie->num_clks < 0)
> > +		return dev_err_probe(dev, pcie->num_clks,
> > +				     "Failed to get pcie clocks\n");
> > +
> > +	for (i = 0; i < EIC7700_NUM_RSTS; i++)
> > +		pcie->resets[i].id = eic7700_pcie_rsts[i];
> > +
> > +	ret = devm_reset_control_bulk_get_exclusive(dev, EIC7700_NUM_RSTS,
> > +						    pcie->resets);
> > +	if (ret)
> > +		return dev_err_probe(dev, ret, "Failed to get resets\n");
> > +
> > +	ret = eic7700_pcie_parse_ports(pcie);
> > +	if (ret)
> > +		return dev_err_probe(dev, ret, "Failed to parse Root Port\n");
> > +
> > +	platform_set_drvdata(pdev, pcie);
> > +
> > +	pm_runtime_no_callbacks(dev);
> > +	devm_pm_runtime_enable(dev);
> > +	ret = pm_runtime_get_sync(dev);
> > +	if (ret < 0)
> > +		goto err_pm_runtime_put;
> > +
> > +	ret = dw_pcie_host_init(&pci->pp);
> > +	if (ret) {
> > +		dev_err(dev, "Failed to init host\n");
> > +		goto err_pm_runtime_put;
> > +	}
> > +
> > +	return 0;
> > +
> > +err_pm_runtime_put:
> > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > +		reset_control_put(port->perst);
> > +		list_del(&port->list);
> > +	}
> > +	pm_runtime_put(dev);
> > +
> > +	return ret;
> > +}
> > +
> > +static int eic7700_pcie_suspend_noirq(struct device *dev)
> > +{
> > +	struct eic7700_pcie *pcie = dev_get_drvdata(dev);
> > +
> > +	/*
> > +	 * The ESWIN EIC7700 SoC lacks hardware support for the L2/L3 low-power
> > +	 * link states. It cannot enter the L2/L3 Ready state through the
> > +	 * PME_Turn_Off/PME_To_Ack handshake protocol. To avoid this problem,
> > +	 * the dw_pcie_suspend_noirq API is not used.
> > +	 */
> 
> With 7.0, you can provide a dummy pme_turn_off() API and set
> 'pci->pp.skip_l23_ready' to reuse the dw_pcie_{suspend/resume}_noirq APIs.
> 

Hi Mani,

Setting pci->pp.skip_l23_ready does indeed allow us to reuse the
dw_pcie_suspend_noirq function. However, for the dw_pcie_resume_noirq
function, if the dw_pcie_start_link and dw_pcie_wait_for_link APIs fail to
execute, the clk/reset resources in the pci->pp.ops->init function cannot
be released. Perhaps the dw_pcie_resume_noirq function needs to be optimized.
I have observed that in the current imx6 case, the clk resources cannot be
released either. If qcom and other manufacturers later switch to using the
dw_pcie_resume_noirq function, they will also encounter this problem.
At present, it seems that implementing the suspend/resume functions by myself
is a bit more convenient.

Kind regards,
Senchuan

> 
> > +	eic7700_pcie_host_deinit(&pcie->pci.pp);
> > +
> > +	return 0;
> > +}
> > +
> > +static int eic7700_pcie_resume_noirq(struct device *dev)
> > +{
> > +	struct eic7700_pcie *pcie = dev_get_drvdata(dev);
> > +	struct eic7700_pcie_port *port, *tmp;
> > +	int ret;
> > +
> > +	ret = eic7700_pcie_host_init(&pcie->pci.pp);
> > +	if (ret) {
> > +		dev_err(dev, "Host init failed: %d\n", ret);
> > +		goto err_init;
> > +	}
> > +
> > +	ret = dw_pcie_setup_rc(&pcie->pci.pp);
> > +	if (ret)
> > +		goto err_setup_rc;
> > +
> > +	ret = eic7700_pcie_start_link(&pcie->pci);
> > +	if (ret)
> > +		goto err_setup_rc;
> > +
> > +	dw_pcie_wait_for_link(&pcie->pci);
> > +
> > +	return 0;
> > +
> > +err_setup_rc:
> > +	eic7700_pcie_host_deinit(&pcie->pci.pp);
> > +err_init:
> > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > +		reset_control_put(port->perst);
> > +		list_del(&port->list);
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +DEFINE_NOIRQ_DEV_PM_OPS(eic7700_pcie_pm, eic7700_pcie_suspend_noirq,
> > +			eic7700_pcie_resume_noirq);
> > +
> > +static const struct of_device_id eic7700_pcie_of_match[] = {
> > +	{ .compatible = "eswin,eic7700-pcie" },
> > +	{}
> > +};
> > +
> > +static struct platform_driver eic7700_pcie_driver = {
> > +	.probe = eic7700_pcie_probe,
> > +	.driver = {
> > +		.name = "eic7700-pcie",
> > +		.of_match_table = eic7700_pcie_of_match,
> > +		.suppress_bind_attrs = true,
> > +		.pm = &eic7700_pcie_pm,
> > +		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
> > +	},
> > +};
> > +builtin_platform_driver(eic7700_pcie_driver);
> > +
> > +MODULE_DESCRIPTION("Eswin EIC7700 PCIe host controller driver");
> > +MODULE_AUTHOR("Yu Ning <ningyu@eswincomputing.com>");
> > +MODULE_AUTHOR("Senchuan Zhang <zhangsenchuan@eswincomputing.com>");
> > +MODULE_AUTHOR("Yanghui Ou <ouyanghui@eswincomputing.com>");
> > +MODULE_LICENSE("GPL");
> > -- 
> > 2.25.1
> > 
> 
> -- 
> மணிவண்ணன் சதாசிவம்

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

* Re: [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver
  2026-02-24  8:14     ` zhangsenchuan
@ 2026-02-25 13:37       ` Manivannan Sadhasivam
  2026-02-26  8:09         ` zhangsenchuan
  0 siblings, 1 reply; 17+ messages in thread
From: Manivannan Sadhasivam @ 2026-02-25 13:37 UTC (permalink / raw)
  To: zhangsenchuan
  Cc: bhelgaas, krzk+dt, conor+dt, lpieralisi, kwilczynski, robh,
	p.zabel, linux-pci, devicetree, linux-kernel, christian.bruel,
	shradha.t, krishna.chundru, thippeswamy.havalige, inochiama,
	Frank.li, ningyu, linmin, pinkesh.vaghela, ouyanghui

On Tue, Feb 24, 2026 at 04:14:16PM +0800, zhangsenchuan wrote:
> 
> 
> 
> > -----Original Messages-----
> > From: "Manivannan Sadhasivam" <mani@kernel.org>
> > Send time:Wednesday, 18/02/2026 20:47:14
> > To: zhangsenchuan@eswincomputing.com
> > Cc: bhelgaas@google.com, krzk+dt@kernel.org, conor+dt@kernel.org, lpieralisi@kernel.org, kwilczynski@kernel.org, robh@kernel.org, p.zabel@pengutronix.de, linux-pci@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, christian.bruel@foss.st.com, shradha.t@samsung.com, krishna.chundru@oss.qualcomm.com, thippeswamy.havalige@amd.com, inochiama@gmail.com, Frank.li@nxp.com, ningyu@eswincomputing.com, linmin@eswincomputing.com, pinkesh.vaghela@einfochips.com, ouyanghui@eswincomputing.com
> > Subject: Re: [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver
> > 
> > On Thu, Jan 29, 2026 at 05:29:00PM +0800, zhangsenchuan@eswincomputing.com wrote:
> > > From: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
> > > 
> > > Add driver for the Eswin EIC7700 PCIe host controller, which is based on
> > > the DesignWare PCIe core, IP revision 5.96a. The PCIe Gen.3 controller
> > > supports a data rate of 8 GT/s and 4 channels, support INTx and MSI
> > > interrupts.
> > > 
> > > Signed-off-by: Yu Ning <ningyu@eswincomputing.com>
> > > Signed-off-by: Yanghui Ou <ouyanghui@eswincomputing.com>
> > > Signed-off-by: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
> > > ---
> > >  drivers/pci/controller/dwc/Kconfig        |  11 +
> > >  drivers/pci/controller/dwc/Makefile       |   1 +
> > >  drivers/pci/controller/dwc/pcie-eic7700.c | 410 ++++++++++++++++++++++
> > >  3 files changed, 422 insertions(+)
> > >  create mode 100644 drivers/pci/controller/dwc/pcie-eic7700.c
> > > 
> > > diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
> > > index 519b59422b47..c837cb5947b6 100644
> > > --- a/drivers/pci/controller/dwc/Kconfig
> > > +++ b/drivers/pci/controller/dwc/Kconfig
> > > @@ -93,6 +93,17 @@ config PCIE_BT1
> > >  	  Enables support for the PCIe controller in the Baikal-T1 SoC to work
> > >  	  in host mode. It's based on the Synopsys DWC PCIe v4.60a IP-core.
> > >  
> > > +config PCIE_EIC7700
> > > +	tristate "Eswin EIC7700 PCIe controller"
> > > +	depends on ARCH_ESWIN || COMPILE_TEST
> > > +	depends on PCI_MSI
> > > +	select PCIE_DW_HOST
> > > +	help
> > > +	  Say Y here if you want PCIe controller support for the Eswin EIC7700.
> > > +	  The PCIe controller on EIC7700 is based on DesignWare hardware,
> > > +	  enables support for the PCIe controller in the EIC7700 SoC to work in
> > > +	  host mode.
> > > +
> > >  config PCI_IMX6
> > >  	bool
> > >  
> > > diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
> > > index 67ba59c02038..7c5a5186ea83 100644
> > > --- a/drivers/pci/controller/dwc/Makefile
> > > +++ b/drivers/pci/controller/dwc/Makefile
> > > @@ -6,6 +6,7 @@ obj-$(CONFIG_PCIE_DW_EP) += pcie-designware-ep.o
> > >  obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o
> > >  obj-$(CONFIG_PCIE_AMD_MDB) += pcie-amd-mdb.o
> > >  obj-$(CONFIG_PCIE_BT1) += pcie-bt1.o
> > > +obj-$(CONFIG_PCIE_EIC7700) += pcie-eic7700.o
> > >  obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
> > >  obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
> > >  obj-$(CONFIG_PCIE_FU740) += pcie-fu740.o
> > > diff --git a/drivers/pci/controller/dwc/pcie-eic7700.c b/drivers/pci/controller/dwc/pcie-eic7700.c
> > > new file mode 100644
> > > index 000000000000..dab8e3b98810
> > > --- /dev/null
> > > +++ b/drivers/pci/controller/dwc/pcie-eic7700.c
> > > @@ -0,0 +1,410 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * ESWIN EIC7700 PCIe root complex driver
> > > + *
> > > + * Copyright 2026, Beijing ESWIN Computing Technology Co., Ltd.
> > > + *
> > > + * Authors: Yu Ning <ningyu@eswincomputing.com>
> > > + *          Senchuan Zhang <zhangsenchuan@eswincomputing.com>
> > > + *          Yanghui Ou <ouyanghui@eswincomputing.com>
> > > + */
> > > +
> > > +#include <linux/interrupt.h>
> > > +#include <linux/iopoll.h>
> > > +#include <linux/module.h>
> > > +#include <linux/of.h>
> > > +#include <linux/pci.h>
> > > +#include <linux/platform_device.h>
> > > +#include <linux/pm_runtime.h>
> > > +#include <linux/resource.h>
> > > +#include <linux/reset.h>
> > > +#include <linux/types.h>
> > > +
> > > +#include "pcie-designware.h"
> > > +
> > > +/* ELBI registers */
> > > +#define PCIEELBI_CTRL0_OFFSET		0x0
> > > +#define PCIEELBI_STATUS0_OFFSET		0x100
> > > +
> > > +/* LTSSM register fields */
> > > +#define PCIEELBI_APP_LTSSM_ENABLE	BIT(5)
> > > +
> > > +/* APP_HOLD_PHY_RST register fields */
> > > +#define PCIEELBI_APP_HOLD_PHY_RST	BIT(6)
> > > +
> > > +/* PM_SEL_AUX_CLK register fields */
> > > +#define PCIEELBI_PM_SEL_AUX_CLK		BIT(16)
> > > +
> > > +/* DEV_TYPE register fields */
> > > +#define PCIEELBI_CTRL0_DEV_TYPE		GENMASK(3, 0)
> > > +
> > > +/* Vendor and device ID value */
> > > +#define PCI_VENDOR_ID_ESWIN		0x1fe1
> > > +#define PCI_DEVICE_ID_ESWIN_EIC7700	0x2030
> > > +
> > > +#define EIC7700_NUM_RSTS		ARRAY_SIZE(eic7700_pcie_rsts)
> > > +
> > > +static const char * const eic7700_pcie_rsts[] = {
> > > +	"pwr",
> > > +	"dbi",
> > > +};
> > > +
> > > +struct eic7700_pcie_port {
> > > +	struct list_head list;
> > > +	struct reset_control *perst;
> > > +	int num_lanes;
> > > +};
> > > +
> > > +struct eic7700_pcie {
> > > +	struct dw_pcie pci;
> > > +	struct clk_bulk_data *clks;
> > > +	struct reset_control_bulk_data resets[EIC7700_NUM_RSTS];
> > > +	struct list_head ports;
> > > +	int num_clks;
> > > +};
> > > +
> > > +#define to_eic7700_pcie(x) dev_get_drvdata((x)->dev)
> > > +
> > > +static int eic7700_pcie_start_link(struct dw_pcie *pci)
> > > +{
> > > +	u32 val;
> > > +
> > > +	/* Enable LTSSM */
> > > +	val = readl_relaxed(pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> > > +	val |= PCIEELBI_APP_LTSSM_ENABLE;
> > > +	writel_relaxed(val, pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static bool eic7700_pcie_link_up(struct dw_pcie *pci)
> > > +{
> > > +	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
> > > +	u16 val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
> > > +
> > > +	return val & PCI_EXP_LNKSTA_DLLLA;
> > > +}
> > > +
> > > +static int eic7700_pcie_perst_reset(struct eic7700_pcie_port *port,
> > > +				    struct eic7700_pcie *pcie)
> > > +{
> > > +	int ret;
> > > +
> > > +	ret = reset_control_assert(port->perst);
> > > +	if (ret) {
> > > +		dev_err(pcie->pci.dev, "Failed to assert PERST#\n");
> > > +		return ret;
> > > +	}
> > > +
> > > +	/* Ensure that PERST# has been asserted for at least 100 ms */
> > > +	msleep(PCIE_T_PVPERL_MS);
> > > +
> > > +	ret = reset_control_deassert(port->perst);
> > > +	if (ret) {
> > > +		dev_err(pcie->pci.dev, "Failed to deassert PERST#\n");
> > > +		return ret;
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static void eic7700_pcie_assert(struct eic7700_pcie *pcie)
> > > +{
> > > +	struct eic7700_pcie_port *port;
> > > +
> > > +	list_for_each_entry(port, &pcie->ports, list)
> > > +		reset_control_assert(port->perst);
> > > +	reset_control_bulk_assert(EIC7700_NUM_RSTS, pcie->resets);
> > > +}
> > > +
> > > +static int eic7700_pcie_parse_port(struct eic7700_pcie *pcie,
> > > +				   struct device_node *node)
> > > +{
> > > +	struct device *dev = pcie->pci.dev;
> > > +	struct eic7700_pcie_port *port;
> > > +
> > > +	port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
> > > +	if (!port)
> > > +		return -ENOMEM;
> > > +
> > > +	port->perst = of_reset_control_get_exclusive(node, "perst");
> > > +	if (IS_ERR(port->perst)) {
> > > +		dev_err(dev, "Failed to get PERST# reset\n");
> > > +		return PTR_ERR(port->perst);
> > > +	}
> > > +
> > > +	/*
> > > +	 * TODO: Since the Root Port node is separated out by pcie devicetree,
> > > +	 * the DWC core initialization code can't parse the num-lanes attribute
> > > +	 * in the Root Port. Before entering the DWC core initialization code,
> > > +	 * the platform driver code parses the Root Port node. The EIC7700 only
> > > +	 * supports one Root Port node, and the num-lanes attribute is suitable
> > > +	 * for the case of one Root Port.
> > > +	 */
> > > +	if (!of_property_read_u32(node, "num-lanes", &port->num_lanes))
> > > +		pcie->pci.num_lanes = port->num_lanes;
> > > +
> > > +	INIT_LIST_HEAD(&port->list);
> > > +	list_add_tail(&port->list, &pcie->ports);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static int eic7700_pcie_parse_ports(struct eic7700_pcie *pcie)
> > > +{
> > > +	struct eic7700_pcie_port *port, *tmp;
> > > +	struct device *dev = pcie->pci.dev;
> > > +	int ret;
> > > +
> > > +	for_each_available_child_of_node_scoped(dev->of_node, of_port) {
> > > +		ret = eic7700_pcie_parse_port(pcie, of_port);
> > > +		if (ret)
> > > +			goto err_port;
> > > +	}
> > > +
> > > +	return 0;
> > > +
> > > +err_port:
> > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > +		reset_control_put(port->perst);
> > > +		list_del(&port->list);
> > > +	}
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static int eic7700_pcie_host_init(struct dw_pcie_rp *pp)
> > > +{
> > > +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > > +	struct eic7700_pcie *pcie = to_eic7700_pcie(pci);
> > > +	struct eic7700_pcie_port *port;
> > > +	u32 val;
> > > +	int ret;
> > > +
> > > +	ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > > +	/*
> > > +	 * The PWR and DBI reset signals are respectively used to reset the
> > > +	 * PCIe controller and the DBI register.
> > > +	 *
> > > +	 * The PERST# signal is a reset signal that simultaneously controls the
> > > +	 * PCIe controller, PHY, and Endpoint. Before configuring the PHY, the
> > > +	 * PERST# signal must first be deasserted.
> > > +	 *
> > > +	 * The external reference clock is supplied simultaneously to the PHY
> > > +	 * and EP. When the PHY is configurable, the entire chip already has
> > > +	 * stable power and reference clock. The PHY will be ready within 20ms
> > > +	 * after writing app_hold_phy_rst register bit of ELBI register space.
> > > +	 */
> > > +	ret = reset_control_bulk_deassert(EIC7700_NUM_RSTS, pcie->resets);
> > > +	if (ret) {
> > > +		dev_err(pcie->pci.dev, "Failed to deassert resets\n");
> > > +		goto err_deassert;
> > > +	}
> > > +
> > > +	/* Configure Root Port type */
> > > +	val = readl_relaxed(pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> > > +	val &= ~PCIEELBI_CTRL0_DEV_TYPE;
> > > +	val |= FIELD_PREP(PCIEELBI_CTRL0_DEV_TYPE, PCI_EXP_TYPE_ROOT_PORT);
> > > +	writel_relaxed(val, pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> > > +
> > > +	list_for_each_entry(port, &pcie->ports, list) {
> > > +		ret = eic7700_pcie_perst_reset(port, pcie);
> > > +		if (ret)
> > > +			goto err_perst;
> > > +	}
> > > +
> > > +	/* Configure app_hold_phy_rst */
> > > +	val = readl_relaxed(pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> > > +	val &= ~PCIEELBI_APP_HOLD_PHY_RST;
> > > +	writel_relaxed(val, pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
> > > +
> > > +	/* The maximum waiting time for the clock switch lock is 20ms */
> > > +	ret = readl_poll_timeout(pci->elbi_base + PCIEELBI_STATUS0_OFFSET, val,
> > > +				 !(val & PCIEELBI_PM_SEL_AUX_CLK), 1000,
> > > +				 20000);
> > > +	if (ret) {
> > > +		dev_err(pci->dev, "Timeout waiting for PM_SEL_AUX_CLK ready\n");
> > > +		goto err_phy_init;
> > > +	}
> > > +
> > > +	/*
> > > +	 * Configure ESWIN VID:DID for Root Port as the default values are
> > > +	 * invalid.
> > > +	 */
> > > +	dw_pcie_dbi_ro_wr_en(pci);
> > > +	dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, PCI_VENDOR_ID_ESWIN);
> > > +	dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, PCI_DEVICE_ID_ESWIN_EIC7700);
> > > +	dw_pcie_dbi_ro_wr_dis(pci);
> > > +
> > > +	return 0;
> > > +
> > > +err_phy_init:
> > > +	list_for_each_entry(port, &pcie->ports, list)
> > > +		reset_control_assert(port->perst);
> > > +err_perst:
> > > +	reset_control_bulk_assert(EIC7700_NUM_RSTS, pcie->resets);
> > > +err_deassert:
> > > +	clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static void eic7700_pcie_host_deinit(struct dw_pcie_rp *pp)
> > > +{
> > > +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > > +	struct eic7700_pcie *pcie = to_eic7700_pcie(pci);
> > > +
> > > +	eic7700_pcie_assert(pcie);
> > > +	clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
> > > +}
> > > +
> > > +static const struct dw_pcie_host_ops eic7700_pcie_host_ops = {
> > > +	.init = eic7700_pcie_host_init,
> > > +	.deinit = eic7700_pcie_host_deinit,
> > > +};
> > > +
> > > +static const struct dw_pcie_ops dw_pcie_ops = {
> > > +	.start_link = eic7700_pcie_start_link,
> > > +	.link_up = eic7700_pcie_link_up,
> > > +};
> > > +
> > > +static int eic7700_pcie_probe(struct platform_device *pdev)
> > > +{
> > > +	struct eic7700_pcie_port *port, *tmp;
> > > +	struct device *dev = &pdev->dev;
> > > +	struct eic7700_pcie *pcie;
> > > +	struct dw_pcie *pci;
> > > +	int ret, i;
> > > +
> > > +	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
> > > +	if (!pcie)
> > > +		return -ENOMEM;
> > > +
> > > +	INIT_LIST_HEAD(&pcie->ports);
> > > +
> > > +	pci = &pcie->pci;
> > > +	pci->dev = dev;
> > > +	pci->ops = &dw_pcie_ops;
> > > +	pci->pp.ops = &eic7700_pcie_host_ops;
> > > +
> > > +	pcie->num_clks = devm_clk_bulk_get_all(dev, &pcie->clks);
> > > +	if (pcie->num_clks < 0)
> > > +		return dev_err_probe(dev, pcie->num_clks,
> > > +				     "Failed to get pcie clocks\n");
> > > +
> > > +	for (i = 0; i < EIC7700_NUM_RSTS; i++)
> > > +		pcie->resets[i].id = eic7700_pcie_rsts[i];
> > > +
> > > +	ret = devm_reset_control_bulk_get_exclusive(dev, EIC7700_NUM_RSTS,
> > > +						    pcie->resets);
> > > +	if (ret)
> > > +		return dev_err_probe(dev, ret, "Failed to get resets\n");
> > > +
> > > +	ret = eic7700_pcie_parse_ports(pcie);
> > > +	if (ret)
> > > +		return dev_err_probe(dev, ret, "Failed to parse Root Port\n");
> > > +
> > > +	platform_set_drvdata(pdev, pcie);
> > > +
> > > +	pm_runtime_no_callbacks(dev);
> > > +	devm_pm_runtime_enable(dev);
> > > +	ret = pm_runtime_get_sync(dev);
> > > +	if (ret < 0)
> > > +		goto err_pm_runtime_put;
> > > +
> > > +	ret = dw_pcie_host_init(&pci->pp);
> > > +	if (ret) {
> > > +		dev_err(dev, "Failed to init host\n");
> > > +		goto err_pm_runtime_put;
> > > +	}
> > > +
> > > +	return 0;
> > > +
> > > +err_pm_runtime_put:
> > > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > > +		reset_control_put(port->perst);
> > > +		list_del(&port->list);
> > > +	}
> > > +	pm_runtime_put(dev);
> > > +
> > > +	return ret;
> > > +}
> > > +
> > > +static int eic7700_pcie_suspend_noirq(struct device *dev)
> > > +{
> > > +	struct eic7700_pcie *pcie = dev_get_drvdata(dev);
> > > +
> > > +	/*
> > > +	 * The ESWIN EIC7700 SoC lacks hardware support for the L2/L3 low-power
> > > +	 * link states. It cannot enter the L2/L3 Ready state through the
> > > +	 * PME_Turn_Off/PME_To_Ack handshake protocol. To avoid this problem,
> > > +	 * the dw_pcie_suspend_noirq API is not used.
> > > +	 */
> > 
> > With 7.0, you can provide a dummy pme_turn_off() API and set
> > 'pci->pp.skip_l23_ready' to reuse the dw_pcie_{suspend/resume}_noirq APIs.
> > 
> 
> Hi Mani,
> 
> Setting pci->pp.skip_l23_ready does indeed allow us to reuse the
> dw_pcie_suspend_noirq function. However, for the dw_pcie_resume_noirq
> function, if the dw_pcie_start_link and dw_pcie_wait_for_link APIs fail to
> execute, the clk/reset resources in the pci->pp.ops->init function cannot
> be released. Perhaps the dw_pcie_resume_noirq function needs to be optimized.

Will this help?

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 6ae6189e9b8a..38ad79bbeab1 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -1300,15 +1300,24 @@ int dw_pcie_resume_noirq(struct dw_pcie *pci)
 
        ret = dw_pcie_start_link(pci);
        if (ret)
-               return ret;
+               goto err_deinit;
 
        ret = dw_pcie_wait_for_link(pci);
        if (ret)
-               return ret;
+               goto err_stop_link;
 
        if (pci->pp.ops->post_init)
                pci->pp.ops->post_init(&pci->pp);
 
+       return 0;
+
+err_stop_link:
+       dw_pcie_stop_link(pci);
+
+err_deinit:
+       if (pci->pp.ops->deinit)
+               pci->pp.ops->deinit(&pci->pp);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(dw_pcie_resume_noirq);

- Mani

-- 
மணிவண்ணன் சதாசிவம்

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

* Re: Re: [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver
  2026-02-25 13:37       ` Manivannan Sadhasivam
@ 2026-02-26  8:09         ` zhangsenchuan
  2026-02-26  8:36           ` Manivannan Sadhasivam
  0 siblings, 1 reply; 17+ messages in thread
From: zhangsenchuan @ 2026-02-26  8:09 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: bhelgaas, krzk+dt, conor+dt, lpieralisi, kwilczynski, robh,
	p.zabel, linux-pci, devicetree, linux-kernel, christian.bruel,
	shradha.t, krishna.chundru, thippeswamy.havalige, inochiama,
	Frank.li, ningyu, linmin, pinkesh.vaghela, ouyanghui


> > > Subject: Re: [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver
> > > 
> > > On Thu, Jan 29, 2026 at 05:29:00PM +0800, zhangsenchuan@eswincomputing.com wrote:
> > > > From: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
> > > >
> > > > +static int eic7700_pcie_suspend_noirq(struct device *dev)
> > > > +{
> > > > +	struct eic7700_pcie *pcie = dev_get_drvdata(dev);
> > > > +
> > > > +	/*
> > > > +	 * The ESWIN EIC7700 SoC lacks hardware support for the L2/L3 low-power
> > > > +	 * link states. It cannot enter the L2/L3 Ready state through the
> > > > +	 * PME_Turn_Off/PME_To_Ack handshake protocol. To avoid this problem,
> > > > +	 * the dw_pcie_suspend_noirq API is not used.
> > > > +	 */
> > > 
> > > With 7.0, you can provide a dummy pme_turn_off() API and set
> > > 'pci->pp.skip_l23_ready' to reuse the dw_pcie_{suspend/resume}_noirq APIs.
> > > 
> > 
> > Hi Mani,
> > 
> > Setting pci->pp.skip_l23_ready does indeed allow us to reuse the
> > dw_pcie_suspend_noirq function. However, for the dw_pcie_resume_noirq
> > function, if the dw_pcie_start_link and dw_pcie_wait_for_link APIs fail to
> > execute, the clk/reset resources in the pci->pp.ops->init function cannot
> > be released. Perhaps the dw_pcie_resume_noirq function needs to be optimized.
> 
> Will this help?
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> index 6ae6189e9b8a..38ad79bbeab1 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -1300,15 +1300,24 @@ int dw_pcie_resume_noirq(struct dw_pcie *pci)
>  
>         ret = dw_pcie_start_link(pci);
>         if (ret)
> -               return ret;
> +               goto err_deinit;
>  
>         ret = dw_pcie_wait_for_link(pci);
>         if (ret)
> -               return ret;
> +               goto err_stop_link;
>  
>         if (pci->pp.ops->post_init)
>                 pci->pp.ops->post_init(&pci->pp);
>  
> +       return 0;
> +
> +err_stop_link:
> +       dw_pcie_stop_link(pci);
> +
> +err_deinit:
> +       if (pci->pp.ops->deinit)
> +               pci->pp.ops->deinit(&pci->pp);
> +
>         return ret;
>  }
>  EXPORT_SYMBOL_GPL(dw_pcie_resume_noirq);
> 

Yes, this can release the resources after init, after optimizing the 
resume function, i can reuse the dw_pcie_{suspend/resume}_noirq APIs.

I noticed that the dw_pcie_wait_for_link function has been optimized. Is 
it necessary to release the resources only when it return -ETIMEOUT?
Perhaps it needs to be slightly improved:

 ret = dw_pcie_wait_for_link(pci);
 if (ret == -ETIMEOUT)
         goto err_stop_link;

What about your suggestion?

Kind regards,
Senchuan

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

* Re: [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver
  2026-02-26  8:09         ` zhangsenchuan
@ 2026-02-26  8:36           ` Manivannan Sadhasivam
  2026-02-26  9:37             ` zhangsenchuan
  0 siblings, 1 reply; 17+ messages in thread
From: Manivannan Sadhasivam @ 2026-02-26  8:36 UTC (permalink / raw)
  To: zhangsenchuan
  Cc: bhelgaas, krzk+dt, conor+dt, lpieralisi, kwilczynski, robh,
	p.zabel, linux-pci, devicetree, linux-kernel, christian.bruel,
	shradha.t, krishna.chundru, thippeswamy.havalige, inochiama,
	Frank.li, ningyu, linmin, pinkesh.vaghela, ouyanghui

On Thu, Feb 26, 2026 at 04:09:44PM +0800, zhangsenchuan wrote:
> 
> > > > Subject: Re: [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver
> > > > 
> > > > On Thu, Jan 29, 2026 at 05:29:00PM +0800, zhangsenchuan@eswincomputing.com wrote:
> > > > > From: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
> > > > >
> > > > > +static int eic7700_pcie_suspend_noirq(struct device *dev)
> > > > > +{
> > > > > +	struct eic7700_pcie *pcie = dev_get_drvdata(dev);
> > > > > +
> > > > > +	/*
> > > > > +	 * The ESWIN EIC7700 SoC lacks hardware support for the L2/L3 low-power
> > > > > +	 * link states. It cannot enter the L2/L3 Ready state through the
> > > > > +	 * PME_Turn_Off/PME_To_Ack handshake protocol. To avoid this problem,
> > > > > +	 * the dw_pcie_suspend_noirq API is not used.
> > > > > +	 */
> > > > 
> > > > With 7.0, you can provide a dummy pme_turn_off() API and set
> > > > 'pci->pp.skip_l23_ready' to reuse the dw_pcie_{suspend/resume}_noirq APIs.
> > > > 
> > > 
> > > Hi Mani,
> > > 
> > > Setting pci->pp.skip_l23_ready does indeed allow us to reuse the
> > > dw_pcie_suspend_noirq function. However, for the dw_pcie_resume_noirq
> > > function, if the dw_pcie_start_link and dw_pcie_wait_for_link APIs fail to
> > > execute, the clk/reset resources in the pci->pp.ops->init function cannot
> > > be released. Perhaps the dw_pcie_resume_noirq function needs to be optimized.
> > 
> > Will this help?
> > 
> > diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> > index 6ae6189e9b8a..38ad79bbeab1 100644
> > --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> > @@ -1300,15 +1300,24 @@ int dw_pcie_resume_noirq(struct dw_pcie *pci)
> >  
> >         ret = dw_pcie_start_link(pci);
> >         if (ret)
> > -               return ret;
> > +               goto err_deinit;
> >  
> >         ret = dw_pcie_wait_for_link(pci);
> >         if (ret)
> > -               return ret;
> > +               goto err_stop_link;
> >  
> >         if (pci->pp.ops->post_init)
> >                 pci->pp.ops->post_init(&pci->pp);
> >  
> > +       return 0;
> > +
> > +err_stop_link:
> > +       dw_pcie_stop_link(pci);
> > +
> > +err_deinit:
> > +       if (pci->pp.ops->deinit)
> > +               pci->pp.ops->deinit(&pci->pp);
> > +
> >         return ret;
> >  }
> >  EXPORT_SYMBOL_GPL(dw_pcie_resume_noirq);
> > 
> 
> Yes, this can release the resources after init, after optimizing the 
> resume function, i can reuse the dw_pcie_{suspend/resume}_noirq APIs.
> 
> I noticed that the dw_pcie_wait_for_link function has been optimized. Is 
> it necessary to release the resources only when it return -ETIMEOUT?
> Perhaps it needs to be slightly improved:
> 
>  ret = dw_pcie_wait_for_link(pci);
>  if (ret == -ETIMEOUT)
>          goto err_stop_link;
> 
> What about your suggestion?
> 

Absolutely! I forgot my own rework ;) I'll cook a patch for the above. Then if
you base your controller driver patch on top of it, we can merge both in a
single tree (if Bjorn agrees).

- Mani

-- 
மணிவண்ணன் சதாசிவம்

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

* Re: Re: [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver
  2026-02-26  8:36           ` Manivannan Sadhasivam
@ 2026-02-26  9:37             ` zhangsenchuan
  2026-02-26 13:46               ` Manivannan Sadhasivam
  0 siblings, 1 reply; 17+ messages in thread
From: zhangsenchuan @ 2026-02-26  9:37 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: bhelgaas, krzk+dt, conor+dt, lpieralisi, kwilczynski, robh,
	p.zabel, linux-pci, devicetree, linux-kernel, christian.bruel,
	shradha.t, krishna.chundru, thippeswamy.havalige, inochiama,
	Frank.li, ningyu, linmin, pinkesh.vaghela, ouyanghui

> > > > > Subject: Re: [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver
> > > > > 
> > > > > On Thu, Jan 29, 2026 at 05:29:00PM +0800, zhangsenchuan@eswincomputing.com wrote:
> > > > > > From: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
> > > > > >
> > > > > > +static int eic7700_pcie_suspend_noirq(struct device *dev)
> > > > > > +{
> > > > > > +	struct eic7700_pcie *pcie = dev_get_drvdata(dev);
> > > > > > +
> > > > > > +	/*
> > > > > > +	 * The ESWIN EIC7700 SoC lacks hardware support for the L2/L3 low-power
> > > > > > +	 * link states. It cannot enter the L2/L3 Ready state through the
> > > > > > +	 * PME_Turn_Off/PME_To_Ack handshake protocol. To avoid this problem,
> > > > > > +	 * the dw_pcie_suspend_noirq API is not used.
> > > > > > +	 */
> > > > > 
> > > > > With 7.0, you can provide a dummy pme_turn_off() API and set
> > > > > 'pci->pp.skip_l23_ready' to reuse the dw_pcie_{suspend/resume}_noirq APIs.
> > > > > 
> > > > 
> > > > Hi Mani,
> > > > 
> > > > Setting pci->pp.skip_l23_ready does indeed allow us to reuse the
> > > > dw_pcie_suspend_noirq function. However, for the dw_pcie_resume_noirq
> > > > function, if the dw_pcie_start_link and dw_pcie_wait_for_link APIs fail to
> > > > execute, the clk/reset resources in the pci->pp.ops->init function cannot
> > > > be released. Perhaps the dw_pcie_resume_noirq function needs to be optimized.
> > > 
> > > Will this help?
> > > 
> > > diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> > > index 6ae6189e9b8a..38ad79bbeab1 100644
> > > --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> > > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> > > @@ -1300,15 +1300,24 @@ int dw_pcie_resume_noirq(struct dw_pcie *pci)
> > >  
> > >         ret = dw_pcie_start_link(pci);
> > >         if (ret)
> > > -               return ret;
> > > +               goto err_deinit;
> > >  
> > >         ret = dw_pcie_wait_for_link(pci);
> > >         if (ret)
> > > -               return ret;
> > > +               goto err_stop_link;
> > >  
> > >         if (pci->pp.ops->post_init)
> > >                 pci->pp.ops->post_init(&pci->pp);
> > >  
> > > +       return 0;
> > > +
> > > +err_stop_link:
> > > +       dw_pcie_stop_link(pci);
> > > +
> > > +err_deinit:
> > > +       if (pci->pp.ops->deinit)
> > > +               pci->pp.ops->deinit(&pci->pp);
> > > +
> > >         return ret;
> > >  }
> > >  EXPORT_SYMBOL_GPL(dw_pcie_resume_noirq);
> > > 
> > 
> > Yes, this can release the resources after init, after optimizing the 
> > resume function, i can reuse the dw_pcie_{suspend/resume}_noirq APIs.
> > 
> > I noticed that the dw_pcie_wait_for_link function has been optimized. Is 
> > it necessary to release the resources only when it return -ETIMEOUT?
> > Perhaps it needs to be slightly improved:
> > 
> >  ret = dw_pcie_wait_for_link(pci);
> >  if (ret == -ETIMEOUT)
> >          goto err_stop_link;
> > 
> > What about your suggestion?
> > 
> 
> Absolutely! I forgot my own rework ;) I'll cook a patch for the above. Then if
> you base your controller driver patch on top of it, we can merge both in a
> single tree (if Bjorn agrees).
> 

Okey,thanks!

I'm a little unsure. Do I need to send the v11 patch here first? Or should I wait
until you release the new fix patch, and then send the v11 patch?

Kind regards,
Senchuan


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

* Re: [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver
  2026-02-26  9:37             ` zhangsenchuan
@ 2026-02-26 13:46               ` Manivannan Sadhasivam
  2026-02-27 11:22                 ` zhangsenchuan
  0 siblings, 1 reply; 17+ messages in thread
From: Manivannan Sadhasivam @ 2026-02-26 13:46 UTC (permalink / raw)
  To: zhangsenchuan
  Cc: bhelgaas, krzk+dt, conor+dt, lpieralisi, kwilczynski, robh,
	p.zabel, linux-pci, devicetree, linux-kernel, christian.bruel,
	shradha.t, krishna.chundru, thippeswamy.havalige, inochiama,
	Frank.li, ningyu, linmin, pinkesh.vaghela, ouyanghui

On Thu, Feb 26, 2026 at 05:37:48PM +0800, zhangsenchuan wrote:
> > > > > > Subject: Re: [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver
> > > > > > 
> > > > > > On Thu, Jan 29, 2026 at 05:29:00PM +0800, zhangsenchuan@eswincomputing.com wrote:
> > > > > > > From: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
> > > > > > >
> > > > > > > +static int eic7700_pcie_suspend_noirq(struct device *dev)
> > > > > > > +{
> > > > > > > +	struct eic7700_pcie *pcie = dev_get_drvdata(dev);
> > > > > > > +
> > > > > > > +	/*
> > > > > > > +	 * The ESWIN EIC7700 SoC lacks hardware support for the L2/L3 low-power
> > > > > > > +	 * link states. It cannot enter the L2/L3 Ready state through the
> > > > > > > +	 * PME_Turn_Off/PME_To_Ack handshake protocol. To avoid this problem,
> > > > > > > +	 * the dw_pcie_suspend_noirq API is not used.
> > > > > > > +	 */
> > > > > > 
> > > > > > With 7.0, you can provide a dummy pme_turn_off() API and set
> > > > > > 'pci->pp.skip_l23_ready' to reuse the dw_pcie_{suspend/resume}_noirq APIs.
> > > > > > 
> > > > > 
> > > > > Hi Mani,
> > > > > 
> > > > > Setting pci->pp.skip_l23_ready does indeed allow us to reuse the
> > > > > dw_pcie_suspend_noirq function. However, for the dw_pcie_resume_noirq
> > > > > function, if the dw_pcie_start_link and dw_pcie_wait_for_link APIs fail to
> > > > > execute, the clk/reset resources in the pci->pp.ops->init function cannot
> > > > > be released. Perhaps the dw_pcie_resume_noirq function needs to be optimized.
> > > > 
> > > > Will this help?
> > > > 
> > > > diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> > > > index 6ae6189e9b8a..38ad79bbeab1 100644
> > > > --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> > > > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> > > > @@ -1300,15 +1300,24 @@ int dw_pcie_resume_noirq(struct dw_pcie *pci)
> > > >  
> > > >         ret = dw_pcie_start_link(pci);
> > > >         if (ret)
> > > > -               return ret;
> > > > +               goto err_deinit;
> > > >  
> > > >         ret = dw_pcie_wait_for_link(pci);
> > > >         if (ret)
> > > > -               return ret;
> > > > +               goto err_stop_link;
> > > >  
> > > >         if (pci->pp.ops->post_init)
> > > >                 pci->pp.ops->post_init(&pci->pp);
> > > >  
> > > > +       return 0;
> > > > +
> > > > +err_stop_link:
> > > > +       dw_pcie_stop_link(pci);
> > > > +
> > > > +err_deinit:
> > > > +       if (pci->pp.ops->deinit)
> > > > +               pci->pp.ops->deinit(&pci->pp);
> > > > +
> > > >         return ret;
> > > >  }
> > > >  EXPORT_SYMBOL_GPL(dw_pcie_resume_noirq);
> > > > 
> > > 
> > > Yes, this can release the resources after init, after optimizing the 
> > > resume function, i can reuse the dw_pcie_{suspend/resume}_noirq APIs.
> > > 
> > > I noticed that the dw_pcie_wait_for_link function has been optimized. Is 
> > > it necessary to release the resources only when it return -ETIMEOUT?
> > > Perhaps it needs to be slightly improved:
> > > 
> > >  ret = dw_pcie_wait_for_link(pci);
> > >  if (ret == -ETIMEOUT)
> > >          goto err_stop_link;
> > > 
> > > What about your suggestion?
> > > 
> > 
> > Absolutely! I forgot my own rework ;) I'll cook a patch for the above. Then if
> > you base your controller driver patch on top of it, we can merge both in a
> > single tree (if Bjorn agrees).
> > 
> 
> Okey,thanks!
> 
> I'm a little unsure. Do I need to send the v11 patch here first? Or should I wait
> until you release the new fix patch, and then send the v11 patch?
> 

I've just sent the fix:
https://lore.kernel.org/linux-pci/20260226133951.296743-1-mani@kernel.org

You can post your series on top of it. There should be no build dependency, but
there is a functional dependency. So we may put this patch and your series in a
single branch.

- Mani

-- 
மணிவண்ணன் சதாசிவம்

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

* Re: Re: [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver
  2026-02-26 13:46               ` Manivannan Sadhasivam
@ 2026-02-27 11:22                 ` zhangsenchuan
  0 siblings, 0 replies; 17+ messages in thread
From: zhangsenchuan @ 2026-02-27 11:22 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: bhelgaas, krzk+dt, conor+dt, lpieralisi, kwilczynski, robh,
	p.zabel, linux-pci, devicetree, linux-kernel, christian.bruel,
	shradha.t, krishna.chundru, thippeswamy.havalige, inochiama,
	Frank.li, ningyu, linmin, pinkesh.vaghela, ouyanghui

> > > > > > > Subject: Re: [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver
> > > > > > > 
> > > > > > > On Thu, Jan 29, 2026 at 05:29:00PM +0800, zhangsenchuan@eswincomputing.com wrote:
> > > > > > > > From: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
> > > > > > > >
> > > > > > > > +static int eic7700_pcie_suspend_noirq(struct device *dev)
> > > > > > > > +{
> > > > > > > > +	struct eic7700_pcie *pcie = dev_get_drvdata(dev);
> > > > > > > > +
> > > > > > > > +	/*
> > > > > > > > +	 * The ESWIN EIC7700 SoC lacks hardware support for the L2/L3 low-power
> > > > > > > > +	 * link states. It cannot enter the L2/L3 Ready state through the
> > > > > > > > +	 * PME_Turn_Off/PME_To_Ack handshake protocol. To avoid this problem,
> > > > > > > > +	 * the dw_pcie_suspend_noirq API is not used.
> > > > > > > > +	 */
> > > > > > > 
> > > > > > > With 7.0, you can provide a dummy pme_turn_off() API and set
> > > > > > > 'pci->pp.skip_l23_ready' to reuse the dw_pcie_{suspend/resume}_noirq APIs.
> > > > > > > 
> > > > > > 
> > > > > > Hi Mani,
> > > > > > 
> > > > > > Setting pci->pp.skip_l23_ready does indeed allow us to reuse the
> > > > > > dw_pcie_suspend_noirq function. However, for the dw_pcie_resume_noirq
> > > > > > function, if the dw_pcie_start_link and dw_pcie_wait_for_link APIs fail to
> > > > > > execute, the clk/reset resources in the pci->pp.ops->init function cannot
> > > > > > be released. Perhaps the dw_pcie_resume_noirq function needs to be optimized.
> > > > > 
> > > > > Will this help?
> > > > > 
> > > > > diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> > > > > index 6ae6189e9b8a..38ad79bbeab1 100644
> > > > > --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> > > > > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> > > > > @@ -1300,15 +1300,24 @@ int dw_pcie_resume_noirq(struct dw_pcie *pci)
> > > > >  
> > > > >         ret = dw_pcie_start_link(pci);
> > > > >         if (ret)
> > > > > -               return ret;
> > > > > +               goto err_deinit;
> > > > >  
> > > > >         ret = dw_pcie_wait_for_link(pci);
> > > > >         if (ret)
> > > > > -               return ret;
> > > > > +               goto err_stop_link;
> > > > >  
> > > > >         if (pci->pp.ops->post_init)
> > > > >                 pci->pp.ops->post_init(&pci->pp);
> > > > >  
> > > > > +       return 0;
> > > > > +
> > > > > +err_stop_link:
> > > > > +       dw_pcie_stop_link(pci);
> > > > > +
> > > > > +err_deinit:
> > > > > +       if (pci->pp.ops->deinit)
> > > > > +               pci->pp.ops->deinit(&pci->pp);
> > > > > +
> > > > >         return ret;
> > > > >  }
> > > > >  EXPORT_SYMBOL_GPL(dw_pcie_resume_noirq);
> > > > > 
> > > > 
> > > > Yes, this can release the resources after init, after optimizing the 
> > > > resume function, i can reuse the dw_pcie_{suspend/resume}_noirq APIs.
> > > > 
> > > > I noticed that the dw_pcie_wait_for_link function has been optimized. Is 
> > > > it necessary to release the resources only when it return -ETIMEOUT?
> > > > Perhaps it needs to be slightly improved:
> > > > 
> > > >  ret = dw_pcie_wait_for_link(pci);
> > > >  if (ret == -ETIMEOUT)
> > > >          goto err_stop_link;
> > > > 
> > > > What about your suggestion?
> > > > 
> > > 
> > > Absolutely! I forgot my own rework ;) I'll cook a patch for the above. Then if
> > > you base your controller driver patch on top of it, we can merge both in a
> > > single tree (if Bjorn agrees).
> > > 
> > 
> > Okey,thanks!
> > 
> > I'm a little unsure. Do I need to send the v11 patch here first? Or should I wait
> > until you release the new fix patch, and then send the v11 patch?
> > 
> 
> I've just sent the fix:
> https://lore.kernel.org/linux-pci/20260226133951.296743-1-mani@kernel.org
> 
> You can post your series on top of it. There should be no build dependency, but
> there is a functional dependency. So we may put this patch and your series in a
> single branch.

Okey,thanks! I have sent the v11 patch.

Kind regards,
Senchuan


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

end of thread, other threads:[~2026-02-27 11:23 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-29  9:26 [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller zhangsenchuan
2026-01-29  9:28 ` [PATCH v10 1/2] dt-bindings: PCI: eic7700: Add Eswin PCIe host controller zhangsenchuan
2026-01-29  9:29 ` [PATCH v10 2/2] PCI: eic7700: Add Eswin PCIe host controller driver zhangsenchuan
2026-02-18 12:47   ` Manivannan Sadhasivam
2026-02-24  8:14     ` zhangsenchuan
2026-02-25 13:37       ` Manivannan Sadhasivam
2026-02-26  8:09         ` zhangsenchuan
2026-02-26  8:36           ` Manivannan Sadhasivam
2026-02-26  9:37             ` zhangsenchuan
2026-02-26 13:46               ` Manivannan Sadhasivam
2026-02-27 11:22                 ` zhangsenchuan
2026-02-01 12:24 ` [PATCH v10 0/2] Add driver support for Eswin EIC7700 SoC PCIe controller Leon Romanovsky
2026-02-01 12:28   ` Leon Romanovsky
2026-02-02 10:57     ` Manivannan Sadhasivam
2026-02-01 12:25 ` Leon Romanovsky
2026-02-02 10:59 ` Manivannan Sadhasivam
2026-02-06 22:20   ` Bjorn Helgaas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox