From nobody Fri Dec 19 22:01:03 2025 Received: from zg8tmja2lje4os4yms4ymjma.icoremail.net (zg8tmja2lje4os4yms4ymjma.icoremail.net [206.189.21.223]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 48A24230BE9; Fri, 16 May 2025 09:43:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=206.189.21.223 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747388602; cv=none; b=T/GhaqXTtW2xtBXakkaTvKVEf1p0CTDFq7YTK3XDQ19CjExZ2XW/+nxiI0Y9Z305myRzZxwVFdLd9BBZBulNwJET+KkUm9wbHUi/IMl6Q6W9huKk9nS1ovYa0DIZpfUO8MPonwdWhIXtC0m4MfUwt0eRl9h+0BkX2ZoVLhn1tWo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747388602; c=relaxed/simple; bh=iRM0oIfGdVUZc4utRbh1pYtMqsKhE0xXF75fL+lPFd8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PP4eScu7GM7Z6TYukoQWqp5UyDzmzUHjZVa0mk2SAqeruCp8+hphufR7QA9mGPPmQcqK3qRT6CnFNT9kFK48/4RNmmyml744z7j/Q7sINxsh0QXlRUoH/PORA559VDQ3BuWKXZ1Xbw5INjjfajT53g++6dhUlHeJlqKKxQNFx2o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=eswincomputing.com; spf=pass smtp.mailfrom=eswincomputing.com; arc=none smtp.client-ip=206.189.21.223 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=eswincomputing.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=eswincomputing.com Received: from E0004758DT.eswin.cn (unknown [10.12.96.83]) by app1 (Coremail) with SMTP id TAJkCgDX7Q6dCCdozst8AA--.60135S2; Fri, 16 May 2025 17:42:55 +0800 (CST) From: zhangsenchuan@eswincomputing.com To: bhelgaas@google.com, lpieralisi@kernel.org, kw@linux.com, manivannan.sadhasivam@linaro.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, linux-pci@vger.kernel.org, devicetree@vger.kernel.or, linux-kernel@vger.kernel.org, p.zabel@pengutronix.de, johan+linaro@kernel.org, quic_schintav@quicinc.com, shradha.t@samsung.com, cassel@kernel.org, thippeswamy.havalige@amd.com Cc: ningyu@eswincomputing.com, linmin@eswincomputing.com, Senchuan Zhang Subject: [PATCH v1 1/2] dt-bindings: PCI: eic7700: Add Eswin eic7700 PCIe host controller Date: Fri, 16 May 2025 17:42:48 +0800 Message-ID: <20250516094249.1879-1-zhangsenchuan@eswincomputing.com> X-Mailer: git-send-email 2.49.0.windows.1 In-Reply-To: <20250516094057.1300-1-zhangsenchuan@eswincomputing.com> References: <20250516094057.1300-1-zhangsenchuan@eswincomputing.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: TAJkCgDX7Q6dCCdozst8AA--.60135S2 X-Coremail-Antispam: 1UD129KBjvJXoWxZw1kXr45urWkXFyUtF13Jwb_yoWrCFW5pF Z8GFykCr48Xr13Zw48JF10kF13JanYkFnYyrn7W3WaqrsYqFyjqr4akF13G343Gr47X34Y gFsIvryxtw17A3DanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBv14x267AKxVW5JVWrJwAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK02 1l84ACjcxK6xIIjxv20xvE14v26w1j6s0DM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r4U JVWxJr1l84ACjcxK6I8E87Iv67AKxVW0oVCq3wA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_Gc CE3s1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E 2Ix0cI8IcVAFwI0_JF0_Jw1lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWUJV W8JwACjcxG0xvY0x0EwIxGrwACjI8F5VA0II8E6IAqYI8I648v4I1lFIxGxcIEc7CjxVA2 Y2ka0xkIwI1lw4CEc2x0rVAKj4xxMxkF7I0En4kS14v26r4a6rW5MxkIecxEwVCm-wCF04 k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18 MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GFv_WrylIxkGc2Ij64vIr4 1lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr0_Cr1l IxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r1j6r4UMIIF0xvEx4 A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x0pRByxiUUUUU= X-CM-SenderInfo: x2kd0wpvhquxxxdqqvxvzl0uprps33xlqjhudrp/ Content-Type: text/plain; charset="utf-8" From: Senchuan Zhang 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. Co-developed-by: Yu Ning Signed-off-by: Yu Ning Signed-off-by: Senchuan Zhang --- .../bindings/pci/eswin,eic7700-pcie.yaml | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/eswin,eic7700-pci= e.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..e1d150c7c81a --- /dev/null +++ b/Documentation/devicetree/bindings/pci/eswin,eic7700-pcie.yaml @@ -0,0 +1,171 @@ +# 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 + - Senchuan Zhang + +description: | + The PCIe controller on EIC7700 SoC. + +properties: + compatible: + const: eswin,eic7700-pcie + + reg: + maxItems: 3 + + reg-names: + items: + - const: dbi + - const: config + - const: mgmt + + "#address-cells": + const: 3 + "#size-cells": + const: 2 + '#interrupt-cells': + const: 1 + + interrupts: + maxItems: 9 + + interrupt-names: + items: + - const: msi + - const: inta + - const: intb + - const: intc + - const: intd + + interrupt-controller: + type: object + + interrupt-map: + maxItems: 4 + + interrupt-map-mask: + items: + - const: 0 + - const: 0 + - const: 0 + - const: 7 + + clocks: + maxItems: 4 + description: handles to clock for the pcie controller. + + clock-names: + items: + - const: pcie_aclk + - const: pcie_cfg_clk + - const: pcie_cr_clk + - const: pcie_aux_clk + description: the name of each clock. + + resets: + description: resets to be used by the controller. + + reset-names: + items: + - const: pcie_cfg + - const: pcie_powerup + - const: pcie_pwren + description: names of the resets listed in resets property in the same= order. + + bus-range: + items: + - const: 0 + - const: 0xff + + device_type: + const: pci + + ranges: true + + dma-noncoherent: true + + num-lanes: + maximum: 4 + + numa-node-id: + maximum: 0 + +required: + - compatible + - reg + - reg-names + - interrupts + - interrupt-names + - interrupt-parent + - interrupt-map-mask + - interrupt-map + - '#address-cells' + - '#size-cells' + - '#interrupt-cells' + - clocks + - clock-names + - resets + - reset-names + - bus-range + - dma-noncoherent + - num-lanes + - ranges + - numa-node-id + +additionalProperties: false + +examples: + - | + soc { + #address-cells =3D <2>; + #size-cells =3D <2>; + + pcie: pcie@54000000 { + compatible =3D "eswin,eic7700-pcie"; + clocks =3D <&clock 562>, + <&clock 563>, + <&clock 564>, + <&clock 565>; + clock-names =3D "pcie_aclk", "pcie_cfg_clk", "pcie_cr_clk", "pci= e_aux_clk"; + + reset-names =3D "pcie_cfg", "pcie_powerup", "pcie_pwren"; + resets =3D <&reset 8 (1 << 0)>, + <&reset 8 (1 << 1)>, + <&reset 8 (1 << 2)>; + + #address-cells =3D <3>; + #size-cells =3D <2>; + #interrupt-cells =3D <1>; + + reg =3D <0x0 0x54000000 0x0 0x4000000>, + <0x0 0x40000000 0x0 0x800000>, + <0x0 0x50000000 0x0 0x100000>; + reg-names =3D "dbi", "config", "mgmt"; + device_type =3D "pci"; + + bus-range =3D <0x0 0xff>; + ranges =3D <0x81000000 0x0 0x40800000 0x0 0x40800000 0x0 0x80000= 0>, + <0x82000000 0x0 0x41000000 0x0 0x41000000 0x0 0xf000000>, + <0xc3000000 0x80 0x00000000 0x80 0x00000000 0x2 0x000000= 00>; + + num-lanes =3D <0x4>; + interrupts =3D <220>, <179>, <180>, <181>, <182>, <183>, <184>, = <185>, <186>; + interrupt-names =3D "msi", "inta", "intb", "intc", "intd"; + interrupt-parent =3D <&plic>; + interrupt-map-mask =3D <0x0 0x0 0x0 0x7>; + interrupt-map =3D <0x0 0x0 0x0 0x1 &plic 179>, + <0x0 0x0 0x0 0x2 &plic 180>, + <0x0 0x0 0x0 0x3 &plic 181>, + <0x0 0x0 0x0 0x4 &plic 182>; + status =3D "disabled"; + numa-node-id =3D <0>; + dma-noncoherent; + }; + }; -- 2.25.1 From nobody Fri Dec 19 22:01:03 2025 Received: from zg8tmja2lje4os4yms4ymjma.icoremail.net (zg8tmja2lje4os4yms4ymjma.icoremail.net [206.189.21.223]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A0EFE23315C; Fri, 16 May 2025 09:43:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=206.189.21.223 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747388629; cv=none; b=FrUR17vCNRAFmbHwbAt2qLqVaKRzK/QgELTx+jbWYIpe5jM4fD0K8WAshE3alup+zd5lsf1me3wvW27PC+11CeAcQYiJDFrnDe18HB40HjWI/FBzZGg7Zd3iDT5B4syLVvr/vjyRRcg36MUEuwUm445nTvE3CDOvPZUUH7U/PpE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747388629; c=relaxed/simple; bh=ZeN1/RCYbStfo+goph2p2P5AN78zGC7EvLUzRMIiCfg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KVXkZthUu3D+b0cgtozhWgofFcTTS4MdyP2c2boDcg9W8HgaNICS7nVZiSXQ7tDHGrwX4uZW7pSy6Cv4dtdPeXmqcM4ttyqVVVMC06Bjk5tti+I1qEnN+rU7BES6RuiNL92GrltKgT2ydSNHKQAqTF8f0vYA7jhwh+3OSeegsGQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=eswincomputing.com; spf=pass smtp.mailfrom=eswincomputing.com; arc=none smtp.client-ip=206.189.21.223 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=eswincomputing.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=eswincomputing.com Received: from E0004758DT.eswin.cn (unknown [10.12.96.83]) by app1 (Coremail) with SMTP id TAJkCgAXLxC8CCdo3st8AA--.47476S2; Fri, 16 May 2025 17:43:26 +0800 (CST) From: zhangsenchuan@eswincomputing.com To: bhelgaas@google.com, lpieralisi@kernel.org, kw@linux.com, manivannan.sadhasivam@linaro.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, linux-pci@vger.kernel.org, devicetree@vger.kernel.or, linux-kernel@vger.kernel.org, p.zabel@pengutronix.de, johan+linaro@kernel.org, quic_schintav@quicinc.com, shradha.t@samsung.com, cassel@kernel.org, thippeswamy.havalige@amd.com Cc: ningyu@eswincomputing.com, linmin@eswincomputing.com, Senchuan Zhang Subject: [PATCH v1 2/2] PCI: eic7700: Add Eswin eic7700 PCIe host controller driver Date: Fri, 16 May 2025 17:43:14 +0800 Message-ID: <20250516094315.179-1-zhangsenchuan@eswincomputing.com> X-Mailer: git-send-email 2.49.0.windows.1 In-Reply-To: <20250516094057.1300-1-zhangsenchuan@eswincomputing.com> References: <20250516094057.1300-1-zhangsenchuan@eswincomputing.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: TAJkCgAXLxC8CCdo3st8AA--.47476S2 X-Coremail-Antispam: 1UD129KBjvAXoW3Kw4kCrWrtF1rJFy7ZFWxtFb_yoW8Gw1xGo Z7Xr93W3WxJr1rArZ2vF1aga47Za42qa9xJrn09rZ7C3s7Arn8Kr1DCw15Zw1akF4rKFW5 Zr1DJwnxuF48Zw1Un29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUYN7AC8VAFwI0_Xr0_Wr1l1xkIjI8I6I8E6xAIw20EY4v20xva j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2 x7M28EF7xvwVC0I7IYx2IY67AKxVWDJVCq3wA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVW8 Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E14v26r xl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj 6xIIjxv20xvE14v26r126r1DMcIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr 0_Gr1lF7xvr2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7M4IIrI8v6xkF7I0E 8cxan2IY04v7M4kE6xkIj40Ew7xC0wCY1x0262kKe7AKxVW8ZVWrXwCY02Avz4vE-syl42 xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWU GwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r4a6rW5MIIYrxkI7VAKI4 8JMIIF0xvE2Ix0cI8IcVAFwI0_Jr0_JF4lIxAIcVC0I7IYx2IY6xkF7I0E14v26F4j6r4U JwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Jr0_Gr1lIxAIcV C2z280aVCY1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7sRihF4tUUUUU== X-CM-SenderInfo: x2kd0wpvhquxxxdqqvxvzl0uprps33xlqjhudrp/ Content-Type: text/plain; charset="utf-8" From: Senchuan Zhang Add driver for the Eswin EIC7700 PCIe host controller. The controller is based on the DesignWare PCIe core. Co-developed-by: Yu Ning Signed-off-by: Yu Ning Signed-off-by: Senchuan Zhang --- drivers/pci/controller/dwc/Kconfig | 12 + drivers/pci/controller/dwc/Makefile | 1 + drivers/pci/controller/dwc/pcie-eic7700.c | 437 ++++++++++++++++++++++ 3 files changed, 450 insertions(+) create mode 100644 drivers/pci/controller/dwc/pcie-eic7700.c diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dw= c/Kconfig index d9f0386396ed..21258f7dada9 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -480,4 +480,16 @@ config PCIE_VISCONTI_HOST Say Y here if you want PCIe controller support on Toshiba Visconti SoC. This driver supports TMPV7708 SoC. +config PCIE_EIC7700 + tristate "ESWIN PCIe host controller" + depends on PCI_MSI + depends on ARCH_ESWIN || COMPILE_TEST + select PCIE_DW_HOST + help + Enables support for the PCIe controller in the Eswin SoC + The PCI controller on Eswin is based on DesignWare hardware + It is a high-speed hardware bus standard used to connect + processors with external devices. Say Y here if you want + PCIe controller support for the ESWIN. + endmenu diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/d= wc/Makefile index 908cb7f345db..2906477d92a5 100644 --- a/drivers/pci/controller/dwc/Makefile +++ b/drivers/pci/controller/dwc/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_PCIE_UNIPHIER) +=3D pcie-uniphier.o obj-$(CONFIG_PCIE_UNIPHIER_EP) +=3D pcie-uniphier-ep.o obj-$(CONFIG_PCIE_VISCONTI_HOST) +=3D pcie-visconti.o obj-$(CONFIG_PCIE_RCAR_GEN4) +=3D pcie-rcar-gen4.o +obj-$(CONFIG_PCIE_EIC7700) +=3D pcie-eic7700.o # The following drivers are for devices that use the generic ACPI # pci_root.c driver but don't support standard ECAM config access. diff --git a/drivers/pci/controller/dwc/pcie-eic7700.c b/drivers/pci/contro= ller/dwc/pcie-eic7700.c new file mode 100644 index 000000000000..0413d1f61cb4 --- /dev/null +++ b/drivers/pci/controller/dwc/pcie-eic7700.c @@ -0,0 +1,437 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ESWIN PCIe root complex driver + * + * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All right= s reserved. + * + * Authors: Yu Ning + * Senchuan Zhang + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pcie-designware.h" +#include +struct eswin_pcie { + struct dw_pcie pci; + void __iomem *mgmt_base; + struct gpio_desc *reset; + struct clk *pcie_aux; + struct clk *pcie_cfg; + struct clk *pcie_cr; + struct clk *pcie_aclk; + struct reset_control *powerup_rst; + struct reset_control *cfg_rst; + struct reset_control *perst; +}; + +#define PCIE_PM_SEL_AUX_CLK BIT(16) +#define PCIEMGMT_APP_HOLD_PHY_RST BIT(6) +#define PCIEMGMT_APP_LTSSM_ENABLE BIT(5) +#define PCIEMGMT_DEVICE_TYPE_MASK 0xf + +#define PCIEMGMT_CTRL0_OFFSET 0x0 +#define PCIEMGMT_STATUS0_OFFSET 0x100 + +#define PCIE_TYPE_DEV_VEND_ID 0x0 +#define PCIE_DSP_PF0_MSI_CAP 0x50 +#define PCIE_NEXT_CAP_PTR 0x70 +#define DEVICE_CONTROL_DEVICE_STATUS 0x78 + +#define PCIE_MSI_MULTIPLE_MSG_32 (0x5 << 17) +#define PCIE_MSI_MULTIPLE_MSG_MASK (0x7 << 17) + +#define PCIEMGMT_LINKUP_STATE_VALIDATE ((0x11 << 2) | 0x3) +#define PCIEMGMT_LINKUP_STATE_MASK 0xff + +static void eswin_pcie_shutdown(struct platform_device *pdev) +{ + struct eswin_pcie *pcie =3D platform_get_drvdata(pdev); + + /* Bring down link, so bootloader gets clean state in case of reboot */ + reset_control_assert(pcie->perst); +} + +static int eswin_pcie_start_link(struct dw_pcie *pci) +{ + struct device *dev =3D pci->dev; + struct eswin_pcie *pcie =3D dev_get_drvdata(dev); + u32 val; + + /* Enable LTSSM */ + val =3D readl_relaxed(pcie->mgmt_base + PCIEMGMT_CTRL0_OFFSET); + val |=3D PCIEMGMT_APP_LTSSM_ENABLE; + writel_relaxed(val, pcie->mgmt_base + PCIEMGMT_CTRL0_OFFSET); + return 0; +} + +static int eswin_pcie_link_up(struct dw_pcie *pci) +{ + struct device *dev =3D pci->dev; + struct eswin_pcie *pcie =3D dev_get_drvdata(dev); + u32 val; + + val =3D readl_relaxed(pcie->mgmt_base + PCIEMGMT_STATUS0_OFFSET); + if ((val & PCIEMGMT_LINKUP_STATE_MASK) =3D=3D + PCIEMGMT_LINKUP_STATE_VALIDATE) + return 1; + else + return 0; +} + +static int eswin_pcie_clk_enable(struct eswin_pcie *pcie) +{ + int ret; + + ret =3D clk_prepare_enable(pcie->pcie_cr); + if (ret) { + pr_err("PCIe: failed to enable cr clk: %d\n", ret); + return ret; + } + + ret =3D clk_prepare_enable(pcie->pcie_aclk); + if (ret) { + pr_err("PCIe: failed to enable aclk: %d\n", ret); + return ret; + } + + ret =3D clk_prepare_enable(pcie->pcie_cfg); + if (ret) { + pr_err("PCIe: failed to enable cfg_clk: %d\n", ret); + return ret; + } + + ret =3D clk_prepare_enable(pcie->pcie_aux); + if (ret) { + pr_err("PCIe: failed to enable aux_clk: %d\n", ret); + return ret; + } + + return 0; +} + +static int eswin_pcie_clk_disable(struct eswin_pcie *eswin_pcie) +{ + clk_disable_unprepare(eswin_pcie->pcie_aux); + clk_disable_unprepare(eswin_pcie->pcie_cfg); + clk_disable_unprepare(eswin_pcie->pcie_cr); + clk_disable_unprepare(eswin_pcie->pcie_aclk); + + return 0; +} + +static int eswin_pcie_power_on(struct eswin_pcie *pcie) +{ + int ret =3D 0; + + /* pciet_cfg_rstn */ + ret =3D reset_control_reset(pcie->cfg_rst); + WARN_ON(ret !=3D 0); + + /* pciet_powerup_rstn */ + ret =3D reset_control_reset(pcie->powerup_rst); + WARN_ON(ret !=3D 0); + + return ret; +} + +static int eswin_pcie_power_off(struct eswin_pcie *eswin_pcie) +{ + reset_control_assert(eswin_pcie->perst); + + reset_control_assert(eswin_pcie->powerup_rst); + + reset_control_assert(eswin_pcie->cfg_rst); + + return 0; +} + +static int eswin_evb_socket_power_on(struct device *dev) +{ + int err_desc =3D 0; + struct gpio_desc *gpio; + + gpio =3D devm_gpiod_get(dev, "pci-socket", GPIOD_OUT_LOW); + err_desc =3D IS_ERR(gpio); + + if (err_desc) { + pr_debug("No power control gpio found, maybe not needed\n"); + return 0; + } + + gpiod_set_value(gpio, 1); + + return err_desc; +} + +static int eswin_pcie_host_init(struct dw_pcie_rp *pp) +{ + struct dw_pcie *pci =3D to_dw_pcie_from_pp(pp); + struct eswin_pcie *pcie =3D dev_get_drvdata(pci->dev); + int ret; + u32 val; + + /* pciet_aux_clken, pcie_cfg_clken */ + ret =3D eswin_pcie_clk_enable(pcie); + if (ret) + return ret; + + ret =3D eswin_pcie_power_on(pcie); + if (ret) + return ret; + + /* set device type : rc */ + val =3D readl_relaxed(pcie->mgmt_base + PCIEMGMT_CTRL0_OFFSET); + val &=3D 0xfffffff0; + writel_relaxed(val | 0x4, pcie->mgmt_base + PCIEMGMT_CTRL0_OFFSET); + + ret =3D reset_control_assert(pcie->perst); + WARN_ON(ret !=3D 0); + + eswin_evb_socket_power_on(pcie->pci.dev); + msleep(100); + ret =3D reset_control_deassert(pcie->perst); + WARN_ON(ret !=3D 0); + + /* app_hold_phy_rst */ + val =3D readl_relaxed(pcie->mgmt_base + PCIEMGMT_CTRL0_OFFSET); + val &=3D ~(0x40); + writel_relaxed(val, pcie->mgmt_base + PCIEMGMT_CTRL0_OFFSET); + + /* wait pm_sel_aux_clk to 0 */ + for (ret =3D 50; ret > 0; ret--) { + val =3D readl_relaxed(pcie->mgmt_base + PCIEMGMT_STATUS0_OFFSET); + if (!(val & PCIE_PM_SEL_AUX_CLK)) + break; + msleep(2); + } + + if (!ret) { + dev_info(pcie->pci.dev, "No clock exist.\n"); + eswin_pcie_power_off(pcie); + eswin_pcie_clk_disable(pcie); + return -ENODEV; + } + + /* config eswin vendor id and win2030 device id */ + dw_pcie_writel_dbi(pci, PCIE_TYPE_DEV_VEND_ID, 0x20301fe1); + + /* lane fix config, real driver NOT need, default x4 */ + val =3D dw_pcie_readl_dbi(pci, PCIE_PORT_MULTI_LANE_CTRL); + val &=3D 0xffffff80; + val |=3D 0x44; + dw_pcie_writel_dbi(pci, PCIE_PORT_MULTI_LANE_CTRL, val); + + val =3D dw_pcie_readl_dbi(pci, DEVICE_CONTROL_DEVICE_STATUS); + val &=3D ~(0x7 << 5); + val |=3D (0x2 << 5); + dw_pcie_writel_dbi(pci, DEVICE_CONTROL_DEVICE_STATUS, val); + + /* config support 32 msi vectors */ + val =3D dw_pcie_readl_dbi(pci, PCIE_DSP_PF0_MSI_CAP); + val &=3D ~PCIE_MSI_MULTIPLE_MSG_MASK; + val |=3D PCIE_MSI_MULTIPLE_MSG_32; + dw_pcie_writel_dbi(pci, PCIE_DSP_PF0_MSI_CAP, val); + + /* disable msix cap */ + val =3D dw_pcie_readl_dbi(pci, PCIE_NEXT_CAP_PTR); + val &=3D 0xffff00ff; + dw_pcie_writel_dbi(pci, PCIE_NEXT_CAP_PTR, val); + + return 0; +} + +static const struct dw_pcie_host_ops eswin_pcie_host_ops =3D { + .init =3D eswin_pcie_host_init, +}; + +static const struct dw_pcie_ops dw_pcie_ops =3D { + .start_link =3D eswin_pcie_start_link, + .link_up =3D eswin_pcie_link_up, +}; + +static int __exit eswin_pcie_remove(struct platform_device *pdev) +{ + struct eswin_pcie *pcie =3D platform_get_drvdata(pdev); + + dw_pcie_host_deinit(&pcie->pci.pp); + + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + + eswin_pcie_power_off(pcie); + eswin_pcie_clk_disable(pcie); + + return 0; +} + +static int eswin_pcie_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct dw_pcie *pci; + struct eswin_pcie *pcie; + int err; + + pcie =3D devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); + if (!pcie) + return -ENOMEM; + pci =3D &pcie->pci; + pci->dev =3D dev; + pci->ops =3D &dw_pcie_ops; + pci->pp.ops =3D &eswin_pcie_host_ops; + + /* SiFive specific region: mgmt */ + pcie->mgmt_base =3D devm_platform_ioremap_resource_byname(pdev, "mgmt"); + if (IS_ERR(pcie->mgmt_base)) + return PTR_ERR(pcie->mgmt_base); + + /* Fetch clocks */ + pcie->pcie_aux =3D devm_clk_get(dev, "pcie_aux_clk"); + if (IS_ERR(pcie->pcie_aux)) { + return dev_err_probe( + dev, PTR_ERR(pcie->pcie_aux), + "pcie_aux clock source missing or invalid\n"); + } + + pcie->pcie_cfg =3D devm_clk_get(dev, "pcie_cfg_clk"); + if (IS_ERR(pcie->pcie_cfg)) { + return dev_err_probe( + dev, PTR_ERR(pcie->pcie_cfg), + "pcie_cfg_clk clock source missing or invalid\n"); + } + + pcie->pcie_cr =3D devm_clk_get(dev, "pcie_cr_clk"); + if (IS_ERR(pcie->pcie_cr)) { + return dev_err_probe( + dev, PTR_ERR(pcie->pcie_cr), + "pcie_cr_clk clock source missing or invalid\n"); + } + + pcie->pcie_aclk =3D devm_clk_get(dev, "pcie_aclk"); + + if (IS_ERR(pcie->pcie_aclk)) { + return dev_err_probe( + dev, PTR_ERR(pcie->pcie_aclk), + "pcie_aclk clock source missing or invalid\n"); + } + + /* Fetch reset */ + pcie->powerup_rst =3D + devm_reset_control_get_optional(&pdev->dev, "pcie_powerup"); + if (IS_ERR_OR_NULL(pcie->powerup_rst)) + dev_err_probe(dev, PTR_ERR(pcie->powerup_rst), + "unable to get powerup reset\n"); + + pcie->cfg_rst =3D devm_reset_control_get_optional(&pdev->dev, "pcie_cfg"); + if (IS_ERR_OR_NULL(pcie->cfg_rst)) + dev_err_probe(dev, PTR_ERR(pcie->cfg_rst), + "unable to get cfg reset\n"); + + pcie->perst =3D devm_reset_control_get_optional(&pdev->dev, "pcie_pwren"); + if (IS_ERR_OR_NULL(pcie->perst)) + dev_err_probe(dev, PTR_ERR(pcie->perst), + "unable to get perst\n"); + + platform_set_drvdata(pdev, pcie); + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + err =3D pm_runtime_get_sync(dev); + if (err < 0) { + dev_err(dev, "pm_runtime_get_sync failed: %d\n", err); + goto pm_runtime_put; + } + + return dw_pcie_host_init(&pci->pp); + +pm_runtime_put: + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + return err; +} + +static const struct of_device_id eswin_pcie_of_match[] =3D { + { + .compatible =3D "eswin,eic7700-pcie", + }, + {}, +}; + +static int eswin_pcie_suspend(struct device *dev) +{ + struct eswin_pcie *pcie =3D dev_get_drvdata(dev); + + dev_dbg(dev, "suspend %s\n", __func__); + if (!pm_runtime_status_suspended(dev)) + eswin_pcie_clk_disable(pcie); + + return 0; +} + +static int eswin_pcie_resume(struct device *dev) +{ + struct eswin_pcie *pcie =3D dev_get_drvdata(dev); + + dev_dbg(dev, "resume %s\n", __func__); + if (!pm_runtime_status_suspended(dev)) + eswin_pcie_clk_enable(pcie); + + return 0; +} + +static int eswin_pcie_runtime_suspend(struct device *dev) +{ + struct eswin_pcie *pcie =3D dev_get_drvdata(dev); + + dev_dbg(dev, "runtime suspend %s\n", __func__); + return eswin_pcie_clk_disable(pcie); +} + +static int eswin_pcie_runtime_resume(struct device *dev) +{ + struct eswin_pcie *pcie =3D dev_get_drvdata(dev); + + dev_dbg(dev, "runtime resume %s\n", __func__); + return eswin_pcie_clk_enable(pcie); +} + +static const struct dev_pm_ops eswin_pcie_pm_ops =3D { + RUNTIME_PM_OPS(eswin_pcie_runtime_suspend, eswin_pcie_runtime_resume, + NULL) + NOIRQ_SYSTEM_SLEEP_PM_OPS(eswin_pcie_suspend, eswin_pcie_resume) +}; + +static struct platform_driver eswin_pcie_driver =3D { + .driver =3D { + .name =3D "eic7700-pcie", + .of_match_table =3D eswin_pcie_of_match, + .suppress_bind_attrs =3D true, + .pm =3D &eswin_pcie_pm_ops, + }, + .probe =3D eswin_pcie_probe, + .remove =3D __exit_p(eswin_pcie_remove), + .shutdown =3D eswin_pcie_shutdown, +}; + +module_platform_driver(eswin_pcie_driver); + +MODULE_DEVICE_TABLE(of, eswin_pcie_of_match); +MODULE_DESCRIPTION("PCIe host controller driver for eic7700 SoCs"); +MODULE_AUTHOR("Yu Ning "); +MODULE_AUTHOR("Senchuan Zhang "); +MODULE_LICENSE("GPL"); -- 2.25.1