All of lore.kernel.org
 help / color / mirror / Atom feed
From: Magnus Damm <magnus.damm@gmail.com>
To: linux-sh@vger.kernel.org
Subject: [PATCH 06/07] ARM: mach-shmobile: Use common INTC IRQ code on sh73a0
Date: Wed, 12 Oct 2011 07:21:42 +0000	[thread overview]
Message-ID: <20111012072142.25511.29276.sendpatchset@w520> (raw)

From: Magnus Damm <damm@opensource.se>

Improve IRQ triggering support by making use of the macro
INTC_IRQ_PINS_32() for INTCA on sh73a0. Unfortunately it
is not as easy as just using the macro as-is, we need to
do mask and unmaks in the GIC but configure other bits
and ack in INTCA. Update GPIO IRQ mappings while at it.

Signed-off-by: Magnus Damm <damm@opensource.se>
---

 arch/arm/mach-shmobile/intc-sh73a0.c |  122 ++++++++++++++++++++++++++++++++++
 arch/arm/mach-shmobile/pfc-sh73a0.c  |   68 +++++++++---------
 2 files changed, 157 insertions(+), 33 deletions(-)

--- 0001/arch/arm/mach-shmobile/intc-sh73a0.c
+++ work/arch/arm/mach-shmobile/intc-sh73a0.c	2011-10-12 15:22:33.000000000 +0900
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sh_intc.h>
+#include <mach/intc.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -255,20 +256,141 @@ static int sh73a0_set_wake(struct irq_da
 	return 0; /* always allow wakeup */
 }
 
+#define RELOC_BASE 0x1000
+
+/* INTCA IRQ pins at INTCS + 0x1000 to make space for GIC+INTC handling */
+#define INTCS_VECT_RELOC(n, vect) INTCS_VECT((n), (vect) + RELOC_BASE)
+
+INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
+		 INTCS_VECT_RELOC, "sh73a0-intca-irq-pins");
+
+static int to_gic_irq(struct irq_data *data)
+{
+	unsigned int vect = irq2evt(data->irq) - INTCS_VECT_BASE;
+
+	if (vect >= 0x3200)
+		vect -= 0x3000;
+	else
+		vect -= 0x0200;
+
+	return gic_spi((vect >> 5) + 1);
+}
+
+static int to_intca_reloc_irq(struct irq_data *data)
+{
+	return data->irq + (RELOC_BASE >> 5);
+}
+
+#define irq_cb(cb, irq) irq_get_chip(irq)->cb(irq_get_irq_data(irq))
+#define irq_cbp(cb, irq, p...) irq_get_chip(irq)->cb(irq_get_irq_data(irq), p)
+
+static void intca_gic_enable(struct irq_data *data)
+{
+	irq_cb(irq_unmask, to_intca_reloc_irq(data));
+	irq_cb(irq_unmask, to_gic_irq(data));
+}
+
+static void intca_gic_disable(struct irq_data *data)
+{
+	irq_cb(irq_mask, to_gic_irq(data));
+	irq_cb(irq_mask, to_intca_reloc_irq(data));
+}
+
+static void intca_gic_mask_ack(struct irq_data *data)
+{
+	irq_cb(irq_mask, to_gic_irq(data));
+	irq_cb(irq_mask_ack, to_intca_reloc_irq(data));
+}
+
+static void intca_gic_eoi(struct irq_data *data)
+{
+	irq_cb(irq_eoi, to_gic_irq(data));
+}
+
+static int intca_gic_set_type(struct irq_data *data, unsigned int type)
+{
+	return irq_cbp(irq_set_type, to_intca_reloc_irq(data), type);
+}
+
+static int intca_gic_set_wake(struct irq_data *data, unsigned int on)
+{
+	return irq_cbp(irq_set_wake, to_intca_reloc_irq(data), on);
+}
+
+#ifdef CONFIG_SMP
+static int intca_gic_set_affinity(struct irq_data *data,
+				  const struct cpumask *cpumask,
+				  bool force)
+{
+	return irq_cbp(irq_set_affinity, to_gic_irq(data), cpumask, force);
+}
+#endif
+
+struct irq_chip intca_gic_irq_chip = {
+	.name			= "INTCA-GIC",
+	.irq_mask		= intca_gic_disable,
+	.irq_unmask		= intca_gic_enable,
+	.irq_mask_ack		= intca_gic_mask_ack,
+	.irq_eoi		= intca_gic_eoi,
+	.irq_enable		= intca_gic_enable,
+	.irq_disable		= intca_gic_disable,
+	.irq_shutdown		= intca_gic_disable,
+	.irq_set_type		= intca_gic_set_type,
+	.irq_set_wake		= intca_gic_set_wake,
+#ifdef CONFIG_SMP
+	.irq_set_affinity	= intca_gic_set_affinity,
+#endif
+};
+
+static int to_intc_vect(int irq)
+{
+	unsigned int irq_pin = irq - gic_spi(1);
+	unsigned int offs;
+
+	if (irq_pin < 16)
+		offs = 0x0200;
+	else
+		offs = 0x3000;
+
+	return offs + (irq_pin << 5);
+}
+
+static irqreturn_t sh73a0_irq_pin_demux(int irq, void *dev_id)
+{
+	generic_handle_irq(intcs_evt2irq(to_intc_vect(irq)));
+	return IRQ_HANDLED;
+}
+
+static struct irqaction sh73a0_irq_pin_cascade[32];
+
 void __init sh73a0_init_irq(void)
 {
 	void __iomem *gic_dist_base = __io(0xf0001000);
 	void __iomem *gic_cpu_base = __io(0xf0000100);
 	void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
+	int k, n;
 
 	gic_init(0, 29, gic_dist_base, gic_cpu_base);
 	gic_arch_extn.irq_set_wake = sh73a0_set_wake;
 
 	register_intc_controller(&intcs_desc);
+	register_intc_controller(&intca_irq_pins_desc);
 
 	/* demux using INTEVTSA */
 	sh73a0_intcs_cascade.name = "INTCS cascade";
 	sh73a0_intcs_cascade.handler = sh73a0_intcs_demux;
 	sh73a0_intcs_cascade.dev_id = intevtsa;
 	setup_irq(gic_spi(50), &sh73a0_intcs_cascade);
+
+	/* IRQ pins require special handling through INTCA and GIC */
+	for (k = 0; k < 32; k++) {
+		sh73a0_irq_pin_cascade[k].name = "INTCA-GIC cascade";
+		sh73a0_irq_pin_cascade[k].handler = sh73a0_irq_pin_demux;
+		setup_irq(gic_spi(1 + k), &sh73a0_irq_pin_cascade[k]);
+
+		n = intcs_evt2irq(to_intc_vect(gic_spi(1 + k)));
+		irq_set_chip_and_handler_name(n, &intca_gic_irq_chip,
+					      handle_level_irq, "level");
+		set_irq_flags(n, IRQF_VALID); /* yuck */
+	}
 }
--- 0007/arch/arm/mach-shmobile/pfc-sh73a0.c
+++ work/arch/arm/mach-shmobile/pfc-sh73a0.c	2011-10-12 15:21:09.000000000 +0900
@@ -2766,41 +2766,43 @@ static struct pinmux_data_reg pinmux_dat
 	{ },
 };
 
-#define EXT_IRQ(n) gic_spi((n) + 1) /* GIC SPI starting from 1 for IRQ0 */
+/* IRQ pins through INTCS with IRQ0->15 from 0x200 and IRQ16-31 from 0x3200 */
+#define EXT_IRQ16L(n) intcs_evt2irq(0x200 + ((n) << 5))
+#define EXT_IRQ16H(n) intcs_evt2irq(0x3200 + ((n - 16) << 5))
 
 static struct pinmux_irq pinmux_irqs[] = {
-	PINMUX_IRQ(EXT_IRQ(19), PORT9_FN0),
-	PINMUX_IRQ(EXT_IRQ(1), PORT10_FN0),
-	PINMUX_IRQ(EXT_IRQ(0), PORT11_FN0),
-	PINMUX_IRQ(EXT_IRQ(18), PORT13_FN0),
-	PINMUX_IRQ(EXT_IRQ(20), PORT14_FN0),
-	PINMUX_IRQ(EXT_IRQ(21), PORT15_FN0),
-	PINMUX_IRQ(EXT_IRQ(31), PORT26_FN0),
-	PINMUX_IRQ(EXT_IRQ(30), PORT27_FN0),
-	PINMUX_IRQ(EXT_IRQ(29), PORT28_FN0),
-	PINMUX_IRQ(EXT_IRQ(22), PORT40_FN0),
-	PINMUX_IRQ(EXT_IRQ(23), PORT53_FN0),
-	PINMUX_IRQ(EXT_IRQ(10), PORT54_FN0),
-	PINMUX_IRQ(EXT_IRQ(9), PORT56_FN0),
-	PINMUX_IRQ(EXT_IRQ(26), PORT115_FN0),
-	PINMUX_IRQ(EXT_IRQ(27), PORT116_FN0),
-	PINMUX_IRQ(EXT_IRQ(28), PORT117_FN0),
-	PINMUX_IRQ(EXT_IRQ(24), PORT118_FN0),
-	PINMUX_IRQ(EXT_IRQ(6), PORT147_FN0),
-	PINMUX_IRQ(EXT_IRQ(2), PORT149_FN0),
-	PINMUX_IRQ(EXT_IRQ(7), PORT150_FN0),
-	PINMUX_IRQ(EXT_IRQ(12), PORT156_FN0),
-	PINMUX_IRQ(EXT_IRQ(4), PORT159_FN0),
-	PINMUX_IRQ(EXT_IRQ(25), PORT164_FN0),
-	PINMUX_IRQ(EXT_IRQ(8), PORT223_FN0),
-	PINMUX_IRQ(EXT_IRQ(3), PORT224_FN0),
-	PINMUX_IRQ(EXT_IRQ(5), PORT227_FN0),
-	PINMUX_IRQ(EXT_IRQ(17), PORT234_FN0),
-	PINMUX_IRQ(EXT_IRQ(11), PORT238_FN0),
-	PINMUX_IRQ(EXT_IRQ(13), PORT239_FN0),
-	PINMUX_IRQ(EXT_IRQ(16), PORT249_FN0),
-	PINMUX_IRQ(EXT_IRQ(14), PORT251_FN0),
-	PINMUX_IRQ(EXT_IRQ(9), PORT308_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(1), PORT10_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(0), PORT11_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(18), PORT13_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(20), PORT14_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(21), PORT15_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(31), PORT26_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(30), PORT27_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(29), PORT28_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(22), PORT40_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(23), PORT53_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(10), PORT54_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(9), PORT56_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(26), PORT115_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(27), PORT116_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(28), PORT117_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(24), PORT118_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(6), PORT147_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(2), PORT149_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(7), PORT150_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(12), PORT156_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(4), PORT159_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(25), PORT164_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(8), PORT223_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(3), PORT224_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(5), PORT227_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(17), PORT234_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(11), PORT238_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(13), PORT239_FN0),
+	PINMUX_IRQ(EXT_IRQ16H(16), PORT249_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(14), PORT251_FN0),
+	PINMUX_IRQ(EXT_IRQ16L(9), PORT308_FN0),
 };
 
 static struct pinmux_info sh73a0_pinmux_info = {

                 reply	other threads:[~2011-10-12  7:21 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20111012072142.25511.29276.sendpatchset@w520 \
    --to=magnus.damm@gmail.com \
    --cc=linux-sh@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.