Re: [PATCH v4 2/3] dwc: PCI: intel: PCIe RC controller driver

From: Dilip Kota
Date: Tue Oct 22 2019 - 06:19:05 EST


Hi Gustavo Pimentel,

On 10/21/2019 6:44 PM, Dilip Kota wrote:
Hi Gustavo Pimentel,

On 10/21/2019 4:29 PM, Gustavo Pimentel wrote:
Hi

On Mon, Oct 21, 2019 at 7:39:19, Dilip Kota <eswara.kota@xxxxxxxxxxxxxxx>
wrote:

Add support to PCIe RC controller on Intel Gateway SoCs.
PCIe controller is based of Synopsys DesignWare pci core.

Intel PCIe driver requires Upconfig support, fast training
sequence configuration and link speed change. So adding the
respective helper functions in the pcie DesignWare framework.
It also programs hardware autonomous speed during speed
configuration so defining it in pci_regs.h.
Please do the replacement in all of your patches

s/pcie/PCIe
s/pci/PCI

Also I think the correct term is Upconfigure and not Upconfig
Yes, i will update it.

Changes on v4:
ÂÂÂÂRename the driver naming and description to
ÂÂÂÂ "PCIe RC controller on Intel Gateway SoCs".
ÂÂÂÂUse PCIe core register macros defined in pci_regs.h
ÂÂÂÂ and remove respective local definitions.
ÂÂÂÂRemove pcie core interrupt handling.
ÂÂÂÂMove pcie link control speed change, upconfig and FTS.
ÂÂÂÂconfiguration functions to DesignWare framework.
ÂÂÂÂUse of_pci_get_max_link_speed().
ÂÂÂÂMark dependency on X86 and COMPILE_TEST in Kconfig.
ÂÂÂÂRemove lanes and add n_fts variables in intel_pcie_port structure.
ÂÂÂÂRename rst_interval variable to rst_intrvl in intel_pcie_port structure.
ÂÂÂÂRemove intel_pcie_mem_iatu() as it is already perfomed in dw_setup_rc()
ÂÂÂÂMove sysfs attributes specific code to separate patch.
ÂÂÂÂRemove redundant error handling.
ÂÂÂÂReduce LoCs by doing variable initializations while declaration itself.
ÂÂÂÂAdd extra line after closing parenthesis.
ÂÂÂÂMove intel_pcie_ep_rst_init() out of get_resources()

changes on v3:
ÂÂÂÂRename PCIe app logic registers with PCIE_APP prefix.
ÂÂÂÂPCIE_IOP_CTRL configuration is not required. Remove respective code.
ÂÂÂÂRemove wrapper functions for clk enable/disable APIs.
ÂÂÂÂUse platform_get_resource_byname() instead of
ÂÂÂÂÂ devm_platform_ioremap_resource() to be similar with DWC framework.
ÂÂÂÂRename phy name to "pciephy".
ÂÂÂÂModify debug message in msi_init() callback to be more specific.
ÂÂÂÂRemove map_irq() callback.
ÂÂÂÂEnable the INTx interrupts at the time of PCIe initialization.
ÂÂÂÂReduce memory fragmentation by using variable "struct dw_pcie pci"
ÂÂÂÂÂ instead of allocating memory.
ÂÂÂÂReduce the delay to 100us during enpoint initialization
ÂÂÂÂÂ intel_pcie_ep_rst_init().
ÂÂÂÂCall dw_pcie_host_deinit() during remove() instead of directly
ÂÂÂÂÂ calling PCIe core APIs.
ÂÂÂÂRename "intel,rst-interval" to "reset-assert-ms".
ÂÂÂÂRemove unused APP logic Interrupt bit macro definitions.
ÂÂÂÂÂ Use dwc framework's dw_pcie_setup_rc() for PCIe host specific
ÂÂÂÂ configuration instead of redefining the same functionality in
ÂÂÂÂ the driver.
ÂÂÂÂMove the whole DT parsing specific code to intel_pcie_get_resources()

Signed-off-by: Dilip Kota <eswara.kota@xxxxxxxxxxxxxxx>
---
 drivers/pci/controller/dwc/Kconfig | 10 +
 drivers/pci/controller/dwc/Makefile | 1 +
 drivers/pci/controller/dwc/pcie-designware.c | 34 ++
 drivers/pci/controller/dwc/pcie-designware.h | 12 +
 drivers/pci/controller/dwc/pcie-intel-gw.c | 590 +++++++++++++++++++++++++++
 include/uapi/linux/pci_regs.h | 1 +
 6 files changed, 648 insertions(+)
 create mode 100644 drivers/pci/controller/dwc/pcie-intel-gw.c

diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
index 0ba988b5b5bc..b33ed1cc873d 100644
--- a/drivers/pci/controller/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
@@ -82,6 +82,16 @@ config PCIE_DW_PLAT_EP
ÂÂÂÂÂÂÂ order to enable device-specific features PCI_DW_PLAT_EP must be
ÂÂÂÂÂÂÂ selected.
 +config PCIE_INTEL_GW
+ÂÂÂÂÂÂÂ bool "Intel Gateway PCIe host controller support"
+ÂÂÂ depends on OF && (X86 || COMPILE_TEST)
+ÂÂÂ select PCIE_DW_HOST
+ÂÂÂ help
+ÂÂÂÂÂÂÂÂÂ Say 'Y' here to enable support for PCIe Host controller driver.
+ÂÂÂÂÂ The PCIe controller on Intel Gateway SoCs is based on the Synopsys
+ÂÂÂÂÂ DesignWare pcie core and therefore uses the DesignWare core
+ÂÂÂÂÂ functions for the driver implementation.
+
 config PCI_EXYNOS
ÂÂÂÂÂ bool "Samsung Exynos PCIe controller"
ÂÂÂÂÂ depends on SOC_EXYNOS5440 || COMPILE_TEST
diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
index b30336181d46..99db83cd2f35 100644
--- a/drivers/pci/controller/dwc/Makefile
+++ b/drivers/pci/controller/dwc/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_PCIE_DW) += pcie-designware.o
 obj-$(CONFIG_PCIE_DW_HOST) += pcie-designware-host.o
 obj-$(CONFIG_PCIE_DW_EP) += pcie-designware-ep.o
 obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o
+obj-$(CONFIG_PCIE_INTEL_GW) += pcie-intel-gw.o
 obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
 obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
 obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 820488dfeaed..4c391bfd681a 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -474,6 +474,40 @@ int dw_pcie_link_up(struct dw_pcie *pci)
ÂÂÂÂÂÂÂÂÂ (!(val & PCIE_PORT_DEBUG1_LINK_IN_TRAINING)));
 }
 +
+void dw_pcie_upconfig_setup(struct dw_pcie *pci)
+{
+ÂÂÂ u32 val;
+
+ÂÂÂ val = dw_pcie_readl_dbi(pci, PCIE_PORT_MULTI_LANE_CTRL);
+ÂÂÂ dw_pcie_writel_dbi(pci, PCIE_PORT_MULTI_LANE_CTRL,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ val | PORT_MLTI_UPCFG_SUPPORT);
+}
+
+void dw_pcie_link_speed_change(struct dw_pcie *pci, bool enable)
+{
+ÂÂÂ u32 val;
+
+ÂÂÂ val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
+
+ÂÂÂ if (enable)
+ÂÂÂÂÂÂÂ val |= PORT_LOGIC_SPEED_CHANGE;
+ÂÂÂ else
+ÂÂÂÂÂÂÂ val &= ~PORT_LOGIC_SPEED_CHANGE;
+
+ÂÂÂ dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
+}
+
+void dw_pcie_link_set_n_fts(struct dw_pcie *pci, u32 n_fts)
+{
+ÂÂÂ u32 val;
+
+ÂÂÂ val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
+ÂÂÂ val &= ~PORT_LOGIC_N_FTS;
+ÂÂÂ val |= n_fts;
+ÂÂÂ dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
+}
+
 static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci)
 {
ÂÂÂÂÂ u32 val;
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 5a18e94e52c8..3beac10e4a4c 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -30,7 +30,12 @@
 #define LINK_WAIT_IATU 9
  /* Synopsys-specific PCIe configuration registers */
+#define PCIE_PORT_AFRÂÂÂÂÂÂÂÂÂÂÂ 0x70C
+#define PORT_AFR_N_FTS_MASKÂÂÂÂÂÂÂ GENMASK(15, 8)
+#define PORT_AFR_CC_N_FTS_MASKÂÂÂÂÂÂÂ GENMASK(23, 16)
+
 #define PCIE_PORT_LINK_CONTROL 0x710
+#define PORT_LINK_DLL_LINK_ENÂÂÂÂÂÂÂ BIT(5)
 #define PORT_LINK_MODE_MASK GENMASK(21, 16)
 #define PORT_LINK_MODE(n) FIELD_PREP(PORT_LINK_MODE_MASK, n)
 #define PORT_LINK_MODE_1_LANES PORT_LINK_MODE(0x1)
@@ -46,6 +51,7 @@
 #define PCIE_PORT_DEBUG1_LINK_IN_TRAINING BIT(29)
  #define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
+#define PORT_LOGIC_N_FTSÂÂÂÂÂÂÂ GENMASK(7, 0)
 #define PORT_LOGIC_SPEED_CHANGE BIT(17)
 #define PORT_LOGIC_LINK_WIDTH_MASK GENMASK(12, 8)
 #define PORT_LOGIC_LINK_WIDTH(n) FIELD_PREP(PORT_LOGIC_LINK_WIDTH_MASK, n)
@@ -60,6 +66,9 @@
 #define PCIE_MSI_INTR0_MASK 0x82C
 #define PCIE_MSI_INTR0_STATUS 0x830
 +#define PCIE_PORT_MULTI_LANE_CTRL 0x8C0
+#define PORT_MLTI_UPCFG_SUPPORTÂÂÂÂÂÂÂ BIT(7)
+
 #define PCIE_ATU_VIEWPORT 0x900
 #define PCIE_ATU_REGION_INBOUND BIT(31)
 #define PCIE_ATU_REGION_OUTBOUND 0
@@ -273,6 +282,9 @@ void dw_pcie_write_dbi2(struct dw_pcie *pci, u32 reg, size_t size, u32 val);
 u32 dw_pcie_read_atu(struct dw_pcie *pci, u32 reg, size_t size);
 void dw_pcie_write_atu(struct dw_pcie *pci, u32 reg, size_t size, u32 val);
 int dw_pcie_link_up(struct dw_pcie *pci);
+void dw_pcie_upconfig_setup(struct dw_pcie *pci);
+void dw_pcie_link_speed_change(struct dw_pcie *pci, bool enable);
+void dw_pcie_link_set_n_fts(struct dw_pcie *pci, u32 n_fts);
 int dw_pcie_wait_for_link(struct dw_pcie *pci);
 void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index,
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ int type, u64 cpu_addr, u64 pci_addr,
diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c
new file mode 100644
index 000000000000..9142c70db808
--- /dev/null
+++ b/drivers/pci/controller/dwc/pcie-intel-gw.c
@@ -0,0 +1,590 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCIe host controller driver for Intel Gateway SoCs
+ *
+ * Copyright (c) 2019 Intel Corporation.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/of_irq.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
+#include <linux/pci_regs.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include "../../pci.h"
+#include "pcie-designware.h"
+
+#define PCIE_CAP_OFSTÂÂÂÂÂÂÂÂÂÂÂ 0x70
+
+#define PORT_AFR_N_FTS_GEN12_DFTÂÂÂ (SZ_128 - 1)
+#define PORT_AFR_N_FTS_GEN3ÂÂÂÂÂÂÂ 180
+#define PORT_AFR_N_FTS_GEN4ÂÂÂÂÂÂÂ 196
+
+/* PCIe Application logic Registers */
+#define PCIE_APP_CCRÂÂÂÂÂÂÂÂÂÂÂ 0x10
+#define PCIE_APP_CCR_LTSSM_ENABLEÂÂÂ BIT(0)
+
+#define PCIE_APP_MSG_CRÂÂÂÂÂÂÂÂÂÂÂ 0x30
+#define PCIE_APP_MSG_XMT_PM_TURNOFFÂÂÂ BIT(0)
+
+#define PCIE_APP_PMCÂÂÂÂÂÂÂÂÂÂÂ 0x44
+#define PCIE_APP_PMC_IN_L2ÂÂÂÂÂÂÂ BIT(20)
+
+#define PCIE_APP_IRNENÂÂÂÂÂÂÂÂÂÂÂ 0xF4
+#define PCIE_APP_IRNCRÂÂÂÂÂÂÂÂÂÂÂ 0xF8
+#define PCIE_APP_IRN_AER_REPORTÂÂÂÂÂÂÂ BIT(0)
+#define PCIE_APP_IRN_PMEÂÂÂÂÂÂÂ BIT(2)
+#define PCIE_APP_IRN_RX_VDM_MSGÂÂÂÂÂÂÂ BIT(4)
+#define PCIE_APP_IRN_PM_TO_ACKÂÂÂÂÂÂÂ BIT(9)
+#define PCIE_APP_IRN_LINK_AUTO_BW_STATÂÂÂ BIT(11)
+#define PCIE_APP_IRN_BW_MGTÂÂÂÂÂÂÂ BIT(12)
+#define PCIE_APP_IRN_MSG_LTRÂÂÂÂÂÂÂ BIT(18)
+#define PCIE_APP_IRN_SYS_ERR_RCÂÂÂÂÂÂÂ BIT(29)
+#define PCIE_APP_INTX_OFSTÂÂÂÂÂÂÂ 12
+
+#define PCIE_APP_IRN_INT \
+ÂÂÂÂÂÂÂÂÂÂÂ (PCIE_APP_IRN_AER_REPORT | PCIE_APP_IRN_PME | \
+ÂÂÂÂÂÂÂÂÂÂÂ PCIE_APP_IRN_RX_VDM_MSG | PCIE_APP_IRN_SYS_ERR_RC | \
+ÂÂÂÂÂÂÂÂÂÂÂ PCIE_APP_IRN_PM_TO_ACK | PCIE_APP_IRN_MSG_LTR | \
+ÂÂÂÂÂÂÂÂÂÂÂ PCIE_APP_IRN_BW_MGT | PCIE_APP_IRN_LINK_AUTO_BW_STAT | \
+ÂÂÂÂÂÂÂÂÂÂÂ (PCIE_APP_INTX_OFST + PCI_INTERRUPT_INTA) | \
+ÂÂÂÂÂÂÂÂÂÂÂ (PCIE_APP_INTX_OFST + PCI_INTERRUPT_INTB) | \
+ÂÂÂÂÂÂÂÂÂÂÂ (PCIE_APP_INTX_OFST + PCI_INTERRUPT_INTC) | \
+ÂÂÂÂÂÂÂÂÂÂÂ (PCIE_APP_INTX_OFST + PCI_INTERRUPT_INTD))
+
+#define BUS_IATU_OFFSÂÂÂÂÂÂÂÂÂÂÂ SZ_256M
+#define RST_INTRVL_DFT_MSÂÂÂÂÂÂÂ 100
+
+enum {
+ÂÂÂ PCIE_LINK_SPEED_AUTO = 0,
+ÂÂÂ PCIE_LINK_SPEED_GEN1,
+ÂÂÂ PCIE_LINK_SPEED_GEN2,
+ÂÂÂ PCIE_LINK_SPEED_GEN3,
+ÂÂÂ PCIE_LINK_SPEED_GEN4,
+};
+
+struct intel_pcie_soc {
+ÂÂÂ unsigned int pcie_ver;
+ÂÂÂ unsigned int pcie_atu_offset;
+ÂÂÂ u32 num_viewport;
+};
+
+struct intel_pcie_port {
+ÂÂÂ struct dw_pcieÂÂÂÂÂÂÂ pci;
+ÂÂÂ unsigned intÂÂÂÂÂÂÂ id; /* Physical RC Index */
+ÂÂÂ void __iomemÂÂÂÂÂÂÂ *app_base;
+ÂÂÂ struct gpio_descÂÂÂ *reset_gpio;
+ÂÂÂ u32ÂÂÂÂÂÂÂÂÂÂÂ rst_intrvl;
+ÂÂÂ u32ÂÂÂÂÂÂÂÂÂÂÂ max_speed;
+ÂÂÂ u32ÂÂÂÂÂÂÂÂÂÂÂ link_gen;
+ÂÂÂ u32ÂÂÂÂÂÂÂÂÂÂÂ max_width;
+ÂÂÂ u32ÂÂÂÂÂÂÂÂÂÂÂ n_fts;
+ÂÂÂ struct clkÂÂÂÂÂÂÂ *core_clk;
+ÂÂÂ struct reset_controlÂÂÂ *core_rst;
+ÂÂÂ struct phyÂÂÂÂÂÂÂ *phy;
+};
+
+static void pcie_update_bits(void __iomem *base, u32 mask, u32 val, u32 ofs)
+{
+ÂÂÂ u32 orig, tmp;
+
+ÂÂÂ orig = readl(base + ofs);
+
+ÂÂÂ tmp = (orig & ~mask) | (val & mask);
+
+ÂÂÂ if (tmp != orig)
+ÂÂÂÂÂÂÂ writel(tmp, base + ofs);
+}
I'd suggest to the a take on FIELD_PREP() and FIELD_GET() and use more
intuitive names such as new and old, instead of orig and tmp.
Sure, i will update it.
I tried using FIELD_PREP and FIELD_GET but it is failing because FIELD_PREP and FIELD_GET
are expecting mask should be constant macro. u32 or u32 const are not accepted.

Regards,
Dilip


+static inline u32 pcie_app_rd(struct intel_pcie_port *lpp, u32 ofs)
+{
+ÂÂÂ return readl(lpp->app_base + ofs);
+}
+
+static inline void pcie_app_wr(struct intel_pcie_port *lpp, u32 val, u32 ofs)
+{
+ÂÂÂ writel(val, lpp->app_base + ofs);
+}
+
+static void pcie_app_wr_mask(struct intel_pcie_port *lpp,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ u32 mask, u32 val, u32 ofs)
+{
+ÂÂÂ pcie_update_bits(lpp->app_base, mask, val, ofs);
+}
+
+static inline u32 pcie_rc_cfg_rd(struct intel_pcie_port *lpp, u32 ofs)
+{
+ÂÂÂ return dw_pcie_readl_dbi(&lpp->pci, ofs);
+}
+
+static inline void pcie_rc_cfg_wr(struct intel_pcie_port *lpp, u32 val, u32 ofs)
+{
+ÂÂÂ dw_pcie_writel_dbi(&lpp->pci, ofs, val);
+}
+
+static void pcie_rc_cfg_wr_mask(struct intel_pcie_port *lpp,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ u32 mask, u32 val, u32 ofs)
+{
+ÂÂÂ pcie_update_bits(lpp->pci.dbi_base, mask, val, ofs);
+}
+
+static void intel_pcie_ltssm_enable(struct intel_pcie_port *lpp)
+{
+ÂÂÂ pcie_app_wr_mask(lpp, PCIE_APP_CCR_LTSSM_ENABLE,
+ÂÂÂÂÂÂÂÂÂÂÂÂ PCIE_APP_CCR_LTSSM_ENABLE, PCIE_APP_CCR);
+}
+
+static void intel_pcie_ltssm_disable(struct intel_pcie_port *lpp)
+{
+ÂÂÂ pcie_app_wr_mask(lpp, PCIE_APP_CCR_LTSSM_ENABLE, 0, PCIE_APP_CCR);
+}
+
+static void intel_pcie_link_setup(struct intel_pcie_port *lpp)
+{
+ÂÂÂ u32 val;
+
+ÂÂÂ val = pcie_rc_cfg_rd(lpp, PCIE_CAP_OFST + PCI_EXP_LNKCAP);
+ÂÂÂ lpp->max_speed = FIELD_GET(PCI_EXP_LNKCAP_SLS, val);
+ÂÂÂ lpp->max_width = FIELD_GET(PCI_EXP_LNKCAP_MLW, val);
+
+ÂÂÂ val = pcie_rc_cfg_rd(lpp, PCIE_CAP_OFST + PCI_EXP_LNKCTL);
+
+ÂÂÂ val &= ~(PCI_EXP_LNKCTL_LD | PCI_EXP_LNKCTL_ASPMC);
+ÂÂÂ val |= (PCI_EXP_LNKSTA_SLC << 16) | PCI_EXP_LNKCTL_CCC |
+ÂÂÂÂÂÂÂÂÂÂ PCI_EXP_LNKCTL_RCB;
+ÂÂÂ pcie_rc_cfg_wr(lpp, val, PCIE_CAP_OFST + PCI_EXP_LNKCTL);
+}
+
+static void intel_pcie_max_speed_setup(struct intel_pcie_port *lpp)
+{
+ÂÂÂ u32 reg, val;
+
+ÂÂÂ reg = pcie_rc_cfg_rd(lpp, PCIE_CAP_OFST + PCI_EXP_LNKCTL2);
+ÂÂÂ switch (lpp->link_gen) {
+ÂÂÂ case PCIE_LINK_SPEED_GEN1:
+ÂÂÂÂÂÂÂ reg &= ~PCI_EXP_LNKCTL2_TLS;
+ÂÂÂÂÂÂÂ reg |= PCI_EXP_LNKCTL2_HASD|
+ÂÂÂÂÂÂÂÂÂÂÂ PCI_EXP_LNKCTL2_TLS_2_5GT;
+ÂÂÂÂÂÂÂ break;
+ÂÂÂ case PCIE_LINK_SPEED_GEN2:
+ÂÂÂÂÂÂÂ reg &= ~PCI_EXP_LNKCTL2_TLS;
+ÂÂÂÂÂÂÂ reg |= PCI_EXP_LNKCTL2_HASD|
+ÂÂÂÂÂÂÂÂÂÂÂ PCI_EXP_LNKCTL2_TLS_5_0GT;
+ÂÂÂÂÂÂÂ break;
+ÂÂÂ case PCIE_LINK_SPEED_GEN3:
+ÂÂÂÂÂÂÂ reg &= ~PCI_EXP_LNKCTL2_TLS;
+ÂÂÂÂÂÂÂ reg |= PCI_EXP_LNKCTL2_HASD|
+ÂÂÂÂÂÂÂÂÂÂÂ PCI_EXP_LNKCTL2_TLS_8_0GT;
+ÂÂÂÂÂÂÂ break;
+ÂÂÂ case PCIE_LINK_SPEED_GEN4:
+ÂÂÂÂÂÂÂ reg &= ~PCI_EXP_LNKCTL2_TLS;
+ÂÂÂÂÂÂÂ reg |= PCI_EXP_LNKCTL2_HASD|
+ÂÂÂÂÂÂÂÂÂÂÂ PCI_EXP_LNKCTL2_TLS_16_0GT;
+ÂÂÂÂÂÂÂ break;
+ÂÂÂ default:
+ÂÂÂÂÂÂÂ /* Use hardware capability */
+ÂÂÂÂÂÂÂ val = pcie_rc_cfg_rd(lpp, PCIE_CAP_OFST + PCI_EXP_LNKCAP);
+ÂÂÂÂÂÂÂ val = FIELD_GET(PCI_EXP_LNKCAP_SLS, val);
+ÂÂÂÂÂÂÂ reg &= ~PCI_EXP_LNKCTL2_HASD;
+ÂÂÂÂÂÂÂ reg |= val;
+ÂÂÂÂÂÂÂ break;
+ÂÂÂ }
+
+ÂÂÂ pcie_rc_cfg_wr(lpp, reg, PCIE_CAP_OFST + PCI_EXP_LNKCTL2);
+ÂÂÂ dw_pcie_link_set_n_fts(&lpp->pci, lpp->n_fts);
+}
+
+
Reduce the number of empty lines here.
Ok, will remove it.

+
+static void intel_pcie_port_logic_setup(struct intel_pcie_port *lpp)
+{
+ÂÂÂ u32 val, mask;
+
+ÂÂÂ switch (lpp->max_speed) {
+ÂÂÂ case PCIE_LINK_SPEED_GEN3:
+ÂÂÂÂÂÂÂ lpp->n_fts = PORT_AFR_N_FTS_GEN3;
+ÂÂÂÂÂÂÂ break;
+ÂÂÂ case PCIE_LINK_SPEED_GEN4:
+ÂÂÂÂÂÂÂ lpp->n_fts = PORT_AFR_N_FTS_GEN4;
+ÂÂÂÂÂÂÂ break;
+ÂÂÂ default:
+ÂÂÂÂÂÂÂ lpp->n_fts = PORT_AFR_N_FTS_GEN12_DFT;
+ÂÂÂÂÂÂÂ break;
+ÂÂÂ }
+
+ÂÂÂ mask = PORT_AFR_N_FTS_MASK | PORT_AFR_CC_N_FTS_MASK;
+ÂÂÂ val = FIELD_PREP(PORT_AFR_N_FTS_MASK, lpp->n_fts) |
+ÂÂÂÂÂÂÂÂÂÂ FIELD_PREP(PORT_AFR_CC_N_FTS_MASK, lpp->n_fts);
+ÂÂÂ pcie_rc_cfg_wr_mask(lpp, mask, val, PCIE_PORT_AFR);
+
+ÂÂÂ /* Port Link Control Register */
+ÂÂÂ pcie_rc_cfg_wr_mask(lpp, PORT_LINK_DLL_LINK_EN,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ PORT_LINK_DLL_LINK_EN, PCIE_PORT_LINK_CONTROL);
+}
+
+static void intel_pcie_rc_setup(struct intel_pcie_port *lpp)
+{
+ÂÂÂ intel_pcie_ltssm_disable(lpp);
+ÂÂÂ intel_pcie_link_setup(lpp);
+ÂÂÂ dw_pcie_setup_rc(&lpp->pci.pp);
+ÂÂÂ dw_pcie_upconfig_setup(&lpp->pci);
+ÂÂÂ intel_pcie_port_logic_setup(lpp);
+ÂÂÂ intel_pcie_max_speed_setup(lpp);
+}
+
+static int intel_pcie_ep_rst_init(struct intel_pcie_port *lpp)
+{
+ÂÂÂ struct device *dev = lpp->pci.dev;
+ÂÂÂ int ret;
+
+ÂÂÂ lpp->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ÂÂÂ if (IS_ERR(lpp->reset_gpio)) {
+ÂÂÂÂÂÂÂ ret = PTR_ERR(lpp->reset_gpio);
+ÂÂÂÂÂÂÂ if (ret != -EPROBE_DEFER)
+ÂÂÂÂÂÂÂÂÂÂÂ dev_err(dev, "failed to request PCIe GPIO: %d\n", ret);
+ÂÂÂÂÂÂÂ return ret;
+ÂÂÂ }
+
+ÂÂÂ /* Make initial reset last for 100us */
+ÂÂÂ usleep_range(100, 200);
+
+ÂÂÂ return 0;
+}
+
+static void intel_pcie_core_rst_assert(struct intel_pcie_port *lpp)
+{
+ÂÂÂ reset_control_assert(lpp->core_rst);
+}
+
+static void intel_pcie_core_rst_deassert(struct intel_pcie_port *lpp)
+{
+ÂÂÂ /*
+ÂÂÂÂ * One micro-second delay to make sure the reset pulse
+ÂÂÂÂ * wide enough so that core reset is clean.
+ÂÂÂÂ */
+ÂÂÂ udelay(1);
+ÂÂÂ reset_control_deassert(lpp->core_rst);
+
+ÂÂÂ /*
+ÂÂÂÂ * Some SoC core reset also reset PHY, more delay needed
+ÂÂÂÂ * to make sure the reset process is done.
+ÂÂÂÂ */
+ÂÂÂ usleep_range(1000, 2000);
+}
+
+static void intel_pcie_device_rst_assert(struct intel_pcie_port *lpp)
+{
+ÂÂÂ gpiod_set_value_cansleep(lpp->reset_gpio, 1);
+}
+
+static void intel_pcie_device_rst_deassert(struct intel_pcie_port *lpp)
+{
+ÂÂÂ msleep(lpp->rst_intrvl);
+ÂÂÂ gpiod_set_value_cansleep(lpp->reset_gpio, 0);
+}
+
+static int intel_pcie_app_logic_setup(struct intel_pcie_port *lpp)
+{
+ÂÂÂ intel_pcie_device_rst_deassert(lpp);
+ÂÂÂ intel_pcie_ltssm_enable(lpp);
+
+ÂÂÂ return dw_pcie_wait_for_link(&lpp->pci);
+}
+
+static void intel_pcie_core_irq_disable(struct intel_pcie_port *lpp)
+{
+ÂÂÂ pcie_app_wr(lpp, 0, PCIE_APP_IRNEN);
+ pcie_app_wr(lpp, PCIE_APP_IRN_INT, PCIE_APP_IRNCR);
+}
+
+static int intel_pcie_get_resources(struct platform_device *pdev)
+{
+ÂÂÂ struct intel_pcie_port *lpp = platform_get_drvdata(pdev);
+ÂÂÂ struct dw_pcie *pci = &lpp->pci;
+ÂÂÂ struct device *dev = pci->dev;
+ÂÂÂ struct resource *res;
+ÂÂÂ int ret;
+
+ÂÂÂ ret = device_property_read_u32(dev, "linux,pci-domain", &lpp->id);
+ÂÂÂ if (ret) {
+ÂÂÂÂÂÂÂ dev_err(dev, "failed to get domain id, errno %d\n", ret);
+ÂÂÂÂÂÂÂ return ret;
+ÂÂÂ }
+
+ÂÂÂ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
+
+ÂÂÂ pci->dbi_base = devm_ioremap_resource(dev, res);
+ÂÂÂ if (IS_ERR(pci->dbi_base))
+ÂÂÂÂÂÂÂ return PTR_ERR(pci->dbi_base);
+
+ÂÂÂ lpp->core_clk = devm_clk_get(dev, NULL);
+ÂÂÂ if (IS_ERR(lpp->core_clk)) {
+ÂÂÂÂÂÂÂ ret = PTR_ERR(lpp->core_clk);
+ÂÂÂÂÂÂÂ if (ret != -EPROBE_DEFER)
+ÂÂÂÂÂÂÂÂÂÂÂ dev_err(dev, "failed to get clks: %d\n", ret);
+ÂÂÂÂÂÂÂ return ret;
+ÂÂÂ }
+
+ÂÂÂ lpp->core_rst = devm_reset_control_get(dev, NULL);
+ÂÂÂ if (IS_ERR(lpp->core_rst)) {
+ÂÂÂÂÂÂÂ ret = PTR_ERR(lpp->core_rst);
+ÂÂÂÂÂÂÂ if (ret != -EPROBE_DEFER)
+ÂÂÂÂÂÂÂÂÂÂÂ dev_err(dev, "failed to get resets: %d\n", ret);
+ÂÂÂÂÂÂÂ return ret;
+ÂÂÂ }
+
+ÂÂÂ ret = device_property_match_string(dev, "device_type", "pci");
+ÂÂÂ if (ret) {
+ÂÂÂÂÂÂÂ dev_err(dev, "failed to find pci device type: %d\n", ret);
+ÂÂÂÂÂÂÂ return ret;
+ÂÂÂ }
+
+ÂÂÂ if (device_property_read_u32(dev, "reset-assert-ms", &lpp->rst_intrvl))
+ÂÂÂÂÂÂÂ lpp->rst_intrvl = RST_INTRVL_DFT_MS;
+
+ÂÂÂ ret = of_pci_get_max_link_speed(dev->of_node);
+ÂÂÂÂÂÂÂ lpp->link_gen = ret < 0 ? 0 : ret;
+
+ÂÂÂ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "app");
+
+ÂÂÂ lpp->app_base = devm_ioremap_resource(dev, res);
+ÂÂÂ if (IS_ERR(lpp->app_base))
+ÂÂÂÂÂÂÂ return PTR_ERR(lpp->app_base);
+
+ÂÂÂ lpp->phy = devm_phy_get(dev, "pcie");
+ÂÂÂ if (IS_ERR(lpp->phy)) {
+ÂÂÂÂÂÂÂ ret = PTR_ERR(lpp->phy);
+ÂÂÂÂÂÂÂ if (ret != -EPROBE_DEFER)
+ÂÂÂÂÂÂÂÂÂÂÂ dev_err(dev, "couldn't get pcie-phy: %d\n", ret);
+ÂÂÂÂÂÂÂ return ret;
+ÂÂÂ }
+
+ÂÂÂ return 0;
+}
+
+static void intel_pcie_deinit_phy(struct intel_pcie_port *lpp)
+{
+ÂÂÂ phy_exit(lpp->phy);
+}
+
+static int intel_pcie_wait_l2(struct intel_pcie_port *lpp)
+{
+ÂÂÂ u32 value;
+ÂÂÂ int ret;
+
+ÂÂÂ if (lpp->max_speed < PCIE_LINK_SPEED_GEN3)
+ÂÂÂÂÂÂÂ return 0;
+
+ÂÂÂ /* Send PME_TURN_OFF message */
+ÂÂÂ pcie_app_wr_mask(lpp, PCIE_APP_MSG_XMT_PM_TURNOFF,
+ÂÂÂÂÂÂÂÂÂÂÂÂ PCIE_APP_MSG_XMT_PM_TURNOFF, PCIE_APP_MSG_CR);
+
+ÂÂÂ /* Read PMC status and wait for falling into L2 link state */
+ÂÂÂ ret = readl_poll_timeout(lpp->app_base + PCIE_APP_PMC, value,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ (value & PCIE_APP_PMC_IN_L2), 20,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ jiffies_to_usecs(5 * HZ));
+ÂÂÂ if (ret)
+ÂÂÂÂÂÂÂ dev_err(lpp->pci.dev, "PCIe link enter L2 timeout!\n");
+
+ÂÂÂ return ret;
+}
+
+static void intel_pcie_turn_off(struct intel_pcie_port *lpp)
+{
+ÂÂÂ if (dw_pcie_link_up(&lpp->pci))
+ÂÂÂÂÂÂÂ intel_pcie_wait_l2(lpp);
+
+ÂÂÂ /* Put endpoint device in reset state */
+ÂÂÂ intel_pcie_device_rst_assert(lpp);
+ÂÂÂ pcie_rc_cfg_wr_mask(lpp, PCI_COMMAND_MEMORY, 0, PCI_COMMAND);
+}
+
+static int intel_pcie_host_setup(struct intel_pcie_port *lpp)
+{
+ÂÂÂ int ret;
+
+ÂÂÂ intel_pcie_core_rst_assert(lpp);
+ÂÂÂ intel_pcie_device_rst_assert(lpp);
+
+ÂÂÂ ret = phy_init(lpp->phy);
+ÂÂÂ if (ret)
+ÂÂÂÂÂÂÂ return ret;
+
+ÂÂÂ intel_pcie_core_rst_deassert(lpp);
+
+ÂÂÂ ret = clk_prepare_enable(lpp->core_clk);
+ÂÂÂ if (ret) {
+ÂÂÂÂÂÂÂ dev_err(lpp->pci.dev, "Core clock enable failed: %d\n", ret);
+ÂÂÂÂÂÂÂ goto clk_err;
+ÂÂÂ }
+
+ÂÂÂ intel_pcie_rc_setup(lpp);
+ÂÂÂ ret = intel_pcie_app_logic_setup(lpp);
+ÂÂÂ if (ret)
+ÂÂÂÂÂÂÂ goto app_init_err;
+
+ÂÂÂ /* Enable integrated interrupts */
+ÂÂÂ pcie_app_wr_mask(lpp, PCIE_APP_IRN_INT, PCIE_APP_IRN_INT,
+ÂÂÂÂÂÂÂÂÂÂÂÂ PCIE_APP_IRNEN);
+ÂÂÂ return 0;
+
+app_init_err:
+ÂÂÂ clk_disable_unprepare(lpp->core_clk);
+clk_err:
+ÂÂÂ intel_pcie_core_rst_assert(lpp);
+ÂÂÂ intel_pcie_deinit_phy(lpp);
+
+ÂÂÂ return ret;
+}
+
+static void __intel_pcie_remove(struct intel_pcie_port *lpp)
+{
+ÂÂÂ intel_pcie_core_irq_disable(lpp);
+ÂÂÂ intel_pcie_turn_off(lpp);
+ÂÂÂ clk_disable_unprepare(lpp->core_clk);
+ÂÂÂ intel_pcie_core_rst_assert(lpp);
+ÂÂÂ intel_pcie_deinit_phy(lpp);
+}
+
+static int intel_pcie_remove(struct platform_device *pdev)
+{
+ÂÂÂ struct intel_pcie_port *lpp = platform_get_drvdata(pdev);
+ÂÂÂ struct pcie_port *pp = &lpp->pci.pp;
+
+ÂÂÂ dw_pcie_host_deinit(pp);
+ÂÂÂ __intel_pcie_remove(lpp);
+
+ÂÂÂ return 0;
+}
+
+static int __maybe_unused intel_pcie_suspend_noirq(struct device *dev)
+{
+ÂÂÂ struct intel_pcie_port *lpp = dev_get_drvdata(dev);
+ÂÂÂ int ret;
+
+ÂÂÂ intel_pcie_core_irq_disable(lpp);
+ÂÂÂ ret = intel_pcie_wait_l2(lpp);
+ÂÂÂ if (ret)
+ÂÂÂÂÂÂÂ return ret;
+
+ÂÂÂ intel_pcie_deinit_phy(lpp);
+ÂÂÂ clk_disable_unprepare(lpp->core_clk);
+ÂÂÂ return ret;
+}
+
+static int __maybe_unused intel_pcie_resume_noirq(struct device *dev)
+{
+ÂÂÂ struct intel_pcie_port *lpp = dev_get_drvdata(dev);
+
+ÂÂÂ return intel_pcie_host_setup(lpp);
+}
+
+static int intel_pcie_rc_init(struct pcie_port *pp)
+{
+ÂÂÂ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ÂÂÂ struct intel_pcie_port *lpp = dev_get_drvdata(pci->dev);
+
+ÂÂÂ return intel_pcie_host_setup(lpp);
+}
+
+int intel_pcie_msi_init(struct pcie_port *pp)
+{
+ÂÂÂ /* PCIe MSI/MSIx is handled by MSI in x86 processor */
+ÂÂÂ return 0;
+}
+
+u64 intel_pcie_cpu_addr(struct dw_pcie *pcie, u64 cpu_addr)
+{
+ÂÂÂ return cpu_addr + BUS_IATU_OFFS;
+}
+
+static const struct dw_pcie_ops intel_pcie_ops = {
+ÂÂÂ .cpu_addr_fixup = intel_pcie_cpu_addr,
+};
+
+static const struct dw_pcie_host_ops intel_pcie_dw_ops = {
+ÂÂÂ .host_init =ÂÂÂÂÂÂÂ intel_pcie_rc_init,
+ÂÂÂ .msi_host_init =ÂÂÂ intel_pcie_msi_init,
+};
+
+static const struct intel_pcie_soc pcie_data = {
+ÂÂÂ .pcie_ver =ÂÂÂÂÂÂÂ 0x520A,
+ÂÂÂ .pcie_atu_offset =ÂÂÂ 0xC0000,
+ÂÂÂ .num_viewport =ÂÂÂÂÂÂÂ 3,
+};
+
+static int intel_pcie_probe(struct platform_device *pdev)
+{
+ÂÂÂ const struct intel_pcie_soc *data;
+ÂÂÂ struct device *dev = &pdev->dev;
+ÂÂÂ struct intel_pcie_port *lpp;
+ÂÂÂ struct pcie_port *pp;
+ÂÂÂ struct dw_pcie *pci;
+ÂÂÂ int ret;
+
+ÂÂÂ lpp = devm_kzalloc(dev, sizeof(*lpp), GFP_KERNEL);
+ÂÂÂ if (!lpp)
+ÂÂÂÂÂÂÂ return -ENOMEM;
+
+ÂÂÂ platform_set_drvdata(pdev, lpp);
+ÂÂÂ pci = &lpp->pci;
+ÂÂÂ pci->dev = dev;
+ÂÂÂ pp = &pci->pp;
+
+ÂÂÂ ret = intel_pcie_get_resources(pdev);
+ÂÂÂ if (ret)
+ÂÂÂÂÂÂÂ return ret;
+
+ÂÂÂ ret = intel_pcie_ep_rst_init(lpp);
+ÂÂÂ if (ret)
+ÂÂÂÂÂÂÂ return ret;
+
+ÂÂÂ data = device_get_match_data(dev);
+ÂÂÂ pci->ops = &intel_pcie_ops;
+ÂÂÂ pci->version = data->pcie_ver;
+ÂÂÂ pci->atu_base = pci->dbi_base + data->pcie_atu_offset;
+ÂÂÂ pp->ops = &intel_pcie_dw_ops;
+
+ÂÂÂ ret = dw_pcie_host_init(pp);
+ÂÂÂ if (ret) {
+ÂÂÂÂÂÂÂ dev_err(dev, "cannot initialize host\n");
+ÂÂÂÂÂÂÂ return ret;
+ÂÂÂ }
+
+ÂÂÂ /* Intel PCIe doesn't configure IO region, so configure
+ÂÂÂÂ * viewport to not to access IO region during register
+ÂÂÂÂ * read write operations.
+ÂÂÂÂ */
+ÂÂÂ pci->num_viewport = data->num_viewport;
+ÂÂÂ dev_info(dev, "Intel PCIe Root Complex Port %d init done\n", lpp->id);
+
+ÂÂÂ return ret;
+}
+
+static const struct dev_pm_ops intel_pcie_pm_ops = {
+ÂÂÂ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(intel_pcie_suspend_noirq,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ intel_pcie_resume_noirq)
+};
+
+static const struct of_device_id of_intel_pcie_match[] = {
+ÂÂÂ { .compatible = "intel,lgm-pcie", .data = &pcie_data },
+ÂÂÂ {}
+};
+
+static struct platform_driver intel_pcie_driver = {
+ÂÂÂ .probe = intel_pcie_probe,
+ÂÂÂ .remove = intel_pcie_remove,
+ÂÂÂ .driver = {
+ÂÂÂÂÂÂÂ .name = "intel-gw-pcie",
+ÂÂÂÂÂÂÂ .of_match_table = of_intel_pcie_match,
+ÂÂÂÂÂÂÂ .pm = &intel_pcie_pm_ops,
+ÂÂÂ },
+};
+builtin_platform_driver(intel_pcie_driver);
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index 29d6e93fd15e..f6e7e402f879 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -673,6 +673,7 @@
 #define PCI_EXP_LNKCTL2_TLS_8_0GT 0x0003 /* Supported Speed 8GT/s */
 #define PCI_EXP_LNKCTL2_TLS_16_0GT 0x0004 /* Supported Speed 16GT/s */
 #define PCI_EXP_LNKCTL2_TLS_32_0GT 0x0005 /* Supported Speed 32GT/s */
+#define PCI_EXP_LNKCTL2_HASD 0x0200 /* Hw Autonomous Speed Disable */
s/Hw/HW

Sure, i will correct it.

Thanks for the valuable inputs.

Regards,
Dilip


 #define PCI_EXP_LNKSTA2 50 /* Link Status 2 */
 #define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 52 /* v2 endpoints with link end here */
 #define PCI_EXP_SLTCAP2 52 /* Slot Capabilities 2 */
--
2.11.0