* [GIT PULL v2] Renesas INTC External IRQ pin driver
@ 2013-03-19 2:19 Simon Horman
2013-03-19 2:19 ` [PATCH 01/14] irqchip: " Simon Horman
` (14 more replies)
0 siblings, 15 replies; 18+ messages in thread
From: Simon Horman @ 2013-03-19 2:19 UTC (permalink / raw)
To: linux-arm-kernel
The following changes since commit d75bc78b508d0a95d7738290d8ec9923691f4301:
r8a7779: Add Display Unit clock support (2013-03-18 21:22:34 +0900)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git intc-external-irq
for you to fetch changes up to 3b8dfa7c2f8af7613dae28ac0f3419bf75ead5d0:
irqchip: irqc: Add DT support (2013-03-18 21:26:07 +0900)
----------------------------------------------------------------
Renesas INTC External IRQ pin driver
This provides two new INTC drivers for use with Renesas ARM-based SoCs and
makes use of them on the r8a7779 and sh73a0 SoCs.
It has been agreed by the relevant parties, Thomas Gleixner, Magnus Damm,
and myself that it would be best to merge this code through the renesas
tree and thus through the arm-soc tree.
This is based on:
git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git renesas-soc-v3.10
----------------------------------------------------------------
Magnus Damm (14):
irqchip: Renesas INTC External IRQ pin driver
ARM: shmobile: irq_pin() for static IRQ pin assignment
ARM: shmobile: INTC External IRQ pin driver on sh73a0
ARM: shmobile: INTC External IRQ pin driver on r8a7779
irqchip: intc-irqpin: Whitespace fixes
irqchip: intc-irqpin: Cache mapped IRQ
irqchip: intc-irqpin: Add force comments
irqchip: intc-irqpin: Make use of devm functions
irqchip: intc-irqpin: GPL header for platform data
irqchip: Renesas IRQC driver
ARM: shmobile: Make sh73a0 INTC irqpin platform data static
ARM: shmobile: Make r8a7779 INTC irqpin platform data static
irqchip: intc-irqpin: Initial DT support
irqchip: irqc: Add DT support
arch/arm/mach-shmobile/Kconfig | 2 +
arch/arm/mach-shmobile/board-kzm9g.c | 14 +-
arch/arm/mach-shmobile/include/mach/common.h | 1 +
arch/arm/mach-shmobile/include/mach/irqs.h | 4 +
arch/arm/mach-shmobile/intc-r8a7779.c | 53 ++-
arch/arm/mach-shmobile/intc-sh73a0.c | 117 -----
arch/arm/mach-shmobile/setup-sh73a0.c | 126 ++++++
drivers/irqchip/Kconfig | 8 +
drivers/irqchip/Makefile | 2 +
drivers/irqchip/irq-renesas-intc-irqpin.c | 471 ++++++++++++++++++++
drivers/irqchip/irq-renesas-irqc.c | 307 +++++++++++++
drivers/pinctrl/sh-pfc/pfc-sh73a0.c | 6 +-
.../linux/platform_data/irq-renesas-intc-irqpin.h | 29 ++
include/linux/platform_data/irq-renesas-irqc.h | 27 ++
14 files changed, 1039 insertions(+), 128 deletions(-)
create mode 100644 drivers/irqchip/irq-renesas-intc-irqpin.c
create mode 100644 drivers/irqchip/irq-renesas-irqc.c
create mode 100644 include/linux/platform_data/irq-renesas-intc-irqpin.h
create mode 100644 include/linux/platform_data/irq-renesas-irqc.h
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 01/14] irqchip: Renesas INTC External IRQ pin driver
2013-03-19 2:19 [GIT PULL v2] Renesas INTC External IRQ pin driver Simon Horman
@ 2013-03-19 2:19 ` Simon Horman
2013-03-19 2:19 ` [PATCH 02/14] ARM: shmobile: irq_pin() for static IRQ pin assignment Simon Horman
` (13 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Simon Horman @ 2013-03-19 2:19 UTC (permalink / raw)
To: linux-arm-kernel
From: Magnus Damm <damm@opensource.se>
This patch adds a driver for external IRQ pins connected
to the INTC block on recent SoCs from Renesas.
The INTC hardware block usually contains a rather wide
range of features ranging from external IRQ pin handling
to legacy interrupt controller support. On older SoCs
the INTC is used as a general purpose interrupt controller
both for external IRQ pins and on-chip devices.
On more recent ARM based SoCs with Cortex-A9 the main
interrupt controller is the GIC, but IRQ trigger setup
still need to happen in the INTC hardware block.
This driver implements the glue code needed to configure
IRQ trigger and also handle mask/unmask and demux of
external IRQ pins hooked up from the INTC to the GIC.
Tested on sh73a0 and r8a7779. The hardware varies quite
a bit with SoC model, for instance register width and
bitfield widths vary wildly. The driver requires one GIC
SPI per external IRQ pin to operate. Each driver instance
will handle up to 8 external IRQ pins.
The SoCs using this driver are currently mainly used
together with regular platform devices so this driver
allows configuration via platform data to support things
like static interrupt base address. DT support will
be added incrementally in the not so distant future.
Signed-off-by: Magnus Damm <damm@opensource.se>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
drivers/irqchip/Kconfig | 4 +
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-renesas-intc-irqpin.c | 464 ++++++++++++++++++++
.../linux/platform_data/irq-renesas-intc-irqpin.h | 10 +
4 files changed, 479 insertions(+)
create mode 100644 drivers/irqchip/irq-renesas-intc-irqpin.c
create mode 100644 include/linux/platform_data/irq-renesas-intc-irqpin.h
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index a350969..0f5f1c3 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -25,6 +25,10 @@ config ARM_VIC_NR
The maximum number of VICs available in the system, for
power management.
+config RENESAS_INTC_IRQPIN
+ bool
+ select IRQ_DOMAIN
+
config VERSATILE_FPGA_IRQ
bool
select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 98e3b87..1aaa407 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -8,4 +8,5 @@ obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi.o
obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
obj-$(CONFIG_ARM_GIC) += irq-gic.o
obj-$(CONFIG_ARM_VIC) += irq-vic.o
+obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o
obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
new file mode 100644
index 0000000..1e5058a
--- /dev/null
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -0,0 +1,464 @@
+/*
+ * Renesas INTC External IRQ Pin Driver
+ *
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * 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; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
+
+#define INTC_IRQPIN_MAX 8 /* maximum 8 interrupts per driver instance */
+
+#define INTC_IRQPIN_REG_SENSE 0 /* ICRn */
+#define INTC_IRQPIN_REG_PRIO 1 /* INTPRInn */
+#define INTC_IRQPIN_REG_SOURCE 2 /* INTREQnn */
+#define INTC_IRQPIN_REG_MASK 3 /* INTMSKnn */
+#define INTC_IRQPIN_REG_CLEAR 4 /* INTMSKCLRnn */
+#define INTC_IRQPIN_REG_NR 5
+
+/* INTC external IRQ PIN hardware register access:
+ *
+ * SENSE is read-write 32-bit with 2-bits or 4-bits per IRQ (*)
+ * PRIO is read-write 32-bit with 4-bits per IRQ (**)
+ * SOURCE is read-only 32-bit or 8-bit with 1-bit per IRQ (***)
+ * MASK is write-only 32-bit or 8-bit with 1-bit per IRQ (***)
+ * CLEAR is write-only 32-bit or 8-bit with 1-bit per IRQ (***)
+ *
+ * (*) May be accessed by more than one driver instance - lock needed
+ * (**) Read-modify-write access by one driver instance - lock needed
+ * (***) Accessed by one driver instance only - no locking needed
+ */
+
+struct intc_irqpin_iomem {
+ void __iomem *iomem;
+ unsigned long (*read)(void __iomem *iomem);
+ void (*write)(void __iomem *iomem, unsigned long data);
+ int width;
+};
+
+struct intc_irqpin_irq {
+ int hw_irq;
+ int irq;
+ struct intc_irqpin_priv *p;
+};
+
+struct intc_irqpin_priv {
+ struct intc_irqpin_iomem iomem[INTC_IRQPIN_REG_NR];
+ struct intc_irqpin_irq irq[INTC_IRQPIN_MAX];
+ struct renesas_intc_irqpin_config config;
+ unsigned int number_of_irqs;
+ struct platform_device *pdev;
+ struct irq_chip irq_chip;
+ struct irq_domain *irq_domain;
+};
+
+static unsigned long intc_irqpin_read32(void __iomem *iomem)
+{
+ return ioread32(iomem);
+}
+
+static unsigned long intc_irqpin_read8(void __iomem *iomem)
+{
+ return ioread8(iomem);
+}
+
+static void intc_irqpin_write32(void __iomem *iomem, unsigned long data)
+{
+ iowrite32(data, iomem);
+}
+
+static void intc_irqpin_write8(void __iomem *iomem, unsigned long data)
+{
+ iowrite8(data, iomem);
+}
+
+static inline unsigned long intc_irqpin_read(struct intc_irqpin_priv *p,
+ int reg)
+{
+ struct intc_irqpin_iomem *i = &p->iomem[reg];
+ return i->read(i->iomem);
+}
+
+static inline void intc_irqpin_write(struct intc_irqpin_priv *p,
+ int reg, unsigned long data)
+{
+ struct intc_irqpin_iomem *i = &p->iomem[reg];
+ i->write(i->iomem, data);
+}
+
+static inline unsigned long intc_irqpin_hwirq_mask(struct intc_irqpin_priv *p,
+ int reg, int hw_irq)
+{
+ return BIT((p->iomem[reg].width - 1) - hw_irq);
+}
+
+static inline void intc_irqpin_irq_write_hwirq(struct intc_irqpin_priv *p,
+ int reg, int hw_irq)
+{
+ intc_irqpin_write(p, reg, intc_irqpin_hwirq_mask(p, reg, hw_irq));
+}
+
+static DEFINE_RAW_SPINLOCK(intc_irqpin_lock); /* only used by slow path */
+
+static void intc_irqpin_read_modify_write(struct intc_irqpin_priv *p,
+ int reg, int shift,
+ int width, int value)
+{
+ unsigned long flags;
+ unsigned long tmp;
+
+ raw_spin_lock_irqsave(&intc_irqpin_lock, flags);
+
+ tmp = intc_irqpin_read(p, reg);
+ tmp &= ~(((1 << width) - 1) << shift);
+ tmp |= value << shift;
+ intc_irqpin_write(p, reg, tmp);
+
+ raw_spin_unlock_irqrestore(&intc_irqpin_lock, flags);
+}
+
+static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
+ int irq, int do_mask)
+{
+ int bitfield_width = 4; /* PRIO assumed to have fixed bitfield width */
+ int shift = (7 - irq) * bitfield_width; /* PRIO assumed to be 32-bit */
+
+ intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_PRIO,
+ shift, bitfield_width,
+ do_mask ? 0 : (1 << bitfield_width) - 1);
+}
+
+static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value)
+{
+ int bitfield_width = p->config.sense_bitfield_width;
+ int shift = (7 - irq) * bitfield_width; /* SENSE assumed to be 32-bit */
+
+ dev_dbg(&p->pdev->dev, "sense irq = %d, mode = %d\n", irq, value);
+
+ if (value >= (1 << bitfield_width))
+ return -EINVAL;
+
+ intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_SENSE, shift,
+ bitfield_width, value);
+ return 0;
+}
+
+static void intc_irqpin_dbg(struct intc_irqpin_irq *i, char *str)
+{
+ dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n",
+ str, i->irq, i->hw_irq,
+ irq_find_mapping(i->p->irq_domain, i->hw_irq));
+}
+
+static void intc_irqpin_irq_enable(struct irq_data *d)
+{
+ struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+ int hw_irq = irqd_to_hwirq(d);
+
+ intc_irqpin_dbg(&p->irq[hw_irq], "enable");
+ intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_CLEAR, hw_irq);
+}
+
+static void intc_irqpin_irq_disable(struct irq_data *d)
+{
+ struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+ int hw_irq = irqd_to_hwirq(d);
+
+ intc_irqpin_dbg(&p->irq[hw_irq], "disable");
+ intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_MASK, hw_irq);
+}
+
+static void intc_irqpin_irq_enable_force(struct irq_data *d)
+{
+ struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+ int irq = p->irq[irqd_to_hwirq(d)].irq;
+
+ intc_irqpin_irq_enable(d);
+ irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq));
+}
+
+static void intc_irqpin_irq_disable_force(struct irq_data *d)
+{
+ struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+ int irq = p->irq[irqd_to_hwirq(d)].irq;
+
+ irq_get_chip(irq)->irq_mask(irq_get_irq_data(irq));
+ intc_irqpin_irq_disable(d);
+}
+
+#define INTC_IRQ_SENSE_VALID 0x10
+#define INTC_IRQ_SENSE(x) (x + INTC_IRQ_SENSE_VALID)
+
+static unsigned char intc_irqpin_sense[IRQ_TYPE_SENSE_MASK + 1] = {
+ [IRQ_TYPE_EDGE_FALLING] = INTC_IRQ_SENSE(0x00),
+ [IRQ_TYPE_EDGE_RISING] = INTC_IRQ_SENSE(0x01),
+ [IRQ_TYPE_LEVEL_LOW] = INTC_IRQ_SENSE(0x02),
+ [IRQ_TYPE_LEVEL_HIGH] = INTC_IRQ_SENSE(0x03),
+ [IRQ_TYPE_EDGE_BOTH] = INTC_IRQ_SENSE(0x04),
+};
+
+static int intc_irqpin_irq_set_type(struct irq_data *d, unsigned int type)
+{
+ unsigned char value = intc_irqpin_sense[type & IRQ_TYPE_SENSE_MASK];
+ struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+
+ if (!(value & INTC_IRQ_SENSE_VALID))
+ return -EINVAL;
+
+ return intc_irqpin_set_sense(p, irqd_to_hwirq(d),
+ value ^ INTC_IRQ_SENSE_VALID);
+}
+
+static irqreturn_t intc_irqpin_irq_handler(int irq, void *dev_id)
+{
+ struct intc_irqpin_irq *i = dev_id;
+ struct intc_irqpin_priv *p = i->p;
+ unsigned long bit;
+
+ intc_irqpin_dbg(i, "demux1");
+ bit = intc_irqpin_hwirq_mask(p, INTC_IRQPIN_REG_SOURCE, i->hw_irq);
+
+ if (intc_irqpin_read(p, INTC_IRQPIN_REG_SOURCE) & bit) {
+ intc_irqpin_write(p, INTC_IRQPIN_REG_SOURCE, ~bit);
+ intc_irqpin_dbg(i, "demux2");
+ generic_handle_irq(irq_find_mapping(p->irq_domain, i->hw_irq));
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+static int intc_irqpin_irq_domain_map(struct irq_domain *h, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct intc_irqpin_priv *p = h->host_data;
+
+ intc_irqpin_dbg(&p->irq[hw], "map");
+ irq_set_chip_data(virq, h->host_data);
+ irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
+ set_irq_flags(virq, IRQF_VALID); /* kill me now */
+ return 0;
+}
+
+static struct irq_domain_ops intc_irqpin_irq_domain_ops = {
+ .map = intc_irqpin_irq_domain_map,
+};
+
+static int intc_irqpin_probe(struct platform_device *pdev)
+{
+ struct renesas_intc_irqpin_config *pdata = pdev->dev.platform_data;
+ struct intc_irqpin_priv *p;
+ struct intc_irqpin_iomem *i;
+ struct resource *io[INTC_IRQPIN_REG_NR];
+ struct resource *irq;
+ struct irq_chip *irq_chip;
+ void (*enable_fn)(struct irq_data *d);
+ void (*disable_fn)(struct irq_data *d);
+ const char *name = dev_name(&pdev->dev);
+ int ret;
+ int k;
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p) {
+ dev_err(&pdev->dev, "failed to allocate driver data\n");
+ ret = -ENOMEM;
+ goto err0;
+ }
+
+ /* deal with driver instance configuration */
+ if (pdata)
+ memcpy(&p->config, pdata, sizeof(*pdata));
+ if (!p->config.sense_bitfield_width)
+ p->config.sense_bitfield_width = 4; /* default to 4 bits */
+
+ p->pdev = pdev;
+ platform_set_drvdata(pdev, p);
+
+ /* get hold of manadatory IOMEM */
+ for (k = 0; k < INTC_IRQPIN_REG_NR; k++) {
+ io[k] = platform_get_resource(pdev, IORESOURCE_MEM, k);
+ if (!io[k]) {
+ dev_err(&pdev->dev, "not enough IOMEM resources\n");
+ ret = -EINVAL;
+ goto err1;
+ }
+ }
+
+ /* allow any number of IRQs between 1 and INTC_IRQPIN_MAX */
+ for (k = 0; k < INTC_IRQPIN_MAX; k++) {
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, k);
+ if (!irq)
+ break;
+
+ p->irq[k].hw_irq = k;
+ p->irq[k].p = p;
+ p->irq[k].irq = irq->start;
+ }
+
+ p->number_of_irqs = k;
+ if (p->number_of_irqs < 1) {
+ dev_err(&pdev->dev, "not enough IRQ resources\n");
+ ret = -EINVAL;
+ goto err1;
+ }
+
+ /* ioremap IOMEM and setup read/write callbacks */
+ for (k = 0; k < INTC_IRQPIN_REG_NR; k++) {
+ i = &p->iomem[k];
+
+ switch (resource_size(io[k])) {
+ case 1:
+ i->width = 8;
+ i->read = intc_irqpin_read8;
+ i->write = intc_irqpin_write8;
+ break;
+ case 4:
+ i->width = 32;
+ i->read = intc_irqpin_read32;
+ i->write = intc_irqpin_write32;
+ break;
+ default:
+ dev_err(&pdev->dev, "IOMEM size mismatch\n");
+ ret = -EINVAL;
+ goto err2;
+ }
+
+ i->iomem = ioremap_nocache(io[k]->start, resource_size(io[k]));
+ if (!i->iomem) {
+ dev_err(&pdev->dev, "failed to remap IOMEM\n");
+ ret = -ENXIO;
+ goto err2;
+ }
+ }
+
+ /* mask all interrupts using priority */
+ for (k = 0; k < p->number_of_irqs; k++)
+ intc_irqpin_mask_unmask_prio(p, k, 1);
+
+ /* use more severe masking method if requested */
+ if (p->config.control_parent) {
+ enable_fn = intc_irqpin_irq_enable_force;
+ disable_fn = intc_irqpin_irq_disable_force;
+ } else {
+ enable_fn = intc_irqpin_irq_enable;
+ disable_fn = intc_irqpin_irq_disable;
+ }
+
+ irq_chip = &p->irq_chip;
+ irq_chip->name = name;
+ irq_chip->irq_mask = disable_fn;
+ irq_chip->irq_unmask = enable_fn;
+ irq_chip->irq_enable = enable_fn;
+ irq_chip->irq_disable = disable_fn;
+ irq_chip->irq_set_type = intc_irqpin_irq_set_type;
+ irq_chip->flags = IRQCHIP_SKIP_SET_WAKE;
+
+ p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
+ p->number_of_irqs,
+ p->config.irq_base,
+ &intc_irqpin_irq_domain_ops, p);
+ if (!p->irq_domain) {
+ ret = -ENXIO;
+ dev_err(&pdev->dev, "cannot initialize irq domain\n");
+ goto err2;
+ }
+
+ /* request and set priority on interrupts one by one */
+ for (k = 0; k < p->number_of_irqs; k++) {
+ if (request_irq(p->irq[k].irq, intc_irqpin_irq_handler,
+ 0, name, &p->irq[k])) {
+ dev_err(&pdev->dev, "failed to request low IRQ\n");
+ ret = -ENOENT;
+ goto err3;
+ }
+ intc_irqpin_mask_unmask_prio(p, k, 0);
+ }
+
+ dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs);
+
+ /* warn in case of mismatch if irq base is specified */
+ if (p->config.irq_base) {
+ k = irq_find_mapping(p->irq_domain, 0);
+ if (p->config.irq_base != k)
+ dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n",
+ p->config.irq_base, k);
+ }
+
+ return 0;
+
+err3:
+ for (; k >= 0; k--)
+ free_irq(p->irq[k - 1].irq, &p->irq[k - 1]);
+
+ irq_domain_remove(p->irq_domain);
+err2:
+ for (k = 0; k < INTC_IRQPIN_REG_NR; k++)
+ iounmap(p->iomem[k].iomem);
+err1:
+ kfree(p);
+err0:
+ return ret;
+}
+
+static int intc_irqpin_remove(struct platform_device *pdev)
+{
+ struct intc_irqpin_priv *p = platform_get_drvdata(pdev);
+ int k;
+
+ for (k = 0; k < p->number_of_irqs; k++)
+ free_irq(p->irq[k].irq, &p->irq[k]);
+
+ irq_domain_remove(p->irq_domain);
+
+ for (k = 0; k < INTC_IRQPIN_REG_NR; k++)
+ iounmap(p->iomem[k].iomem);
+
+ kfree(p);
+ return 0;
+}
+
+static struct platform_driver intc_irqpin_device_driver = {
+ .probe = intc_irqpin_probe,
+ .remove = intc_irqpin_remove,
+ .driver = {
+ .name = "renesas_intc_irqpin",
+ }
+};
+
+static int __init intc_irqpin_init(void)
+{
+ return platform_driver_register(&intc_irqpin_device_driver);
+}
+postcore_initcall(intc_irqpin_init);
+
+static void __exit intc_irqpin_exit(void)
+{
+ platform_driver_unregister(&intc_irqpin_device_driver);
+}
+module_exit(intc_irqpin_exit);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("Renesas INTC External IRQ Pin Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/platform_data/irq-renesas-intc-irqpin.h b/include/linux/platform_data/irq-renesas-intc-irqpin.h
new file mode 100644
index 0000000..00ccac3
--- /dev/null
+++ b/include/linux/platform_data/irq-renesas-intc-irqpin.h
@@ -0,0 +1,10 @@
+#ifndef __IRQ_RENESAS_INTC_IRQPIN_H__
+#define __IRQ_RENESAS_INTC_IRQPIN_H__
+
+struct renesas_intc_irqpin_config {
+ unsigned int sense_bitfield_width;
+ unsigned int irq_base;
+ bool control_parent;
+};
+
+#endif /* __IRQ_RENESAS_INTC_IRQPIN_H__ */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 02/14] ARM: shmobile: irq_pin() for static IRQ pin assignment
2013-03-19 2:19 [GIT PULL v2] Renesas INTC External IRQ pin driver Simon Horman
2013-03-19 2:19 ` [PATCH 01/14] irqchip: " Simon Horman
@ 2013-03-19 2:19 ` Simon Horman
2013-03-19 2:19 ` [PATCH 03/14] ARM: shmobile: INTC External IRQ pin driver on sh73a0 Simon Horman
` (12 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Simon Horman @ 2013-03-19 2:19 UTC (permalink / raw)
To: linux-arm-kernel
From: Magnus Damm <damm@opensource.se>
Add the macro irq_pin() to let board-specific code using
platform devices tie in external IRQn pins in a common way.
Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
arch/arm/mach-shmobile/include/mach/irqs.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/mach-shmobile/include/mach/irqs.h b/arch/arm/mach-shmobile/include/mach/irqs.h
index 992ed21..b2074e2 100644
--- a/arch/arm/mach-shmobile/include/mach/irqs.h
+++ b/arch/arm/mach-shmobile/include/mach/irqs.h
@@ -12,4 +12,8 @@
#define INTCS_VECT(n, vect) INTC_VECT((n), INTCS_VECT_BASE + (vect))
#define intcs_evt2irq(evt) evt2irq(INTCS_VECT_BASE + (evt))
+/* External IRQ pins */
+#define IRQPIN_BASE 2000
+#define irq_pin(nr) ((nr) + IRQPIN_BASE)
+
#endif /* __ASM_MACH_IRQS_H */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 03/14] ARM: shmobile: INTC External IRQ pin driver on sh73a0
2013-03-19 2:19 [GIT PULL v2] Renesas INTC External IRQ pin driver Simon Horman
2013-03-19 2:19 ` [PATCH 01/14] irqchip: " Simon Horman
2013-03-19 2:19 ` [PATCH 02/14] ARM: shmobile: irq_pin() for static IRQ pin assignment Simon Horman
@ 2013-03-19 2:19 ` Simon Horman
2013-03-19 2:19 ` [PATCH 04/14] ARM: shmobile: INTC External IRQ pin driver on r8a7779 Simon Horman
` (11 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Simon Horman @ 2013-03-19 2:19 UTC (permalink / raw)
To: linux-arm-kernel
From: Magnus Damm <damm@opensource.se>
Adjust the sh73a0 IRQ code to make use of the
INTC External IRQ pin driver for external
interrupt pins IRQ0 -> IRQ31.
This removes quite a bit of special-case code
in intc-sh73a0.c but the number of lines get
replaced with platform device information in
setup-sh73a0.c. The PFC code is also adjusted
to make gpio_to_irq() return the correct
interrupt number.
At this point the DT reference implementations
are not covered. In the future such code shall
tie in the INTC External IRQ pin driver via
DT, so this kind of verbose code is not needed
for the long term DT case.
Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
arch/arm/mach-shmobile/Kconfig | 1 +
arch/arm/mach-shmobile/board-kzm9g.c | 14 ++--
arch/arm/mach-shmobile/intc-sh73a0.c | 117 ------------------------------
arch/arm/mach-shmobile/setup-sh73a0.c | 126 +++++++++++++++++++++++++++++++++
drivers/pinctrl/sh-pfc/pfc-sh73a0.c | 6 +-
5 files changed, 137 insertions(+), 127 deletions(-)
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 9255546..f964accb 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -16,6 +16,7 @@ config ARCH_SH73A0
select CPU_V7
select I2C
select SH_CLK_CPG
+ select RENESAS_INTC_IRQPIN
config ARCH_R8A7740
bool "R-Mobile A1 (R8A77400)"
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
index 7f3a6b7..d34d12a 100644
--- a/arch/arm/mach-shmobile/board-kzm9g.c
+++ b/arch/arm/mach-shmobile/board-kzm9g.c
@@ -81,7 +81,7 @@ static struct resource smsc9221_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = intcs_evt2irq(0x260), /* IRQ3 */
+ .start = irq_pin(3), /* IRQ3 */
.flags = IORESOURCE_IRQ,
},
};
@@ -115,7 +115,7 @@ static struct resource usb_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = intcs_evt2irq(0x220), /* IRQ1 */
+ .start = irq_pin(1), /* IRQ1 */
.flags = IORESOURCE_IRQ,
},
};
@@ -138,7 +138,7 @@ struct usbhs_private {
struct renesas_usbhs_platform_info info;
};
-#define IRQ15 intcs_evt2irq(0x03e0)
+#define IRQ15 irq_pin(15)
#define USB_PHY_MODE (1 << 4)
#define USB_PHY_INT_EN ((1 << 3) | (1 << 2))
#define USB_PHY_ON (1 << 1)
@@ -563,25 +563,25 @@ static struct i2c_board_info i2c0_devices[] = {
},
{
I2C_BOARD_INFO("ak8975", 0x0c),
- .irq = intcs_evt2irq(0x3380), /* IRQ28 */
+ .irq = irq_pin(28), /* IRQ28 */
},
{
I2C_BOARD_INFO("adxl34x", 0x1d),
- .irq = intcs_evt2irq(0x3340), /* IRQ26 */
+ .irq = irq_pin(26), /* IRQ26 */
},
};
static struct i2c_board_info i2c1_devices[] = {
{
I2C_BOARD_INFO("st1232-ts", 0x55),
- .irq = intcs_evt2irq(0x300), /* IRQ8 */
+ .irq = irq_pin(8), /* IRQ8 */
},
};
static struct i2c_board_info i2c3_devices[] = {
{
I2C_BOARD_INFO("pcf8575", 0x20),
- .irq = intcs_evt2irq(0x3260), /* IRQ19 */
+ .irq = irq_pin(19), /* IRQ19 */
.platform_data = &pcf8575_pdata,
},
};
diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c
index a81a1d8..19a26f4 100644
--- a/arch/arm/mach-shmobile/intc-sh73a0.c
+++ b/arch/arm/mach-shmobile/intc-sh73a0.c
@@ -260,108 +260,6 @@ static int sh73a0_set_wake(struct irq_data *data, unsigned int on)
return 0; /* always allow wakeup */
}
-#define RELOC_BASE 0x1200
-
-/* INTCA IRQ pins@INTCS + RELOC_BASE 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);
-}
-
-#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 = sh73a0_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];
-
#define PINTER0_PHYS 0xe69000a0
#define PINTER1_PHYS 0xe69000a4
#define PINTER0_VIRT IOMEM(0xe69000a0)
@@ -422,13 +320,11 @@ void __init sh73a0_init_irq(void)
void __iomem *gic_dist_base = IOMEM(0xf0001000);
void __iomem *gic_cpu_base = IOMEM(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);
register_intc_controller(&intc_pint0_desc);
register_intc_controller(&intc_pint1_desc);
@@ -438,19 +334,6 @@ void __init sh73a0_init_irq(void)
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)));
- WARN_ON(irq_alloc_desc_at(n, numa_node_id()) != n);
- irq_set_chip_and_handler_name(n, &intca_gic_irq_chip,
- handle_level_irq, "level");
- set_irq_flags(n, IRQF_VALID); /* yuck */
- }
-
/* PINT pins are sanely tied to the GIC as SPI */
sh73a0_pint0_cascade.name = "PINT0 cascade";
sh73a0_pint0_cascade.handler = sh73a0_pint0_demux;
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index 2257a91..638735f 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -33,6 +33,7 @@
#include <linux/sh_intc.h>
#include <linux/sh_timer.h>
#include <linux/platform_data/sh_ipmmu.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
#include <mach/dma-register.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
@@ -811,6 +812,127 @@ static struct platform_device ipmmu_device = {
.num_resources = ARRAY_SIZE(ipmmu_resources),
};
+struct renesas_intc_irqpin_config irqpin0_platform_data = {
+ .irq_base = irq_pin(0), /* IRQ0 -> IRQ7 */
+};
+
+static struct resource irqpin0_resources[] = {
+ DEFINE_RES_MEM(0xe6900000, 4), /* ICR1A */
+ DEFINE_RES_MEM(0xe6900010, 4), /* INTPRI00A */
+ DEFINE_RES_MEM(0xe6900020, 1), /* INTREQ00A */
+ DEFINE_RES_MEM(0xe6900040, 1), /* INTMSK00A */
+ DEFINE_RES_MEM(0xe6900060, 1), /* INTMSKCLR00A */
+ DEFINE_RES_IRQ(gic_spi(1)), /* IRQ0 */
+ DEFINE_RES_IRQ(gic_spi(2)), /* IRQ1 */
+ DEFINE_RES_IRQ(gic_spi(3)), /* IRQ2 */
+ DEFINE_RES_IRQ(gic_spi(4)), /* IRQ3 */
+ DEFINE_RES_IRQ(gic_spi(5)), /* IRQ4 */
+ DEFINE_RES_IRQ(gic_spi(6)), /* IRQ5 */
+ DEFINE_RES_IRQ(gic_spi(7)), /* IRQ6 */
+ DEFINE_RES_IRQ(gic_spi(8)), /* IRQ7 */
+};
+
+static struct platform_device irqpin0_device = {
+ .name = "renesas_intc_irqpin",
+ .id = 0,
+ .resource = irqpin0_resources,
+ .num_resources = ARRAY_SIZE(irqpin0_resources),
+ .dev = {
+ .platform_data = &irqpin0_platform_data,
+ },
+};
+
+struct renesas_intc_irqpin_config irqpin1_platform_data = {
+ .irq_base = irq_pin(8), /* IRQ8 -> IRQ15 */
+ .control_parent = true, /* Disable spurious IRQ10 */
+};
+
+static struct resource irqpin1_resources[] = {
+ DEFINE_RES_MEM(0xe6900004, 4), /* ICR2A */
+ DEFINE_RES_MEM(0xe6900014, 4), /* INTPRI10A */
+ DEFINE_RES_MEM(0xe6900024, 1), /* INTREQ10A */
+ DEFINE_RES_MEM(0xe6900044, 1), /* INTMSK10A */
+ DEFINE_RES_MEM(0xe6900064, 1), /* INTMSKCLR10A */
+ DEFINE_RES_IRQ(gic_spi(9)), /* IRQ8 */
+ DEFINE_RES_IRQ(gic_spi(10)), /* IRQ9 */
+ DEFINE_RES_IRQ(gic_spi(11)), /* IRQ10 */
+ DEFINE_RES_IRQ(gic_spi(12)), /* IRQ11 */
+ DEFINE_RES_IRQ(gic_spi(13)), /* IRQ12 */
+ DEFINE_RES_IRQ(gic_spi(14)), /* IRQ13 */
+ DEFINE_RES_IRQ(gic_spi(15)), /* IRQ14 */
+ DEFINE_RES_IRQ(gic_spi(16)), /* IRQ15 */
+};
+
+static struct platform_device irqpin1_device = {
+ .name = "renesas_intc_irqpin",
+ .id = 1,
+ .resource = irqpin1_resources,
+ .num_resources = ARRAY_SIZE(irqpin1_resources),
+ .dev = {
+ .platform_data = &irqpin1_platform_data,
+ },
+};
+
+struct renesas_intc_irqpin_config irqpin2_platform_data = {
+ .irq_base = irq_pin(16), /* IRQ16 -> IRQ23 */
+};
+
+static struct resource irqpin2_resources[] = {
+ DEFINE_RES_MEM(0xe6900008, 4), /* ICR3A */
+ DEFINE_RES_MEM(0xe6900018, 4), /* INTPRI20A */
+ DEFINE_RES_MEM(0xe6900028, 1), /* INTREQ20A */
+ DEFINE_RES_MEM(0xe6900048, 1), /* INTMSK20A */
+ DEFINE_RES_MEM(0xe6900068, 1), /* INTMSKCLR20A */
+ DEFINE_RES_IRQ(gic_spi(17)), /* IRQ16 */
+ DEFINE_RES_IRQ(gic_spi(18)), /* IRQ17 */
+ DEFINE_RES_IRQ(gic_spi(19)), /* IRQ18 */
+ DEFINE_RES_IRQ(gic_spi(20)), /* IRQ19 */
+ DEFINE_RES_IRQ(gic_spi(21)), /* IRQ20 */
+ DEFINE_RES_IRQ(gic_spi(22)), /* IRQ21 */
+ DEFINE_RES_IRQ(gic_spi(23)), /* IRQ22 */
+ DEFINE_RES_IRQ(gic_spi(24)), /* IRQ23 */
+};
+
+static struct platform_device irqpin2_device = {
+ .name = "renesas_intc_irqpin",
+ .id = 2,
+ .resource = irqpin2_resources,
+ .num_resources = ARRAY_SIZE(irqpin2_resources),
+ .dev = {
+ .platform_data = &irqpin2_platform_data,
+ },
+};
+
+struct renesas_intc_irqpin_config irqpin3_platform_data = {
+ .irq_base = irq_pin(24), /* IRQ24 -> IRQ31 */
+};
+
+static struct resource irqpin3_resources[] = {
+ DEFINE_RES_MEM(0xe690000c, 4), /* ICR4A */
+ DEFINE_RES_MEM(0xe690001c, 4), /* INTPRI30A */
+ DEFINE_RES_MEM(0xe690002c, 1), /* INTREQ30A */
+ DEFINE_RES_MEM(0xe690004c, 1), /* INTMSK30A */
+ DEFINE_RES_MEM(0xe690006c, 1), /* INTMSKCLR30A */
+ DEFINE_RES_IRQ(gic_spi(25)), /* IRQ24 */
+ DEFINE_RES_IRQ(gic_spi(26)), /* IRQ25 */
+ DEFINE_RES_IRQ(gic_spi(27)), /* IRQ26 */
+ DEFINE_RES_IRQ(gic_spi(28)), /* IRQ27 */
+ DEFINE_RES_IRQ(gic_spi(29)), /* IRQ28 */
+ DEFINE_RES_IRQ(gic_spi(30)), /* IRQ29 */
+ DEFINE_RES_IRQ(gic_spi(31)), /* IRQ30 */
+ DEFINE_RES_IRQ(gic_spi(32)), /* IRQ31 */
+};
+
+static struct platform_device irqpin3_device = {
+ .name = "renesas_intc_irqpin",
+ .id = 3,
+ .resource = irqpin3_resources,
+ .num_resources = ARRAY_SIZE(irqpin3_resources),
+ .dev = {
+ .platform_data = &irqpin3_platform_data,
+ },
+};
+
static struct platform_device *sh73a0_devices_dt[] __initdata = {
&scif0_device,
&scif1_device,
@@ -839,6 +961,10 @@ static struct platform_device *sh73a0_late_devices[] __initdata = {
&dma0_device,
&mpdma0_device,
&pmu_device,
+ &irqpin0_device,
+ &irqpin1_device,
+ &irqpin2_device,
+ &irqpin3_device,
};
#define SRCR2 IOMEM(0xe61580b0)
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
index 709008e..6f15c03 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
@@ -2733,9 +2733,9 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
{ },
};
-/* 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))
+/* External IRQ pins mapped@IRQPIN_BASE */
+#define EXT_IRQ16L(n) irq_pin(n)
+#define EXT_IRQ16H(n) irq_pin(n)
static struct pinmux_irq pinmux_irqs[] = {
PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0),
--
1.7.10.4
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 04/14] ARM: shmobile: INTC External IRQ pin driver on r8a7779
2013-03-19 2:19 [GIT PULL v2] Renesas INTC External IRQ pin driver Simon Horman
` (2 preceding siblings ...)
2013-03-19 2:19 ` [PATCH 03/14] ARM: shmobile: INTC External IRQ pin driver on sh73a0 Simon Horman
@ 2013-03-19 2:19 ` Simon Horman
2013-03-19 2:19 ` [PATCH 05/14] irqchip: intc-irqpin: Whitespace fixes Simon Horman
` (10 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Simon Horman @ 2013-03-19 2:19 UTC (permalink / raw)
To: linux-arm-kernel
From: Magnus Damm <damm@opensource.se>
Update the r8a7779 IRQ code to make use of the
INTC External IRQ pin driver for external
interrupt pins IRQ0 -> IRQ3.
The r8a7779 SoC can like older SH SoCs configure
to use the IRQ0 -> IRQ3 signals as individual
interrupts or a combined IRL mode.
Without this patch the r8a7779 SoC code does
not fully support external IRQ pins in individual
IRQ mode. The r8a7779 PFC code does not yet have
gpio_to_irq() support so no need to update such
code.
At this point the DT reference implementations
are not covered. In the future such code shall
tie in the INTC External IRQ pin driver via
DT, so this kind of verbose code is not needed
for the long term DT case.
Signed-off-by: Magnus Damm <damm@opensource.se>
Tested-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
arch/arm/mach-shmobile/Kconfig | 1 +
arch/arm/mach-shmobile/include/mach/common.h | 1 +
arch/arm/mach-shmobile/intc-r8a7779.c | 53 +++++++++++++++++++++++++-
3 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index f964accb..75d413c 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -32,6 +32,7 @@ config ARCH_R8A7779
select SH_CLK_CPG
select USB_ARCH_HAS_EHCI
select USB_ARCH_HAS_OHCI
+ select RENESAS_INTC_IRQPIN
config ARCH_EMEV2
bool "Emma Mobile EV2"
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index 86fcdf9..03f73de 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -61,6 +61,7 @@ extern void r8a7740_pm_init(void);
extern void r8a7779_init_delay(void);
extern void r8a7779_init_irq(void);
+extern void r8a7779_init_irq_extpin(int irlm);
extern void r8a7779_init_irq_dt(void);
extern void r8a7779_map_io(void);
extern void r8a7779_earlytimer_init(void);
diff --git a/arch/arm/mach-shmobile/intc-r8a7779.c b/arch/arm/mach-shmobile/intc-r8a7779.c
index f9cc4bc..fb0363c 100644
--- a/arch/arm/mach-shmobile/intc-r8a7779.c
+++ b/arch/arm/mach-shmobile/intc-r8a7779.c
@@ -19,13 +19,16 @@
*/
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/irqchip/arm-gic.h>
-#include <mach/common.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
#include <linux/irqchip.h>
+#include <mach/common.h>
#include <mach/intc.h>
+#include <mach/irqs.h>
#include <mach/r8a7779.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -39,6 +42,54 @@
#define INT2NTSR0 IOMEM(0xfe700060)
#define INT2NTSR1 IOMEM(0xfe700064)
+struct renesas_intc_irqpin_config irqpin0_platform_data = {
+ .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
+ .sense_bitfield_width = 2,
+};
+
+static struct resource irqpin0_resources[] = {
+ DEFINE_RES_MEM(0xfe78001c, 4), /* ICR1 */
+ DEFINE_RES_MEM(0xfe780010, 4), /* INTPRI */
+ DEFINE_RES_MEM(0xfe780024, 4), /* INTREQ */
+ DEFINE_RES_MEM(0xfe780044, 4), /* INTMSK0 */
+ DEFINE_RES_MEM(0xfe780064, 4), /* INTMSKCLR0 */
+ DEFINE_RES_IRQ(gic_spi(27)), /* IRQ0 */
+ DEFINE_RES_IRQ(gic_spi(28)), /* IRQ1 */
+ DEFINE_RES_IRQ(gic_spi(29)), /* IRQ2 */
+ DEFINE_RES_IRQ(gic_spi(30)), /* IRQ3 */
+};
+
+static struct platform_device irqpin0_device = {
+ .name = "renesas_intc_irqpin",
+ .id = 0,
+ .resource = irqpin0_resources,
+ .num_resources = ARRAY_SIZE(irqpin0_resources),
+ .dev = {
+ .platform_data = &irqpin0_platform_data,
+ },
+};
+
+void __init r8a7779_init_irq_extpin(int irlm)
+{
+ void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE);
+ unsigned long tmp;
+
+ if (icr0) {
+ tmp = ioread32(icr0);
+ if (irlm)
+ tmp |= 1 << 23; /* IRQ0 -> IRQ3 as individual pins */
+ else
+ tmp &= ~(1 << 23); /* IRL mode - not supported */
+ tmp |= (1 << 21); /* LVLMODE = 1 */
+ iowrite32(tmp, icr0);
+ iounmap(icr0);
+
+ if (irlm)
+ platform_device_register(&irqpin0_device);
+ } else
+ pr_warn("r8a7779: unable to setup external irq pin mode\n");
+}
+
static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
{
return 0; /* always allow wakeup */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 05/14] irqchip: intc-irqpin: Whitespace fixes
2013-03-19 2:19 [GIT PULL v2] Renesas INTC External IRQ pin driver Simon Horman
` (3 preceding siblings ...)
2013-03-19 2:19 ` [PATCH 04/14] ARM: shmobile: INTC External IRQ pin driver on r8a7779 Simon Horman
@ 2013-03-19 2:19 ` Simon Horman
2013-03-19 2:19 ` [PATCH 06/14] irqchip: intc-irqpin: Cache mapped IRQ Simon Horman
` (9 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Simon Horman @ 2013-03-19 2:19 UTC (permalink / raw)
To: linux-arm-kernel
From: Magnus Damm <damm@opensource.se>
Remove whitespace damage and add newline
between variables and code.
Signed-off-by: Magnus Damm <damm@opensource.se>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
drivers/irqchip/irq-renesas-intc-irqpin.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
index 1e5058a..4b5933f 100644
--- a/drivers/irqchip/irq-renesas-intc-irqpin.c
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -57,13 +57,13 @@ struct intc_irqpin_iomem {
unsigned long (*read)(void __iomem *iomem);
void (*write)(void __iomem *iomem, unsigned long data);
int width;
-};
+};
struct intc_irqpin_irq {
int hw_irq;
int irq;
struct intc_irqpin_priv *p;
-};
+};
struct intc_irqpin_priv {
struct intc_irqpin_iomem iomem[INTC_IRQPIN_REG_NR];
@@ -99,6 +99,7 @@ static inline unsigned long intc_irqpin_read(struct intc_irqpin_priv *p,
int reg)
{
struct intc_irqpin_iomem *i = &p->iomem[reg];
+
return i->read(i->iomem);
}
@@ -106,6 +107,7 @@ static inline void intc_irqpin_write(struct intc_irqpin_priv *p,
int reg, unsigned long data)
{
struct intc_irqpin_iomem *i = &p->iomem[reg];
+
i->write(i->iomem, data);
}
@@ -405,7 +407,7 @@ static int intc_irqpin_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n",
p->config.irq_base, k);
}
-
+
return 0;
err3:
--
1.7.10.4
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 06/14] irqchip: intc-irqpin: Cache mapped IRQ
2013-03-19 2:19 [GIT PULL v2] Renesas INTC External IRQ pin driver Simon Horman
` (4 preceding siblings ...)
2013-03-19 2:19 ` [PATCH 05/14] irqchip: intc-irqpin: Whitespace fixes Simon Horman
@ 2013-03-19 2:19 ` Simon Horman
2013-03-19 2:19 ` [PATCH 07/14] irqchip: intc-irqpin: Add force comments Simon Horman
` (8 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Simon Horman @ 2013-03-19 2:19 UTC (permalink / raw)
To: linux-arm-kernel
From: Magnus Damm <damm@opensource.se>
Cache IRQ in domain_irq variable instead of
making use of irq_find_mapping(). While at it
rename the irq variable to requested_irq.
Signed-off-by: Magnus Damm <damm@opensource.se>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
drivers/irqchip/irq-renesas-intc-irqpin.c | 30 +++++++++++++++--------------
1 file changed, 16 insertions(+), 14 deletions(-)
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
index 4b5933f..0ac2bf6 100644
--- a/drivers/irqchip/irq-renesas-intc-irqpin.c
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -61,7 +61,8 @@ struct intc_irqpin_iomem {
struct intc_irqpin_irq {
int hw_irq;
- int irq;
+ int requested_irq;
+ int domain_irq;
struct intc_irqpin_priv *p;
};
@@ -171,8 +172,7 @@ static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value)
static void intc_irqpin_dbg(struct intc_irqpin_irq *i, char *str)
{
dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n",
- str, i->irq, i->hw_irq,
- irq_find_mapping(i->p->irq_domain, i->hw_irq));
+ str, i->requested_irq, i->hw_irq, i->domain_irq);
}
static void intc_irqpin_irq_enable(struct irq_data *d)
@@ -196,7 +196,7 @@ static void intc_irqpin_irq_disable(struct irq_data *d)
static void intc_irqpin_irq_enable_force(struct irq_data *d)
{
struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
- int irq = p->irq[irqd_to_hwirq(d)].irq;
+ int irq = p->irq[irqd_to_hwirq(d)].requested_irq;
intc_irqpin_irq_enable(d);
irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq));
@@ -205,7 +205,7 @@ static void intc_irqpin_irq_enable_force(struct irq_data *d)
static void intc_irqpin_irq_disable_force(struct irq_data *d)
{
struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
- int irq = p->irq[irqd_to_hwirq(d)].irq;
+ int irq = p->irq[irqd_to_hwirq(d)].requested_irq;
irq_get_chip(irq)->irq_mask(irq_get_irq_data(irq));
intc_irqpin_irq_disable(d);
@@ -246,7 +246,7 @@ static irqreturn_t intc_irqpin_irq_handler(int irq, void *dev_id)
if (intc_irqpin_read(p, INTC_IRQPIN_REG_SOURCE) & bit) {
intc_irqpin_write(p, INTC_IRQPIN_REG_SOURCE, ~bit);
intc_irqpin_dbg(i, "demux2");
- generic_handle_irq(irq_find_mapping(p->irq_domain, i->hw_irq));
+ generic_handle_irq(i->domain_irq);
return IRQ_HANDLED;
}
return IRQ_NONE;
@@ -257,6 +257,9 @@ static int intc_irqpin_irq_domain_map(struct irq_domain *h, unsigned int virq,
{
struct intc_irqpin_priv *p = h->host_data;
+ p->irq[hw].domain_irq = virq;
+ p->irq[hw].hw_irq = hw;
+
intc_irqpin_dbg(&p->irq[hw], "map");
irq_set_chip_data(virq, h->host_data);
irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
@@ -314,9 +317,8 @@ static int intc_irqpin_probe(struct platform_device *pdev)
if (!irq)
break;
- p->irq[k].hw_irq = k;
p->irq[k].p = p;
- p->irq[k].irq = irq->start;
+ p->irq[k].requested_irq = irq->start;
}
p->number_of_irqs = k;
@@ -389,7 +391,8 @@ static int intc_irqpin_probe(struct platform_device *pdev)
/* request and set priority on interrupts one by one */
for (k = 0; k < p->number_of_irqs; k++) {
- if (request_irq(p->irq[k].irq, intc_irqpin_irq_handler,
+ if (request_irq(p->irq[k].requested_irq,
+ intc_irqpin_irq_handler,
0, name, &p->irq[k])) {
dev_err(&pdev->dev, "failed to request low IRQ\n");
ret = -ENOENT;
@@ -402,17 +405,16 @@ static int intc_irqpin_probe(struct platform_device *pdev)
/* warn in case of mismatch if irq base is specified */
if (p->config.irq_base) {
- k = irq_find_mapping(p->irq_domain, 0);
- if (p->config.irq_base != k)
+ if (p->config.irq_base != p->irq[0].domain_irq)
dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n",
- p->config.irq_base, k);
+ p->config.irq_base, p->irq[0].domain_irq);
}
return 0;
err3:
for (; k >= 0; k--)
- free_irq(p->irq[k - 1].irq, &p->irq[k - 1]);
+ free_irq(p->irq[k - 1].requested_irq, &p->irq[k - 1]);
irq_domain_remove(p->irq_domain);
err2:
@@ -430,7 +432,7 @@ static int intc_irqpin_remove(struct platform_device *pdev)
int k;
for (k = 0; k < p->number_of_irqs; k++)
- free_irq(p->irq[k].irq, &p->irq[k]);
+ free_irq(p->irq[k].requested_irq, &p->irq[k]);
irq_domain_remove(p->irq_domain);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 07/14] irqchip: intc-irqpin: Add force comments
2013-03-19 2:19 [GIT PULL v2] Renesas INTC External IRQ pin driver Simon Horman
` (5 preceding siblings ...)
2013-03-19 2:19 ` [PATCH 06/14] irqchip: intc-irqpin: Cache mapped IRQ Simon Horman
@ 2013-03-19 2:19 ` Simon Horman
2013-03-19 2:19 ` [PATCH 08/14] irqchip: intc-irqpin: Make use of devm functions Simon Horman
` (7 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Simon Horman @ 2013-03-19 2:19 UTC (permalink / raw)
To: linux-arm-kernel
From: Magnus Damm <damm@opensource.se>
Add comments to describe the special case for
"force" versions of enable and disable functions.
Signed-off-by: Magnus Damm <damm@opensource.se>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
drivers/irqchip/irq-renesas-intc-irqpin.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
index 0ac2bf6..59c0cbc 100644
--- a/drivers/irqchip/irq-renesas-intc-irqpin.c
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -199,6 +199,11 @@ static void intc_irqpin_irq_enable_force(struct irq_data *d)
int irq = p->irq[irqd_to_hwirq(d)].requested_irq;
intc_irqpin_irq_enable(d);
+
+ /* enable interrupt through parent interrupt controller,
+ * assumes non-shared interrupt with 1:1 mapping
+ * needed for busted IRQs on some SoCs like sh73a0
+ */
irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq));
}
@@ -207,6 +212,10 @@ static void intc_irqpin_irq_disable_force(struct irq_data *d)
struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
int irq = p->irq[irqd_to_hwirq(d)].requested_irq;
+ /* disable interrupt through parent interrupt controller,
+ * assumes non-shared interrupt with 1:1 mapping
+ * needed for busted IRQs on some SoCs like sh73a0
+ */
irq_get_chip(irq)->irq_mask(irq_get_irq_data(irq));
intc_irqpin_irq_disable(d);
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 08/14] irqchip: intc-irqpin: Make use of devm functions
2013-03-19 2:19 [GIT PULL v2] Renesas INTC External IRQ pin driver Simon Horman
` (6 preceding siblings ...)
2013-03-19 2:19 ` [PATCH 07/14] irqchip: intc-irqpin: Add force comments Simon Horman
@ 2013-03-19 2:19 ` Simon Horman
2013-03-19 2:19 ` [PATCH 09/14] irqchip: intc-irqpin: GPL header for platform data Simon Horman
` (6 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Simon Horman @ 2013-03-19 2:19 UTC (permalink / raw)
To: linux-arm-kernel
From: Magnus Damm <damm@opensource.se>
Use devm_kzalloc(), devm_ioremap_nocache()
and devm_request_irq() to simplify error
handling.
Signed-off-by: Magnus Damm <damm@opensource.se>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
drivers/irqchip/irq-renesas-intc-irqpin.c | 41 +++++++++--------------------
1 file changed, 13 insertions(+), 28 deletions(-)
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
index 59c0cbc..21f4602 100644
--- a/drivers/irqchip/irq-renesas-intc-irqpin.c
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -294,7 +294,7 @@ static int intc_irqpin_probe(struct platform_device *pdev)
int ret;
int k;
- p = kzalloc(sizeof(*p), GFP_KERNEL);
+ p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
if (!p) {
dev_err(&pdev->dev, "failed to allocate driver data\n");
ret = -ENOMEM;
@@ -316,7 +316,7 @@ static int intc_irqpin_probe(struct platform_device *pdev)
if (!io[k]) {
dev_err(&pdev->dev, "not enough IOMEM resources\n");
ret = -EINVAL;
- goto err1;
+ goto err0;
}
}
@@ -334,7 +334,7 @@ static int intc_irqpin_probe(struct platform_device *pdev)
if (p->number_of_irqs < 1) {
dev_err(&pdev->dev, "not enough IRQ resources\n");
ret = -EINVAL;
- goto err1;
+ goto err0;
}
/* ioremap IOMEM and setup read/write callbacks */
@@ -355,14 +355,15 @@ static int intc_irqpin_probe(struct platform_device *pdev)
default:
dev_err(&pdev->dev, "IOMEM size mismatch\n");
ret = -EINVAL;
- goto err2;
+ goto err0;
}
- i->iomem = ioremap_nocache(io[k]->start, resource_size(io[k]));
+ i->iomem = devm_ioremap_nocache(&pdev->dev, io[k]->start,
+ resource_size(io[k]));
if (!i->iomem) {
dev_err(&pdev->dev, "failed to remap IOMEM\n");
ret = -ENXIO;
- goto err2;
+ goto err0;
}
}
@@ -395,17 +396,17 @@ static int intc_irqpin_probe(struct platform_device *pdev)
if (!p->irq_domain) {
ret = -ENXIO;
dev_err(&pdev->dev, "cannot initialize irq domain\n");
- goto err2;
+ goto err0;
}
/* request and set priority on interrupts one by one */
for (k = 0; k < p->number_of_irqs; k++) {
- if (request_irq(p->irq[k].requested_irq,
- intc_irqpin_irq_handler,
- 0, name, &p->irq[k])) {
+ if (devm_request_irq(&pdev->dev, p->irq[k].requested_irq,
+ intc_irqpin_irq_handler,
+ 0, name, &p->irq[k])) {
dev_err(&pdev->dev, "failed to request low IRQ\n");
ret = -ENOENT;
- goto err3;
+ goto err1;
}
intc_irqpin_mask_unmask_prio(p, k, 0);
}
@@ -421,16 +422,8 @@ static int intc_irqpin_probe(struct platform_device *pdev)
return 0;
-err3:
- for (; k >= 0; k--)
- free_irq(p->irq[k - 1].requested_irq, &p->irq[k - 1]);
-
- irq_domain_remove(p->irq_domain);
-err2:
- for (k = 0; k < INTC_IRQPIN_REG_NR; k++)
- iounmap(p->iomem[k].iomem);
err1:
- kfree(p);
+ irq_domain_remove(p->irq_domain);
err0:
return ret;
}
@@ -438,17 +431,9 @@ err0:
static int intc_irqpin_remove(struct platform_device *pdev)
{
struct intc_irqpin_priv *p = platform_get_drvdata(pdev);
- int k;
-
- for (k = 0; k < p->number_of_irqs; k++)
- free_irq(p->irq[k].requested_irq, &p->irq[k]);
irq_domain_remove(p->irq_domain);
- for (k = 0; k < INTC_IRQPIN_REG_NR; k++)
- iounmap(p->iomem[k].iomem);
-
- kfree(p);
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 09/14] irqchip: intc-irqpin: GPL header for platform data
2013-03-19 2:19 [GIT PULL v2] Renesas INTC External IRQ pin driver Simon Horman
` (7 preceding siblings ...)
2013-03-19 2:19 ` [PATCH 08/14] irqchip: intc-irqpin: Make use of devm functions Simon Horman
@ 2013-03-19 2:19 ` Simon Horman
2013-03-19 2:19 ` [PATCH 10/14] irqchip: Renesas IRQC driver Simon Horman
` (5 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Simon Horman @ 2013-03-19 2:19 UTC (permalink / raw)
To: linux-arm-kernel
From: Magnus Damm <damm@opensource.se>
Add GPL header to platform data include file.
Signed-off-by: Magnus Damm <damm@opensource.se>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
.../linux/platform_data/irq-renesas-intc-irqpin.h | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/include/linux/platform_data/irq-renesas-intc-irqpin.h b/include/linux/platform_data/irq-renesas-intc-irqpin.h
index 00ccac3..e4cb911 100644
--- a/include/linux/platform_data/irq-renesas-intc-irqpin.h
+++ b/include/linux/platform_data/irq-renesas-intc-irqpin.h
@@ -1,3 +1,22 @@
+/*
+ * Renesas INTC External IRQ Pin Driver
+ *
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * 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; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
#ifndef __IRQ_RENESAS_INTC_IRQPIN_H__
#define __IRQ_RENESAS_INTC_IRQPIN_H__
--
1.7.10.4
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 10/14] irqchip: Renesas IRQC driver
2013-03-19 2:19 [GIT PULL v2] Renesas INTC External IRQ pin driver Simon Horman
` (8 preceding siblings ...)
2013-03-19 2:19 ` [PATCH 09/14] irqchip: intc-irqpin: GPL header for platform data Simon Horman
@ 2013-03-19 2:19 ` Simon Horman
2013-03-19 2:19 ` [PATCH 11/14] ARM: shmobile: Make sh73a0 INTC irqpin platform data static Simon Horman
` (4 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Simon Horman @ 2013-03-19 2:19 UTC (permalink / raw)
To: linux-arm-kernel
From: Magnus Damm <damm@opensource.se>
This patch adds a driver for external IRQ pins connected
to the IRQC hardware block on recent SoCs from Renesas.
The IRQC hardware block is used together with more
recent ARM based SoCs using the GIC. As usual the GIC
requires external IRQ trigger setup somewhere else
which in this particular case happens to be IRQC.
This driver implements the glue code needed to configure
IRQ trigger and also handle mask/unmask and demux of
external IRQ pins hooked up from the IRQC to the GIC.
Tested on r8a73a4 but is designed to work with a wide
range of SoCs. The driver requires one GIC SPI per
external IRQ pin to operate. Each driver instance
will handle up to 32 external IRQ pins.
The SoCs using this driver are currently mainly used
together with regular platform devices so this driver
allows configuration via platform data to support things
like static interrupt base address. DT support will
be added incrementally in the not so distant future.
Signed-off-by: Magnus Damm <damm@opensource.se>
Tested-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
drivers/irqchip/Kconfig | 4 +
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-renesas-irqc.c | 298 ++++++++++++++++++++++++
include/linux/platform_data/irq-renesas-irqc.h | 27 +++
4 files changed, 330 insertions(+)
create mode 100644 drivers/irqchip/irq-renesas-irqc.c
create mode 100644 include/linux/platform_data/irq-renesas-irqc.h
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 0f5f1c3..4a33351 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -29,6 +29,10 @@ config RENESAS_INTC_IRQPIN
bool
select IRQ_DOMAIN
+config RENESAS_IRQC
+ bool
+ select IRQ_DOMAIN
+
config VERSATILE_FPGA_IRQ
bool
select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 1aaa407..e41ceb9 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
obj-$(CONFIG_ARM_GIC) += irq-gic.o
obj-$(CONFIG_ARM_VIC) += irq-vic.o
obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o
+obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o
obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o
diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c
new file mode 100644
index 0000000..95d69bf
--- /dev/null
+++ b/drivers/irqchip/irq-renesas-irqc.c
@@ -0,0 +1,298 @@
+/*
+ * Renesas IRQC Driver
+ *
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * 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; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_data/irq-renesas-irqc.h>
+
+#define IRQC_IRQ_MAX 32 /* maximum 32 interrupts per driver instance */
+
+#define IRQC_REQ_STS 0x00
+#define IRQC_EN_STS 0x04
+#define IRQC_EN_SET 0x08
+#define IRQC_INT_CPU_BASE(n) (0x000 + ((n) * 0x10))
+#define DETECT_STATUS 0x100
+#define IRQC_CONFIG(n) (0x180 + ((n) * 0x04))
+
+struct irqc_irq {
+ int hw_irq;
+ int requested_irq;
+ int domain_irq;
+ struct irqc_priv *p;
+};
+
+struct irqc_priv {
+ void __iomem *iomem;
+ void __iomem *cpu_int_base;
+ struct irqc_irq irq[IRQC_IRQ_MAX];
+ struct renesas_irqc_config config;
+ unsigned int number_of_irqs;
+ struct platform_device *pdev;
+ struct irq_chip irq_chip;
+ struct irq_domain *irq_domain;
+};
+
+static void irqc_dbg(struct irqc_irq *i, char *str)
+{
+ dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n",
+ str, i->requested_irq, i->hw_irq, i->domain_irq);
+}
+
+static void irqc_irq_enable(struct irq_data *d)
+{
+ struct irqc_priv *p = irq_data_get_irq_chip_data(d);
+ int hw_irq = irqd_to_hwirq(d);
+
+ irqc_dbg(&p->irq[hw_irq], "enable");
+ iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_SET);
+}
+
+static void irqc_irq_disable(struct irq_data *d)
+{
+ struct irqc_priv *p = irq_data_get_irq_chip_data(d);
+ int hw_irq = irqd_to_hwirq(d);
+
+ irqc_dbg(&p->irq[hw_irq], "disable");
+ iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_STS);
+}
+
+#define INTC_IRQ_SENSE_VALID 0x10
+#define INTC_IRQ_SENSE(x) (x + INTC_IRQ_SENSE_VALID)
+
+static unsigned char irqc_sense[IRQ_TYPE_SENSE_MASK + 1] = {
+ [IRQ_TYPE_LEVEL_LOW] = INTC_IRQ_SENSE(0x01),
+ [IRQ_TYPE_LEVEL_HIGH] = INTC_IRQ_SENSE(0x02),
+ [IRQ_TYPE_EDGE_FALLING] = INTC_IRQ_SENSE(0x04), /* Synchronous */
+ [IRQ_TYPE_EDGE_RISING] = INTC_IRQ_SENSE(0x08), /* Synchronous */
+ [IRQ_TYPE_EDGE_BOTH] = INTC_IRQ_SENSE(0x0c), /* Synchronous */
+};
+
+static int irqc_irq_set_type(struct irq_data *d, unsigned int type)
+{
+ struct irqc_priv *p = irq_data_get_irq_chip_data(d);
+ int hw_irq = irqd_to_hwirq(d);
+ unsigned char value = irqc_sense[type & IRQ_TYPE_SENSE_MASK];
+ unsigned long tmp;
+
+ irqc_dbg(&p->irq[hw_irq], "sense");
+
+ if (!(value & INTC_IRQ_SENSE_VALID))
+ return -EINVAL;
+
+ tmp = ioread32(p->iomem + IRQC_CONFIG(hw_irq));
+ tmp &= ~0x3f;
+ tmp |= value ^ INTC_IRQ_SENSE_VALID;
+ iowrite32(tmp, p->iomem + IRQC_CONFIG(hw_irq));
+ return 0;
+}
+
+static irqreturn_t irqc_irq_handler(int irq, void *dev_id)
+{
+ struct irqc_irq *i = dev_id;
+ struct irqc_priv *p = i->p;
+ unsigned long bit = BIT(i->hw_irq);
+
+ irqc_dbg(i, "demux1");
+
+ if (ioread32(p->iomem + DETECT_STATUS) & bit) {
+ iowrite32(bit, p->iomem + DETECT_STATUS);
+ irqc_dbg(i, "demux2");
+ generic_handle_irq(i->domain_irq);
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+static int irqc_irq_domain_map(struct irq_domain *h, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct irqc_priv *p = h->host_data;
+
+ p->irq[hw].domain_irq = virq;
+ p->irq[hw].hw_irq = hw;
+
+ irqc_dbg(&p->irq[hw], "map");
+ irq_set_chip_data(virq, h->host_data);
+ irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
+ set_irq_flags(virq, IRQF_VALID); /* kill me now */
+ return 0;
+}
+
+static struct irq_domain_ops irqc_irq_domain_ops = {
+ .map = irqc_irq_domain_map,
+};
+
+static int irqc_probe(struct platform_device *pdev)
+{
+ struct renesas_irqc_config *pdata = pdev->dev.platform_data;
+ struct irqc_priv *p;
+ struct resource *io;
+ struct resource *irq;
+ struct irq_chip *irq_chip;
+ const char *name = dev_name(&pdev->dev);
+ int ret;
+ int k;
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p) {
+ dev_err(&pdev->dev, "failed to allocate driver data\n");
+ ret = -ENOMEM;
+ goto err0;
+ }
+
+ /* deal with driver instance configuration */
+ if (pdata)
+ memcpy(&p->config, pdata, sizeof(*pdata));
+
+ p->pdev = pdev;
+ platform_set_drvdata(pdev, p);
+
+ /* get hold of manadatory IOMEM */
+ io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!io) {
+ dev_err(&pdev->dev, "not enough IOMEM resources\n");
+ ret = -EINVAL;
+ goto err1;
+ }
+
+ /* allow any number of IRQs between 1 and IRQC_IRQ_MAX */
+ for (k = 0; k < IRQC_IRQ_MAX; k++) {
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, k);
+ if (!irq)
+ break;
+
+ p->irq[k].p = p;
+ p->irq[k].requested_irq = irq->start;
+ }
+
+ p->number_of_irqs = k;
+ if (p->number_of_irqs < 1) {
+ dev_err(&pdev->dev, "not enough IRQ resources\n");
+ ret = -EINVAL;
+ goto err1;
+ }
+
+ /* ioremap IOMEM and setup read/write callbacks */
+ p->iomem = ioremap_nocache(io->start, resource_size(io));
+ if (!p->iomem) {
+ dev_err(&pdev->dev, "failed to remap IOMEM\n");
+ ret = -ENXIO;
+ goto err2;
+ }
+
+ p->cpu_int_base = p->iomem + IRQC_INT_CPU_BASE(0); /* SYS-SPI */
+
+ irq_chip = &p->irq_chip;
+ irq_chip->name = name;
+ irq_chip->irq_mask = irqc_irq_disable;
+ irq_chip->irq_unmask = irqc_irq_enable;
+ irq_chip->irq_enable = irqc_irq_enable;
+ irq_chip->irq_disable = irqc_irq_disable;
+ irq_chip->irq_set_type = irqc_irq_set_type;
+ irq_chip->flags = IRQCHIP_SKIP_SET_WAKE;
+
+ p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
+ p->number_of_irqs,
+ p->config.irq_base,
+ &irqc_irq_domain_ops, p);
+ if (!p->irq_domain) {
+ ret = -ENXIO;
+ dev_err(&pdev->dev, "cannot initialize irq domain\n");
+ goto err2;
+ }
+
+ /* request interrupts one by one */
+ for (k = 0; k < p->number_of_irqs; k++) {
+ if (request_irq(p->irq[k].requested_irq, irqc_irq_handler,
+ 0, name, &p->irq[k])) {
+ dev_err(&pdev->dev, "failed to request IRQ\n");
+ ret = -ENOENT;
+ goto err3;
+ }
+ }
+
+ dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs);
+
+ /* warn in case of mismatch if irq base is specified */
+ if (p->config.irq_base) {
+ if (p->config.irq_base != p->irq[0].domain_irq)
+ dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n",
+ p->config.irq_base, p->irq[0].domain_irq);
+ }
+
+ return 0;
+err3:
+ for (; k >= 0; k--)
+ free_irq(p->irq[k - 1].requested_irq, &p->irq[k - 1]);
+
+ irq_domain_remove(p->irq_domain);
+err2:
+ iounmap(p->iomem);
+err1:
+ kfree(p);
+err0:
+ return ret;
+}
+
+static int irqc_remove(struct platform_device *pdev)
+{
+ struct irqc_priv *p = platform_get_drvdata(pdev);
+ int k;
+
+ for (k = 0; k < p->number_of_irqs; k++)
+ free_irq(p->irq[k].requested_irq, &p->irq[k]);
+
+ irq_domain_remove(p->irq_domain);
+ iounmap(p->iomem);
+ kfree(p);
+ return 0;
+}
+
+static struct platform_driver irqc_device_driver = {
+ .probe = irqc_probe,
+ .remove = irqc_remove,
+ .driver = {
+ .name = "renesas_irqc",
+ }
+};
+
+static int __init irqc_init(void)
+{
+ return platform_driver_register(&irqc_device_driver);
+}
+postcore_initcall(irqc_init);
+
+static void __exit irqc_exit(void)
+{
+ platform_driver_unregister(&irqc_device_driver);
+}
+module_exit(irqc_exit);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("Renesas IRQC Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/platform_data/irq-renesas-irqc.h b/include/linux/platform_data/irq-renesas-irqc.h
new file mode 100644
index 0000000..3ae17b3
--- /dev/null
+++ b/include/linux/platform_data/irq-renesas-irqc.h
@@ -0,0 +1,27 @@
+/*
+ * Renesas IRQC Driver
+ *
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * 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; either version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __IRQ_RENESAS_IRQC_H__
+#define __IRQ_RENESAS_IRQC_H__
+
+struct renesas_irqc_config {
+ unsigned int irq_base;
+};
+
+#endif /* __IRQ_RENESAS_IRQC_H__ */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 11/14] ARM: shmobile: Make sh73a0 INTC irqpin platform data static
2013-03-19 2:19 [GIT PULL v2] Renesas INTC External IRQ pin driver Simon Horman
` (9 preceding siblings ...)
2013-03-19 2:19 ` [PATCH 10/14] irqchip: Renesas IRQC driver Simon Horman
@ 2013-03-19 2:19 ` Simon Horman
2013-03-19 2:19 ` [PATCH 12/14] ARM: shmobile: Make r8a7779 " Simon Horman
` (3 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Simon Horman @ 2013-03-19 2:19 UTC (permalink / raw)
To: linux-arm-kernel
From: Magnus Damm <damm@opensource.se>
The platform data for the INTC irq pin driver
seems to be global symbols, make it static to
allow multi-soc build.
Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
arch/arm/mach-shmobile/setup-sh73a0.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index 638735f..e8cd93a 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -812,7 +812,7 @@ static struct platform_device ipmmu_device = {
.num_resources = ARRAY_SIZE(ipmmu_resources),
};
-struct renesas_intc_irqpin_config irqpin0_platform_data = {
+static struct renesas_intc_irqpin_config irqpin0_platform_data = {
.irq_base = irq_pin(0), /* IRQ0 -> IRQ7 */
};
@@ -842,7 +842,7 @@ static struct platform_device irqpin0_device = {
},
};
-struct renesas_intc_irqpin_config irqpin1_platform_data = {
+static struct renesas_intc_irqpin_config irqpin1_platform_data = {
.irq_base = irq_pin(8), /* IRQ8 -> IRQ15 */
.control_parent = true, /* Disable spurious IRQ10 */
};
@@ -873,7 +873,7 @@ static struct platform_device irqpin1_device = {
},
};
-struct renesas_intc_irqpin_config irqpin2_platform_data = {
+static struct renesas_intc_irqpin_config irqpin2_platform_data = {
.irq_base = irq_pin(16), /* IRQ16 -> IRQ23 */
};
@@ -903,7 +903,7 @@ static struct platform_device irqpin2_device = {
},
};
-struct renesas_intc_irqpin_config irqpin3_platform_data = {
+static struct renesas_intc_irqpin_config irqpin3_platform_data = {
.irq_base = irq_pin(24), /* IRQ24 -> IRQ31 */
};
--
1.7.10.4
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 12/14] ARM: shmobile: Make r8a7779 INTC irqpin platform data static
2013-03-19 2:19 [GIT PULL v2] Renesas INTC External IRQ pin driver Simon Horman
` (10 preceding siblings ...)
2013-03-19 2:19 ` [PATCH 11/14] ARM: shmobile: Make sh73a0 INTC irqpin platform data static Simon Horman
@ 2013-03-19 2:19 ` Simon Horman
2013-03-19 2:19 ` [PATCH 13/14] irqchip: intc-irqpin: Initial DT support Simon Horman
` (2 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Simon Horman @ 2013-03-19 2:19 UTC (permalink / raw)
To: linux-arm-kernel
From: Magnus Damm <damm@opensource.se>
The platform data for the INTC irq pin driver
seems to be global symbols, make it static to
allow multi-soc build.
Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
arch/arm/mach-shmobile/intc-r8a7779.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-shmobile/intc-r8a7779.c b/arch/arm/mach-shmobile/intc-r8a7779.c
index fb0363c..b86dc89 100644
--- a/arch/arm/mach-shmobile/intc-r8a7779.c
+++ b/arch/arm/mach-shmobile/intc-r8a7779.c
@@ -42,7 +42,7 @@
#define INT2NTSR0 IOMEM(0xfe700060)
#define INT2NTSR1 IOMEM(0xfe700064)
-struct renesas_intc_irqpin_config irqpin0_platform_data = {
+static struct renesas_intc_irqpin_config irqpin0_platform_data = {
.irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
.sense_bitfield_width = 2,
};
--
1.7.10.4
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 13/14] irqchip: intc-irqpin: Initial DT support
2013-03-19 2:19 [GIT PULL v2] Renesas INTC External IRQ pin driver Simon Horman
` (11 preceding siblings ...)
2013-03-19 2:19 ` [PATCH 12/14] ARM: shmobile: Make r8a7779 " Simon Horman
@ 2013-03-19 2:19 ` Simon Horman
2013-03-19 2:19 ` [PATCH 14/14] irqchip: irqc: Add " Simon Horman
2013-03-21 17:09 ` [GIT PULL v2] Renesas INTC External IRQ pin driver Arnd Bergmann
14 siblings, 0 replies; 18+ messages in thread
From: Simon Horman @ 2013-03-19 2:19 UTC (permalink / raw)
To: linux-arm-kernel
From: Magnus Damm <damm@opensource.se>
Add initial DT support to the INTC External IRQ Pin
driver. At this point only hardware with 4-bit wide
sense registers is supported via DT.
Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
drivers/irqchip/irq-renesas-intc-irqpin.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
index 21f4602..fd5dabc 100644
--- a/drivers/irqchip/irq-renesas-intc-irqpin.c
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -278,6 +278,7 @@ static int intc_irqpin_irq_domain_map(struct irq_domain *h, unsigned int virq,
static struct irq_domain_ops intc_irqpin_irq_domain_ops = {
.map = intc_irqpin_irq_domain_map,
+ .xlate = irq_domain_xlate_twocell,
};
static int intc_irqpin_probe(struct platform_device *pdev)
@@ -437,11 +438,19 @@ static int intc_irqpin_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id intc_irqpin_dt_ids[] = {
+ { .compatible = "renesas,intc-irqpin", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids);
+
static struct platform_driver intc_irqpin_device_driver = {
.probe = intc_irqpin_probe,
.remove = intc_irqpin_remove,
.driver = {
.name = "renesas_intc_irqpin",
+ .of_match_table = intc_irqpin_dt_ids,
+ .owner = THIS_MODULE,
}
};
--
1.7.10.4
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH 14/14] irqchip: irqc: Add DT support
2013-03-19 2:19 [GIT PULL v2] Renesas INTC External IRQ pin driver Simon Horman
` (12 preceding siblings ...)
2013-03-19 2:19 ` [PATCH 13/14] irqchip: intc-irqpin: Initial DT support Simon Horman
@ 2013-03-19 2:19 ` Simon Horman
2013-03-21 17:09 ` [GIT PULL v2] Renesas INTC External IRQ pin driver Arnd Bergmann
14 siblings, 0 replies; 18+ messages in thread
From: Simon Horman @ 2013-03-19 2:19 UTC (permalink / raw)
To: linux-arm-kernel
From: Magnus Damm <damm@opensource.se>
Add DT support to the IRQC External IRQ Pin driver.
Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
drivers/irqchip/irq-renesas-irqc.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c
index 95d69bf..927bff3 100644
--- a/drivers/irqchip/irq-renesas-irqc.c
+++ b/drivers/irqchip/irq-renesas-irqc.c
@@ -145,6 +145,7 @@ static int irqc_irq_domain_map(struct irq_domain *h, unsigned int virq,
static struct irq_domain_ops irqc_irq_domain_ops = {
.map = irqc_irq_domain_map,
+ .xlate = irq_domain_xlate_twocell,
};
static int irqc_probe(struct platform_device *pdev)
@@ -273,11 +274,19 @@ static int irqc_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id irqc_dt_ids[] = {
+ { .compatible = "renesas,irqc", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, irqc_dt_ids);
+
static struct platform_driver irqc_device_driver = {
.probe = irqc_probe,
.remove = irqc_remove,
.driver = {
.name = "renesas_irqc",
+ .of_match_table = irqc_dt_ids,
+ .owner = THIS_MODULE,
}
};
--
1.7.10.4
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [GIT PULL v2] Renesas INTC External IRQ pin driver
2013-03-19 2:19 [GIT PULL v2] Renesas INTC External IRQ pin driver Simon Horman
` (13 preceding siblings ...)
2013-03-19 2:19 ` [PATCH 14/14] irqchip: irqc: Add " Simon Horman
@ 2013-03-21 17:09 ` Arnd Bergmann
2013-03-22 0:50 ` Simon Horman
14 siblings, 1 reply; 18+ messages in thread
From: Arnd Bergmann @ 2013-03-21 17:09 UTC (permalink / raw)
To: linux-arm-kernel
On Tuesday 19 March 2013, Simon Horman wrote:
> The following changes since commit d75bc78b508d0a95d7738290d8ec9923691f4301:
>
> r8a7779: Add Display Unit clock support (2013-03-18 21:22:34 +0900)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git intc-external-irq
>
> for you to fetch changes up to 3b8dfa7c2f8af7613dae28ac0f3419bf75ead5d0:
>
Pulled into next/drivers.
I have also made sure that I got the right version of the "soc" branch.
Thanks,
Arnd
^ permalink raw reply [flat|nested] 18+ messages in thread
* [GIT PULL v2] Renesas INTC External IRQ pin driver
2013-03-21 17:09 ` [GIT PULL v2] Renesas INTC External IRQ pin driver Arnd Bergmann
@ 2013-03-22 0:50 ` Simon Horman
2013-03-22 6:51 ` Arnd Bergmann
0 siblings, 1 reply; 18+ messages in thread
From: Simon Horman @ 2013-03-22 0:50 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Mar 21, 2013 at 05:09:30PM +0000, Arnd Bergmann wrote:
> On Tuesday 19 March 2013, Simon Horman wrote:
> > The following changes since commit d75bc78b508d0a95d7738290d8ec9923691f4301:
> >
> > r8a7779: Add Display Unit clock support (2013-03-18 21:22:34 +0900)
> >
> > are available in the git repository at:
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git intc-external-irq
> >
> > for you to fetch changes up to 3b8dfa7c2f8af7613dae28ac0f3419bf75ead5d0:
> >
>
> Pulled into next/drivers.
>
> I have also made sure that I got the right version of the "soc" branch.
Thanks.
I am trying to make use of tags in order to make things a bit clearer.
Please let me know if there is anything else I could be doing to make
things easier for you.
^ permalink raw reply [flat|nested] 18+ messages in thread
* [GIT PULL v2] Renesas INTC External IRQ pin driver
2013-03-22 0:50 ` Simon Horman
@ 2013-03-22 6:51 ` Arnd Bergmann
0 siblings, 0 replies; 18+ messages in thread
From: Arnd Bergmann @ 2013-03-22 6:51 UTC (permalink / raw)
To: linux-arm-kernel
On Friday 22 March 2013, Simon Horman wrote:
>
> I am trying to make use of tags in order to make things a bit clearer.
> Please let me know if there is anything else I could be doing to make
> things easier for you.
You did everything right here, I was just double checking because not
everyone does, and I did not check that the commit IDs from the pull
request were lining up with what I pulled initially.
Arnd
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2013-03-22 6:51 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-19 2:19 [GIT PULL v2] Renesas INTC External IRQ pin driver Simon Horman
2013-03-19 2:19 ` [PATCH 01/14] irqchip: " Simon Horman
2013-03-19 2:19 ` [PATCH 02/14] ARM: shmobile: irq_pin() for static IRQ pin assignment Simon Horman
2013-03-19 2:19 ` [PATCH 03/14] ARM: shmobile: INTC External IRQ pin driver on sh73a0 Simon Horman
2013-03-19 2:19 ` [PATCH 04/14] ARM: shmobile: INTC External IRQ pin driver on r8a7779 Simon Horman
2013-03-19 2:19 ` [PATCH 05/14] irqchip: intc-irqpin: Whitespace fixes Simon Horman
2013-03-19 2:19 ` [PATCH 06/14] irqchip: intc-irqpin: Cache mapped IRQ Simon Horman
2013-03-19 2:19 ` [PATCH 07/14] irqchip: intc-irqpin: Add force comments Simon Horman
2013-03-19 2:19 ` [PATCH 08/14] irqchip: intc-irqpin: Make use of devm functions Simon Horman
2013-03-19 2:19 ` [PATCH 09/14] irqchip: intc-irqpin: GPL header for platform data Simon Horman
2013-03-19 2:19 ` [PATCH 10/14] irqchip: Renesas IRQC driver Simon Horman
2013-03-19 2:19 ` [PATCH 11/14] ARM: shmobile: Make sh73a0 INTC irqpin platform data static Simon Horman
2013-03-19 2:19 ` [PATCH 12/14] ARM: shmobile: Make r8a7779 " Simon Horman
2013-03-19 2:19 ` [PATCH 13/14] irqchip: intc-irqpin: Initial DT support Simon Horman
2013-03-19 2:19 ` [PATCH 14/14] irqchip: irqc: Add " Simon Horman
2013-03-21 17:09 ` [GIT PULL v2] Renesas INTC External IRQ pin driver Arnd Bergmann
2013-03-22 0:50 ` Simon Horman
2013-03-22 6:51 ` Arnd Bergmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).