PCI: dwc: Read DWC IP core version from register
authorSerge Semin <Sergey.Semin@baikalelectronics.ru>
Fri, 24 Jun 2022 14:39:36 +0000 (17:39 +0300)
committerBjorn Helgaas <bhelgaas@google.com>
Mon, 1 Aug 2022 20:02:11 +0000 (15:02 -0500)
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 <Sergey.Semin@baikalelectronics.ru>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
drivers/pci/controller/dwc/pcie-designware-ep.c
drivers/pci/controller/dwc/pcie-designware-host.c
drivers/pci/controller/dwc/pcie-designware.c
drivers/pci/controller/dwc/pcie-designware.h

index 1e35542d6f725a1a6f20fb91c9649cfc798d8c09..ffbd3af6d65a275e4aede2f37b49737bd1412ca3 100644 (file)
@@ -711,6 +711,8 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
        ep->phys_base = res->start;
        ep->addr_size = resource_size(res);
 
+       dw_pcie_version_detect(pci);
+
        dw_pcie_iatu_detect(pci);
 
        ep->ib_window_map = devm_kcalloc(dev,
index 1314bb128128155ee92df49283d91dc7458137ea..479ab6cadbac58a6c71fea80d27a8e0df9cb4ddb 100644 (file)
@@ -405,6 +405,8 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
                }
        }
 
+       dw_pcie_version_detect(pci);
+
        dw_pcie_iatu_detect(pci);
 
        dw_pcie_setup_rc(pp);
index f10a7d5d94e8630e7b8268dd45d82ce04ebb35d8..cbb36ccaa48be6038cf739db20d8513d3cc0e51f 100644 (file)
 #include "../../pci.h"
 #include "pcie-designware.h"
 
+void dw_pcie_version_detect(struct dw_pcie *pci)
+{
+       u32 ver;
+
+       /* The content of the CSR is zero on DWC PCIe older than v4.70a */
+       ver = dw_pcie_readl_dbi(pci, PCIE_VERSION_NUMBER);
+       if (!ver)
+               return;
+
+       if (pci->version && pci->version != ver)
+               dev_warn(pci->dev, "Versions don't match (%08x != %08x)\n",
+                        pci->version, ver);
+       else
+               pci->version = ver;
+
+       ver = dw_pcie_readl_dbi(pci, PCIE_VERSION_TYPE);
+
+       if (pci->type && pci->type != ver)
+               dev_warn(pci->dev, "Types don't match (%08x != %08x)\n",
+                        pci->type, ver);
+       else
+               pci->type = ver;
+}
+
 /*
  * These interfaces resemble the pci_find_*capability() interfaces, but these
  * are for configuring host controllers, which are bridges *to* PCI devices but
index 6b81530fb2ca8f5f1c6135d6cdb2a6645496587f..7899808bdbc61869bd395c3ab718901c12be04ed 100644 (file)
@@ -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);