From a37beefbde8802a4eab2545fee1b1780a03f2aa0 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 24 Jun 2022 17:34:23 +0300 Subject: PCI: dwc: Add start_link/stop_link inlines Factor out this pattern: if (!pci->ops || !pci->ops->start_link) return -EINVAL; return pci->ops->start_link(pci); into a new dw_pcie_start_link() wrapper and do the same for the stop_link() method. Note that dw_pcie_ep_start() previously returned -EINVAL if there was no platform start_link() method, which didn't make much sense since that is not an error. It will now return 0 in that case. As a side-effect, drop the empty start_link() and dummy dw_pcie_ops instances from the generic DW PCIe and Layerscape EP platform drivers. [bhelgaas: commit log] Link: https://lore.kernel.org/r/20220624143428.8334-14-Sergey.Semin@baikalelectronics.ru Signed-off-by: Serge Semin Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring Reviewed-by: Manivannan Sadhasivam --- drivers/pci/controller/dwc/pcie-designware.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 7d6e9b7576be..8ba239292634 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -365,6 +365,20 @@ static inline void dw_pcie_dbi_ro_wr_dis(struct dw_pcie *pci) dw_pcie_writel_dbi(pci, reg, val); } +static inline int dw_pcie_start_link(struct dw_pcie *pci) +{ + if (pci->ops && pci->ops->start_link) + return pci->ops->start_link(pci); + + return 0; +} + +static inline void dw_pcie_stop_link(struct dw_pcie *pci) +{ + if (pci->ops && pci->ops->stop_link) + pci->ops->stop_link(pci); +} + #ifdef CONFIG_PCIE_DW_HOST irqreturn_t dw_handle_msi_irq(struct pcie_port *pp); void dw_pcie_setup_rc(struct pcie_port *pp); -- cgit v1.2.3 From d6bdbcd8bfe134566035d3eabed915ed27a04320 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 24 Jun 2022 17:34:24 +0300 Subject: PCI: dwc: Move io_cfg_atu_shared to struct pcie_port The io_cfg_atu_shared flag is set if there is an outbound iATU window used for both config space accesses and IO port transfers. Since the flag semantic is purely Root Port specific, it's not used in either the DW PCIe common code or in the DW PCIe Endpoint driver. Move it to the struct pcie_port and rename to cfg0_io_shared. [bhelgaas: commit log] Link: https://lore.kernel.org/r/20220624143428.8334-15-Sergey.Semin@baikalelectronics.ru Signed-off-by: Serge Semin Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring Reviewed-by: Manivannan Sadhasivam --- drivers/pci/controller/dwc/pcie-designware.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 8ba239292634..13bffa3eaed6 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -179,6 +179,7 @@ struct dw_pcie_host_ops { struct pcie_port { bool has_msi_ctrl:1; + bool cfg0_io_shared:1; u64 cfg0_base; void __iomem *va_cfg0_base; u32 cfg0_size; @@ -274,7 +275,6 @@ struct dw_pcie { int link_gen; u8 n_fts[2]; bool iatu_unroll_enabled: 1; - bool io_cfg_atu_shared: 1; }; #define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp) -- cgit v1.2.3 From 60b3c27fb9b92b8b55cd8bdcc444c3f7cb556652 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 24 Jun 2022 17:34:25 +0300 Subject: PCI: dwc: Rename struct pcie_port to dw_pcie_rp All of the DW PCIe core driver entities except the pcie_port struct have names with the "dw_" prefix to distinguish local and common PCIe name spaces, and endpoint-related entities have an "_ep" suffix. Rename struct pcie_port to dw_pcie_rp to make it more consistent with other names. [bhelgaas: commit log] Link: https://lore.kernel.org/r/20220624143428.8334-16-Sergey.Semin@baikalelectronics.ru Signed-off-by: Serge Semin Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring Reviewed-by: Neil Armstrong Reviewed-by: Manivannan Sadhasivam Acked-by: Jesper Nilsson --- drivers/pci/controller/dwc/pcie-designware.h | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 13bffa3eaed6..32df3ebccf19 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -155,8 +155,8 @@ #define MAX_IATU_IN 256 #define MAX_IATU_OUT 256 -struct pcie_port; struct dw_pcie; +struct dw_pcie_rp; struct dw_pcie_ep; enum dw_pcie_region_type { @@ -173,11 +173,11 @@ enum dw_pcie_device_mode { }; struct dw_pcie_host_ops { - int (*host_init)(struct pcie_port *pp); - int (*msi_host_init)(struct pcie_port *pp); + int (*host_init)(struct dw_pcie_rp *pp); + int (*msi_host_init)(struct dw_pcie_rp *pp); }; -struct pcie_port { +struct dw_pcie_rp { bool has_msi_ctrl:1; bool cfg0_io_shared:1; u64 cfg0_base; @@ -267,7 +267,7 @@ struct dw_pcie { size_t atu_size; u32 num_ib_windows; u32 num_ob_windows; - struct pcie_port pp; + struct dw_pcie_rp pp; struct dw_pcie_ep ep; const struct dw_pcie_ops *ops; unsigned int version; @@ -380,33 +380,33 @@ static inline void dw_pcie_stop_link(struct dw_pcie *pci) } #ifdef CONFIG_PCIE_DW_HOST -irqreturn_t dw_handle_msi_irq(struct pcie_port *pp); -void dw_pcie_setup_rc(struct pcie_port *pp); -int dw_pcie_host_init(struct pcie_port *pp); -void dw_pcie_host_deinit(struct pcie_port *pp); -int dw_pcie_allocate_domains(struct pcie_port *pp); +irqreturn_t dw_handle_msi_irq(struct dw_pcie_rp *pp); +void dw_pcie_setup_rc(struct dw_pcie_rp *pp); +int dw_pcie_host_init(struct dw_pcie_rp *pp); +void dw_pcie_host_deinit(struct dw_pcie_rp *pp); +int dw_pcie_allocate_domains(struct dw_pcie_rp *pp); void __iomem *dw_pcie_own_conf_map_bus(struct pci_bus *bus, unsigned int devfn, int where); #else -static inline irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) +static inline irqreturn_t dw_handle_msi_irq(struct dw_pcie_rp *pp) { return IRQ_NONE; } -static inline void dw_pcie_setup_rc(struct pcie_port *pp) +static inline void dw_pcie_setup_rc(struct dw_pcie_rp *pp) { } -static inline int dw_pcie_host_init(struct pcie_port *pp) +static inline int dw_pcie_host_init(struct dw_pcie_rp *pp) { return 0; } -static inline void dw_pcie_host_deinit(struct pcie_port *pp) +static inline void dw_pcie_host_deinit(struct dw_pcie_rp *pp) { } -static inline int dw_pcie_allocate_domains(struct pcie_port *pp) +static inline int dw_pcie_allocate_domains(struct dw_pcie_rp *pp) { return 0; } -- cgit v1.2.3 From 996ab868d6302534c22d52075c71b97e4d70f519 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Tue, 21 Jun 2022 11:54:52 +0300 Subject: PCI: dwc: Move GEN3_RELATED DBI definitions to common header These are common dwc macros that will be used for other platforms. Link: https://lore.kernel.org/r/1c2d5a7a139be81fa15f356b2380163dbdebdc09.1655799816.git.baruch@tkos.co.il Signed-off-by: Baruch Siach Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring --- drivers/pci/controller/dwc/pcie-designware.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 7d6e9b7576be..ea87809ee298 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -74,6 +74,12 @@ #define PCIE_MSI_INTR0_MASK 0x82C #define PCIE_MSI_INTR0_STATUS 0x830 +#define GEN3_RELATED_OFF 0x890 +#define GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL BIT(0) +#define GEN3_RELATED_OFF_GEN3_EQ_DISABLE BIT(16) +#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_SHIFT 24 +#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK GENMASK(25, 24) + #define PCIE_PORT_MULTI_LANE_CTRL 0x8C0 #define PORT_MLTI_UPCFG_SUPPORT BIT(7) -- cgit v1.2.3 From 0cf7c2efe8ac76bb6b90abc64bcf8df124509d7d Mon Sep 17 00:00:00 2001 From: Selvam Sathappan Periakaruppan Date: Tue, 21 Jun 2022 11:54:54 +0300 Subject: PCI: qcom: Add IPQ60xx support IPQ60xx series of SoCs have one port of PCIe gen 3. Add support for that platform. The code is based on downstream[1] Codeaurora kernel v5.4 (branch win.linuxopenwrt.2.0). Split out the DBI registers access part from .init into .post_init. DBI registers are only accessible after phy_power_on(). [1] https://source.codeaurora.org/quic/qsdk/oss/kernel/linux-ipq-5.4/ Link: https://lore.kernel.org/r/f7f848653c99abbf9a0f877949a44e52329543ae.1655799816.git.baruch@tkos.co.il Tested-by: Robert Marko Signed-off-by: Selvam Sathappan Periakaruppan Signed-off-by: Baruch Siach Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring Reviewed-by: Johan Hovold Acked-by: Stanimir Varbanov --- drivers/pci/controller/dwc/pcie-designware.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index ea87809ee298..279c3778a13b 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -76,6 +76,7 @@ #define GEN3_RELATED_OFF 0x890 #define GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL BIT(0) +#define GEN3_RELATED_OFF_RXEQ_RGRDLESS_RXTS BIT(13) #define GEN3_RELATED_OFF_GEN3_EQ_DISABLE BIT(16) #define GEN3_RELATED_OFF_RATE_SHADOW_SEL_SHIFT 24 #define GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK GENMASK(25, 24) -- cgit v1.2.3 From 997b99e3b386bde1d519d39f5276b10c67a8f172 Mon Sep 17 00:00:00 2001 From: Vidya Sagar Date: Thu, 21 Jul 2022 19:50:45 +0530 Subject: PCI: tegra194: Find RAS DES PCIe capability offset Find RAS DES PCIe capability offset instead of hardcoding the offset for each controller. Link: https://lore.kernel.org/r/20220721142052.25971-10-vidyas@nvidia.com Signed-off-by: Vidya Sagar Signed-off-by: Bjorn Helgaas --- drivers/pci/controller/dwc/pcie-designware.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 7d6e9b7576be..56d93e67a964 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -130,6 +130,25 @@ #define PCIE_ATU_UNR_UPPER_TARGET 0x18 #define PCIE_ATU_UNR_UPPER_LIMIT 0x20 +/* + * RAS-DES register definitions + */ +#define PCIE_RAS_DES_EVENT_COUNTER_CONTROL 0x8 +#define EVENT_COUNTER_ALL_CLEAR 0x3 +#define EVENT_COUNTER_ENABLE_ALL 0x7 +#define EVENT_COUNTER_ENABLE_SHIFT 2 +#define EVENT_COUNTER_EVENT_SEL_MASK GENMASK(7, 0) +#define EVENT_COUNTER_EVENT_SEL_SHIFT 16 +#define EVENT_COUNTER_EVENT_Tx_L0S 0x2 +#define EVENT_COUNTER_EVENT_Rx_L0S 0x3 +#define EVENT_COUNTER_EVENT_L1 0x5 +#define EVENT_COUNTER_EVENT_L1_1 0x7 +#define EVENT_COUNTER_EVENT_L1_2 0x8 +#define EVENT_COUNTER_GROUP_SEL_SHIFT 24 +#define EVENT_COUNTER_GROUP_5 0x5 + +#define PCIE_RAS_DES_EVENT_COUNTER_DATA 0xc + /* * The default address offset between dbi_base and atu_base. Root controller * drivers are not required to initialize atu_base if the offset matches this -- cgit v1.2.3 From afe1c6d50d33ea7d888b0105670fb2aaa5abf495 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 24 Jun 2022 17:39:35 +0300 Subject: PCI: dwc: Use native DWC IP core version representation Save the DWC IP core version in the same format as the PORT_LOGIC.PCIE_VERSION_OFF register, similar to what other drivers for DWC IP do (dw_spi_hw_init(), dwc3_core_is_valid(), stmmac_hwif_init()). [bhelgaas: trim commit log] Link: https://lore.kernel.org/r/20220624143947.8991-4-Sergey.Semin@baikalelectronics.ru Signed-off-by: Serge Semin Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring Reviewed-by: Manivannan Sadhasivam --- drivers/pci/controller/dwc/pcie-designware.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 32df3ebccf19..6b81530fb2ca 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -20,6 +20,14 @@ #include #include +/* DWC PCIe IP-core versions (native support since v4.70a) */ +#define DW_PCIE_VER_365A 0x3336352a +#define DW_PCIE_VER_460A 0x3436302a +#define DW_PCIE_VER_470A 0x3437302a +#define DW_PCIE_VER_480A 0x3438302a +#define DW_PCIE_VER_490A 0x3439302a +#define DW_PCIE_VER_520A 0x3532302a + /* Parameters for the waiting for link up routine */ #define LINK_WAIT_MAX_RETRIES 10 #define LINK_WAIT_USLEEP_MIN 90000 @@ -270,7 +278,7 @@ struct dw_pcie { struct dw_pcie_rp pp; struct dw_pcie_ep ep; const struct dw_pcie_ops *ops; - unsigned int version; + u32 version; int num_lanes; int link_gen; u8 n_fts[2]; -- cgit v1.2.3 From 13e9d3900c20247993db68856d9898161acb403a Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 24 Jun 2022 17:39:36 +0300 Subject: PCI: dwc: Read DWC IP core version from register Since DWC PCIe v4.70a, the controller version and version type can be read from the PORT_LOGIC.PCIE_VERSION_OFF and PORT_LOGIC.PCIE_VERSION_TYPE_OFF registers respectively. Read the version from those registers and warn if if's different from the version we got from the device tree. We can only read the version after platform-specific drivers have done any DBI-related initialization, such as reference clock activation. [bhelgaas: commit log] Link: https://lore.kernel.org/r/20220624143947.8991-5-Sergey.Semin@baikalelectronics.ru Signed-off-by: Serge Semin Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring Reviewed-by: Manivannan Sadhasivam --- drivers/pci/controller/dwc/pcie-designware.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 6b81530fb2ca..7899808bdbc6 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -85,6 +85,9 @@ #define PCIE_PORT_MULTI_LANE_CTRL 0x8C0 #define PORT_MLTI_UPCFG_SUPPORT BIT(7) +#define PCIE_VERSION_NUMBER 0x8F8 +#define PCIE_VERSION_TYPE 0x8FC + #define PCIE_ATU_VIEWPORT 0x900 #define PCIE_ATU_REGION_INBOUND BIT(31) #define PCIE_ATU_REGION_OUTBOUND 0 @@ -279,6 +282,7 @@ struct dw_pcie { struct dw_pcie_ep ep; const struct dw_pcie_ops *ops; u32 version; + u32 type; int num_lanes; int link_gen; u8 n_fts[2]; @@ -290,6 +294,8 @@ struct dw_pcie { #define to_dw_pcie_from_ep(endpoint) \ container_of((endpoint), struct dw_pcie, ep) +void dw_pcie_version_detect(struct dw_pcie *pci); + u8 dw_pcie_find_capability(struct dw_pcie *pci, u8 cap); u16 dw_pcie_find_ext_capability(struct dw_pcie *pci, u8 cap); -- cgit v1.2.3 From 0b0a780d52ad2bd51e4e154c190abcfed43e33bb Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 24 Jun 2022 17:39:37 +0300 Subject: PCI: dwc: Add macros to compare Synopsys IP core versions Add macros to compare DWC IP core versions: dw_pcie_ver_is() dw_pcie_ver_is_ge() dw_pcie_ver_type_is() dw_pcie_ver_type_is_ge() These are along the lines of DWC3_VER_IS() and dw_spi_ver_is(). [bhelgaas: commit log] Link: https://lore.kernel.org/r/20220624143947.8991-6-Sergey.Semin@baikalelectronics.ru Signed-off-by: Serge Semin Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring --- drivers/pci/controller/dwc/pcie-designware.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 7899808bdbc6..d247f227464c 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -28,6 +28,21 @@ #define DW_PCIE_VER_490A 0x3439302a #define DW_PCIE_VER_520A 0x3532302a +#define __dw_pcie_ver_cmp(_pci, _ver, _op) \ + ((_pci)->version _op DW_PCIE_VER_ ## _ver) + +#define dw_pcie_ver_is(_pci, _ver) __dw_pcie_ver_cmp(_pci, _ver, ==) + +#define dw_pcie_ver_is_ge(_pci, _ver) __dw_pcie_ver_cmp(_pci, _ver, >=) + +#define dw_pcie_ver_type_is(_pci, _ver, _type) \ + (__dw_pcie_ver_cmp(_pci, _ver, ==) && \ + __dw_pcie_ver_cmp(_pci, TYPE_ ## _type, ==)) + +#define dw_pcie_ver_type_is_ge(_pci, _ver, _type) \ + (__dw_pcie_ver_cmp(_pci, _ver, ==) && \ + __dw_pcie_ver_cmp(_pci, TYPE_ ## _type, >=)) + /* Parameters for the waiting for link up routine */ #define LINK_WAIT_MAX_RETRIES 10 #define LINK_WAIT_USLEEP_MIN 90000 -- cgit v1.2.3 From c6481d51dc65f27cf35df499d1cafbfe9327f7a3 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 24 Jun 2022 17:39:40 +0300 Subject: PCI: dwc: Add dw_pcie_ops.host_deinit() callback dw_pcie_host_init() calls the dw_pcie_ops.host_init() callback to do platform-specific host initialization. Add a dw_pcie_ops.host_deinit() callback to perform the corresponding cleanups in dw_pcie_host_deinit() and in dw_pcie_host_init() failure paths. Link: https://lore.kernel.org/r/20220624143947.8991-9-Sergey.Semin@baikalelectronics.ru Signed-off-by: Serge Semin Signed-off-by: Bjorn Helgaas Reviewed-by: Manivannan Sadhasivam --- drivers/pci/controller/dwc/pcie-designware.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index d247f227464c..7f1c00fa084d 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -200,6 +200,7 @@ enum dw_pcie_device_mode { struct dw_pcie_host_ops { int (*host_init)(struct dw_pcie_rp *pp); + void (*host_deinit)(struct dw_pcie_rp *pp); int (*msi_host_init)(struct dw_pcie_rp *pp); }; -- cgit v1.2.3 From 4859db9bca5daafc4ec9ef4e5aab9e054b483e0c Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 24 Jun 2022 17:39:41 +0300 Subject: PCI: dwc: Drop enum dw_pcie_as_type in favor of PCIE_ATU_TYPE_MEM/IO Previously dw_pcie_ep_set_bar() converted the BAR PCI_BASE_ADDRESS_SPACE bit to the internal dw_pcie_as_type enum (DW_PCIE_AS_MEM, DW_PCIE_AS_IO) and passed it down to dw_pcie_prog_inbound_atu(), which converted the enum to the PCIE_ATU_TYPE_MEM/PCIE_ATU_TYPE_IO values needed to program the ATU registers. Simplify the code by dropping the dw_pcie_as_type enum and passing PCIE_ATU_TYPE_MEM or PCIE_ATU_TYPE_IO directly. Reorder inbound ATU function arguments to match the outbound functions, with address-related parameters at the end. [bhelgaas: commit log] Link: https://lore.kernel.org/r/20220624143947.8991-10-Sergey.Semin@baikalelectronics.ru Signed-off-by: Serge Semin Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring Reviewed-by: Manivannan Sadhasivam --- drivers/pci/controller/dwc/pcie-designware.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 7f1c00fa084d..c63ace3c3f25 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -228,12 +228,6 @@ struct dw_pcie_rp { DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS); }; -enum dw_pcie_as_type { - DW_PCIE_AS_UNKNOWN, - DW_PCIE_AS_MEM, - DW_PCIE_AS_IO, -}; - struct dw_pcie_ep_ops { void (*ep_init)(struct dw_pcie_ep *ep); int (*raise_irq)(struct dw_pcie_ep *ep, u8 func_no, @@ -331,8 +325,7 @@ void dw_pcie_prog_ep_outbound_atu(struct dw_pcie *pci, u8 func_no, int index, int type, u64 cpu_addr, u64 pci_addr, u64 size); int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, u8 func_no, int index, - int bar, u64 cpu_addr, - enum dw_pcie_as_type as_type); + int type, u64 cpu_addr, u8 bar); void dw_pcie_disable_atu(struct dw_pcie *pci, int index, enum dw_pcie_region_type type); void dw_pcie_setup(struct dw_pcie *pci); -- cgit v1.2.3 From 38fe272389f44c223c689d74d9e2365257ed85e1 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 24 Jun 2022 17:39:42 +0300 Subject: PCI: dwc: Drop enum dw_pcie_region_type in favor of PCIE_ATU_REGION_DIR_IB/OB Previously callers of dw_pcie_disable_atu() supplied enum dw_pcie_region_type (DW_PCIE_REGION_INBOUND, DW_PCIE_REGION_OUTBOUND), which dw_pcie_disable_atu() converted to the PCIE_ATU_REGION_DIR_IB or PCIE_ATU_REGION_DIR_OB values needed to program the ATU registers. Simplify the code by dropping the dw_pcie_region_type enum and passing PCIE_ATU_REGION_DIR_IB or PCIE_ATU_REGION_DIR_OB directly. Reorder dw_pcie_disable_atu() arguments to (dir, index) since "index" indicates an ATU window in the regions of the corresponding direction. [bhelgaas: commit log] Link: https://lore.kernel.org/r/20220624143947.8991-11-Sergey.Semin@baikalelectronics.ru Signed-off-by: Serge Semin Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring Reviewed-by: Manivannan Sadhasivam --- drivers/pci/controller/dwc/pcie-designware.h | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index c63ace3c3f25..72d185ff72f3 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -104,8 +104,8 @@ #define PCIE_VERSION_TYPE 0x8FC #define PCIE_ATU_VIEWPORT 0x900 -#define PCIE_ATU_REGION_INBOUND BIT(31) -#define PCIE_ATU_REGION_OUTBOUND 0 +#define PCIE_ATU_REGION_DIR_IB BIT(31) +#define PCIE_ATU_REGION_DIR_OB 0 #define PCIE_ATU_CR1 0x904 #define PCIE_ATU_INCREASE_REGION_SIZE BIT(13) #define PCIE_ATU_TYPE_MEM 0x0 @@ -185,12 +185,6 @@ struct dw_pcie; struct dw_pcie_rp; struct dw_pcie_ep; -enum dw_pcie_region_type { - DW_PCIE_REGION_UNKNOWN, - DW_PCIE_REGION_INBOUND, - DW_PCIE_REGION_OUTBOUND, -}; - enum dw_pcie_device_mode { DW_PCIE_UNKNOWN_TYPE, DW_PCIE_EP_TYPE, @@ -326,8 +320,7 @@ void dw_pcie_prog_ep_outbound_atu(struct dw_pcie *pci, u8 func_no, int index, u64 size); int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, u8 func_no, int index, int type, u64 cpu_addr, u8 bar); -void dw_pcie_disable_atu(struct dw_pcie *pci, int index, - enum dw_pcie_region_type type); +void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index); void dw_pcie_setup(struct dw_pcie *pci); void dw_pcie_iatu_detect(struct dw_pcie *pci); -- cgit v1.2.3 From 5a163f5998185d3af58d825501765b08fd6ed32e Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 24 Jun 2022 17:39:43 +0300 Subject: PCI: dwc: Simplify in/outbound iATU setup methods Previously __dw_pcie_prog_outbound_atu() duplicated a lot of code between the iatu_unroll_enabled version and the PCIE_ATU_VIEWPORT version: __dw_pcie_prog_outbound_atu if (iatu_unroll_enabled) dw_pcie_prog_outbound_atu_unroll dw_pcie_writel_ob_unroll(PCIE_ATU_UNR_LOWER_BASE, ...) dw_pcie_writel_ob_unroll(PCIE_ATU_UNR_UPPER_BASE, ...) ... return dw_pcie_writel_dbi(PCIE_ATU_VIEWPORT, ...) dw_pcie_writel_dbi(PCIE_ATU_LOWER_BASE, ...) dw_pcie_writel_dbi(PCIE_ATU_UPPER_BASE, ...) ... Unify those by pushing the unroll address computation and viewport selection down into dw_pcie_writel_atu() so we can use the same dw_pcie_writel_atu_ob() accessor for both paths: __dw_pcie_prog_outbound_atu dw_pcie_writel_atu_ob(PCIE_ATU_LOWER_BASE, ...) dw_pcie_writel_atu dw_pcie_select_atu # new if (iatu_unroll_enabled) return pci->atu_base + PCIE_ATU_UNROLL_BASE(...) dw_pcie_writel_dbi(PCIE_ATU_VIEWPORT, ...) return pci->atu_base dw_pcie_write(base + reg) dw_pcie_writel_atu_ob(PCIE_ATU_UPPER_BASE, ...) ... In the non-unroll case, this does involve more MMIO writes to PCIE_ATU_VIEWPORT, but it's mainly in initialization paths and the code simplification is significant. [bhelgaas: commit log, simplify dw_pcie_select_atu()] Link: https://lore.kernel.org/r/20220624143947.8991-12-Sergey.Semin@baikalelectronics.ru Signed-off-by: Serge Semin Signed-off-by: Bjorn Helgaas --- drivers/pci/controller/dwc/pcie-designware.h | 48 +++++++++++----------------- 1 file changed, 19 insertions(+), 29 deletions(-) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 72d185ff72f3..c18f0db09b31 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -103,10 +103,21 @@ #define PCIE_VERSION_NUMBER 0x8F8 #define PCIE_VERSION_TYPE 0x8FC +/* + * iATU inbound and outbound windows CSRs. Before the IP-core v4.80a each + * iATU region CSRs had been indirectly accessible by means of the dedicated + * viewport selector. The iATU/eDMA CSRs space was re-designed in DWC PCIe + * v4.80a in a way so the viewport was unrolled into the directly accessible + * iATU/eDMA CSRs space. + */ #define PCIE_ATU_VIEWPORT 0x900 #define PCIE_ATU_REGION_DIR_IB BIT(31) #define PCIE_ATU_REGION_DIR_OB 0 -#define PCIE_ATU_CR1 0x904 +#define PCIE_ATU_VIEWPORT_BASE 0x904 +#define PCIE_ATU_UNROLL_BASE(dir, index) \ + (((index) << 9) | ((dir == PCIE_ATU_REGION_DIR_IB) ? BIT(8) : 0)) +#define PCIE_ATU_VIEWPORT_SIZE 0x2C +#define PCIE_ATU_REGION_CTRL1 0x000 #define PCIE_ATU_INCREASE_REGION_SIZE BIT(13) #define PCIE_ATU_TYPE_MEM 0x0 #define PCIE_ATU_TYPE_IO 0x2 @@ -114,19 +125,19 @@ #define PCIE_ATU_TYPE_CFG1 0x5 #define PCIE_ATU_TD BIT(8) #define PCIE_ATU_FUNC_NUM(pf) ((pf) << 20) -#define PCIE_ATU_CR2 0x908 +#define PCIE_ATU_REGION_CTRL2 0x004 #define PCIE_ATU_ENABLE BIT(31) #define PCIE_ATU_BAR_MODE_ENABLE BIT(30) #define PCIE_ATU_FUNC_NUM_MATCH_EN BIT(19) -#define PCIE_ATU_LOWER_BASE 0x90C -#define PCIE_ATU_UPPER_BASE 0x910 -#define PCIE_ATU_LIMIT 0x914 -#define PCIE_ATU_LOWER_TARGET 0x918 +#define PCIE_ATU_LOWER_BASE 0x008 +#define PCIE_ATU_UPPER_BASE 0x00C +#define PCIE_ATU_LIMIT 0x010 +#define PCIE_ATU_LOWER_TARGET 0x014 #define PCIE_ATU_BUS(x) FIELD_PREP(GENMASK(31, 24), x) #define PCIE_ATU_DEV(x) FIELD_PREP(GENMASK(23, 19), x) #define PCIE_ATU_FUNC(x) FIELD_PREP(GENMASK(18, 16), x) -#define PCIE_ATU_UPPER_TARGET 0x91C -#define PCIE_ATU_UPPER_LIMIT 0x924 +#define PCIE_ATU_UPPER_TARGET 0x018 +#define PCIE_ATU_UPPER_LIMIT 0x020 #define PCIE_MISC_CONTROL_1_OFF 0x8BC #define PCIE_DBI_RO_WR_EN BIT(0) @@ -143,19 +154,6 @@ #define PCIE_PL_CHK_REG_ERR_ADDR 0xB28 -/* - * iATU Unroll-specific register definitions - * From 4.80 core version the address translation will be made by unroll - */ -#define PCIE_ATU_UNR_REGION_CTRL1 0x00 -#define PCIE_ATU_UNR_REGION_CTRL2 0x04 -#define PCIE_ATU_UNR_LOWER_BASE 0x08 -#define PCIE_ATU_UNR_UPPER_BASE 0x0C -#define PCIE_ATU_UNR_LOWER_LIMIT 0x10 -#define PCIE_ATU_UNR_LOWER_TARGET 0x14 -#define PCIE_ATU_UNR_UPPER_TARGET 0x18 -#define PCIE_ATU_UNR_UPPER_LIMIT 0x20 - /* * The default address offset between dbi_base and atu_base. Root controller * drivers are not required to initialize atu_base if the offset matches this @@ -164,13 +162,6 @@ */ #define DEFAULT_DBI_ATU_OFFSET (0x3 << 20) -/* Register address builder */ -#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) \ - ((region) << 9) - -#define PCIE_GET_ATU_INB_UNR_REG_OFFSET(region) \ - (((region) << 9) | BIT(8)) - #define MAX_MSI_IRQS 256 #define MAX_MSI_IRQS_PER_CTRL 32 #define MAX_MSI_CTRLS (MAX_MSI_IRQS / MAX_MSI_IRQS_PER_CTRL) @@ -277,7 +268,6 @@ struct dw_pcie { struct device *dev; void __iomem *dbi_base; void __iomem *dbi_base2; - /* Used when iatu_unroll_enabled is true */ void __iomem *atu_base; size_t atu_size; u32 num_ib_windows; -- cgit v1.2.3 From 89473aa9ab261948ed13b16effe841a675efed77 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 24 Jun 2022 17:39:44 +0300 Subject: PCI: dwc: Add iATU regions size detection procedure The DWC PCIe RC/EP/DM IP core configuration parameters determine the number of inbound and outbound iATU windows, alignment requirements (which is also the minimum window size), minimum and maximum sizes. If internal ATU is enabled, the former settings are determined by CX_ATU_MIN_REGION_SIZE; the latter are determined by CX_ATU_MAX_REGION_SIZE. Determine the required alignment and maximum size supported by the controller and log it to help verify whether the requested inbound or outbound memory mappings can be fully created. Note 1. The extended iATU regions have been supported since DWC PCIe v4.60a. There is no need in testing the upper limit register availability for the older cores. Note 2. The regions alignment is determined with using the fls() method since the lower four bits of the ATU Limit register can be occupied with the Circular Buffer Increment setting, which can be initialized with zeros. Link: https://lore.kernel.org/r/20220624143947.8991-13-Sergey.Semin@baikalelectronics.ru Signed-off-by: Serge Semin Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring Reviewed-by: Manivannan Sadhasivam --- drivers/pci/controller/dwc/pcie-designware.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index c18f0db09b31..25c86771c810 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -272,6 +272,8 @@ struct dw_pcie { size_t atu_size; u32 num_ib_windows; u32 num_ob_windows; + u32 region_align; + u64 region_limit; struct dw_pcie_rp pp; struct dw_pcie_ep ep; const struct dw_pcie_ops *ops; -- cgit v1.2.3 From edf408b946d37cc70fbf0db6ab85bbf67dae1894 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 24 Jun 2022 17:39:45 +0300 Subject: PCI: dwc: Validate iATU outbound mappings against hardware constraints Make __dw_pcie_prog_outbound_atu() check the requested region base and size against what the hardware can support. Return error if the region is not correctly aligned or of a supported size. [bhelgaas: commit log] Link: https://lore.kernel.org/r/20220624143947.8991-14-Sergey.Semin@baikalelectronics.ru Signed-off-by: Serge Semin Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring Reviewed-by: Manivannan Sadhasivam --- drivers/pci/controller/dwc/pcie-designware.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 25c86771c810..60f1ddc54933 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -304,12 +304,10 @@ void dw_pcie_write_dbi2(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); 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, - u64 size); -void dw_pcie_prog_ep_outbound_atu(struct dw_pcie *pci, u8 func_no, int index, - int type, u64 cpu_addr, u64 pci_addr, - u64 size); +int dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type, + u64 cpu_addr, u64 pci_addr, u64 size); +int dw_pcie_prog_ep_outbound_atu(struct dw_pcie *pci, u8 func_no, int index, + int type, u64 cpu_addr, u64 pci_addr, u64 size); int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, u8 func_no, int index, int type, u64 cpu_addr, u8 bar); void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index); -- cgit v1.2.3 From ce06bf570390fb8b41d581e5d594727b51367179 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 24 Jun 2022 17:39:46 +0300 Subject: PCI: dwc: Check iATU in/outbound range setup status Make the DWC PCIe RC/EP safer and more verbose for invalid or failed inbound and outbound iATU window setups. Silently ignoring iATU regions setup errors may cause unpredictable errors. For instance if a cfg or IO window fails to be activated, then any CFG/IO requested won't reach target PCIe devices and the corresponding accessors will return platform-specific random values. [bhelgaas: trim commit log] Link: https://lore.kernel.org/r/20220624143947.8991-15-Sergey.Semin@baikalelectronics.ru Signed-off-by: Serge Semin Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring Reviewed-by: Manivannan Sadhasivam --- drivers/pci/controller/dwc/pcie-designware.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 60f1ddc54933..c3e73ed9aff5 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -387,7 +387,7 @@ static inline void dw_pcie_stop_link(struct dw_pcie *pci) #ifdef CONFIG_PCIE_DW_HOST irqreturn_t dw_handle_msi_irq(struct dw_pcie_rp *pp); -void dw_pcie_setup_rc(struct dw_pcie_rp *pp); +int dw_pcie_setup_rc(struct dw_pcie_rp *pp); int dw_pcie_host_init(struct dw_pcie_rp *pp); void dw_pcie_host_deinit(struct dw_pcie_rp *pp); int dw_pcie_allocate_domains(struct dw_pcie_rp *pp); @@ -399,8 +399,9 @@ static inline irqreturn_t dw_handle_msi_irq(struct dw_pcie_rp *pp) return IRQ_NONE; } -static inline void dw_pcie_setup_rc(struct dw_pcie_rp *pp) +static inline int dw_pcie_setup_rc(struct dw_pcie_rp *pp) { + return 0; } static inline int dw_pcie_host_init(struct dw_pcie_rp *pp) -- cgit v1.2.3 From 35797e672ff0610224d80e3cc08393fef1032f9a Mon Sep 17 00:00:00 2001 From: Will McVicker Date: Mon, 13 Jun 2022 17:26:11 -0500 Subject: PCI: dwc: Fix MSI msi_msg DMA mapping As of 07940c369a6b ("PCI: dwc: Fix MSI page leakage in suspend/resume"), the PCIe designware host driver has been using the driver data allocation for the msi_msg DMA mapping which can result in a DMA_MAPPING_ERROR due to the DMA overflow check in dma_direct_map_page() when the address is greater than 32 bits (reported in [1]). The commit was trying to address a memory leak on suspend/resume by moving the MSI mapping to dw_pcie_host_init(), but subsequently dropped the page allocation thinking it wasn't needed. To fix the DMA mapping issue as well as make msi_msg DMA'able, switch back to allocating a 32-bit page for the msi_msg. To avoid the suspend/resume leak, allocate the page in dw_pcie_host_init() since that shouldn't be called during suspend/resume. [1] https://lore.kernel.org/all/Yo0soniFborDl7+C@google.com/ Signed-off-by: Will McVicker Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring --- drivers/pci/controller/dwc/pcie-designware.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index c3e73ed9aff5..7c63204d23ba 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -203,8 +203,8 @@ struct dw_pcie_rp { int msi_irq; struct irq_domain *irq_domain; struct irq_domain *msi_domain; - u16 msi_msg; dma_addr_t msi_data; + struct page *msi_page; struct irq_chip *msi_irq_chip; u32 num_vectors; u32 irq_mask[MAX_MSI_CTRLS]; -- cgit v1.2.3 From db388348acffe954656ec38440809ec770707417 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 22 Jul 2022 11:34:12 -0500 Subject: PCI: dwc: Convert struct pcie_port.msi_irq to an array The Qualcomm DWC PCIe controller supports more than 32 MSI interrupts, but they are routed to separate interrupts in groups of 32 vectors. To support this configuration, change the msi_irq field to an array. Let the DWC core handle all interrupts that were set in this array. [bhelgaas: reorder, drop "irq" temporary to make patch cleaner] Link: https://lore.kernel.org/r/20220707134733.2436629-3-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring Reviewed-by: Johan Hovold Reviewed-by: Manivannan Sadhasivam --- drivers/pci/controller/dwc/pcie-designware.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci/controller/dwc/pcie-designware.h') diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 7c63204d23ba..16489c629ac2 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -200,7 +200,7 @@ struct dw_pcie_rp { u32 io_size; int irq; const struct dw_pcie_host_ops *ops; - int msi_irq; + int msi_irq[MAX_MSI_CTRLS]; struct irq_domain *irq_domain; struct irq_domain *msi_domain; dma_addr_t msi_data; -- cgit v1.2.3