summaryrefslogtreecommitdiff
path: root/drivers/pci/controller
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2023-06-26 21:00:00 +0300
committerBjorn Helgaas <bhelgaas@google.com>2023-06-26 21:00:00 +0300
commitd8c226ac1f748d0eac54ef869a4f41b26bc4f825 (patch)
tree6199f0e7586b1d1e07544a3ffb680dd224eaed4a /drivers/pci/controller
parentb5abb12cdd297339b30e95bc3e5e8e26723cf923 (diff)
parent061cbfab09fb35898f2907d42f936cf9ae271d93 (diff)
downloadlinux-d8c226ac1f748d0eac54ef869a4f41b26bc4f825.tar.xz
Merge branch 'pci/controller/endpoint'
- Change "PCI Endpoint Virtual NTB driver" Kconfig prompt to be different from "PCI Endpoint NTB driver" (Shunsuke Mie) - Automatically create a function specific attributes group for endpoint drivers to avoid reference counting issues (Damien Le Moal) - Move and unexport pci_epf_type_add_cfs() (Damien Le Moal) - Reinitialize EPF test DMA transfer completion before submitting it to avoid losing the completion notification (Damien Le Moal) - Fix EPF test DMA transfer completion detection (Damien Le Moal) - Submit EPF test DMA transfers with dmaengine_submit(), not tx_submit() (Damien Le Moal) - Simplify EPF test read/write/copy functions (Damien Le Moal) - Simplify EPF test "raise IRQ" interface (Damien Le Moal) - Simplify EPF test IRQ command execution (Damien Le Moal) - Improve EPF test command/status register handling (Damien Le Moal) - Free IRQs before removing device (Damien Le Moal) - Reinitialize IRQ completions for every test (Damien Le Moal) - Don't write status in IRQ handler to avoid race (Damien Le Moal) - Fix dma_chan direction in data transfer test (Yoshihiro Shimoda) - Return pci_epf_type_add_cfs() error if EPF has no driver (Damien Le Moal) - Add kernel-doc for pci_epc_raise_irq() and pci_epc_map_msi_irq() MSI vector parameters (Manivannan Sadhasivam) - Pass EPF device ID to driver probe functions (Manivannan Sadhasivam) - Return -EALREADY if EPC has already been started/stopped (Manivannan Sadhasivam) - Add linkdown notifier support and use it in qcom-ep (Manivannan Sadhasivam) - Add Bus Master Enable event support and use it in qcom-ep (Manivannan Sadhasivam) - Add Qualcomm Modem Host Interface (MHI) endpoint driver (Manivannan Sadhasivam) - Add Layerscape PME interrupt handling to manage link-up notification (Frank Li) * pci/controller/endpoint: PCI: layerscape: Add the endpoint linkup notifier support PCI: endpoint: pci-epf-vntb: Fix typo in comments MAINTAINERS: Add PCI MHI endpoint function driver under MHI bus PCI: endpoint: Add PCI Endpoint function driver for MHI bus PCI: qcom-ep: Add support for BME notification PCI: qcom-ep: Add support for Link down notification PCI: endpoint: Add BME notifier support PCI: endpoint: Add linkdown notifier support PCI: endpoint: Return error if EPC is started/stopped multiple times PCI: endpoint: Pass EPF device ID to the probe function PCI: endpoint: Add missing documentation about the MSI/MSI-X range PCI: endpoint: Improve pci_epf_type_add_cfs() PCI: endpoint: functions/pci-epf-test: Fix dma_chan direction misc: pci_endpoint_test: Simplify pci_endpoint_test_msi_irq() misc: pci_endpoint_test: Do not write status in IRQ handler misc: pci_endpoint_test: Re-init completion for every test misc: pci_endpoint_test: Free IRQs before removing the device PCI: epf-test: Simplify transfers result print PCI: epf-test: Simplify DMA support checks PCI: epf-test: Cleanup request result handling PCI: epf-test: Cleanup pci_epf_test_cmd_handler() PCI: epf-test: Improve handling of command and status registers PCI: epf-test: Simplify IRQ test commands execution PCI: epf-test: Simplify pci_epf_test_raise_irq() PCI: epf-test: Simplify read/write/copy test functions PCI: epf-test: Use dmaengine_submit() to initiate DMA transfer PCI: epf-test: Fix DMA transfer completion detection PCI: epf-test: Fix DMA transfer completion initialization PCI: endpoint: Move pci_epf_type_add_cfs() code PCI: endpoint: Automatically create a function specific attributes group PCI: endpoint: Fix a Kconfig prompt of vNTB driver
Diffstat (limited to 'drivers/pci/controller')
-rw-r--r--drivers/pci/controller/dwc/pci-layerscape-ep.c100
-rw-r--r--drivers/pci/controller/dwc/pcie-qcom-ep.c2
2 files changed, 101 insertions, 1 deletions
diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c b/drivers/pci/controller/dwc/pci-layerscape-ep.c
index c640db60edc6..de4c1758a6c3 100644
--- a/drivers/pci/controller/dwc/pci-layerscape-ep.c
+++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c
@@ -18,6 +18,20 @@
#include "pcie-designware.h"
+#define PEX_PF0_CONFIG 0xC0014
+#define PEX_PF0_CFG_READY BIT(0)
+
+/* PEX PFa PCIE PME and message interrupt registers*/
+#define PEX_PF0_PME_MES_DR 0xC0020
+#define PEX_PF0_PME_MES_DR_LUD BIT(7)
+#define PEX_PF0_PME_MES_DR_LDD BIT(9)
+#define PEX_PF0_PME_MES_DR_HRD BIT(10)
+
+#define PEX_PF0_PME_MES_IER 0xC0028
+#define PEX_PF0_PME_MES_IER_LUDIE BIT(7)
+#define PEX_PF0_PME_MES_IER_LDDIE BIT(9)
+#define PEX_PF0_PME_MES_IER_HRDIE BIT(10)
+
#define to_ls_pcie_ep(x) dev_get_drvdata((x)->dev)
struct ls_pcie_ep_drvdata {
@@ -30,8 +44,84 @@ struct ls_pcie_ep {
struct dw_pcie *pci;
struct pci_epc_features *ls_epc;
const struct ls_pcie_ep_drvdata *drvdata;
+ int irq;
+ bool big_endian;
};
+static u32 ls_lut_readl(struct ls_pcie_ep *pcie, u32 offset)
+{
+ struct dw_pcie *pci = pcie->pci;
+
+ if (pcie->big_endian)
+ return ioread32be(pci->dbi_base + offset);
+ else
+ return ioread32(pci->dbi_base + offset);
+}
+
+static void ls_lut_writel(struct ls_pcie_ep *pcie, u32 offset, u32 value)
+{
+ struct dw_pcie *pci = pcie->pci;
+
+ if (pcie->big_endian)
+ iowrite32be(value, pci->dbi_base + offset);
+ else
+ iowrite32(value, pci->dbi_base + offset);
+}
+
+static irqreturn_t ls_pcie_ep_event_handler(int irq, void *dev_id)
+{
+ struct ls_pcie_ep *pcie = dev_id;
+ struct dw_pcie *pci = pcie->pci;
+ u32 val, cfg;
+
+ val = ls_lut_readl(pcie, PEX_PF0_PME_MES_DR);
+ ls_lut_writel(pcie, PEX_PF0_PME_MES_DR, val);
+
+ if (!val)
+ return IRQ_NONE;
+
+ if (val & PEX_PF0_PME_MES_DR_LUD) {
+ cfg = ls_lut_readl(pcie, PEX_PF0_CONFIG);
+ cfg |= PEX_PF0_CFG_READY;
+ ls_lut_writel(pcie, PEX_PF0_CONFIG, cfg);
+ dw_pcie_ep_linkup(&pci->ep);
+
+ dev_dbg(pci->dev, "Link up\n");
+ } else if (val & PEX_PF0_PME_MES_DR_LDD) {
+ dev_dbg(pci->dev, "Link down\n");
+ } else if (val & PEX_PF0_PME_MES_DR_HRD) {
+ dev_dbg(pci->dev, "Hot reset\n");
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int ls_pcie_ep_interrupt_init(struct ls_pcie_ep *pcie,
+ struct platform_device *pdev)
+{
+ u32 val;
+ int ret;
+
+ pcie->irq = platform_get_irq_byname(pdev, "pme");
+ if (pcie->irq < 0)
+ return pcie->irq;
+
+ ret = devm_request_irq(&pdev->dev, pcie->irq, ls_pcie_ep_event_handler,
+ IRQF_SHARED, pdev->name, pcie);
+ if (ret) {
+ dev_err(&pdev->dev, "Can't register PCIe IRQ\n");
+ return ret;
+ }
+
+ /* Enable interrupts */
+ val = ls_lut_readl(pcie, PEX_PF0_PME_MES_IER);
+ val |= PEX_PF0_PME_MES_IER_LDDIE | PEX_PF0_PME_MES_IER_HRDIE |
+ PEX_PF0_PME_MES_IER_LUDIE;
+ ls_lut_writel(pcie, PEX_PF0_PME_MES_IER, val);
+
+ return 0;
+}
+
static const struct pci_epc_features*
ls_pcie_ep_get_features(struct dw_pcie_ep *ep)
{
@@ -125,6 +215,7 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev)
struct ls_pcie_ep *pcie;
struct pci_epc_features *ls_epc;
struct resource *dbi_base;
+ int ret;
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
@@ -144,6 +235,7 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev)
pci->ops = pcie->drvdata->dw_pcie_ops;
ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4);
+ ls_epc->linkup_notifier = true;
pcie->pci = pci;
pcie->ls_epc = ls_epc;
@@ -155,9 +247,15 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev)
pci->ep.ops = &ls_pcie_ep_ops;
+ pcie->big_endian = of_property_read_bool(dev->of_node, "big-endian");
+
platform_set_drvdata(pdev, pcie);
- return dw_pcie_ep_init(&pci->ep);
+ ret = dw_pcie_ep_init(&pci->ep);
+ if (ret)
+ return ret;
+
+ return ls_pcie_ep_interrupt_init(pcie, pdev);
}
static struct platform_driver ls_pcie_ep_driver = {
diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c
index 19b32839ea26..1435f516d3f7 100644
--- a/drivers/pci/controller/dwc/pcie-qcom-ep.c
+++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c
@@ -569,9 +569,11 @@ static irqreturn_t qcom_pcie_ep_global_irq_thread(int irq, void *data)
if (FIELD_GET(PARF_INT_ALL_LINK_DOWN, status)) {
dev_dbg(dev, "Received Linkdown event\n");
pcie_ep->link_status = QCOM_PCIE_EP_LINK_DOWN;
+ pci_epc_linkdown(pci->ep.epc);
} else if (FIELD_GET(PARF_INT_ALL_BME, status)) {
dev_dbg(dev, "Received BME event. Link is enabled!\n");
pcie_ep->link_status = QCOM_PCIE_EP_LINK_ENABLED;
+ pci_epc_bme_notify(pci->ep.epc);
} else if (FIELD_GET(PARF_INT_ALL_PM_TURNOFF, status)) {
dev_dbg(dev, "Received PM Turn-off event! Entering L23\n");
val = readl_relaxed(pcie_ep->parf + PARF_PM_CTRL);