[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20230907091058.125630-7-minda.chen@starfivetech.com>
Date: Thu, 7 Sep 2023 17:10:53 +0800
From: Minda Chen <minda.chen@...rfivetech.com>
To: Daire McNamara <daire.mcnamara@...rochip.com>,
Conor Dooley <conor@...nel.org>,
Rob Herring <robh+dt@...nel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@...aro.org>,
Bjorn Helgaas <bhelgaas@...gle.com>,
Lorenzo Pieralisi <lpieralisi@...nel.org>,
Krzysztof Wilczyński <kw@...ux.com>,
Emil Renner Berthing <emil.renner.berthing@...onical.com>
CC: <devicetree@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
<linux-riscv@...ts.infradead.org>, <linux-pci@...r.kernel.org>,
Pali Rohár <pali@...nel.org>,
Paul Walmsley <paul.walmsley@...ive.com>,
Palmer Dabbelt <palmer@...belt.com>,
Albert Ou <aou@...s.berkeley.edu>,
Philipp Zabel <p.zabel@...gutronix.de>,
Mason Huo <mason.huo@...rfivetech.com>,
Leyfoon Tan <leyfoon.tan@...rfivetech.com>,
Kevin Xie <kevin.xie@...rfivetech.com>,
Minda Chen <minda.chen@...rfivetech.com>
Subject: [PATCH v5 06/11] PCI: plda: Add event interrupt codes and IRQ domain ops
For PolarFire implements non-PLDA local interrupt events, most of
event interrupt process codes can not be re-used. PLDA implements
new codes and IRQ domain ops like PolarFire.
plda_get_events() adds a new IRQ num to event num mapping codes for
PLDA local event except DMA engine interrupt events. The DMA engine
interrupt events are implemented by vendors.
Signed-off-by: Minda Chen <minda.chen@...rfivetech.com>
---
drivers/pci/controller/plda/pcie-plda-host.c | 115 +++++++++++++++++++
drivers/pci/controller/plda/pcie-plda.h | 10 ++
2 files changed, 125 insertions(+)
diff --git a/drivers/pci/controller/plda/pcie-plda-host.c b/drivers/pci/controller/plda/pcie-plda-host.c
index ce02cfe6b5fa..8a8b463281cb 100644
--- a/drivers/pci/controller/plda/pcie-plda-host.c
+++ b/drivers/pci/controller/plda/pcie-plda-host.c
@@ -250,6 +250,121 @@ int plda_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
return 0;
}
+irqreturn_t plda_event_handler(int irq, void *dev_id)
+{
+ return IRQ_HANDLED;
+}
+
+static u32 plda_get_events(struct plda_pcie_rp *port)
+{
+ u32 events, val, origin;
+
+ origin = readl_relaxed(port->bridge_addr + ISTATUS_LOCAL);
+
+ /* Error events and doorbell events */
+ events = (origin >> A_ATR_EVT_POST_ERR_SHIFT) & 0xff;
+
+ /* INTx events */
+ if (origin & PM_MSI_INT_INTX_MASK)
+ events |= BIT(EVENT_PM_MSI_INT_INTX);
+
+ /* MSI event and sys events */
+ val = (origin >> PM_MSI_INT_MSI_SHIFT) & 0xf;
+ events |= val << EVENT_PM_MSI_INT_MSI;
+
+ return events;
+}
+
+void plda_handle_event(struct irq_desc *desc)
+{
+ struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ u32 bit;
+ unsigned long events;
+
+ chained_irq_enter(chip, desc);
+
+ events = plda_get_events(port);
+ for_each_set_bit(bit, &events, port->num_events)
+ generic_handle_domain_irq(port->event_domain, bit);
+
+ chained_irq_exit(chip, desc);
+}
+
+static u32 plda_hwirq_to_mask(int hwirq)
+{
+ u32 mask;
+
+ if (hwirq < EVENT_PM_MSI_INT_INTX)
+ mask = BIT(hwirq + A_ATR_EVT_POST_ERR_SHIFT);
+ else if (hwirq == EVENT_PM_MSI_INT_INTX)
+ mask = PM_MSI_INT_INTX_MASK;
+ else
+ mask = BIT(hwirq + PM_MSI_TO_MASK_OFFSET);
+
+ return mask;
+}
+
+static void plda_ack_event_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+
+ writel_relaxed(plda_hwirq_to_mask(data->hwirq),
+ port->bridge_addr + ISTATUS_LOCAL);
+}
+
+static void plda_mask_event_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ u32 mask, val;
+
+ mask = plda_hwirq_to_mask(data->hwirq);
+
+ raw_spin_lock(&port->lock);
+ val = readl_relaxed(port->bridge_addr + IMASK_LOCAL);
+ val &= ~mask;
+ writel_relaxed(val, port->bridge_addr + IMASK_LOCAL);
+ raw_spin_unlock(&port->lock);
+}
+
+static void plda_unmask_event_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ u32 mask, val;
+
+ mask = plda_hwirq_to_mask(data->hwirq);
+
+ raw_spin_lock(&port->lock);
+ val = readl_relaxed(port->bridge_addr + IMASK_LOCAL);
+ val |= mask;
+ writel_relaxed(val, port->bridge_addr + IMASK_LOCAL);
+ raw_spin_unlock(&port->lock);
+}
+
+static struct irq_chip plda_event_irq_chip = {
+ .name = "PLDA PCIe EVENT",
+ .irq_ack = plda_ack_event_irq,
+ .irq_mask = plda_mask_event_irq,
+ .irq_unmask = plda_unmask_event_irq,
+};
+
+static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ irq_set_chip_and_handler(irq, &plda_event_irq_chip, handle_level_irq);
+ irq_set_chip_data(irq, domain->host_data);
+
+ return 0;
+}
+
+static const struct irq_domain_ops plda_evt_dom_ops = {
+ .map = plda_pcie_event_map,
+};
+
+static const struct plda_event_ops plda_event_ops = {
+ .get_events = plda_get_events,
+};
+
void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
phys_addr_t axi_addr, phys_addr_t pci_addr,
size_t size)
diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
index a5eb02ec6171..cc8fc8a2da91 100644
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -102,6 +102,14 @@
#define EVENT_PM_MSI_INT_SYS_ERR 12
#define NUM_PLDA_EVENTS 13
+#define PM_MSI_TO_MASK_OFFSET 19
+
+struct plda_pcie_rp;
+
+struct plda_event_ops {
+ u32 (*get_events)(struct plda_pcie_rp *pcie);
+};
+
struct plda_msi {
struct mutex lock; /* Protect used bitmap */
struct irq_domain *msi_domain;
@@ -118,10 +126,12 @@ struct plda_pcie_rp {
raw_spinlock_t lock;
struct plda_msi msi;
void __iomem *bridge_addr;
+ int num_events;
};
void plda_handle_msi(struct irq_desc *desc);
int plda_allocate_msi_domains(struct plda_pcie_rp *port);
+irqreturn_t plda_event_handler(int irq, void *dev_id);
void plda_handle_intx(struct irq_desc *desc);
int plda_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
irq_hw_number_t hwirq);
--
2.17.1
Powered by blists - more mailing lists