Skip to content

Commit 025dd3d

Browse files
Murali Karicheribjorn-helgaas
authored andcommitted
PCI: keystone: Add error IRQ handler
Keystone PCI hardware generates error interrupts at RC using a platform IRQ instead of a standard MSI or legacy IRQ. Add a simple error handler that logs the fatal interrupt status to the console. [bhelgaas: s/node/dev->of_node/, tidy comments, return irqreturn_t directly] Signed-off-by: Murali Karicheri <m-karicheri2@ti.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Rob Herring <robh@kernel.org> CC: Pawel Moll <pawel.moll@arm.com> CC: Mark Rutland <mark.rutland@arm.com> CC: Ian Campbell <ijc+devicetree@hellion.org.uk> CC: Kumar Gala <galak@codeaurora.org>
1 parent 9735a22 commit 025dd3d

File tree

4 files changed

+74
-0
lines changed

4 files changed

+74
-0
lines changed

Documentation/devicetree/bindings/pci/pci-keystone.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Optional properties:-
5656
phy-names: name of the Generic Keystine SerDes phy for PCI
5757
- If boot loader already does PCI link establishment, then phys and
5858
phy-names shouldn't be present.
59+
interrupts: platform interrupt for error interrupts.
5960

6061
Designware DT Properties not applicable for Keystone PCI
6162

drivers/pci/host/pci-keystone-dw.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <linux/irq.h>
1616
#include <linux/irqdomain.h>
17+
#include <linux/irqreturn.h>
1718
#include <linux/module.h>
1819
#include <linux/of.h>
1920
#include <linux/of_pci.h>
@@ -53,6 +54,21 @@
5354
#define IRQ_STATUS 0x184
5455
#define MSI_IRQ_OFFSET 4
5556

57+
/* Error IRQ bits */
58+
#define ERR_AER BIT(5) /* ECRC error */
59+
#define ERR_AXI BIT(4) /* AXI tag lookup fatal error */
60+
#define ERR_CORR BIT(3) /* Correctable error */
61+
#define ERR_NONFATAL BIT(2) /* Non-fatal error */
62+
#define ERR_FATAL BIT(1) /* Fatal error */
63+
#define ERR_SYS BIT(0) /* System (fatal, non-fatal, or correctable) */
64+
#define ERR_IRQ_ALL (ERR_AER | ERR_AXI | ERR_CORR | \
65+
ERR_NONFATAL | ERR_FATAL | ERR_SYS)
66+
#define ERR_FATAL_IRQ (ERR_FATAL | ERR_AXI)
67+
#define ERR_IRQ_STATUS_RAW 0x1c0
68+
#define ERR_IRQ_STATUS 0x1c4
69+
#define ERR_IRQ_ENABLE_SET 0x1c8
70+
#define ERR_IRQ_ENABLE_CLR 0x1cc
71+
5672
/* Config space registers */
5773
#define DEBUG0 0x728
5874

@@ -243,6 +259,28 @@ void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, int offset)
243259
writel(offset, ks_pcie->va_app_base + IRQ_EOI);
244260
}
245261

262+
void ks_dw_pcie_enable_error_irq(void __iomem *reg_base)
263+
{
264+
writel(ERR_IRQ_ALL, reg_base + ERR_IRQ_ENABLE_SET);
265+
}
266+
267+
irqreturn_t ks_dw_pcie_handle_error_irq(struct device *dev,
268+
void __iomem *reg_base)
269+
{
270+
u32 status;
271+
272+
status = readl(reg_base + ERR_IRQ_STATUS_RAW) & ERR_IRQ_ALL;
273+
if (!status)
274+
return IRQ_NONE;
275+
276+
if (status & ERR_FATAL_IRQ)
277+
dev_err(dev, "fatal error (status %#010x)\n", status);
278+
279+
/* Ack the IRQ; status bits are RW1C */
280+
writel(status, reg_base + ERR_IRQ_STATUS);
281+
return IRQ_HANDLED;
282+
}
283+
246284
static void ks_dw_pcie_ack_legacy_irq(struct irq_data *d)
247285
{
248286
}

drivers/pci/host/pci-keystone.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/irqchip/chained_irq.h>
1616
#include <linux/clk.h>
1717
#include <linux/delay.h>
18+
#include <linux/interrupt.h>
1819
#include <linux/irqdomain.h>
1920
#include <linux/module.h>
2021
#include <linux/msi.h>
@@ -226,6 +227,9 @@ static void ks_pcie_setup_interrupts(struct keystone_pcie *ks_pcie)
226227
ks_pcie);
227228
}
228229
}
230+
231+
if (ks_pcie->error_irq > 0)
232+
ks_dw_pcie_enable_error_irq(ks_pcie->va_app_base);
229233
}
230234

231235
/*
@@ -289,6 +293,14 @@ static struct pcie_host_ops keystone_pcie_host_ops = {
289293
.scan_bus = ks_dw_pcie_v3_65_scan_bus,
290294
};
291295

296+
static irqreturn_t pcie_err_irq_handler(int irq, void *priv)
297+
{
298+
struct keystone_pcie *ks_pcie = priv;
299+
300+
return ks_dw_pcie_handle_error_irq(ks_pcie->pp.dev,
301+
ks_pcie->va_app_base);
302+
}
303+
292304
static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
293305
struct platform_device *pdev)
294306
{
@@ -309,6 +321,22 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
309321
return ret;
310322
}
311323

324+
/*
325+
* Index 0 is the platform interrupt for error interrupt
326+
* from RC. This is optional.
327+
*/
328+
ks_pcie->error_irq = irq_of_parse_and_map(ks_pcie->np, 0);
329+
if (ks_pcie->error_irq <= 0)
330+
dev_info(&pdev->dev, "no error IRQ defined\n");
331+
else {
332+
if (request_irq(ks_pcie->error_irq, pcie_err_irq_handler,
333+
IRQF_SHARED, "pcie-error-irq", ks_pcie) < 0) {
334+
dev_err(&pdev->dev, "failed to request error IRQ %d\n",
335+
ks_pcie->error_irq);
336+
return ret;
337+
}
338+
}
339+
312340
pp->root_bus_nr = -1;
313341
pp->ops = &keystone_pcie_host_ops;
314342
ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
@@ -376,6 +404,7 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
376404
devm_release_mem_region(dev, res->start, resource_size(res));
377405

378406
pp->dev = dev;
407+
ks_pcie->np = dev->of_node;
379408
platform_set_drvdata(pdev, ks_pcie);
380409
ks_pcie->clk = devm_clk_get(dev, "pcie");
381410
if (IS_ERR(ks_pcie->clk)) {

drivers/pci/host/pci-keystone.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ struct keystone_pcie {
2929
int msi_host_irqs[MAX_MSI_HOST_IRQS];
3030
struct device_node *msi_intc_np;
3131
struct irq_domain *legacy_irq_domain;
32+
struct device_node *np;
33+
34+
int error_irq;
3235

3336
/* Application register space */
3437
void __iomem *va_app_base;
@@ -42,6 +45,9 @@ phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp);
4245
/* Keystone specific PCI controller APIs */
4346
void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie);
4447
void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, int offset);
48+
void ks_dw_pcie_enable_error_irq(void __iomem *reg_base);
49+
irqreturn_t ks_dw_pcie_handle_error_irq(struct device *dev,
50+
void __iomem *reg_base);
4551
int ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
4652
struct device_node *msi_intc_np);
4753
int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,

0 commit comments

Comments
 (0)