[PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt support.

Subsystems: linux for powerpc (32-bit and 64-bit), the rest

STALE5129d

10 messages, 4 authors, 2012-08-07 · open the first message on its own page

[PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt support.

From: Varun Sethi <hidden>
Date: 2012-07-31 14:44:35

All SOC device error interrupts are muxed and delivered to the core as a single
MPIC error interrupt. Currently all the device drivers requiring access to device
errors have to register for the MPIC error interrupt as a shared interrupt.

With this patch we add interrupt demuxing capability in the mpic driver, allowing
device drivers to register for their individual error interrupts. This is achieved
by handling error interrupts in a cascaded fashion.

MPIC error interrupt is handled by the "error_int_handler", which subsequently demuxes
it using the EISR and delivers it to the respective drivers. 

The error interrupt capability is dependent on the MPIC EIMR register, which was
introduced in FSL MPIC version 4.1 (P4080 rev2). So, error interrupt demuxing capability
is dependent on the MPIC version and can be used for versions >= 4.1.

Signed-off-by: Varun Sethi <redacted>
Signed-off-by: Bogdan Hamciuc <redacted>
[In the initial version of the patch we were using handle_simple_irq
 as the handler for cascaded error interrupts, this resulted
 in issues in case of threaded isrs (with RT kernel). This issue was
 debugged by Bogdan and decision was taken to use the handle_level_irq
 handler]

---
 arch/powerpc/include/asm/mpic.h    |   13 +++
 arch/powerpc/sysdev/Makefile       |    2 +-
 arch/powerpc/sysdev/fsl_mpic_err.c |  152 ++++++++++++++++++++++++++++++++++++
 arch/powerpc/sysdev/mpic.c         |   41 ++++++++++-
 arch/powerpc/sysdev/mpic.h         |   22 +++++
 5 files changed, 228 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/sysdev/fsl_mpic_err.c
diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h
index e14d35d..5cc8000 100644
--- a/arch/powerpc/include/asm/mpic.h
+++ b/arch/powerpc/include/asm/mpic.h
@@ -118,6 +118,9 @@
 #define MPIC_MAX_CPUS		32
 #define MPIC_MAX_ISU		32
 
+#define MPIC_MAX_ERR      32
+#define MPIC_FSL_ERR_INT  16
+
 /*
  * Tsi108 implementation of MPIC has many differences from the original one
  */
@@ -270,6 +273,7 @@ struct mpic
 	struct irq_chip		hc_ipi;
 #endif
 	struct irq_chip		hc_tm;
+	struct irq_chip		hc_err;
 	const char		*name;
 	/* Flags */
 	unsigned int		flags;
@@ -283,6 +287,8 @@ struct mpic
 	/* vector numbers used for internal sources (ipi/timers) */
 	unsigned int		ipi_vecs[4];
 	unsigned int		timer_vecs[8];
+	/* vector numbers used for FSL MPIC error interrupts */
+	unsigned int		err_int_vecs[MPIC_MAX_ERR];
 
 	/* Spurious vector to program into unused sources */
 	unsigned int		spurious_vec;
@@ -306,6 +312,11 @@ struct mpic
 	struct mpic_reg_bank	cpuregs[MPIC_MAX_CPUS];
 	struct mpic_reg_bank	isus[MPIC_MAX_ISU];
 
+	/* ioremap'ed base for error interrupt registers */
+	u32 __iomem	*err_regs;
+	/* error interrupt config */
+	u32			err_int_config_done;
+
 	/* Protected sources */
 	unsigned long		*protected;
 
@@ -370,6 +381,8 @@ struct mpic
 #define MPIC_NO_RESET			0x00004000
 /* Freescale MPIC (compatible includes "fsl,mpic") */
 #define MPIC_FSL			0x00008000
+/* Freescale MPIC supports EIMR (error interrupt mask register)*/
+#define MPIC_FSL_HAS_EIMR		0x00010000
 
 /* MPIC HW modification ID */
 #define MPIC_REGSET_MASK		0xf0000000
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 1bd7ecb..a57600b 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_PPC_DCR_NATIVE)	+= dcr-low.o
 obj-$(CONFIG_PPC_PMI)		+= pmi.o
 obj-$(CONFIG_U3_DART)		+= dart_iommu.o
 obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
-obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
+obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o fsl_mpic_err.o
 obj-$(CONFIG_FSL_PCI)		+= fsl_pci.o $(fsl-msi-obj-y)
 obj-$(CONFIG_FSL_PMC)		+= fsl_pmc.o
 obj-$(CONFIG_FSL_LBC)		+= fsl_lbc.o
diff --git a/arch/powerpc/sysdev/fsl_mpic_err.c b/arch/powerpc/sysdev/fsl_mpic_err.c
new file mode 100644
index 0000000..1ebfa36
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_mpic_err.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *
+ * Author: Varun Sethi <varun.sethi@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mpic.h>
+
+#include "mpic.h"
+
+#define MPIC_ERR_INT_BASE	0x3900
+#define MPIC_ERR_INT_EISR	0x0000
+#define MPIC_ERR_INT_EIMR	0x0010
+
+static inline u32 mpic_fsl_err_read(u32 __iomem *base, unsigned int err_reg)
+{
+	return in_be32(base + (err_reg >> 2));
+}
+
+static inline void mpic_fsl_err_write(u32 __iomem *base, u32 value)
+{
+	out_be32(base + (MPIC_ERR_INT_EIMR >> 2), value);
+}
+
+static void fsl_mpic_mask_err(struct irq_data *d)
+{
+	u32 eimr;
+	struct mpic *mpic = irq_data_get_irq_chip_data(d);
+	unsigned int src = virq_to_hw(d->irq) - mpic->err_int_vecs[0];
+
+	eimr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+	eimr |= (1 << (31 - src));
+	mpic_fsl_err_write(mpic->err_regs, eimr);
+}
+
+static void fsl_mpic_unmask_err(struct irq_data *d)
+{
+	u32 eimr;
+	struct mpic *mpic = irq_data_get_irq_chip_data(d);
+	unsigned int src = virq_to_hw(d->irq) - mpic->err_int_vecs[0];
+
+	eimr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+	eimr &= ~(1 << (31 - src));
+	mpic_fsl_err_write(mpic->err_regs, eimr);
+}
+
+static struct irq_chip fsl_mpic_err_chip = {
+	.irq_disable	= fsl_mpic_mask_err,
+	.irq_mask	= fsl_mpic_mask_err,
+	.irq_unmask	= fsl_mpic_unmask_err,
+};
+
+void mpic_setup_error_int(struct mpic *mpic, int intvec)
+{
+	int i;
+
+	mpic->err_regs = ioremap(mpic->paddr + MPIC_ERR_INT_BASE, 0x1000);
+	if (!mpic->err_regs) {
+		pr_err("could not map mpic error registers\n");
+		return;
+	}
+	mpic->hc_err = fsl_mpic_err_chip;
+	mpic->hc_err.name = mpic->name;
+	mpic->flags |= MPIC_FSL_HAS_EIMR;
+	/* allocate interrupt vectors for error interrupts */
+	for (i = MPIC_MAX_ERR - 1; i >= 0; i--)
+		mpic->err_int_vecs[i] = --intvec;
+
+}
+
+int mpic_map_error_int(struct mpic *mpic, unsigned int virq, irq_hw_number_t  hw)
+{
+	if ((mpic->flags & MPIC_FSL_HAS_EIMR) &&
+	    (hw >= mpic->err_int_vecs[0] &&
+	     hw <= mpic->err_int_vecs[MPIC_MAX_ERR - 1])) {
+		WARN_ON(mpic->flags & MPIC_SECONDARY);
+
+		pr_debug("mpic: mapping as Error Interrupt\n");
+		irq_set_chip_data(virq, mpic);
+		irq_set_chip_and_handler(virq, &mpic->hc_err,
+					 handle_level_irq);
+		return 1;
+	}
+
+	return 0;
+}
+
+static irqreturn_t fsl_error_int_handler(int irq, void *data)
+{
+	struct mpic *mpic = (struct mpic *) data;
+	u32 eisr, eimr;
+	int errint;
+	unsigned int cascade_irq;
+
+	eisr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EISR);
+	eimr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+
+	if (!(eisr & ~eimr))
+		return IRQ_NONE;
+
+	while (eisr) {
+		errint = __builtin_clz(eisr);
+		cascade_irq = irq_linear_revmap(mpic->irqhost,
+				 mpic->err_int_vecs[errint]);
+		WARN_ON(cascade_irq == NO_IRQ);
+		if (cascade_irq != NO_IRQ) {
+			generic_handle_irq(cascade_irq);
+		} else {
+			eimr |=  1 << (31 - errint);
+			mpic_fsl_err_write(mpic->err_regs, eimr);
+		}
+		eisr &= ~(1 << (31 - errint));
+	}
+
+	return IRQ_HANDLED;
+}
+
+int mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum)
+{
+	unsigned int virq;
+	int ret;
+
+	virq = irq_create_mapping(mpic->irqhost, irqnum);
+	if (virq == NO_IRQ) {
+		pr_err("Error interrupt setup failed\n");
+		return 0;
+	}
+
+	/* Mask all error interrupts */
+	mpic_fsl_err_write(mpic->err_regs, ~0);
+
+	ret = request_irq(virq, fsl_error_int_handler, IRQF_NO_THREAD,
+		    "mpic-error-int", mpic);
+	if (ret) {
+		pr_err("Failed to register error interrupt handler\n");
+		return 0;
+	}
+
+	return 1;
+}
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 7e32db7..2a0b632 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1026,6 +1026,9 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,
 		return 0;
 	}
 
+	if (mpic_map_error_int(mpic, virq, hw))
+		return 0;
+
 	if (hw >= mpic->num_sources)
 		return -EINVAL;
 
@@ -1085,7 +1088,16 @@ static int mpic_host_xlate(struct irq_domain *h, struct device_node *ct,
 		 */
 		switch (intspec[2]) {
 		case 0:
-		case 1: /* no EISR/EIMR support for now, treat as shared IRQ */
+			break;
+		case 1:
+			if (!mpic->err_int_config_done)
+				break;
+
+			if (intspec[3] >= ARRAY_SIZE(mpic->err_int_vecs))
+				return -EINVAL;
+
+			*out_hwirq = mpic->err_int_vecs[intspec[3]];
+
 			break;
 		case 2:
 			if (intspec[0] >= ARRAY_SIZE(mpic->ipi_vecs))
@@ -1302,6 +1314,8 @@ struct mpic * __init mpic_alloc(struct device_node *node,
 	mpic_map(mpic, mpic->paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
 
 	if (mpic->flags & MPIC_FSL) {
+		u32 brr1, version;
+
 		/*
 		 * Yes, Freescale really did put global registers in the
 		 * magic per-cpu area -- and they don't even show up in the
@@ -1309,6 +1323,26 @@ struct mpic * __init mpic_alloc(struct device_node *node,
 		 */
 		mpic_map(mpic, mpic->paddr, &mpic->thiscpuregs,
 			 MPIC_CPU_THISBASE, 0x1000);
+
+		brr1 = _mpic_read(mpic->reg_type, &mpic->thiscpuregs,
+				MPIC_FSL_BRR1);
+		version = brr1 & MPIC_FSL_BRR1_VER;
+
+		/* Error interrupt mask register (EIMR) is required for
+		 * handling individual device error interrupts. EIMR
+		 * was added in MPIC version 4.1.
+		 *
+		 * Over here we reserve vector number space for error
+		 * interrupt vectors. This space is stolen from the
+		 * global vector number space, as in case of ipis
+		 * and timer interrupts.
+		 *
+		 * Available vector space = intvec_top - 12, where 12
+		 * is the number of vectors which have been consumed by
+		 * ipis and timer interrupts.
+		 */
+		if (version >= 0x401)
+			mpic_setup_error_int(mpic, intvec_top - 12);
 	}
 
 	/* Reset */
@@ -1474,6 +1508,11 @@ void __init mpic_init(struct mpic *mpic)
 			num_timers = 8;
 	}
 
+	/* FSL mpic error interrupt intialization */
+	if (mpic->flags & MPIC_FSL_HAS_EIMR)
+		mpic->err_int_config_done =
+			mpic_err_int_init(mpic, MPIC_FSL_ERR_INT);
+
 	/* Initialize timers to our reserved vectors and mask them for now */
 	for (i = 0; i < num_timers; i++) {
 		unsigned int offset = mpic_tm_offset(mpic, i);
diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h
index 13f3e89..1a6995a 100644
--- a/arch/powerpc/sysdev/mpic.h
+++ b/arch/powerpc/sysdev/mpic.h
@@ -40,4 +40,26 @@ extern int mpic_set_affinity(struct irq_data *d,
 			     const struct cpumask *cpumask, bool force);
 extern void mpic_reset_core(int cpu);
 
+#ifdef CONFIG_FSL_SOC
+extern int mpic_map_error_int(struct mpic *mpic, unsigned int virq, irq_hw_number_t  hw);
+extern int mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum);
+extern void mpic_setup_error_int(struct mpic *mpic, int intvec);
+#else
+static inline int mpic_map_error_int(struct mpic *mpic, unsigned int virq, irq_hw_number_t  hw)
+{
+	return 0;
+}
+
+
+static inline int mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum)
+{
+	return -1;
+}
+
+static inline void mpic_setup_error_int(struct mpic *mpic, int intvec)
+{
+	return;
+}
+#endif
+
 #endif /* _POWERPC_SYSDEV_MPIC_H */
-- 
1.7.4.1

Re: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt support.

From: Kumar Gala <hidden>
Date: 2012-08-03 13:19:24

On Jul 31, 2012, at 9:42 AM, Varun Sethi wrote:
All SOC device error interrupts are muxed and delivered to the core as =
a single
MPIC error interrupt. Currently all the device drivers requiring =
access to device
errors have to register for the MPIC error interrupt as a shared =
interrupt.
=20
With this patch we add interrupt demuxing capability in the mpic =
driver, allowing
device drivers to register for their individual error interrupts. This =
is achieved
by handling error interrupts in a cascaded fashion.
=20
MPIC error interrupt is handled by the "error_int_handler", which =
subsequently demuxes
it using the EISR and delivers it to the respective drivers.=20
=20
The error interrupt capability is dependent on the MPIC EIMR register, =
which was
introduced in FSL MPIC version 4.1 (P4080 rev2). So, error interrupt =
demuxing capability
is dependent on the MPIC version and can be used for versions >=3D =
4.1.
=20
Signed-off-by: Varun Sethi <redacted>
Signed-off-by: Bogdan Hamciuc <redacted>
[In the initial version of the patch we were using handle_simple_irq
as the handler for cascaded error interrupts, this resulted
in issues in case of threaded isrs (with RT kernel). This issue was
debugged by Bogdan and decision was taken to use the handle_level_irq
handler]
[ fix commit message to wrap at 75 char columns ]
=20
---
arch/powerpc/include/asm/mpic.h    |   13 +++
arch/powerpc/sysdev/Makefile       |    2 +-
arch/powerpc/sysdev/fsl_mpic_err.c |  152 =
++++++++++++++++++++++++++++++++++++
quoted hunk
arch/powerpc/sysdev/mpic.c         |   41 ++++++++++-
arch/powerpc/sysdev/mpic.h         |   22 +++++
5 files changed, 228 insertions(+), 2 deletions(-)
create mode 100644 arch/powerpc/sysdev/fsl_mpic_err.c
=20
diff --git a/arch/powerpc/include/asm/mpic.h =
b/arch/powerpc/include/asm/mpic.h
quoted hunk
index e14d35d..5cc8000 100644
--- a/arch/powerpc/include/asm/mpic.h
+++ b/arch/powerpc/include/asm/mpic.h
@@ -118,6 +118,9 @@
#define MPIC_MAX_CPUS		32
#define MPIC_MAX_ISU		32
=20
+#define MPIC_MAX_ERR      32
+#define MPIC_FSL_ERR_INT  16
+
/*
* Tsi108 implementation of MPIC has many differences from the original =
one
quoted hunk
*/
@@ -270,6 +273,7 @@ struct mpic
	struct irq_chip		hc_ipi;
#endif
	struct irq_chip		hc_tm;
+	struct irq_chip		hc_err;
	const char		*name;
	/* Flags */
	unsigned int		flags;
@@ -283,6 +287,8 @@ struct mpic
	/* vector numbers used for internal sources (ipi/timers) */
	unsigned int		ipi_vecs[4];
	unsigned int		timer_vecs[8];
+	/* vector numbers used for FSL MPIC error interrupts */
+	unsigned int		err_int_vecs[MPIC_MAX_ERR];
=20
	/* Spurious vector to program into unused sources */
	unsigned int		spurious_vec;
@@ -306,6 +312,11 @@ struct mpic
	struct mpic_reg_bank	cpuregs[MPIC_MAX_CPUS];
	struct mpic_reg_bank	isus[MPIC_MAX_ISU];
=20
+	/* ioremap'ed base for error interrupt registers */
+	u32 __iomem	*err_regs;
+	/* error interrupt config */
+	u32			err_int_config_done;
+
Is this really needed ?
quoted hunk
	/* Protected sources */
	unsigned long		*protected;
=20
@@ -370,6 +381,8 @@ struct mpic
#define MPIC_NO_RESET			0x00004000
/* Freescale MPIC (compatible includes "fsl,mpic") */
#define MPIC_FSL			0x00008000
+/* Freescale MPIC supports EIMR (error interrupt mask register)*/
+#define MPIC_FSL_HAS_EIMR		0x00010000
Can't we use BRR for this?
quoted hunk
=20
/* MPIC HW modification ID */
#define MPIC_REGSET_MASK		0xf0000000
diff --git a/arch/powerpc/sysdev/Makefile =
b/arch/powerpc/sysdev/Makefile
quoted hunk
index 1bd7ecb..a57600b 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_PPC_DCR_NATIVE)	+=3D dcr-low.o
obj-$(CONFIG_PPC_PMI)		+=3D pmi.o
obj-$(CONFIG_U3_DART)		+=3D dart_iommu.o
obj-$(CONFIG_MMIO_NVRAM)	+=3D mmio_nvram.o
-obj-$(CONFIG_FSL_SOC)		+=3D fsl_soc.o
+obj-$(CONFIG_FSL_SOC)		+=3D fsl_soc.o fsl_mpic_err.o
obj-$(CONFIG_FSL_PCI)		+=3D fsl_pci.o $(fsl-msi-obj-y)
obj-$(CONFIG_FSL_PMC)		+=3D fsl_pmc.o
obj-$(CONFIG_FSL_LBC)		+=3D fsl_lbc.o
diff --git a/arch/powerpc/sysdev/fsl_mpic_err.c =
b/arch/powerpc/sysdev/fsl_mpic_err.c
quoted hunk
new file mode 100644
index 0000000..1ebfa36
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_mpic_err.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *
+ * Author: Varun Sethi <varun.sethi@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mpic.h>
+
+#include "mpic.h"
+
+#define MPIC_ERR_INT_BASE	0x3900
+#define MPIC_ERR_INT_EISR	0x0000
+#define MPIC_ERR_INT_EIMR	0x0010
+
+static inline u32 mpic_fsl_err_read(u32 __iomem *base, unsigned int =
err_reg)
+{
+	return in_be32(base + (err_reg >> 2));
+}
+
+static inline void mpic_fsl_err_write(u32 __iomem *base, u32 value)
+{
+	out_be32(base + (MPIC_ERR_INT_EIMR >> 2), value);
+}
+
+static void fsl_mpic_mask_err(struct irq_data *d)
+{
+	u32 eimr;
+	struct mpic *mpic =3D irq_data_get_irq_chip_data(d);
+	unsigned int src =3D virq_to_hw(d->irq) - mpic->err_int_vecs[0];
+
+	eimr =3D mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+	eimr |=3D (1 << (31 - src));
+	mpic_fsl_err_write(mpic->err_regs, eimr);
+}
+
+static void fsl_mpic_unmask_err(struct irq_data *d)
+{
+	u32 eimr;
+	struct mpic *mpic =3D irq_data_get_irq_chip_data(d);
+	unsigned int src =3D virq_to_hw(d->irq) - mpic->err_int_vecs[0];
+
+	eimr =3D mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+	eimr &=3D ~(1 << (31 - src));
+	mpic_fsl_err_write(mpic->err_regs, eimr);
+}
+
+static struct irq_chip fsl_mpic_err_chip =3D {
+	.irq_disable	=3D fsl_mpic_mask_err,
+	.irq_mask	=3D fsl_mpic_mask_err,
+	.irq_unmask	=3D fsl_mpic_unmask_err,
+};
+
+void mpic_setup_error_int(struct mpic *mpic, int intvec)
+{
+	int i;
+
+	mpic->err_regs =3D ioremap(mpic->paddr + MPIC_ERR_INT_BASE, =
0x1000);
+	if (!mpic->err_regs) {
+		pr_err("could not map mpic error registers\n");
+		return;
we should propagate an error back up if ioremap failed.
+	}
+	mpic->hc_err =3D fsl_mpic_err_chip;
+	mpic->hc_err.name =3D mpic->name;
+	mpic->flags |=3D MPIC_FSL_HAS_EIMR;
+	/* allocate interrupt vectors for error interrupts */
+	for (i =3D MPIC_MAX_ERR - 1; i >=3D 0; i--)
+		mpic->err_int_vecs[i] =3D --intvec;
+
+}
+
+int mpic_map_error_int(struct mpic *mpic, unsigned int virq, =
irq_hw_number_t  hw)
quoted hunk
+{
+	if ((mpic->flags & MPIC_FSL_HAS_EIMR) &&
+	    (hw >=3D mpic->err_int_vecs[0] &&
+	     hw <=3D mpic->err_int_vecs[MPIC_MAX_ERR - 1])) {
+		WARN_ON(mpic->flags & MPIC_SECONDARY);
+
+		pr_debug("mpic: mapping as Error Interrupt\n");
+		irq_set_chip_data(virq, mpic);
+		irq_set_chip_and_handler(virq, &mpic->hc_err,
+					 handle_level_irq);
+		return 1;
+	}
+
+	return 0;
+}
+
+static irqreturn_t fsl_error_int_handler(int irq, void *data)
+{
+	struct mpic *mpic =3D (struct mpic *) data;
+	u32 eisr, eimr;
+	int errint;
+	unsigned int cascade_irq;
+
+	eisr =3D mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EISR);
+	eimr =3D mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+
+	if (!(eisr & ~eimr))
+		return IRQ_NONE;
+
+	while (eisr) {
+		errint =3D __builtin_clz(eisr);
+		cascade_irq =3D irq_linear_revmap(mpic->irqhost,
+				 mpic->err_int_vecs[errint]);
+		WARN_ON(cascade_irq =3D=3D NO_IRQ);
+		if (cascade_irq !=3D NO_IRQ) {
+			generic_handle_irq(cascade_irq);
+		} else {
+			eimr |=3D  1 << (31 - errint);
+			mpic_fsl_err_write(mpic->err_regs, eimr);
+		}
+		eisr &=3D ~(1 << (31 - errint));
+	}
+
+	return IRQ_HANDLED;
+}
+
+int mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum)
+{
+	unsigned int virq;
+	int ret;
+
+	virq =3D irq_create_mapping(mpic->irqhost, irqnum);
+	if (virq =3D=3D NO_IRQ) {
+		pr_err("Error interrupt setup failed\n");
+		return 0;
+	}
+
+	/* Mask all error interrupts */
+	mpic_fsl_err_write(mpic->err_regs, ~0);
+
+	ret =3D request_irq(virq, fsl_error_int_handler, IRQF_NO_THREAD,
+		    "mpic-error-int", mpic);
+	if (ret) {
+		pr_err("Failed to register error interrupt handler\n");
+		return 0;
+	}
+
+	return 1;
+}
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 7e32db7..2a0b632 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1026,6 +1026,9 @@ static int mpic_host_map(struct irq_domain *h, =
unsigned int virq,
quoted hunk
		return 0;
	}
=20
+	if (mpic_map_error_int(mpic, virq, hw))
+		return 0;
+
	if (hw >=3D mpic->num_sources)
		return -EINVAL;
=20
@@ -1085,7 +1088,16 @@ static int mpic_host_xlate(struct irq_domain =
*h, struct device_node *ct,
		 */
		switch (intspec[2]) {
		case 0:
-		case 1: /* no EISR/EIMR support for now, treat as shared =
IRQ */
+			break;
+		case 1:
+			if (!mpic->err_int_config_done)
+				break;
+
Under what case would we call mpic_host_xlate and have not called =
mpic_init?
+			if (intspec[3] >=3D =
ARRAY_SIZE(mpic->err_int_vecs))
quoted hunk
+				return -EINVAL;
+
+			*out_hwirq =3D mpic->err_int_vecs[intspec[3]];
+
			break;
		case 2:
			if (intspec[0] >=3D ARRAY_SIZE(mpic->ipi_vecs))
@@ -1302,6 +1314,8 @@ struct mpic * __init mpic_alloc(struct =
device_node *node,
	mpic_map(mpic, mpic->paddr, &mpic->tmregs, =
MPIC_INFO(TIMER_BASE), 0x1000);
=20
	if (mpic->flags & MPIC_FSL) {
+		u32 brr1, version;
+
		/*
		 * Yes, Freescale really did put global registers in the
		 * magic per-cpu area -- and they don't even show up in =
the
quoted hunk
@@ -1309,6 +1323,26 @@ struct mpic * __init mpic_alloc(struct =
device_node *node,
quoted hunk
		 */
		mpic_map(mpic, mpic->paddr, &mpic->thiscpuregs,
			 MPIC_CPU_THISBASE, 0x1000);
+
+		brr1 =3D _mpic_read(mpic->reg_type, &mpic->thiscpuregs,
+				MPIC_FSL_BRR1);
+		version =3D brr1 & MPIC_FSL_BRR1_VER;
+
+		/* Error interrupt mask register (EIMR) is required for
+		 * handling individual device error interrupts. EIMR
+		 * was added in MPIC version 4.1.
+		 *
+		 * Over here we reserve vector number space for error
+		 * interrupt vectors. This space is stolen from the
+		 * global vector number space, as in case of ipis
+		 * and timer interrupts.
+		 *
+		 * Available vector space =3D intvec_top - 12, where 12
+		 * is the number of vectors which have been consumed by
+		 * ipis and timer interrupts.
+		 */
+		if (version >=3D 0x401)
+			mpic_setup_error_int(mpic, intvec_top - 12);
	}
=20
	/* Reset */
@@ -1474,6 +1508,11 @@ void __init mpic_init(struct mpic *mpic)
			num_timers =3D 8;
	}
=20
+	/* FSL mpic error interrupt intialization */
+	if (mpic->flags & MPIC_FSL_HAS_EIMR)
+		mpic->err_int_config_done =3D
+			mpic_err_int_init(mpic, MPIC_FSL_ERR_INT);
+
	/* Initialize timers to our reserved vectors and mask them for =
now */
quoted hunk
	for (i =3D 0; i < num_timers; i++) {
		unsigned int offset =3D mpic_tm_offset(mpic, i);
diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h
index 13f3e89..1a6995a 100644
--- a/arch/powerpc/sysdev/mpic.h
+++ b/arch/powerpc/sysdev/mpic.h
@@ -40,4 +40,26 @@ extern int mpic_set_affinity(struct irq_data *d,
			     const struct cpumask *cpumask, bool force);
extern void mpic_reset_core(int cpu);
=20
+#ifdef CONFIG_FSL_SOC
+extern int mpic_map_error_int(struct mpic *mpic, unsigned int virq, =
irq_hw_number_t  hw);
+extern int mpic_err_int_init(struct mpic *mpic, irq_hw_number_t =
irqnum);
+extern void mpic_setup_error_int(struct mpic *mpic, int intvec);
+#else
+static inline int mpic_map_error_int(struct mpic *mpic, unsigned int =
virq, irq_hw_number_t  hw)
+{
+	return 0;
+}
+
+
+static inline int mpic_err_int_init(struct mpic *mpic, =
irq_hw_number_t irqnum)
+{
+	return -1;
+}
+
+static inline void mpic_setup_error_int(struct mpic *mpic, int =
intvec)
+{
+	return;
+}
+#endif
+
#endif /* _POWERPC_SYSDEV_MPIC_H */
--=20
1.7.4.1
=20
=20
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt support.

From: Scott Wood <hidden>
Date: 2012-08-03 16:45:03

On 08/03/2012 08:19 AM, Kumar Gala wrote:
On Jul 31, 2012, at 9:42 AM, Varun Sethi wrote:
quoted
+	/* ioremap'ed base for error interrupt registers */
+	u32 __iomem	*err_regs;
+	/* error interrupt config */
+	u32			err_int_config_done;
+
Is this really needed ?
Probably a left over from when it was done on demand.
quoted
	/* Protected sources */
	unsigned long		*protected;
@@ -370,6 +381,8 @@ struct mpic
#define MPIC_NO_RESET			0x00004000
/* Freescale MPIC (compatible includes "fsl,mpic") */
#define MPIC_FSL			0x00008000
+/* Freescale MPIC supports EIMR (error interrupt mask register)*/
+#define MPIC_FSL_HAS_EIMR		0x00010000
Can't we use BRR for this?
BRR is used, and this is set as a result.  Better than opencoding a BRR
check a bunch of places...

-Scott

RE: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt support.

From: Sethi Varun-B16395 <hidden>
Date: 2012-08-03 18:52:33

-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org]
Sent: Friday, August 03, 2012 6:49 PM
To: Sethi Varun-B16395
Cc: linuxppc-dev@lists.ozlabs.org; Hamciuc Bogdan-BHAMCIU1
Subject: Re: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt
support.
=20
=20
On Jul 31, 2012, at 9:42 AM, Varun Sethi wrote:
=20
quoted
All SOC device error interrupts are muxed and delivered to the core as
a single MPIC error interrupt. Currently all the device drivers
requiring access to device errors have to register for the MPIC error
interrupt as a shared interrupt.
quoted
With this patch we add interrupt demuxing capability in the mpic
driver, allowing device drivers to register for their individual error
interrupts. This is achieved by handling error interrupts in a cascaded
fashion.
quoted
MPIC error interrupt is handled by the "error_int_handler", which
subsequently demuxes it using the EISR and delivers it to the
respective drivers.
quoted
The error interrupt capability is dependent on the MPIC EIMR register,
which was introduced in FSL MPIC version 4.1 (P4080 rev2). So, error
interrupt demuxing capability is dependent on the MPIC version and can
be used for versions >=3D 4.1.
quoted
Signed-off-by: Varun Sethi <redacted>
Signed-off-by: Bogdan Hamciuc <redacted> [In the
initial version of the patch we were using handle_simple_irq as the
handler for cascaded error interrupts, this resulted in issues in case
of threaded isrs (with RT kernel). This issue was debugged by Bogdan
and decision was taken to use the handle_level_irq handler]
=20
[ fix commit message to wrap at 75 char columns ]
=20
quoted
---
arch/powerpc/include/asm/mpic.h    |   13 +++
arch/powerpc/sysdev/Makefile       |    2 +-
arch/powerpc/sysdev/fsl_mpic_err.c |  152
++++++++++++++++++++++++++++++++++++
quoted
arch/powerpc/sysdev/mpic.c         |   41 ++++++++++-
arch/powerpc/sysdev/mpic.h         |   22 +++++
5 files changed, 228 insertions(+), 2 deletions(-) create mode 100644
arch/powerpc/sysdev/fsl_mpic_err.c
diff --git a/arch/powerpc/include/asm/mpic.h
b/arch/powerpc/include/asm/mpic.h index e14d35d..5cc8000 100644
--- a/arch/powerpc/include/asm/mpic.h
+++ b/arch/powerpc/include/asm/mpic.h
@@ -118,6 +118,9 @@
#define MPIC_MAX_CPUS		32
#define MPIC_MAX_ISU		32

+#define MPIC_MAX_ERR      32
+#define MPIC_FSL_ERR_INT  16
+
/*
* Tsi108 implementation of MPIC has many differences from the original
one */ @@ -270,6 +273,7 @@ struct mpic
	struct irq_chip		hc_ipi;
#endif
	struct irq_chip		hc_tm;
+	struct irq_chip		hc_err;
	const char		*name;
	/* Flags */
	unsigned int		flags;
@@ -283,6 +287,8 @@ struct mpic
	/* vector numbers used for internal sources (ipi/timers) */
	unsigned int		ipi_vecs[4];
	unsigned int		timer_vecs[8];
+	/* vector numbers used for FSL MPIC error interrupts */
+	unsigned int		err_int_vecs[MPIC_MAX_ERR];

	/* Spurious vector to program into unused sources */
	unsigned int		spurious_vec;
@@ -306,6 +312,11 @@ struct mpic
	struct mpic_reg_bank	cpuregs[MPIC_MAX_CPUS];
	struct mpic_reg_bank	isus[MPIC_MAX_ISU];

+	/* ioremap'ed base for error interrupt registers */
+	u32 __iomem	*err_regs;
+	/* error interrupt config */
+	u32			err_int_config_done;
+
=20
Is this really needed ?
[Sethi Varun-B16395] check for verifying if mpic_err_int_init was successfu=
l or not.
=20
quoted
	/* Protected sources */
	unsigned long		*protected;
@@ -370,6 +381,8 @@ struct mpic
#define MPIC_NO_RESET			0x00004000
/* Freescale MPIC (compatible includes "fsl,mpic") */
#define MPIC_FSL			0x00008000
+/* Freescale MPIC supports EIMR (error interrupt mask register)*/
+#define MPIC_FSL_HAS_EIMR		0x00010000
=20
Can't we use BRR for this?
[Sethi Varun-B16395] This flag is set based on the BRR check. This is check=
ed at various places.
=20
quoted
/* MPIC HW modification ID */
#define MPIC_REGSET_MASK		0xf0000000
diff --git a/arch/powerpc/sysdev/Makefile
b/arch/powerpc/sysdev/Makefile index 1bd7ecb..a57600b 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_PPC_DCR_NATIVE)	+=3D dcr-low.o
obj-$(CONFIG_PPC_PMI)		+=3D pmi.o
obj-$(CONFIG_U3_DART)		+=3D dart_iommu.o
obj-$(CONFIG_MMIO_NVRAM)	+=3D mmio_nvram.o
-obj-$(CONFIG_FSL_SOC)		+=3D fsl_soc.o
+obj-$(CONFIG_FSL_SOC)		+=3D fsl_soc.o fsl_mpic_err.o
obj-$(CONFIG_FSL_PCI)		+=3D fsl_pci.o $(fsl-msi-obj-y)
obj-$(CONFIG_FSL_PMC)		+=3D fsl_pmc.o
obj-$(CONFIG_FSL_LBC)		+=3D fsl_lbc.o
diff --git a/arch/powerpc/sysdev/fsl_mpic_err.c
b/arch/powerpc/sysdev/fsl_mpic_err.c
new file mode 100644
index 0000000..1ebfa36
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_mpic_err.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *
+ * Author: Varun Sethi <varun.sethi@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mpic.h>
+
+#include "mpic.h"
+
+#define MPIC_ERR_INT_BASE	0x3900
+#define MPIC_ERR_INT_EISR	0x0000
+#define MPIC_ERR_INT_EIMR	0x0010
+
+static inline u32 mpic_fsl_err_read(u32 __iomem *base, unsigned int
+err_reg) {
+	return in_be32(base + (err_reg >> 2)); }
+
+static inline void mpic_fsl_err_write(u32 __iomem *base, u32 value) {
+	out_be32(base + (MPIC_ERR_INT_EIMR >> 2), value); }
+
+static void fsl_mpic_mask_err(struct irq_data *d) {
+	u32 eimr;
+	struct mpic *mpic =3D irq_data_get_irq_chip_data(d);
+	unsigned int src =3D virq_to_hw(d->irq) - mpic->err_int_vecs[0];
+
+	eimr =3D mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+	eimr |=3D (1 << (31 - src));
+	mpic_fsl_err_write(mpic->err_regs, eimr); }
+
+static void fsl_mpic_unmask_err(struct irq_data *d) {
+	u32 eimr;
+	struct mpic *mpic =3D irq_data_get_irq_chip_data(d);
+	unsigned int src =3D virq_to_hw(d->irq) - mpic->err_int_vecs[0];
+
+	eimr =3D mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+	eimr &=3D ~(1 << (31 - src));
+	mpic_fsl_err_write(mpic->err_regs, eimr); }
+
+static struct irq_chip fsl_mpic_err_chip =3D {
+	.irq_disable	=3D fsl_mpic_mask_err,
+	.irq_mask	=3D fsl_mpic_mask_err,
+	.irq_unmask	=3D fsl_mpic_unmask_err,
+};
+
+void mpic_setup_error_int(struct mpic *mpic, int intvec) {
+	int i;
+
+	mpic->err_regs =3D ioremap(mpic->paddr + MPIC_ERR_INT_BASE, 0x1000);
+	if (!mpic->err_regs) {
+		pr_err("could not map mpic error registers\n");
+		return;
=20
we should propagate an error back up if ioremap failed.
[Sethi Varun-B16395] Should we fail mpic_alloc when this fails?
=20
quoted
+	}
+	mpic->hc_err =3D fsl_mpic_err_chip;
+	mpic->hc_err.name =3D mpic->name;
+	mpic->flags |=3D MPIC_FSL_HAS_EIMR;
+	/* allocate interrupt vectors for error interrupts */
+	for (i =3D MPIC_MAX_ERR - 1; i >=3D 0; i--)
+		mpic->err_int_vecs[i] =3D --intvec;
+
+}
+
+int mpic_map_error_int(struct mpic *mpic, unsigned int virq,
+irq_hw_number_t  hw) {
+	if ((mpic->flags & MPIC_FSL_HAS_EIMR) &&
+	    (hw >=3D mpic->err_int_vecs[0] &&
+	     hw <=3D mpic->err_int_vecs[MPIC_MAX_ERR - 1])) {
+		WARN_ON(mpic->flags & MPIC_SECONDARY);
+
+		pr_debug("mpic: mapping as Error Interrupt\n");
+		irq_set_chip_data(virq, mpic);
+		irq_set_chip_and_handler(virq, &mpic->hc_err,
+					 handle_level_irq);
+		return 1;
+	}
+
+	return 0;
+}
+
+static irqreturn_t fsl_error_int_handler(int irq, void *data) {
+	struct mpic *mpic =3D (struct mpic *) data;
+	u32 eisr, eimr;
+	int errint;
+	unsigned int cascade_irq;
+
+	eisr =3D mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EISR);
+	eimr =3D mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+
+	if (!(eisr & ~eimr))
+		return IRQ_NONE;
+
+	while (eisr) {
+		errint =3D __builtin_clz(eisr);
+		cascade_irq =3D irq_linear_revmap(mpic->irqhost,
+				 mpic->err_int_vecs[errint]);
+		WARN_ON(cascade_irq =3D=3D NO_IRQ);
+		if (cascade_irq !=3D NO_IRQ) {
+			generic_handle_irq(cascade_irq);
+		} else {
+			eimr |=3D  1 << (31 - errint);
+			mpic_fsl_err_write(mpic->err_regs, eimr);
+		}
+		eisr &=3D ~(1 << (31 - errint));
+	}
+
+	return IRQ_HANDLED;
+}
+
+int mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum) {
+	unsigned int virq;
+	int ret;
+
+	virq =3D irq_create_mapping(mpic->irqhost, irqnum);
+	if (virq =3D=3D NO_IRQ) {
+		pr_err("Error interrupt setup failed\n");
+		return 0;
+	}
+
+	/* Mask all error interrupts */
+	mpic_fsl_err_write(mpic->err_regs, ~0);
+
+	ret =3D request_irq(virq, fsl_error_int_handler, IRQF_NO_THREAD,
+		    "mpic-error-int", mpic);
+	if (ret) {
+		pr_err("Failed to register error interrupt handler\n");
+		return 0;
+	}
+
+	return 1;
+}
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 7e32db7..2a0b632 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1026,6 +1026,9 @@ static int mpic_host_map(struct irq_domain *h,
unsigned int virq,
quoted
		return 0;
	}

+	if (mpic_map_error_int(mpic, virq, hw))
+		return 0;
+
	if (hw >=3D mpic->num_sources)
		return -EINVAL;
@@ -1085,7 +1088,16 @@ static int mpic_host_xlate(struct irq_domain *h,
struct device_node *ct,
quoted
		 */
		switch (intspec[2]) {
		case 0:
-		case 1: /* no EISR/EIMR support for now, treat as shared IRQ
*/
quoted
+			break;
+		case 1:
+			if (!mpic->err_int_config_done)
+				break;
+
=20
Under what case would we call mpic_host_xlate and have not called
mpic_init?
=20
[Sethi Varun-B16395] Never, but we shouldn't translate the error interrupt =
specifier
If mpic_err_int_init failed.

-Varun

Re: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt support.

From: Kumar Gala <hidden>
Date: 2012-08-03 19:14:06

On Aug 3, 2012, at 11:44 AM, Scott Wood wrote:
On 08/03/2012 08:19 AM, Kumar Gala wrote:
quoted
=20
On Jul 31, 2012, at 9:42 AM, Varun Sethi wrote:
quoted
+	/* ioremap'ed base for error interrupt registers */
+	u32 __iomem	*err_regs;
+	/* error interrupt config */
+	u32			err_int_config_done;
+
=20
Is this really needed ?
=20
Probably a left over from when it was done on demand.
=20
quoted
=20
quoted
	/* Protected sources */
	unsigned long		*protected;
=20
@@ -370,6 +381,8 @@ struct mpic
#define MPIC_NO_RESET			0x00004000
/* Freescale MPIC (compatible includes "fsl,mpic") */
#define MPIC_FSL			0x00008000
+/* Freescale MPIC supports EIMR (error interrupt mask register)*/
+#define MPIC_FSL_HAS_EIMR		0x00010000
=20
Can't we use BRR for this?
=20
BRR is used, and this is set as a result.  Better than opencoding a =
BRR
check a bunch of places...
I'm fine w/that, but didn't see where MPIC_FSL_HAS_EMIR was being set.. =
Just want to avoid the caller of mpic_alloc() having to pass it in.

- k=

RE: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt support.

From: Sethi Varun-B16395 <hidden>
Date: 2012-08-03 19:16:17

-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org]
Sent: Saturday, August 04, 2012 12:43 AM
To: Wood Scott-B07421
Cc: Sethi Varun-B16395; Hamciuc Bogdan-BHAMCIU1; linuxppc-
dev@lists.ozlabs.org
Subject: Re: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt
support.
=20
=20
On Aug 3, 2012, at 11:44 AM, Scott Wood wrote:
=20
quoted
On 08/03/2012 08:19 AM, Kumar Gala wrote:
quoted
On Jul 31, 2012, at 9:42 AM, Varun Sethi wrote:
quoted
+	/* ioremap'ed base for error interrupt registers */
+	u32 __iomem	*err_regs;
+	/* error interrupt config */
+	u32			err_int_config_done;
+
Is this really needed ?
Probably a left over from when it was done on demand.
quoted
quoted
	/* Protected sources */
	unsigned long		*protected;
@@ -370,6 +381,8 @@ struct mpic
#define MPIC_NO_RESET			0x00004000
/* Freescale MPIC (compatible includes "fsl,mpic") */
#define MPIC_FSL			0x00008000
+/* Freescale MPIC supports EIMR (error interrupt mask register)*/
+#define MPIC_FSL_HAS_EIMR		0x00010000
Can't we use BRR for this?
BRR is used, and this is set as a result.  Better than opencoding a
BRR check a bunch of places...
=20
I'm fine w/that, but didn't see where MPIC_FSL_HAS_EMIR was being set..
Just want to avoid the caller of mpic_alloc() having to pass it in.
It's being set in mpic_setup_error_int (called from mpic_alloc)

-Varun

Re: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt support.

From: Kumar Gala <hidden>
Date: 2012-08-03 19:22:19

On Aug 3, 2012, at 2:16 PM, Sethi Varun-B16395 wrote:
quoted
-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org]
Sent: Saturday, August 04, 2012 12:43 AM
To: Wood Scott-B07421
Cc: Sethi Varun-B16395; Hamciuc Bogdan-BHAMCIU1; linuxppc-
dev@lists.ozlabs.org
Subject: Re: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt
support.


On Aug 3, 2012, at 11:44 AM, Scott Wood wrote:
quoted
On 08/03/2012 08:19 AM, Kumar Gala wrote:
quoted
On Jul 31, 2012, at 9:42 AM, Varun Sethi wrote:
quoted
+	/* ioremap'ed base for error interrupt registers */
+	u32 __iomem	*err_regs;
+	/* error interrupt config */
+	u32			err_int_config_done;
+
Is this really needed ?
Probably a left over from when it was done on demand.
quoted
quoted
	/* Protected sources */
	unsigned long		*protected;
@@ -370,6 +381,8 @@ struct mpic
#define MPIC_NO_RESET			0x00004000
/* Freescale MPIC (compatible includes "fsl,mpic") */
#define MPIC_FSL			0x00008000
+/* Freescale MPIC supports EIMR (error interrupt mask register)*/
+#define MPIC_FSL_HAS_EIMR		0x00010000
Can't we use BRR for this?
BRR is used, and this is set as a result.  Better than opencoding a
BRR check a bunch of places...
I'm fine w/that, but didn't see where MPIC_FSL_HAS_EMIR was being set..
Just want to avoid the caller of mpic_alloc() having to pass it in.
It's being set in mpic_setup_error_int (called from mpic_alloc)
See it now.  Odd my search didn't find it.

- k

Re: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt support.

From: Kumar Gala <hidden>
Date: 2012-08-03 19:24:38

On Aug 3, 2012, at 1:52 PM, Sethi Varun-B16395 wrote:
=20
=20
quoted
-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org]
Sent: Friday, August 03, 2012 6:49 PM
To: Sethi Varun-B16395
Cc: linuxppc-dev@lists.ozlabs.org; Hamciuc Bogdan-BHAMCIU1
Subject: Re: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt
support.
=20
=20
On Jul 31, 2012, at 9:42 AM, Varun Sethi wrote:
=20
quoted
All SOC device error interrupts are muxed and delivered to the core =
as
quoted
quoted
a single MPIC error interrupt. Currently all the device drivers
requiring access to device errors have to register for the MPIC =
error
quoted
interrupt as a shared interrupt.
quoted
=20
With this patch we add interrupt demuxing capability in the mpic
driver, allowing device drivers to register for their individual =
error
quoted
quoted
interrupts. This is achieved by handling error interrupts in a =
cascaded
quoted
fashion.
quoted
=20
MPIC error interrupt is handled by the "error_int_handler", which
subsequently demuxes it using the EISR and delivers it to the
respective drivers.
quoted
=20
The error interrupt capability is dependent on the MPIC EIMR =
register,
quoted
quoted
which was introduced in FSL MPIC version 4.1 (P4080 rev2). So, error
interrupt demuxing capability is dependent on the MPIC version and =
can
quoted
be used for versions >=3D 4.1.
quoted
=20
Signed-off-by: Varun Sethi <redacted>
Signed-off-by: Bogdan Hamciuc <redacted> [In the
initial version of the patch we were using handle_simple_irq as the
handler for cascaded error interrupts, this resulted in issues in =
case
quoted
quoted
of threaded isrs (with RT kernel). This issue was debugged by Bogdan
and decision was taken to use the handle_level_irq handler]
=20
[ fix commit message to wrap at 75 char columns ]
=20
quoted
=20
---
arch/powerpc/include/asm/mpic.h    |   13 +++
arch/powerpc/sysdev/Makefile       |    2 +-
arch/powerpc/sysdev/fsl_mpic_err.c |  152
++++++++++++++++++++++++++++++++++++
quoted
arch/powerpc/sysdev/mpic.c         |   41 ++++++++++-
arch/powerpc/sysdev/mpic.h         |   22 +++++
5 files changed, 228 insertions(+), 2 deletions(-) create mode =
100644
quoted
quoted
arch/powerpc/sysdev/fsl_mpic_err.c
=20
diff --git a/arch/powerpc/include/asm/mpic.h
b/arch/powerpc/include/asm/mpic.h index e14d35d..5cc8000 100644
--- a/arch/powerpc/include/asm/mpic.h
+++ b/arch/powerpc/include/asm/mpic.h
@@ -118,6 +118,9 @@
#define MPIC_MAX_CPUS		32
#define MPIC_MAX_ISU		32
=20
+#define MPIC_MAX_ERR      32
+#define MPIC_FSL_ERR_INT  16
+
/*
* Tsi108 implementation of MPIC has many differences from the =
original
quoted
quoted
one */ @@ -270,6 +273,7 @@ struct mpic
	struct irq_chip		hc_ipi;
#endif
	struct irq_chip		hc_tm;
+	struct irq_chip		hc_err;
	const char		*name;
	/* Flags */
	unsigned int		flags;
@@ -283,6 +287,8 @@ struct mpic
	/* vector numbers used for internal sources (ipi/timers) */
	unsigned int		ipi_vecs[4];
	unsigned int		timer_vecs[8];
+	/* vector numbers used for FSL MPIC error interrupts */
+	unsigned int		err_int_vecs[MPIC_MAX_ERR];
=20
	/* Spurious vector to program into unused sources */
	unsigned int		spurious_vec;
@@ -306,6 +312,11 @@ struct mpic
	struct mpic_reg_bank	cpuregs[MPIC_MAX_CPUS];
	struct mpic_reg_bank	isus[MPIC_MAX_ISU];
=20
+	/* ioremap'ed base for error interrupt registers */
+	u32 __iomem	*err_regs;
+	/* error interrupt config */
+	u32			err_int_config_done;
+
=20
Is this really needed ?
[Sethi Varun-B16395] check for verifying if mpic_err_int_init was =
successful or not.

See comment below, I think we can reasonable remove this check.
=20
quoted
=20
quoted
	/* Protected sources */
	unsigned long		*protected;
=20
@@ -370,6 +381,8 @@ struct mpic
#define MPIC_NO_RESET			0x00004000
/* Freescale MPIC (compatible includes "fsl,mpic") */
#define MPIC_FSL			0x00008000
+/* Freescale MPIC supports EIMR (error interrupt mask register)*/
+#define MPIC_FSL_HAS_EIMR		0x00010000
=20
Can't we use BRR for this?
[Sethi Varun-B16395] This flag is set based on the BRR check. This is =
checked at various places.

I see it now.  How about we add a comment that we expect to set this =
flag via determining version of controller. (ie reading BRR)
=20
quoted
=20
quoted
=20
/* MPIC HW modification ID */
#define MPIC_REGSET_MASK		0xf0000000
diff --git a/arch/powerpc/sysdev/Makefile
b/arch/powerpc/sysdev/Makefile index 1bd7ecb..a57600b 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_PPC_DCR_NATIVE)	+=3D dcr-low.o
obj-$(CONFIG_PPC_PMI)		+=3D pmi.o
obj-$(CONFIG_U3_DART)		+=3D dart_iommu.o
obj-$(CONFIG_MMIO_NVRAM)	+=3D mmio_nvram.o
-obj-$(CONFIG_FSL_SOC)		+=3D fsl_soc.o
+obj-$(CONFIG_FSL_SOC)		+=3D fsl_soc.o fsl_mpic_err.o
obj-$(CONFIG_FSL_PCI)		+=3D fsl_pci.o $(fsl-msi-obj-y)
obj-$(CONFIG_FSL_PMC)		+=3D fsl_pmc.o
obj-$(CONFIG_FSL_LBC)		+=3D fsl_lbc.o
diff --git a/arch/powerpc/sysdev/fsl_mpic_err.c
b/arch/powerpc/sysdev/fsl_mpic_err.c
new file mode 100644
index 0000000..1ebfa36
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_mpic_err.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *
+ * Author: Varun Sethi <varun.sethi@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mpic.h>
+
+#include "mpic.h"
+
+#define MPIC_ERR_INT_BASE	0x3900
+#define MPIC_ERR_INT_EISR	0x0000
+#define MPIC_ERR_INT_EIMR	0x0010
+
+static inline u32 mpic_fsl_err_read(u32 __iomem *base, unsigned int
+err_reg) {
+	return in_be32(base + (err_reg >> 2)); }
+
+static inline void mpic_fsl_err_write(u32 __iomem *base, u32 value) =
{
quoted
quoted
+	out_be32(base + (MPIC_ERR_INT_EIMR >> 2), value); }
+
+static void fsl_mpic_mask_err(struct irq_data *d) {
+	u32 eimr;
+	struct mpic *mpic =3D irq_data_get_irq_chip_data(d);
+	unsigned int src =3D virq_to_hw(d->irq) - mpic->err_int_vecs[0];
+
+	eimr =3D mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+	eimr |=3D (1 << (31 - src));
+	mpic_fsl_err_write(mpic->err_regs, eimr); }
+
+static void fsl_mpic_unmask_err(struct irq_data *d) {
+	u32 eimr;
+	struct mpic *mpic =3D irq_data_get_irq_chip_data(d);
+	unsigned int src =3D virq_to_hw(d->irq) - mpic->err_int_vecs[0];
+
+	eimr =3D mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+	eimr &=3D ~(1 << (31 - src));
+	mpic_fsl_err_write(mpic->err_regs, eimr); }
+
+static struct irq_chip fsl_mpic_err_chip =3D {
+	.irq_disable	=3D fsl_mpic_mask_err,
+	.irq_mask	=3D fsl_mpic_mask_err,
+	.irq_unmask	=3D fsl_mpic_unmask_err,
+};
+
+void mpic_setup_error_int(struct mpic *mpic, int intvec) {
+	int i;
+
+	mpic->err_regs =3D ioremap(mpic->paddr + MPIC_ERR_INT_BASE, =
0x1000);
quoted
quoted
+	if (!mpic->err_regs) {
+		pr_err("could not map mpic error registers\n");
+		return;
=20
we should propagate an error back up if ioremap failed.
[Sethi Varun-B16395] Should we fail mpic_alloc when this fails?
Yes, we should return 0 in mpic_alloc.
=20
quoted
=20
quoted
+	}
+	mpic->hc_err =3D fsl_mpic_err_chip;
+	mpic->hc_err.name =3D mpic->name;
+	mpic->flags |=3D MPIC_FSL_HAS_EIMR;
+	/* allocate interrupt vectors for error interrupts */
+	for (i =3D MPIC_MAX_ERR - 1; i >=3D 0; i--)
+		mpic->err_int_vecs[i] =3D --intvec;
+
+}
+
+int mpic_map_error_int(struct mpic *mpic, unsigned int virq,
+irq_hw_number_t  hw) {
+	if ((mpic->flags & MPIC_FSL_HAS_EIMR) &&
+	    (hw >=3D mpic->err_int_vecs[0] &&
+	     hw <=3D mpic->err_int_vecs[MPIC_MAX_ERR - 1])) {
+		WARN_ON(mpic->flags & MPIC_SECONDARY);
+
+		pr_debug("mpic: mapping as Error Interrupt\n");
+		irq_set_chip_data(virq, mpic);
+		irq_set_chip_and_handler(virq, &mpic->hc_err,
+					 handle_level_irq);
+		return 1;
+	}
+
+	return 0;
+}
+
+static irqreturn_t fsl_error_int_handler(int irq, void *data) {
+	struct mpic *mpic =3D (struct mpic *) data;
+	u32 eisr, eimr;
+	int errint;
+	unsigned int cascade_irq;
+
+	eisr =3D mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EISR);
+	eimr =3D mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+
+	if (!(eisr & ~eimr))
+		return IRQ_NONE;
+
+	while (eisr) {
+		errint =3D __builtin_clz(eisr);
+		cascade_irq =3D irq_linear_revmap(mpic->irqhost,
+				 mpic->err_int_vecs[errint]);
+		WARN_ON(cascade_irq =3D=3D NO_IRQ);
+		if (cascade_irq !=3D NO_IRQ) {
+			generic_handle_irq(cascade_irq);
+		} else {
+			eimr |=3D  1 << (31 - errint);
+			mpic_fsl_err_write(mpic->err_regs, eimr);
+		}
+		eisr &=3D ~(1 << (31 - errint));
+	}
+
+	return IRQ_HANDLED;
+}
+
+int mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum) {
+	unsigned int virq;
+	int ret;
+
+	virq =3D irq_create_mapping(mpic->irqhost, irqnum);
+	if (virq =3D=3D NO_IRQ) {
+		pr_err("Error interrupt setup failed\n");
+		return 0;
+	}
+
+	/* Mask all error interrupts */
+	mpic_fsl_err_write(mpic->err_regs, ~0);
+
+	ret =3D request_irq(virq, fsl_error_int_handler, IRQF_NO_THREAD,
+		    "mpic-error-int", mpic);
+	if (ret) {
+		pr_err("Failed to register error interrupt handler\n");
+		return 0;
+	}
+
+	return 1;
+}
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 7e32db7..2a0b632 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1026,6 +1026,9 @@ static int mpic_host_map(struct irq_domain *h,
unsigned int virq,
quoted
		return 0;
	}
=20
+	if (mpic_map_error_int(mpic, virq, hw))
+		return 0;
+
	if (hw >=3D mpic->num_sources)
		return -EINVAL;
=20
@@ -1085,7 +1088,16 @@ static int mpic_host_xlate(struct irq_domain =
*h,
quoted
struct device_node *ct,
quoted
		 */
		switch (intspec[2]) {
		case 0:
-		case 1: /* no EISR/EIMR support for now, treat as shared =
IRQ
quoted
*/
quoted
+			break;
+		case 1:
+			if (!mpic->err_int_config_done)
+				break;
+
=20
Under what case would we call mpic_host_xlate and have not called
mpic_init?
=20
[Sethi Varun-B16395] Never, but we shouldn't translate the error =
interrupt specifier
If mpic_err_int_init failed.
Isnt that true of a 1000 other things.  If init failed we shouldn't even =
call map for other reasons.  I don't think we need a special check here.=

RE: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt support.

From: Sethi Varun-B16395 <hidden>
Date: 2012-08-03 19:32:42

-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org]
Sent: Saturday, August 04, 2012 12:55 AM
To: Sethi Varun-B16395
Cc: linuxppc-dev@lists.ozlabs.org; Hamciuc Bogdan-BHAMCIU1
Subject: Re: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt
support.
=20
=20
On Aug 3, 2012, at 1:52 PM, Sethi Varun-B16395 wrote:
=20
quoted
quoted
-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org]
Sent: Friday, August 03, 2012 6:49 PM
To: Sethi Varun-B16395
Cc: linuxppc-dev@lists.ozlabs.org; Hamciuc Bogdan-BHAMCIU1
Subject: Re: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt
support.
quoted
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 7e32db7..2a0b632 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1026,6 +1026,9 @@ static int mpic_host_map(struct irq_domain *h,
unsigned int virq,
quoted
		return 0;
	}

+	if (mpic_map_error_int(mpic, virq, hw))
+		return 0;
+
	if (hw >=3D mpic->num_sources)
		return -EINVAL;
@@ -1085,7 +1088,16 @@ static int mpic_host_xlate(struct irq_domain
*h,
struct device_node *ct,
quoted
		 */
		switch (intspec[2]) {
		case 0:
-		case 1: /* no EISR/EIMR support for now, treat as shared IRQ
*/
quoted
+			break;
+		case 1:
+			if (!mpic->err_int_config_done)
+				break;
+
Under what case would we call mpic_host_xlate and have not called
mpic_init?
[Sethi Varun-B16395] Never, but we shouldn't translate the error
interrupt specifier If mpic_err_int_init failed.
=20
Isnt that true of a 1000 other things.  If init failed we shouldn't even
call map for other reasons.  I don't think we need a special check here.
[Sethi Varun-B16395] There is no specific check to see if mpic_init failed.
In this particular case if we fail to register the error interrupt handler
we cannot use the error sub interrupts.

-Varun

Re: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt support.

From: Scott Wood <hidden>
Date: 2012-08-07 18:57:15

On 08/03/2012 02:32 PM, Sethi Varun-B16395 wrote:
quoted
-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org]
Sent: Saturday, August 04, 2012 12:55 AM
To: Sethi Varun-B16395
Cc: linuxppc-dev@lists.ozlabs.org; Hamciuc Bogdan-BHAMCIU1
Subject: Re: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt
support.


On Aug 3, 2012, at 1:52 PM, Sethi Varun-B16395 wrote:
quoted
quoted
-----Original Message-----
From: Kumar Gala [mailto:galak@kernel.crashing.org]
Sent: Friday, August 03, 2012 6:49 PM
To: Sethi Varun-B16395
Cc: linuxppc-dev@lists.ozlabs.org; Hamciuc Bogdan-BHAMCIU1
Subject: Re: [PATCH 3/3 v3] powerpc/mpic: FSL MPIC error interrupt
support.
quoted
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 7e32db7..2a0b632 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1026,6 +1026,9 @@ static int mpic_host_map(struct irq_domain *h,
unsigned int virq,
quoted
		return 0;
	}

+	if (mpic_map_error_int(mpic, virq, hw))
+		return 0;
+
	if (hw >= mpic->num_sources)
		return -EINVAL;
@@ -1085,7 +1088,16 @@ static int mpic_host_xlate(struct irq_domain
*h,
struct device_node *ct,
quoted
		 */
		switch (intspec[2]) {
		case 0:
-		case 1: /* no EISR/EIMR support for now, treat as shared IRQ
*/
quoted
+			break;
+		case 1:
+			if (!mpic->err_int_config_done)
+				break;
+
Under what case would we call mpic_host_xlate and have not called
mpic_init?
[Sethi Varun-B16395] Never, but we shouldn't translate the error
interrupt specifier If mpic_err_int_init failed.
Isnt that true of a 1000 other things.  If init failed we shouldn't even
call map for other reasons.  I don't think we need a special check here.
[Sethi Varun-B16395] There is no specific check to see if mpic_init failed.
In this particular case if we fail to register the error interrupt handler
we cannot use the error sub interrupts.
As Kumar says, you could say the same thing about all the ioremaps it
does, or any other bit of init.  If mpic_init() fails, we're broken.
There's no point trying to hobble along by testing whether this bit or
that bit actually succeeded.

-Scott
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help