Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1718838 > unrolled thread
| Started by | Oza Pawandeep <oza.oza@broadcom.com> |
|---|---|
| First post | 2017-08-24 07:10 +0200 |
| Last post | 2017-08-24 07:10 +0200 |
| Articles | 2 — 1 participant |
Back to article view | Back to linux.kernel
[PATCH v8 0/3] PCI: iproc: SOC specific fixes Oza Pawandeep <oza.oza@broadcom.com> - 2017-08-24 07:10 +0200
[PATCH v8 3/3] PCI: iproc: add device shutdown for PCI RC Oza Pawandeep <oza.oza@broadcom.com> - 2017-08-24 07:10 +0200
| From | Oza Pawandeep <oza.oza@broadcom.com> |
|---|---|
| Date | 2017-08-24 07:10 +0200 |
| Subject | [PATCH v8 0/3] PCI: iproc: SOC specific fixes |
| Message-ID | <uhSz0-23F-7@gated-at.bofh.it> |
PCI: iproc: Retry request when CRS returned from EP Above patch adds support for CRS in PCI RC driver, otherwise if not handled at lower level, the user space PMD (poll mode drivers) can timeout. PCI: iproc: add device shutdown for PCI RC This fixes the issue where certian PCI endpoints are not getting detected on Stingray SOC after reboot. Changes Since v7: Factor out the ep config access code. Changes Since v6: Rebased patches on top of Lorenzo's patches. Bjorn's comments addressed. now the confg retry returns 0xffffffff as data. Added reference to PCIe spec and iproc Controller spec in Changelog. Changes Since v5: Ray's comments addressed. Changes Since v4: Bjorn's comments addressed. Changes Since v3: [re-send] Changes Since v2: Fix compilation errors for pcie-iproc-platform.ko which was caught by kbuild. Oza Pawandeep (3): PCI: iproc: factor-out ep configuration access PCI: iproc: Retry request when CRS returned from EP PCI: iproc: add device shutdown for PCI RC drivers/pci/host/pcie-iproc-platform.c | 8 ++ drivers/pci/host/pcie-iproc.c | 143 ++++++++++++++++++++++++++------- drivers/pci/host/pcie-iproc.h | 1 + 3 files changed, 124 insertions(+), 28 deletions(-) -- 1.9.1
[toc] | [next] | [standalone]
| From | Oza Pawandeep <oza.oza@broadcom.com> |
|---|---|
| Date | 2017-08-24 07:10 +0200 |
| Subject | [PATCH v8 3/3] PCI: iproc: add device shutdown for PCI RC |
| Message-ID | <uhSz1-23F-21@gated-at.bofh.it> |
| In reply to | #1718838 |
PERST must be asserted around ~500ms before the reboot is applied.
During soft reset (e.g., "reboot" from Linux) on some iproc based SOCs
LCPLL clock and PERST both goes off simultaneously.
This will cause certain Endpoints Intel NVMe not get detected, upon
next boot sequence.
This is specifically happening with Intel P3700 400GB series.
Endpoint is expecting the clock for some amount of time after PERST is
asserted, which is not happening in Stingray (iproc based SOC).
This causes NVMe to behave in undefined way.
On the contrary, Intel x86 boards will have ref clock running, so we
do not see this behavior there.
Besides, PCI spec does not stipulate about such timings.
In-fact it does not tell us, whether PCIe device should consider
refclk to be available or not to be.
It is completely up to vendor to design their EP the way they want
with respect to ref clock availability.
500ms is just based on the observation and taken as safe margin.
This patch adds platform shutdown where it should be
called in device_shutdown while reboot command is issued.
So in sequence first Endpoint Shutdown (e.g. nvme_shutdown)
followed by RC shutdown, which issues safe PERST assertion.
Signed-off-by: Oza Pawandeep <oza.oza@broadcom.com>
Reviewed-by: Ray Jui <ray.jui@broadcom.com>
Reviewed-by: Scott Branden <scott.branden@broadcom.com>
diff --git a/drivers/pci/host/pcie-iproc-platform.c b/drivers/pci/host/pcie-iproc-platform.c
index 2253119..a5073a9 100644
--- a/drivers/pci/host/pcie-iproc-platform.c
+++ b/drivers/pci/host/pcie-iproc-platform.c
@@ -134,6 +134,13 @@ static int iproc_pcie_pltfm_remove(struct platform_device *pdev)
return iproc_pcie_remove(pcie);
}
+static void iproc_pcie_pltfm_shutdown(struct platform_device *pdev)
+{
+ struct iproc_pcie *pcie = platform_get_drvdata(pdev);
+
+ iproc_pcie_shutdown(pcie);
+}
+
static struct platform_driver iproc_pcie_pltfm_driver = {
.driver = {
.name = "iproc-pcie",
@@ -141,6 +148,7 @@ static int iproc_pcie_pltfm_remove(struct platform_device *pdev)
},
.probe = iproc_pcie_pltfm_probe,
.remove = iproc_pcie_pltfm_remove,
+ .shutdown = iproc_pcie_pltfm_shutdown,
};
module_platform_driver(iproc_pcie_pltfm_driver);
diff --git a/drivers/pci/host/pcie-iproc.c b/drivers/pci/host/pcie-iproc.c
index 37f4adf..cbdabe8 100644
--- a/drivers/pci/host/pcie-iproc.c
+++ b/drivers/pci/host/pcie-iproc.c
@@ -659,7 +659,7 @@ static int iproc_pcie_config_write32(struct pci_bus *bus, unsigned int devfn,
.write = iproc_pcie_config_write32,
};
-static void iproc_pcie_reset(struct iproc_pcie *pcie)
+static void iproc_pcie_perst_ctrl(struct iproc_pcie *pcie, bool assert)
{
u32 val;
@@ -671,19 +671,26 @@ static void iproc_pcie_reset(struct iproc_pcie *pcie)
if (pcie->ep_is_internal)
return;
- /*
- * Select perst_b signal as reset source. Put the device into reset,
- * and then bring it out of reset
- */
- val = iproc_pcie_read_reg(pcie, IPROC_PCIE_CLK_CTRL);
- val &= ~EP_PERST_SOURCE_SELECT & ~EP_MODE_SURVIVE_PERST &
- ~RC_PCIE_RST_OUTPUT;
- iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val);
- udelay(250);
-
- val |= RC_PCIE_RST_OUTPUT;
- iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val);
- msleep(100);
+ if (assert) {
+ val = iproc_pcie_read_reg(pcie, IPROC_PCIE_CLK_CTRL);
+ val &= ~EP_PERST_SOURCE_SELECT & ~EP_MODE_SURVIVE_PERST &
+ ~RC_PCIE_RST_OUTPUT;
+ iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val);
+ udelay(250);
+ } else {
+ val = iproc_pcie_read_reg(pcie, IPROC_PCIE_CLK_CTRL);
+ val |= RC_PCIE_RST_OUTPUT;
+ iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val);
+ msleep(100);
+ }
+}
+
+int iproc_pcie_shutdown(struct iproc_pcie *pcie)
+{
+ iproc_pcie_perst_ctrl(pcie, true);
+ msleep(500);
+
+ return 0;
}
static int iproc_pcie_check_link(struct iproc_pcie *pcie)
@@ -1365,7 +1372,8 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
goto err_exit_phy;
}
- iproc_pcie_reset(pcie);
+ iproc_pcie_perst_ctrl(pcie, true);
+ iproc_pcie_perst_ctrl(pcie, false);
if (pcie->need_ob_cfg) {
ret = iproc_pcie_map_ranges(pcie, res);
diff --git a/drivers/pci/host/pcie-iproc.h b/drivers/pci/host/pcie-iproc.h
index 0bbe2ea..a6b55ce 100644
--- a/drivers/pci/host/pcie-iproc.h
+++ b/drivers/pci/host/pcie-iproc.h
@@ -110,6 +110,7 @@ struct iproc_pcie {
int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res);
int iproc_pcie_remove(struct iproc_pcie *pcie);
+int iproc_pcie_shutdown(struct iproc_pcie *pcie);
#ifdef CONFIG_PCIE_IPROC_MSI
int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node);
--
1.9.1
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web