Message ID | 20220624143947.8991-5-Sergey.Semin@baikalelectronics.ru (mailing list archive) |
---|---|
State | Accepted |
Commit | 4519a771236c7c59794711283bebedad266d5a12 |
Headers | show |
Series | PCI: dwc: Add hw version and dma-ranges support | expand |
On Fri, Jun 24, 2022 at 05:39:36PM +0300, Serge Semin wrote: > 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. Seeing the generic code has got version-dependent > parts let's use these registers to find out the controller version. The > detection procedure is executed for both RC and EP modes right after the > platform-specific initialization. We can't do that earlier since the > glue-drivers can perform the DBI-related setups there including the bus > reference clocks activation, without which the CSRs just can't be read. > > Note the CSRs content is zero on the older DWC PCIe controller. In that > case we have no choice but to rely on the platform setup. > > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru> Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> > Reviewed-by: Rob Herring <robh@kernel.org> > > --- > > Changelog v2: > - Move the IP-core version detection procedure call from > dw_pcie_ep_init_complete() to dw_pcie_ep_init(). > --- > .../pci/controller/dwc/pcie-designware-ep.c | 2 ++ > .../pci/controller/dwc/pcie-designware-host.c | 2 ++ > drivers/pci/controller/dwc/pcie-designware.c | 24 +++++++++++++++++++ > drivers/pci/controller/dwc/pcie-designware.h | 6 +++++ > 4 files changed, 34 insertions(+) > > diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c > index 1e35542d6f72..ffbd3af6d65a 100644 > --- a/drivers/pci/controller/dwc/pcie-designware-ep.c > +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c > @@ -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); > + There is still an ongoing debate about moving all DBI accesses to init_complete. But this is fine atm. Thanks, Mani > dw_pcie_iatu_detect(pci); > > ep->ib_window_map = devm_kcalloc(dev, > diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c > index 95256434913f..b1437b37140f 100644 > --- a/drivers/pci/controller/dwc/pcie-designware-host.c > +++ b/drivers/pci/controller/dwc/pcie-designware-host.c > @@ -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); > diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c > index f10a7d5d94e8..cbb36ccaa48b 100644 > --- a/drivers/pci/controller/dwc/pcie-designware.c > +++ b/drivers/pci/controller/dwc/pcie-designware.c > @@ -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 > 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); > > -- > 2.35.1 >
On Mon, Aug 01, 2022 at 06:42:19PM +0530, Manivannan Sadhasivam wrote: > On Fri, Jun 24, 2022 at 05:39:36PM +0300, Serge Semin wrote: > > 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. Seeing the generic code has got version-dependent > > parts let's use these registers to find out the controller version. The > > detection procedure is executed for both RC and EP modes right after the > > platform-specific initialization. We can't do that earlier since the > > glue-drivers can perform the DBI-related setups there including the bus > > reference clocks activation, without which the CSRs just can't be read. > > > > Note the CSRs content is zero on the older DWC PCIe controller. In that > > case we have no choice but to rely on the platform setup. > > > > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru> > > Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> > > > Reviewed-by: Rob Herring <robh@kernel.org> > > @@ -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); > > + > > There is still an ongoing debate about moving all DBI accesses to > init_complete. But this is fine atm. Well, if I understand it correctly, e966f7390da9 ("PCI: dwc: Refactor core initialization code for EP mode") claims that all DBI accesses should be in dw_pcie_ep_init_complete(), so it's not so much a debate as a discussion about how best to achieve that. But you're right, we can fix that up later if necessary. > > dw_pcie_iatu_detect(pci);
On Mon, Aug 01, 2022 at 03:06:06PM -0500, Bjorn Helgaas wrote: > On Mon, Aug 01, 2022 at 06:42:19PM +0530, Manivannan Sadhasivam wrote: > > On Fri, Jun 24, 2022 at 05:39:36PM +0300, Serge Semin wrote: > > > 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. Seeing the generic code has got version-dependent > > > parts let's use these registers to find out the controller version. The > > > detection procedure is executed for both RC and EP modes right after the > > > platform-specific initialization. We can't do that earlier since the > > > glue-drivers can perform the DBI-related setups there including the bus > > > reference clocks activation, without which the CSRs just can't be read. > > > > > > Note the CSRs content is zero on the older DWC PCIe controller. In that > > > case we have no choice but to rely on the platform setup. > > > > > > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru> > > > > Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> > > > > > Reviewed-by: Rob Herring <robh@kernel.org> > > > > @@ -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); > > > + > > > > There is still an ongoing debate about moving all DBI accesses to > > init_complete. But this is fine atm. > > Well, if I understand it correctly, e966f7390da9 ("PCI: dwc: Refactor > core initialization code for EP mode") claims that all DBI accesses > should be in dw_pcie_ep_init_complete(), so it's not so much a debate > as a discussion about how best to achieve that. > Glad to know that we are on the same page. Let's continue the discussion in that thread. Thanks, Mani > But you're right, we can fix that up later if necessary. > > > > dw_pcie_iatu_detect(pci);
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index 1e35542d6f72..ffbd3af6d65a 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -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, diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 95256434913f..b1437b37140f 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -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); diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index f10a7d5d94e8..cbb36ccaa48b 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -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 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);