Commit 13e9d390 authored by Serge Semin's avatar Serge Semin Committed by Bjorn Helgaas
Browse files

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: default avatarSerge Semin <Sergey.Semin@baikalelectronics.ru>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarRob Herring <robh@kernel.org>
Reviewed-by: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
parent afe1c6d5
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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,
+2 −0
Original line number Diff line number Diff line
@@ -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);
+24 −0
Original line number Diff line number Diff line
@@ -16,6 +16,30 @@
#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
+6 −0
Original line number Diff line number Diff line
@@ -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);