All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] GIC OF bindings
@ 2011-09-30 19:27 ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-30 19:27 UTC (permalink / raw)
  To: linux-arm-kernel, devicetree-discuss, linux-kernel
  Cc: grant.likely, marc.zyngier, thomas.abraham, jamie, b-cousson,
	shawn.guo, Rob Herring

From: Rob Herring <rob.herring@calxeda.com>

Another round of GIC devicetree support.

This moves the tracking of the starting hwirq number into the irq domain
code. Doing this makes hwirq == GIC interrupt ID and simplifies the GIC
code removing irq_offset.

The full series is available here. This includes Russell's devel-stable and
for-next branches and Nico's vmalloc branch:

git://git.jdl.com/software/linux-3.0.git gic-v2

Tested on highbank and Realview 11MPCore qemu (2 GICs).

Rob

Rob Herring (3):
  irq: support domains with non-zero hwirq base
  ARM: gic: add irq_domain support
  ARM: gic: add OF based initialization

 Documentation/devicetree/bindings/arm/gic.txt |   55 ++++++++++
 arch/arm/common/Kconfig                       |    1 +
 arch/arm/common/gic.c                         |  142 +++++++++++++++++++------
 arch/arm/include/asm/hardware/gic.h           |    5 +-
 include/linux/irqdomain.h                     |   16 +++-
 kernel/irq/irqdomain.c                        |   12 +-
 6 files changed, 189 insertions(+), 42 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/gic.txt

-- 
1.7.5.4


^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 0/3] GIC OF bindings
@ 2011-09-30 19:27 ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-30 19:27 UTC (permalink / raw)
  To: linux-arm-kernel

From: Rob Herring <rob.herring@calxeda.com>

Another round of GIC devicetree support.

This moves the tracking of the starting hwirq number into the irq domain
code. Doing this makes hwirq == GIC interrupt ID and simplifies the GIC
code removing irq_offset.

The full series is available here. This includes Russell's devel-stable and
for-next branches and Nico's vmalloc branch:

git://git.jdl.com/software/linux-3.0.git gic-v2

Tested on highbank and Realview 11MPCore qemu (2 GICs).

Rob

Rob Herring (3):
  irq: support domains with non-zero hwirq base
  ARM: gic: add irq_domain support
  ARM: gic: add OF based initialization

 Documentation/devicetree/bindings/arm/gic.txt |   55 ++++++++++
 arch/arm/common/Kconfig                       |    1 +
 arch/arm/common/gic.c                         |  142 +++++++++++++++++++------
 arch/arm/include/asm/hardware/gic.h           |    5 +-
 include/linux/irqdomain.h                     |   16 +++-
 kernel/irq/irqdomain.c                        |   12 +-
 6 files changed, 189 insertions(+), 42 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/gic.txt

-- 
1.7.5.4

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 1/3] irq: support domains with non-zero hwirq base
@ 2011-09-30 19:27   ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-30 19:27 UTC (permalink / raw)
  To: linux-arm-kernel, devicetree-discuss, linux-kernel
  Cc: grant.likely, marc.zyngier, thomas.abraham, jamie, b-cousson,
	shawn.guo, Rob Herring, Thomas Gleixner

From: Rob Herring <rob.herring@calxeda.com>

Interrupt controllers can have non-zero starting value for h/w irq numbers.
Adding support in irq_domain allows the domain hwirq numbering to match
the interrupt controllers' numbering.

As this makes looping over irqs for a domain more complicated, add loop
iterators to iterate over all hwirqs and irqs for a domain.

Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 include/linux/irqdomain.h |   16 +++++++++++++++-
 kernel/irq/irqdomain.c    |   12 ++++++------
 2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 3ad553e..c0026b6 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -47,6 +47,7 @@ struct irq_domain_ops {
  *            of the irq_domain is responsible for allocating the array of
  *            irq_desc structures.
  * @nr_irq: Number of irqs managed by the irq domain
+ * @hwirq_base: Starting number for hwirqs managed by the irq domain
  * @ops: pointer to irq_domain methods
  * @priv: private data pointer for use by owner.  Not touched by irq_domain
  *        core code.
@@ -57,6 +58,7 @@ struct irq_domain {
 	struct list_head list;
 	unsigned int irq_base;
 	unsigned int nr_irq;
+	unsigned int hwirq_base;
 	const struct irq_domain_ops *ops;
 	void *priv;
 	struct device_node *of_node;
@@ -72,9 +74,21 @@ struct irq_domain {
 static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
 					     unsigned long hwirq)
 {
-	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
+	if (d->ops->to_irq)
+		return d->ops->to_irq(d, hwirq);
+	if (hwirq < d->hwirq_base)
+		return NO_IRQ;
+	return d->irq_base + hwirq - d->hwirq_base;
 }
 
+#define irq_domain_for_each_hwirq(d, hw) \
+	for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++)
+
+#define irq_domain_for_each_irq(d, hw, irq) \
+	for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \
+	     hw < d->hwirq_base + d->nr_irq; \
+	     hw++, irq = irq_domain_to_irq(d, hw))
+
 extern void irq_domain_add(struct irq_domain *domain);
 extern void irq_domain_del(struct irq_domain *domain);
 #endif /* CONFIG_IRQ_DOMAIN */
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 84f4110..6b67057 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -20,15 +20,15 @@ static DEFINE_MUTEX(irq_domain_mutex);
 void irq_domain_add(struct irq_domain *domain)
 {
 	struct irq_data *d;
-	int hwirq;
+	int hwirq, irq;
 
 	/*
 	 * This assumes that the irq_domain owner has already allocated
 	 * the irq_descs.  This block will be removed when support for dynamic
 	 * allocation of irq_descs is added to irq_domain.
 	 */
-	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
-		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+	irq_domain_for_each_irq(domain, hwirq, irq) {
+		d = irq_get_irq_data(irq);
 		if (d && d->domain) {
 			/* things are broken; just report, don't clean up */
 			WARN(1, "error: irq_desc already assigned to a domain");
@@ -50,15 +50,15 @@ void irq_domain_add(struct irq_domain *domain)
 void irq_domain_del(struct irq_domain *domain)
 {
 	struct irq_data *d;
-	int hwirq;
+	int hwirq, irq;
 
 	mutex_lock(&irq_domain_mutex);
 	list_del(&domain->list);
 	mutex_unlock(&irq_domain_mutex);
 
 	/* Clear the irq_domain assignments */
-	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
-		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+	irq_domain_for_each_irq(domain, hwirq, irq) {
+		d = irq_get_irq_data(irq);
 		d->domain = NULL;
 	}
 }
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 1/3] irq: support domains with non-zero hwirq base
@ 2011-09-30 19:27   ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-30 19:27 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Rob Herring, Thomas Gleixner

From: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>

Interrupt controllers can have non-zero starting value for h/w irq numbers.
Adding support in irq_domain allows the domain hwirq numbering to match
the interrupt controllers' numbering.

As this makes looping over irqs for a domain more complicated, add loop
iterators to iterate over all hwirqs and irqs for a domain.

Cc: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
Cc: Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
Signed-off-by: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
---
 include/linux/irqdomain.h |   16 +++++++++++++++-
 kernel/irq/irqdomain.c    |   12 ++++++------
 2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 3ad553e..c0026b6 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -47,6 +47,7 @@ struct irq_domain_ops {
  *            of the irq_domain is responsible for allocating the array of
  *            irq_desc structures.
  * @nr_irq: Number of irqs managed by the irq domain
+ * @hwirq_base: Starting number for hwirqs managed by the irq domain
  * @ops: pointer to irq_domain methods
  * @priv: private data pointer for use by owner.  Not touched by irq_domain
  *        core code.
@@ -57,6 +58,7 @@ struct irq_domain {
 	struct list_head list;
 	unsigned int irq_base;
 	unsigned int nr_irq;
+	unsigned int hwirq_base;
 	const struct irq_domain_ops *ops;
 	void *priv;
 	struct device_node *of_node;
@@ -72,9 +74,21 @@ struct irq_domain {
 static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
 					     unsigned long hwirq)
 {
-	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
+	if (d->ops->to_irq)
+		return d->ops->to_irq(d, hwirq);
+	if (hwirq < d->hwirq_base)
+		return NO_IRQ;
+	return d->irq_base + hwirq - d->hwirq_base;
 }
 
+#define irq_domain_for_each_hwirq(d, hw) \
+	for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++)
+
+#define irq_domain_for_each_irq(d, hw, irq) \
+	for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \
+	     hw < d->hwirq_base + d->nr_irq; \
+	     hw++, irq = irq_domain_to_irq(d, hw))
+
 extern void irq_domain_add(struct irq_domain *domain);
 extern void irq_domain_del(struct irq_domain *domain);
 #endif /* CONFIG_IRQ_DOMAIN */
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 84f4110..6b67057 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -20,15 +20,15 @@ static DEFINE_MUTEX(irq_domain_mutex);
 void irq_domain_add(struct irq_domain *domain)
 {
 	struct irq_data *d;
-	int hwirq;
+	int hwirq, irq;
 
 	/*
 	 * This assumes that the irq_domain owner has already allocated
 	 * the irq_descs.  This block will be removed when support for dynamic
 	 * allocation of irq_descs is added to irq_domain.
 	 */
-	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
-		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+	irq_domain_for_each_irq(domain, hwirq, irq) {
+		d = irq_get_irq_data(irq);
 		if (d && d->domain) {
 			/* things are broken; just report, don't clean up */
 			WARN(1, "error: irq_desc already assigned to a domain");
@@ -50,15 +50,15 @@ void irq_domain_add(struct irq_domain *domain)
 void irq_domain_del(struct irq_domain *domain)
 {
 	struct irq_data *d;
-	int hwirq;
+	int hwirq, irq;
 
 	mutex_lock(&irq_domain_mutex);
 	list_del(&domain->list);
 	mutex_unlock(&irq_domain_mutex);
 
 	/* Clear the irq_domain assignments */
-	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
-		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+	irq_domain_for_each_irq(domain, hwirq, irq) {
+		d = irq_get_irq_data(irq);
 		d->domain = NULL;
 	}
 }
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 1/3] irq: support domains with non-zero hwirq base
@ 2011-09-30 19:27   ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-30 19:27 UTC (permalink / raw)
  To: linux-arm-kernel

From: Rob Herring <rob.herring@calxeda.com>

Interrupt controllers can have non-zero starting value for h/w irq numbers.
Adding support in irq_domain allows the domain hwirq numbering to match
the interrupt controllers' numbering.

As this makes looping over irqs for a domain more complicated, add loop
iterators to iterate over all hwirqs and irqs for a domain.

Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 include/linux/irqdomain.h |   16 +++++++++++++++-
 kernel/irq/irqdomain.c    |   12 ++++++------
 2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 3ad553e..c0026b6 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -47,6 +47,7 @@ struct irq_domain_ops {
  *            of the irq_domain is responsible for allocating the array of
  *            irq_desc structures.
  * @nr_irq: Number of irqs managed by the irq domain
+ * @hwirq_base: Starting number for hwirqs managed by the irq domain
  * @ops: pointer to irq_domain methods
  * @priv: private data pointer for use by owner.  Not touched by irq_domain
  *        core code.
@@ -57,6 +58,7 @@ struct irq_domain {
 	struct list_head list;
 	unsigned int irq_base;
 	unsigned int nr_irq;
+	unsigned int hwirq_base;
 	const struct irq_domain_ops *ops;
 	void *priv;
 	struct device_node *of_node;
@@ -72,9 +74,21 @@ struct irq_domain {
 static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
 					     unsigned long hwirq)
 {
-	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
+	if (d->ops->to_irq)
+		return d->ops->to_irq(d, hwirq);
+	if (hwirq < d->hwirq_base)
+		return NO_IRQ;
+	return d->irq_base + hwirq - d->hwirq_base;
 }
 
+#define irq_domain_for_each_hwirq(d, hw) \
+	for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++)
+
+#define irq_domain_for_each_irq(d, hw, irq) \
+	for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \
+	     hw < d->hwirq_base + d->nr_irq; \
+	     hw++, irq = irq_domain_to_irq(d, hw))
+
 extern void irq_domain_add(struct irq_domain *domain);
 extern void irq_domain_del(struct irq_domain *domain);
 #endif /* CONFIG_IRQ_DOMAIN */
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 84f4110..6b67057 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -20,15 +20,15 @@ static DEFINE_MUTEX(irq_domain_mutex);
 void irq_domain_add(struct irq_domain *domain)
 {
 	struct irq_data *d;
-	int hwirq;
+	int hwirq, irq;
 
 	/*
 	 * This assumes that the irq_domain owner has already allocated
 	 * the irq_descs.  This block will be removed when support for dynamic
 	 * allocation of irq_descs is added to irq_domain.
 	 */
-	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
-		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+	irq_domain_for_each_irq(domain, hwirq, irq) {
+		d = irq_get_irq_data(irq);
 		if (d && d->domain) {
 			/* things are broken; just report, don't clean up */
 			WARN(1, "error: irq_desc already assigned to a domain");
@@ -50,15 +50,15 @@ void irq_domain_add(struct irq_domain *domain)
 void irq_domain_del(struct irq_domain *domain)
 {
 	struct irq_data *d;
-	int hwirq;
+	int hwirq, irq;
 
 	mutex_lock(&irq_domain_mutex);
 	list_del(&domain->list);
 	mutex_unlock(&irq_domain_mutex);
 
 	/* Clear the irq_domain assignments */
-	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
-		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+	irq_domain_for_each_irq(domain, hwirq, irq) {
+		d = irq_get_irq_data(irq);
 		d->domain = NULL;
 	}
 }
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 2/3] ARM: gic: add irq_domain support
@ 2011-09-30 19:27   ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-30 19:27 UTC (permalink / raw)
  To: linux-arm-kernel, devicetree-discuss, linux-kernel
  Cc: grant.likely, marc.zyngier, thomas.abraham, jamie, b-cousson,
	shawn.guo, Rob Herring

From: Rob Herring <rob.herring@calxeda.com>

Convert the gic interrupt controller to use irq domains in preparation
for device-tree binding and MULTI_IRQ. This allows for translation between
GIC interrupt IDs and Linux irq numbers.

The meaning of irq_offset has changed. It now is just the number of skipped
GIC interrupt IDs for the controller. It will be 16 for primary GIC and 32
for secondary GICs.

Cc: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 arch/arm/common/Kconfig             |    1 +
 arch/arm/common/gic.c               |   81 ++++++++++++++++++++---------------
 arch/arm/include/asm/hardware/gic.h |    4 +-
 3 files changed, 51 insertions(+), 35 deletions(-)

diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 4b71766..74df9ca 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -1,4 +1,5 @@
 config ARM_GIC
+	select IRQ_DOMAIN
 	bool
 
 config ARM_VIC
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 8b5be72..6fbe1db 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -29,6 +29,7 @@
 #include <linux/cpu_pm.h>
 #include <linux/cpumask.h>
 #include <linux/io.h>
+#include <linux/irqdomain.h>
 
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
@@ -72,8 +73,7 @@ static inline void __iomem *gic_cpu_base(struct irq_data *d)
 
 static inline unsigned int gic_irq(struct irq_data *d)
 {
-	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
-	return d->irq - gic_data->irq_offset;
+	return d->hwirq;
 }
 
 /*
@@ -81,7 +81,7 @@ static inline unsigned int gic_irq(struct irq_data *d)
  */
 static void gic_mask_irq(struct irq_data *d)
 {
-	u32 mask = 1 << (d->irq % 32);
+	u32 mask = 1 << (gic_irq(d) % 32);
 
 	spin_lock(&irq_controller_lock);
 	writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
@@ -92,7 +92,7 @@ static void gic_mask_irq(struct irq_data *d)
 
 static void gic_unmask_irq(struct irq_data *d)
 {
-	u32 mask = 1 << (d->irq % 32);
+	u32 mask = 1 << (gic_irq(d) % 32);
 
 	spin_lock(&irq_controller_lock);
 	if (gic_arch_extn.irq_unmask)
@@ -173,7 +173,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 			    bool force)
 {
 	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
-	unsigned int shift = (d->irq % 4) * 8;
+	unsigned int shift = (gic_irq(d) % 4) * 8;
 	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
 	u32 val, mask, bit;
 
@@ -224,7 +224,7 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 	if (gic_irq == 1023)
 		goto out;
 
-	cascade_irq = gic_irq + chip_data->irq_offset;
+	cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq);
 	if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS))
 		do_bad_IRQ(cascade_irq, desc);
 	else
@@ -256,10 +256,11 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 	irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
-static void __init gic_dist_init(struct gic_chip_data *gic,
-	unsigned int irq_start)
+static void __init gic_dist_init(struct gic_chip_data *gic)
 {
-	unsigned int gic_irqs, irq_limit, i;
+	unsigned int gic_irqs = gic->gic_irqs;
+	struct irq_domain *domain = &gic->domain;
+	unsigned int i, irq;
 	u32 cpumask;
 	void __iomem *base = gic->dist_base;
 	u32 cpu = 0;
@@ -275,17 +276,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 	writel_relaxed(0, base + GIC_DIST_CTRL);
 
 	/*
-	 * Find out how many interrupts are supported.
-	 * The GIC only supports up to 1020 interrupt sources.
-	 */
-	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
-	gic_irqs = (gic_irqs + 1) * 32;
-	if (gic_irqs > 1020)
-		gic_irqs = 1020;
-
-	gic->gic_irqs = gic_irqs;
-
-	/*
 	 * Set all global interrupts to be level triggered, active low.
 	 */
 	for (i = 32; i < gic_irqs; i += 16)
@@ -311,19 +301,12 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
 
 	/*
-	 * Limit number of interrupts registered to the platform maximum
-	 */
-	irq_limit = gic->irq_offset + gic_irqs;
-	if (WARN_ON(irq_limit > NR_IRQS))
-		irq_limit = NR_IRQS;
-
-	/*
 	 * Setup the Linux IRQ subsystem.
 	 */
-	for (i = irq_start; i < irq_limit; i++) {
-		irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq);
-		irq_set_chip_data(i, gic);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	irq_domain_for_each_irq(domain, i, irq) {
+		irq_set_chip_and_handler(irq, &gic_chip, handle_fasteoi_irq);
+		irq_set_chip_data(irq, gic);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
 	writel_relaxed(1, base + GIC_DIST_CTRL);
@@ -535,23 +518,53 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
 }
 #endif
 
+const struct irq_domain_ops gic_irq_domain_ops = {
+};
+
 void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
 	void __iomem *dist_base, void __iomem *cpu_base)
 {
 	struct gic_chip_data *gic;
+	struct irq_domain *domain;
+	int gic_irqs;
 
 	BUG_ON(gic_nr >= MAX_GIC_NR);
 
 	gic = &gic_data[gic_nr];
+	domain = &gic->domain;
 	gic->dist_base = dist_base;
 	gic->cpu_base = cpu_base;
-	gic->irq_offset = (irq_start - 1) & ~31;
 
-	if (gic_nr == 0)
+	/*
+	 * For primary GICs, skip over SGIs.
+	 * For secondary GICs, skip over PPIs, too.
+	 */
+	if (gic_nr == 0) {
 		gic_cpu_base_addr = cpu_base;
+		domain->hwirq_base = 16;
+		irq_start = (irq_start & ~31) + 16;
+	} else
+		domain->hwirq_base = 32;
+
+	/*
+	 * Find out how many interrupts are supported.
+	 * The GIC only supports up to 1020 interrupt sources.
+	 */
+	gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
+	gic_irqs = (gic_irqs + 1) * 32;
+	if (gic_irqs > 1020)
+		gic_irqs = 1020;
+	gic->gic_irqs = gic_irqs;
+
+	domain->nr_irq = gic_irqs - domain->hwirq_base;
+	domain->irq_base = irq_alloc_descs(-1, irq_start, domain->nr_irq,
+					   numa_node_id());
+	domain->priv = gic;
+	domain->ops = &gic_irq_domain_ops;
+	irq_domain_add(domain);
 
 	gic_chip.flags |= gic_arch_extn.flags;
-	gic_dist_init(gic, irq_start);
+	gic_dist_init(gic);
 	gic_cpu_init(gic);
 	gic_pm_init(gic);
 }
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index c562705..ade84a4 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -33,6 +33,8 @@
 #define GIC_DIST_SOFTINT		0xf00
 
 #ifndef __ASSEMBLY__
+#include <linux/irqdomain.h>
+
 extern void __iomem *gic_cpu_base_addr;
 extern struct irq_chip gic_arch_extn;
 
@@ -43,7 +45,6 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
 void gic_enable_ppi(unsigned int);
 
 struct gic_chip_data {
-	unsigned int irq_offset;
 	void __iomem *dist_base;
 	void __iomem *cpu_base;
 #ifdef CONFIG_CPU_PM
@@ -53,6 +54,7 @@ struct gic_chip_data {
 	u32 __percpu *saved_ppi_enable;
 	u32 __percpu *saved_ppi_conf;
 #endif
+	struct irq_domain domain;
 	unsigned int gic_irqs;
 };
 #endif
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 2/3] ARM: gic: add irq_domain support
@ 2011-09-30 19:27   ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-30 19:27 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Rob Herring

From: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>

Convert the gic interrupt controller to use irq domains in preparation
for device-tree binding and MULTI_IRQ. This allows for translation between
GIC interrupt IDs and Linux irq numbers.

The meaning of irq_offset has changed. It now is just the number of skipped
GIC interrupt IDs for the controller. It will be 16 for primary GIC and 32
for secondary GICs.

Cc: Marc Zyngier <marc.zyngier-5wv7dgnIgG8@public.gmane.org>
Signed-off-by: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
---
 arch/arm/common/Kconfig             |    1 +
 arch/arm/common/gic.c               |   81 ++++++++++++++++++++---------------
 arch/arm/include/asm/hardware/gic.h |    4 +-
 3 files changed, 51 insertions(+), 35 deletions(-)

diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 4b71766..74df9ca 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -1,4 +1,5 @@
 config ARM_GIC
+	select IRQ_DOMAIN
 	bool
 
 config ARM_VIC
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 8b5be72..6fbe1db 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -29,6 +29,7 @@
 #include <linux/cpu_pm.h>
 #include <linux/cpumask.h>
 #include <linux/io.h>
+#include <linux/irqdomain.h>
 
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
@@ -72,8 +73,7 @@ static inline void __iomem *gic_cpu_base(struct irq_data *d)
 
 static inline unsigned int gic_irq(struct irq_data *d)
 {
-	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
-	return d->irq - gic_data->irq_offset;
+	return d->hwirq;
 }
 
 /*
@@ -81,7 +81,7 @@ static inline unsigned int gic_irq(struct irq_data *d)
  */
 static void gic_mask_irq(struct irq_data *d)
 {
-	u32 mask = 1 << (d->irq % 32);
+	u32 mask = 1 << (gic_irq(d) % 32);
 
 	spin_lock(&irq_controller_lock);
 	writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
@@ -92,7 +92,7 @@ static void gic_mask_irq(struct irq_data *d)
 
 static void gic_unmask_irq(struct irq_data *d)
 {
-	u32 mask = 1 << (d->irq % 32);
+	u32 mask = 1 << (gic_irq(d) % 32);
 
 	spin_lock(&irq_controller_lock);
 	if (gic_arch_extn.irq_unmask)
@@ -173,7 +173,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 			    bool force)
 {
 	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
-	unsigned int shift = (d->irq % 4) * 8;
+	unsigned int shift = (gic_irq(d) % 4) * 8;
 	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
 	u32 val, mask, bit;
 
@@ -224,7 +224,7 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 	if (gic_irq == 1023)
 		goto out;
 
-	cascade_irq = gic_irq + chip_data->irq_offset;
+	cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq);
 	if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS))
 		do_bad_IRQ(cascade_irq, desc);
 	else
@@ -256,10 +256,11 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 	irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
-static void __init gic_dist_init(struct gic_chip_data *gic,
-	unsigned int irq_start)
+static void __init gic_dist_init(struct gic_chip_data *gic)
 {
-	unsigned int gic_irqs, irq_limit, i;
+	unsigned int gic_irqs = gic->gic_irqs;
+	struct irq_domain *domain = &gic->domain;
+	unsigned int i, irq;
 	u32 cpumask;
 	void __iomem *base = gic->dist_base;
 	u32 cpu = 0;
@@ -275,17 +276,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 	writel_relaxed(0, base + GIC_DIST_CTRL);
 
 	/*
-	 * Find out how many interrupts are supported.
-	 * The GIC only supports up to 1020 interrupt sources.
-	 */
-	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
-	gic_irqs = (gic_irqs + 1) * 32;
-	if (gic_irqs > 1020)
-		gic_irqs = 1020;
-
-	gic->gic_irqs = gic_irqs;
-
-	/*
 	 * Set all global interrupts to be level triggered, active low.
 	 */
 	for (i = 32; i < gic_irqs; i += 16)
@@ -311,19 +301,12 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
 
 	/*
-	 * Limit number of interrupts registered to the platform maximum
-	 */
-	irq_limit = gic->irq_offset + gic_irqs;
-	if (WARN_ON(irq_limit > NR_IRQS))
-		irq_limit = NR_IRQS;
-
-	/*
 	 * Setup the Linux IRQ subsystem.
 	 */
-	for (i = irq_start; i < irq_limit; i++) {
-		irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq);
-		irq_set_chip_data(i, gic);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	irq_domain_for_each_irq(domain, i, irq) {
+		irq_set_chip_and_handler(irq, &gic_chip, handle_fasteoi_irq);
+		irq_set_chip_data(irq, gic);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
 	writel_relaxed(1, base + GIC_DIST_CTRL);
@@ -535,23 +518,53 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
 }
 #endif
 
+const struct irq_domain_ops gic_irq_domain_ops = {
+};
+
 void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
 	void __iomem *dist_base, void __iomem *cpu_base)
 {
 	struct gic_chip_data *gic;
+	struct irq_domain *domain;
+	int gic_irqs;
 
 	BUG_ON(gic_nr >= MAX_GIC_NR);
 
 	gic = &gic_data[gic_nr];
+	domain = &gic->domain;
 	gic->dist_base = dist_base;
 	gic->cpu_base = cpu_base;
-	gic->irq_offset = (irq_start - 1) & ~31;
 
-	if (gic_nr == 0)
+	/*
+	 * For primary GICs, skip over SGIs.
+	 * For secondary GICs, skip over PPIs, too.
+	 */
+	if (gic_nr == 0) {
 		gic_cpu_base_addr = cpu_base;
+		domain->hwirq_base = 16;
+		irq_start = (irq_start & ~31) + 16;
+	} else
+		domain->hwirq_base = 32;
+
+	/*
+	 * Find out how many interrupts are supported.
+	 * The GIC only supports up to 1020 interrupt sources.
+	 */
+	gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
+	gic_irqs = (gic_irqs + 1) * 32;
+	if (gic_irqs > 1020)
+		gic_irqs = 1020;
+	gic->gic_irqs = gic_irqs;
+
+	domain->nr_irq = gic_irqs - domain->hwirq_base;
+	domain->irq_base = irq_alloc_descs(-1, irq_start, domain->nr_irq,
+					   numa_node_id());
+	domain->priv = gic;
+	domain->ops = &gic_irq_domain_ops;
+	irq_domain_add(domain);
 
 	gic_chip.flags |= gic_arch_extn.flags;
-	gic_dist_init(gic, irq_start);
+	gic_dist_init(gic);
 	gic_cpu_init(gic);
 	gic_pm_init(gic);
 }
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index c562705..ade84a4 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -33,6 +33,8 @@
 #define GIC_DIST_SOFTINT		0xf00
 
 #ifndef __ASSEMBLY__
+#include <linux/irqdomain.h>
+
 extern void __iomem *gic_cpu_base_addr;
 extern struct irq_chip gic_arch_extn;
 
@@ -43,7 +45,6 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
 void gic_enable_ppi(unsigned int);
 
 struct gic_chip_data {
-	unsigned int irq_offset;
 	void __iomem *dist_base;
 	void __iomem *cpu_base;
 #ifdef CONFIG_CPU_PM
@@ -53,6 +54,7 @@ struct gic_chip_data {
 	u32 __percpu *saved_ppi_enable;
 	u32 __percpu *saved_ppi_conf;
 #endif
+	struct irq_domain domain;
 	unsigned int gic_irqs;
 };
 #endif
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 2/3] ARM: gic: add irq_domain support
@ 2011-09-30 19:27   ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-30 19:27 UTC (permalink / raw)
  To: linux-arm-kernel

From: Rob Herring <rob.herring@calxeda.com>

Convert the gic interrupt controller to use irq domains in preparation
for device-tree binding and MULTI_IRQ. This allows for translation between
GIC interrupt IDs and Linux irq numbers.

The meaning of irq_offset has changed. It now is just the number of skipped
GIC interrupt IDs for the controller. It will be 16 for primary GIC and 32
for secondary GICs.

Cc: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 arch/arm/common/Kconfig             |    1 +
 arch/arm/common/gic.c               |   81 ++++++++++++++++++++---------------
 arch/arm/include/asm/hardware/gic.h |    4 +-
 3 files changed, 51 insertions(+), 35 deletions(-)

diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 4b71766..74df9ca 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -1,4 +1,5 @@
 config ARM_GIC
+	select IRQ_DOMAIN
 	bool
 
 config ARM_VIC
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 8b5be72..6fbe1db 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -29,6 +29,7 @@
 #include <linux/cpu_pm.h>
 #include <linux/cpumask.h>
 #include <linux/io.h>
+#include <linux/irqdomain.h>
 
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
@@ -72,8 +73,7 @@ static inline void __iomem *gic_cpu_base(struct irq_data *d)
 
 static inline unsigned int gic_irq(struct irq_data *d)
 {
-	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
-	return d->irq - gic_data->irq_offset;
+	return d->hwirq;
 }
 
 /*
@@ -81,7 +81,7 @@ static inline unsigned int gic_irq(struct irq_data *d)
  */
 static void gic_mask_irq(struct irq_data *d)
 {
-	u32 mask = 1 << (d->irq % 32);
+	u32 mask = 1 << (gic_irq(d) % 32);
 
 	spin_lock(&irq_controller_lock);
 	writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
@@ -92,7 +92,7 @@ static void gic_mask_irq(struct irq_data *d)
 
 static void gic_unmask_irq(struct irq_data *d)
 {
-	u32 mask = 1 << (d->irq % 32);
+	u32 mask = 1 << (gic_irq(d) % 32);
 
 	spin_lock(&irq_controller_lock);
 	if (gic_arch_extn.irq_unmask)
@@ -173,7 +173,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 			    bool force)
 {
 	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
-	unsigned int shift = (d->irq % 4) * 8;
+	unsigned int shift = (gic_irq(d) % 4) * 8;
 	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
 	u32 val, mask, bit;
 
@@ -224,7 +224,7 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 	if (gic_irq == 1023)
 		goto out;
 
-	cascade_irq = gic_irq + chip_data->irq_offset;
+	cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq);
 	if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS))
 		do_bad_IRQ(cascade_irq, desc);
 	else
@@ -256,10 +256,11 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 	irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
-static void __init gic_dist_init(struct gic_chip_data *gic,
-	unsigned int irq_start)
+static void __init gic_dist_init(struct gic_chip_data *gic)
 {
-	unsigned int gic_irqs, irq_limit, i;
+	unsigned int gic_irqs = gic->gic_irqs;
+	struct irq_domain *domain = &gic->domain;
+	unsigned int i, irq;
 	u32 cpumask;
 	void __iomem *base = gic->dist_base;
 	u32 cpu = 0;
@@ -275,17 +276,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 	writel_relaxed(0, base + GIC_DIST_CTRL);
 
 	/*
-	 * Find out how many interrupts are supported.
-	 * The GIC only supports up to 1020 interrupt sources.
-	 */
-	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
-	gic_irqs = (gic_irqs + 1) * 32;
-	if (gic_irqs > 1020)
-		gic_irqs = 1020;
-
-	gic->gic_irqs = gic_irqs;
-
-	/*
 	 * Set all global interrupts to be level triggered, active low.
 	 */
 	for (i = 32; i < gic_irqs; i += 16)
@@ -311,19 +301,12 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
 
 	/*
-	 * Limit number of interrupts registered to the platform maximum
-	 */
-	irq_limit = gic->irq_offset + gic_irqs;
-	if (WARN_ON(irq_limit > NR_IRQS))
-		irq_limit = NR_IRQS;
-
-	/*
 	 * Setup the Linux IRQ subsystem.
 	 */
-	for (i = irq_start; i < irq_limit; i++) {
-		irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq);
-		irq_set_chip_data(i, gic);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	irq_domain_for_each_irq(domain, i, irq) {
+		irq_set_chip_and_handler(irq, &gic_chip, handle_fasteoi_irq);
+		irq_set_chip_data(irq, gic);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
 	writel_relaxed(1, base + GIC_DIST_CTRL);
@@ -535,23 +518,53 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
 }
 #endif
 
+const struct irq_domain_ops gic_irq_domain_ops = {
+};
+
 void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
 	void __iomem *dist_base, void __iomem *cpu_base)
 {
 	struct gic_chip_data *gic;
+	struct irq_domain *domain;
+	int gic_irqs;
 
 	BUG_ON(gic_nr >= MAX_GIC_NR);
 
 	gic = &gic_data[gic_nr];
+	domain = &gic->domain;
 	gic->dist_base = dist_base;
 	gic->cpu_base = cpu_base;
-	gic->irq_offset = (irq_start - 1) & ~31;
 
-	if (gic_nr == 0)
+	/*
+	 * For primary GICs, skip over SGIs.
+	 * For secondary GICs, skip over PPIs, too.
+	 */
+	if (gic_nr == 0) {
 		gic_cpu_base_addr = cpu_base;
+		domain->hwirq_base = 16;
+		irq_start = (irq_start & ~31) + 16;
+	} else
+		domain->hwirq_base = 32;
+
+	/*
+	 * Find out how many interrupts are supported.
+	 * The GIC only supports up to 1020 interrupt sources.
+	 */
+	gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
+	gic_irqs = (gic_irqs + 1) * 32;
+	if (gic_irqs > 1020)
+		gic_irqs = 1020;
+	gic->gic_irqs = gic_irqs;
+
+	domain->nr_irq = gic_irqs - domain->hwirq_base;
+	domain->irq_base = irq_alloc_descs(-1, irq_start, domain->nr_irq,
+					   numa_node_id());
+	domain->priv = gic;
+	domain->ops = &gic_irq_domain_ops;
+	irq_domain_add(domain);
 
 	gic_chip.flags |= gic_arch_extn.flags;
-	gic_dist_init(gic, irq_start);
+	gic_dist_init(gic);
 	gic_cpu_init(gic);
 	gic_pm_init(gic);
 }
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index c562705..ade84a4 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -33,6 +33,8 @@
 #define GIC_DIST_SOFTINT		0xf00
 
 #ifndef __ASSEMBLY__
+#include <linux/irqdomain.h>
+
 extern void __iomem *gic_cpu_base_addr;
 extern struct irq_chip gic_arch_extn;
 
@@ -43,7 +45,6 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
 void gic_enable_ppi(unsigned int);
 
 struct gic_chip_data {
-	unsigned int irq_offset;
 	void __iomem *dist_base;
 	void __iomem *cpu_base;
 #ifdef CONFIG_CPU_PM
@@ -53,6 +54,7 @@ struct gic_chip_data {
 	u32 __percpu *saved_ppi_enable;
 	u32 __percpu *saved_ppi_conf;
 #endif
+	struct irq_domain domain;
 	unsigned int gic_irqs;
 };
 #endif
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-30 19:28   ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-30 19:28 UTC (permalink / raw)
  To: linux-arm-kernel, devicetree-discuss, linux-kernel
  Cc: grant.likely, marc.zyngier, thomas.abraham, jamie, b-cousson,
	shawn.guo, Rob Herring

From: Rob Herring <rob.herring@calxeda.com>

This adds ARM gic interrupt controller initialization using device tree
data.

The initialization function is intended to be called by of_irq_init
function like this:

const static struct of_device_id irq_match[] = {
	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
	{}
};

static void __init init_irqs(void)
{
	of_irq_init(irq_match);
}

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 Documentation/devicetree/bindings/arm/gic.txt |   55 ++++++++++++++++++++++
 arch/arm/common/gic.c                         |   61 +++++++++++++++++++++++++
 arch/arm/include/asm/hardware/gic.h           |    1 +
 3 files changed, 117 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/gic.txt

diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
new file mode 100644
index 0000000..52916b4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/gic.txt
@@ -0,0 +1,55 @@
+* ARM Generic Interrupt Controller
+
+ARM SMP cores are often associated with a GIC, providing per processor
+interrupts (PPI), shared processor interrupts (SPI) and software
+generated interrupts (SGI).
+
+Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
+Secondary GICs are cascaded into the upward interrupt controller and do not
+have PPIs or SGIs.
+
+Main node required properties:
+
+- compatible : should be one of:
+	"arm,cortex-a9-gic"
+	"arm,arm11mp-gic"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source.  The type shall be a <u32> and the value shall be 3.
+
+  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
+  interrupts.
+
+  The 2nd cell contains the interrupt number for the interrupt type.
+  SPI interrupts are in the range [0-987].  PPI interrupts are in the
+  range [0-15].
+
+  The 3rd cell is the flags, encoded as follows:
+	bits[3:0] trigger type and level flags.
+		1 = low-to-high edge triggered
+		2 = high-to-low edge triggered
+		4 = active high level-sensitive
+		8 = active low level-sensitive
+	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
+	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
+	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
+
+- reg : Specifies base physical address(s) and size of the GIC registers. The
+  first region is the GIC distributor register base and size. The 2nd region is
+  the GIC cpu interface register base and size.
+
+Optional
+- interrupts	: Interrupt source of the parent interrupt controller. Only
+  present on secondary GICs.
+
+Example:
+
+	intc: interrupt-controller@fff11000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <1>;
+		interrupt-controller;
+		reg = <0xfff11000 0x1000>,
+		      <0xfff10100 0x100>;
+	};
+
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 6fbe1db..3e67970 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -29,6 +29,9 @@
 #include <linux/cpu_pm.h>
 #include <linux/cpumask.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/irqdomain.h>
 
 #include <asm/irq.h>
@@ -518,7 +521,33 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
 }
 #endif
 
+#ifdef CONFIG_OF
+static int gic_irq_domain_dt_translate(struct irq_domain *d,
+				       struct device_node *controller,
+				       const u32 *intspec, unsigned int intsize,
+				       unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 3)
+		return -EINVAL;
+
+	/* Get the interrupt number and add 16 to skip over SGIs */
+	*out_hwirq = intspec[1] + 16;
+
+	/* For SPIs, we need to add 16 more to get the GIC irq ID number */
+	if (!intspec[0])
+		*out_hwirq += 16;
+
+	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+#endif
+
 const struct irq_domain_ops gic_irq_domain_ops = {
+#ifdef CONFIG_OF
+	.dt_translate = gic_irq_domain_dt_translate,
+#endif
 };
 
 void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
@@ -606,3 +635,35 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
 }
 #endif
+
+#ifdef CONFIG_OF
+static int gic_cnt __initdata = 0;
+
+int __init gic_of_init(struct device_node *node, struct device_node *parent)
+{
+	void __iomem *cpu_base;
+	void __iomem *dist_base;
+	int irq;
+	struct irq_domain *domain = &gic_data[gic_cnt].domain;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	dist_base = of_iomap(node, 0);
+	WARN(!dist_base, "unable to map gic dist registers\n");
+
+	cpu_base = of_iomap(node, 1);
+	WARN(!cpu_base, "unable to map gic cpu registers\n");
+
+	domain->of_node = of_node_get(node);
+
+	gic_init(gic_cnt, 16, dist_base, cpu_base);
+
+	if (parent) {
+		irq = irq_of_parse_and_map(node, 0);
+		gic_cascade_irq(gic_cnt, irq);
+	}
+	gic_cnt++;
+	return 0;
+}
+#endif
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index ade84a4..1a776a1 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -39,6 +39,7 @@ extern void __iomem *gic_cpu_base_addr;
 extern struct irq_chip gic_arch_extn;
 
 void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
+int gic_of_init(struct device_node *node, struct device_node *parent);
 void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-30 19:28   ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-30 19:28 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: Rob Herring

From: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>

This adds ARM gic interrupt controller initialization using device tree
data.

The initialization function is intended to be called by of_irq_init
function like this:

const static struct of_device_id irq_match[] = {
	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
	{}
};

static void __init init_irqs(void)
{
	of_irq_init(irq_match);
}

Signed-off-by: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
---
 Documentation/devicetree/bindings/arm/gic.txt |   55 ++++++++++++++++++++++
 arch/arm/common/gic.c                         |   61 +++++++++++++++++++++++++
 arch/arm/include/asm/hardware/gic.h           |    1 +
 3 files changed, 117 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/gic.txt

diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
new file mode 100644
index 0000000..52916b4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/gic.txt
@@ -0,0 +1,55 @@
+* ARM Generic Interrupt Controller
+
+ARM SMP cores are often associated with a GIC, providing per processor
+interrupts (PPI), shared processor interrupts (SPI) and software
+generated interrupts (SGI).
+
+Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
+Secondary GICs are cascaded into the upward interrupt controller and do not
+have PPIs or SGIs.
+
+Main node required properties:
+
+- compatible : should be one of:
+	"arm,cortex-a9-gic"
+	"arm,arm11mp-gic"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source.  The type shall be a <u32> and the value shall be 3.
+
+  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
+  interrupts.
+
+  The 2nd cell contains the interrupt number for the interrupt type.
+  SPI interrupts are in the range [0-987].  PPI interrupts are in the
+  range [0-15].
+
+  The 3rd cell is the flags, encoded as follows:
+	bits[3:0] trigger type and level flags.
+		1 = low-to-high edge triggered
+		2 = high-to-low edge triggered
+		4 = active high level-sensitive
+		8 = active low level-sensitive
+	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
+	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
+	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
+
+- reg : Specifies base physical address(s) and size of the GIC registers. The
+  first region is the GIC distributor register base and size. The 2nd region is
+  the GIC cpu interface register base and size.
+
+Optional
+- interrupts	: Interrupt source of the parent interrupt controller. Only
+  present on secondary GICs.
+
+Example:
+
+	intc: interrupt-controller@fff11000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <1>;
+		interrupt-controller;
+		reg = <0xfff11000 0x1000>,
+		      <0xfff10100 0x100>;
+	};
+
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 6fbe1db..3e67970 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -29,6 +29,9 @@
 #include <linux/cpu_pm.h>
 #include <linux/cpumask.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/irqdomain.h>
 
 #include <asm/irq.h>
@@ -518,7 +521,33 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
 }
 #endif
 
+#ifdef CONFIG_OF
+static int gic_irq_domain_dt_translate(struct irq_domain *d,
+				       struct device_node *controller,
+				       const u32 *intspec, unsigned int intsize,
+				       unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 3)
+		return -EINVAL;
+
+	/* Get the interrupt number and add 16 to skip over SGIs */
+	*out_hwirq = intspec[1] + 16;
+
+	/* For SPIs, we need to add 16 more to get the GIC irq ID number */
+	if (!intspec[0])
+		*out_hwirq += 16;
+
+	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+#endif
+
 const struct irq_domain_ops gic_irq_domain_ops = {
+#ifdef CONFIG_OF
+	.dt_translate = gic_irq_domain_dt_translate,
+#endif
 };
 
 void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
@@ -606,3 +635,35 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
 }
 #endif
+
+#ifdef CONFIG_OF
+static int gic_cnt __initdata = 0;
+
+int __init gic_of_init(struct device_node *node, struct device_node *parent)
+{
+	void __iomem *cpu_base;
+	void __iomem *dist_base;
+	int irq;
+	struct irq_domain *domain = &gic_data[gic_cnt].domain;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	dist_base = of_iomap(node, 0);
+	WARN(!dist_base, "unable to map gic dist registers\n");
+
+	cpu_base = of_iomap(node, 1);
+	WARN(!cpu_base, "unable to map gic cpu registers\n");
+
+	domain->of_node = of_node_get(node);
+
+	gic_init(gic_cnt, 16, dist_base, cpu_base);
+
+	if (parent) {
+		irq = irq_of_parse_and_map(node, 0);
+		gic_cascade_irq(gic_cnt, irq);
+	}
+	gic_cnt++;
+	return 0;
+}
+#endif
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index ade84a4..1a776a1 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -39,6 +39,7 @@ extern void __iomem *gic_cpu_base_addr;
 extern struct irq_chip gic_arch_extn;
 
 void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
+int gic_of_init(struct device_node *node, struct device_node *parent);
 void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-30 19:28   ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-30 19:28 UTC (permalink / raw)
  To: linux-arm-kernel

From: Rob Herring <rob.herring@calxeda.com>

This adds ARM gic interrupt controller initialization using device tree
data.

The initialization function is intended to be called by of_irq_init
function like this:

const static struct of_device_id irq_match[] = {
	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
	{}
};

static void __init init_irqs(void)
{
	of_irq_init(irq_match);
}

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 Documentation/devicetree/bindings/arm/gic.txt |   55 ++++++++++++++++++++++
 arch/arm/common/gic.c                         |   61 +++++++++++++++++++++++++
 arch/arm/include/asm/hardware/gic.h           |    1 +
 3 files changed, 117 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/gic.txt

diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
new file mode 100644
index 0000000..52916b4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/gic.txt
@@ -0,0 +1,55 @@
+* ARM Generic Interrupt Controller
+
+ARM SMP cores are often associated with a GIC, providing per processor
+interrupts (PPI), shared processor interrupts (SPI) and software
+generated interrupts (SGI).
+
+Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
+Secondary GICs are cascaded into the upward interrupt controller and do not
+have PPIs or SGIs.
+
+Main node required properties:
+
+- compatible : should be one of:
+	"arm,cortex-a9-gic"
+	"arm,arm11mp-gic"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source.  The type shall be a <u32> and the value shall be 3.
+
+  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
+  interrupts.
+
+  The 2nd cell contains the interrupt number for the interrupt type.
+  SPI interrupts are in the range [0-987].  PPI interrupts are in the
+  range [0-15].
+
+  The 3rd cell is the flags, encoded as follows:
+	bits[3:0] trigger type and level flags.
+		1 = low-to-high edge triggered
+		2 = high-to-low edge triggered
+		4 = active high level-sensitive
+		8 = active low level-sensitive
+	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
+	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
+	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
+
+- reg : Specifies base physical address(s) and size of the GIC registers. The
+  first region is the GIC distributor register base and size. The 2nd region is
+  the GIC cpu interface register base and size.
+
+Optional
+- interrupts	: Interrupt source of the parent interrupt controller. Only
+  present on secondary GICs.
+
+Example:
+
+	intc: interrupt-controller at fff11000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <1>;
+		interrupt-controller;
+		reg = <0xfff11000 0x1000>,
+		      <0xfff10100 0x100>;
+	};
+
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 6fbe1db..3e67970 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -29,6 +29,9 @@
 #include <linux/cpu_pm.h>
 #include <linux/cpumask.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/irqdomain.h>
 
 #include <asm/irq.h>
@@ -518,7 +521,33 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
 }
 #endif
 
+#ifdef CONFIG_OF
+static int gic_irq_domain_dt_translate(struct irq_domain *d,
+				       struct device_node *controller,
+				       const u32 *intspec, unsigned int intsize,
+				       unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 3)
+		return -EINVAL;
+
+	/* Get the interrupt number and add 16 to skip over SGIs */
+	*out_hwirq = intspec[1] + 16;
+
+	/* For SPIs, we need to add 16 more to get the GIC irq ID number */
+	if (!intspec[0])
+		*out_hwirq += 16;
+
+	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+#endif
+
 const struct irq_domain_ops gic_irq_domain_ops = {
+#ifdef CONFIG_OF
+	.dt_translate = gic_irq_domain_dt_translate,
+#endif
 };
 
 void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
@@ -606,3 +635,35 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
 }
 #endif
+
+#ifdef CONFIG_OF
+static int gic_cnt __initdata = 0;
+
+int __init gic_of_init(struct device_node *node, struct device_node *parent)
+{
+	void __iomem *cpu_base;
+	void __iomem *dist_base;
+	int irq;
+	struct irq_domain *domain = &gic_data[gic_cnt].domain;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	dist_base = of_iomap(node, 0);
+	WARN(!dist_base, "unable to map gic dist registers\n");
+
+	cpu_base = of_iomap(node, 1);
+	WARN(!cpu_base, "unable to map gic cpu registers\n");
+
+	domain->of_node = of_node_get(node);
+
+	gic_init(gic_cnt, 16, dist_base, cpu_base);
+
+	if (parent) {
+		irq = irq_of_parse_and_map(node, 0);
+		gic_cascade_irq(gic_cnt, irq);
+	}
+	gic_cnt++;
+	return 0;
+}
+#endif
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index ade84a4..1a776a1 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -39,6 +39,7 @@ extern void __iomem *gic_cpu_base_addr;
 extern struct irq_chip gic_arch_extn;
 
 void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
+int gic_of_init(struct device_node *node, struct device_node *parent);
 void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* Re: [PATCH 0/3] GIC OF bindings
@ 2011-10-04 16:15   ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-10-04 16:15 UTC (permalink / raw)
  To: grant.likely
  Cc: linux-arm-kernel, devicetree-discuss, linux-kernel, marc.zyngier,
	thomas.abraham, jamie, b-cousson, shawn.guo

Grant,

On 09/30/2011 02:27 PM, Rob Herring wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> Another round of GIC devicetree support.
> 
> This moves the tracking of the starting hwirq number into the irq domain
> code. Doing this makes hwirq == GIC interrupt ID and simplifies the GIC
> code removing irq_offset.
> 
> The full series is available here. This includes Russell's devel-stable and
> for-next branches and Nico's vmalloc branch:
> 
> git://git.jdl.com/software/linux-3.0.git gic-v2
> 
> Tested on highbank and Realview 11MPCore qemu (2 GICs).
> 
> Rob
> 
> Rob Herring (3):
>   irq: support domains with non-zero hwirq base
>   ARM: gic: add irq_domain support
>   ARM: gic: add OF based initialization
> 
>  Documentation/devicetree/bindings/arm/gic.txt |   55 ++++++++++
>  arch/arm/common/Kconfig                       |    1 +
>  arch/arm/common/gic.c                         |  142 +++++++++++++++++++------
>  arch/arm/include/asm/hardware/gic.h           |    5 +-
>  include/linux/irqdomain.h                     |   16 +++-
>  kernel/irq/irqdomain.c                        |   12 +-
>  6 files changed, 189 insertions(+), 42 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/gic.txt
> 

Ping. Can you please comment on this series.

Rob

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 0/3] GIC OF bindings
@ 2011-10-04 16:15   ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-10-04 16:15 UTC (permalink / raw)
  To: grant.likely-s3s/WqlpOiPyB63q8FvJNQ
  Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Grant,

On 09/30/2011 02:27 PM, Rob Herring wrote:
> From: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
> 
> Another round of GIC devicetree support.
> 
> This moves the tracking of the starting hwirq number into the irq domain
> code. Doing this makes hwirq == GIC interrupt ID and simplifies the GIC
> code removing irq_offset.
> 
> The full series is available here. This includes Russell's devel-stable and
> for-next branches and Nico's vmalloc branch:
> 
> git://git.jdl.com/software/linux-3.0.git gic-v2
> 
> Tested on highbank and Realview 11MPCore qemu (2 GICs).
> 
> Rob
> 
> Rob Herring (3):
>   irq: support domains with non-zero hwirq base
>   ARM: gic: add irq_domain support
>   ARM: gic: add OF based initialization
> 
>  Documentation/devicetree/bindings/arm/gic.txt |   55 ++++++++++
>  arch/arm/common/Kconfig                       |    1 +
>  arch/arm/common/gic.c                         |  142 +++++++++++++++++++------
>  arch/arm/include/asm/hardware/gic.h           |    5 +-
>  include/linux/irqdomain.h                     |   16 +++-
>  kernel/irq/irqdomain.c                        |   12 +-
>  6 files changed, 189 insertions(+), 42 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/gic.txt
> 

Ping. Can you please comment on this series.

Rob

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 0/3] GIC OF bindings
@ 2011-10-04 16:15   ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-10-04 16:15 UTC (permalink / raw)
  To: linux-arm-kernel

Grant,

On 09/30/2011 02:27 PM, Rob Herring wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> Another round of GIC devicetree support.
> 
> This moves the tracking of the starting hwirq number into the irq domain
> code. Doing this makes hwirq == GIC interrupt ID and simplifies the GIC
> code removing irq_offset.
> 
> The full series is available here. This includes Russell's devel-stable and
> for-next branches and Nico's vmalloc branch:
> 
> git://git.jdl.com/software/linux-3.0.git gic-v2
> 
> Tested on highbank and Realview 11MPCore qemu (2 GICs).
> 
> Rob
> 
> Rob Herring (3):
>   irq: support domains with non-zero hwirq base
>   ARM: gic: add irq_domain support
>   ARM: gic: add OF based initialization
> 
>  Documentation/devicetree/bindings/arm/gic.txt |   55 ++++++++++
>  arch/arm/common/Kconfig                       |    1 +
>  arch/arm/common/gic.c                         |  142 +++++++++++++++++++------
>  arch/arm/include/asm/hardware/gic.h           |    5 +-
>  include/linux/irqdomain.h                     |   16 +++-
>  kernel/irq/irqdomain.c                        |   12 +-
>  6 files changed, 189 insertions(+), 42 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/gic.txt
> 

Ping. Can you please comment on this series.

Rob

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 1/3] irq: support domains with non-zero hwirq base
  2011-09-30 19:27   ` Rob Herring
@ 2011-10-04 23:39     ` Grant Likely
  -1 siblings, 0 replies; 68+ messages in thread
From: Grant Likely @ 2011-10-04 23:39 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-arm-kernel, devicetree-discuss, linux-kernel, marc.zyngier,
	thomas.abraham, jamie, b-cousson, shawn.guo, Rob Herring,
	Thomas Gleixner

On Fri, Sep 30, 2011 at 02:27:58PM -0500, Rob Herring wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> Interrupt controllers can have non-zero starting value for h/w irq numbers.
> Adding support in irq_domain allows the domain hwirq numbering to match
> the interrupt controllers' numbering.
> 
> As this makes looping over irqs for a domain more complicated, add loop
> iterators to iterate over all hwirqs and irqs for a domain.
> 
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> ---
>  include/linux/irqdomain.h |   16 +++++++++++++++-
>  kernel/irq/irqdomain.c    |   12 ++++++------
>  2 files changed, 21 insertions(+), 7 deletions(-)
> 
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index 3ad553e..c0026b6 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -47,6 +47,7 @@ struct irq_domain_ops {
>   *            of the irq_domain is responsible for allocating the array of
>   *            irq_desc structures.
>   * @nr_irq: Number of irqs managed by the irq domain
> + * @hwirq_base: Starting number for hwirqs managed by the irq domain
>   * @ops: pointer to irq_domain methods
>   * @priv: private data pointer for use by owner.  Not touched by irq_domain
>   *        core code.
> @@ -57,6 +58,7 @@ struct irq_domain {
>  	struct list_head list;
>  	unsigned int irq_base;
>  	unsigned int nr_irq;
> +	unsigned int hwirq_base;
>  	const struct irq_domain_ops *ops;
>  	void *priv;
>  	struct device_node *of_node;
> @@ -72,9 +74,21 @@ struct irq_domain {
>  static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
>  					     unsigned long hwirq)
>  {
> -	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
> +	if (d->ops->to_irq)
> +		return d->ops->to_irq(d, hwirq);
> +	if (hwirq < d->hwirq_base)
> +		return NO_IRQ;

NO_IRQ is probably not available on x86.  Also, if this condition
is hit then something is definitely wrong.  You should WARN() and
return 0.

Otherwise looks good and you can add my a-b:

Acked-by: Grant Likely <grant.likely@secretlab.ca>


^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 1/3] irq: support domains with non-zero hwirq base
@ 2011-10-04 23:39     ` Grant Likely
  0 siblings, 0 replies; 68+ messages in thread
From: Grant Likely @ 2011-10-04 23:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Sep 30, 2011 at 02:27:58PM -0500, Rob Herring wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> Interrupt controllers can have non-zero starting value for h/w irq numbers.
> Adding support in irq_domain allows the domain hwirq numbering to match
> the interrupt controllers' numbering.
> 
> As this makes looping over irqs for a domain more complicated, add loop
> iterators to iterate over all hwirqs and irqs for a domain.
> 
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> ---
>  include/linux/irqdomain.h |   16 +++++++++++++++-
>  kernel/irq/irqdomain.c    |   12 ++++++------
>  2 files changed, 21 insertions(+), 7 deletions(-)
> 
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index 3ad553e..c0026b6 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -47,6 +47,7 @@ struct irq_domain_ops {
>   *            of the irq_domain is responsible for allocating the array of
>   *            irq_desc structures.
>   * @nr_irq: Number of irqs managed by the irq domain
> + * @hwirq_base: Starting number for hwirqs managed by the irq domain
>   * @ops: pointer to irq_domain methods
>   * @priv: private data pointer for use by owner.  Not touched by irq_domain
>   *        core code.
> @@ -57,6 +58,7 @@ struct irq_domain {
>  	struct list_head list;
>  	unsigned int irq_base;
>  	unsigned int nr_irq;
> +	unsigned int hwirq_base;
>  	const struct irq_domain_ops *ops;
>  	void *priv;
>  	struct device_node *of_node;
> @@ -72,9 +74,21 @@ struct irq_domain {
>  static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
>  					     unsigned long hwirq)
>  {
> -	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
> +	if (d->ops->to_irq)
> +		return d->ops->to_irq(d, hwirq);
> +	if (hwirq < d->hwirq_base)
> +		return NO_IRQ;

NO_IRQ is probably not available on x86.  Also, if this condition
is hit then something is definitely wrong.  You should WARN() and
return 0.

Otherwise looks good and you can add my a-b:

Acked-by: Grant Likely <grant.likely@secretlab.ca>

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 2/3] ARM: gic: add irq_domain support
  2011-09-30 19:27   ` Rob Herring
@ 2011-10-04 23:41     ` Grant Likely
  -1 siblings, 0 replies; 68+ messages in thread
From: Grant Likely @ 2011-10-04 23:41 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-arm-kernel, devicetree-discuss, linux-kernel, marc.zyngier,
	thomas.abraham, jamie, b-cousson, shawn.guo, Rob Herring

On Fri, Sep 30, 2011 at 02:27:59PM -0500, Rob Herring wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> Convert the gic interrupt controller to use irq domains in preparation
> for device-tree binding and MULTI_IRQ. This allows for translation between
> GIC interrupt IDs and Linux irq numbers.
> 
> The meaning of irq_offset has changed. It now is just the number of skipped
> GIC interrupt IDs for the controller. It will be 16 for primary GIC and 32
> for secondary GICs.
> 
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> ---
>  arch/arm/common/Kconfig             |    1 +
>  arch/arm/common/gic.c               |   81 ++++++++++++++++++++---------------
>  arch/arm/include/asm/hardware/gic.h |    4 +-
>  3 files changed, 51 insertions(+), 35 deletions(-)
> 
> diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
> index 4b71766..74df9ca 100644
> --- a/arch/arm/common/Kconfig
> +++ b/arch/arm/common/Kconfig
> @@ -1,4 +1,5 @@
>  config ARM_GIC
> +	select IRQ_DOMAIN
>  	bool
>  
>  config ARM_VIC
> diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
> index 8b5be72..6fbe1db 100644
> --- a/arch/arm/common/gic.c
> +++ b/arch/arm/common/gic.c
> @@ -29,6 +29,7 @@
>  #include <linux/cpu_pm.h>
>  #include <linux/cpumask.h>
>  #include <linux/io.h>
> +#include <linux/irqdomain.h>
>  
>  #include <asm/irq.h>
>  #include <asm/mach/irq.h>
> @@ -72,8 +73,7 @@ static inline void __iomem *gic_cpu_base(struct irq_data *d)
>  
>  static inline unsigned int gic_irq(struct irq_data *d)
>  {
> -	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
> -	return d->irq - gic_data->irq_offset;
> +	return d->hwirq;
>  }

Nit: Personally, I'd just drop gic_irq() entirely and reference
d->hwirq directly.  However, it isn't enough to withhold my a-b.

Acked-by: Grant Likely <grant.likely@secretlab.ca>

>  
>  /*
> @@ -81,7 +81,7 @@ static inline unsigned int gic_irq(struct irq_data *d)
>   */
>  static void gic_mask_irq(struct irq_data *d)
>  {
> -	u32 mask = 1 << (d->irq % 32);
> +	u32 mask = 1 << (gic_irq(d) % 32);
>  
>  	spin_lock(&irq_controller_lock);
>  	writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
> @@ -92,7 +92,7 @@ static void gic_mask_irq(struct irq_data *d)
>  
>  static void gic_unmask_irq(struct irq_data *d)
>  {
> -	u32 mask = 1 << (d->irq % 32);
> +	u32 mask = 1 << (gic_irq(d) % 32);
>  
>  	spin_lock(&irq_controller_lock);
>  	if (gic_arch_extn.irq_unmask)
> @@ -173,7 +173,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
>  			    bool force)
>  {
>  	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
> -	unsigned int shift = (d->irq % 4) * 8;
> +	unsigned int shift = (gic_irq(d) % 4) * 8;
>  	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
>  	u32 val, mask, bit;
>  
> @@ -224,7 +224,7 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
>  	if (gic_irq == 1023)
>  		goto out;
>  
> -	cascade_irq = gic_irq + chip_data->irq_offset;
> +	cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq);
>  	if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS))
>  		do_bad_IRQ(cascade_irq, desc);
>  	else
> @@ -256,10 +256,11 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
>  	irq_set_chained_handler(irq, gic_handle_cascade_irq);
>  }
>  
> -static void __init gic_dist_init(struct gic_chip_data *gic,
> -	unsigned int irq_start)
> +static void __init gic_dist_init(struct gic_chip_data *gic)
>  {
> -	unsigned int gic_irqs, irq_limit, i;
> +	unsigned int gic_irqs = gic->gic_irqs;
> +	struct irq_domain *domain = &gic->domain;
> +	unsigned int i, irq;
>  	u32 cpumask;
>  	void __iomem *base = gic->dist_base;
>  	u32 cpu = 0;
> @@ -275,17 +276,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
>  	writel_relaxed(0, base + GIC_DIST_CTRL);
>  
>  	/*
> -	 * Find out how many interrupts are supported.
> -	 * The GIC only supports up to 1020 interrupt sources.
> -	 */
> -	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
> -	gic_irqs = (gic_irqs + 1) * 32;
> -	if (gic_irqs > 1020)
> -		gic_irqs = 1020;
> -
> -	gic->gic_irqs = gic_irqs;
> -
> -	/*
>  	 * Set all global interrupts to be level triggered, active low.
>  	 */
>  	for (i = 32; i < gic_irqs; i += 16)
> @@ -311,19 +301,12 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
>  		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
>  
>  	/*
> -	 * Limit number of interrupts registered to the platform maximum
> -	 */
> -	irq_limit = gic->irq_offset + gic_irqs;
> -	if (WARN_ON(irq_limit > NR_IRQS))
> -		irq_limit = NR_IRQS;
> -
> -	/*
>  	 * Setup the Linux IRQ subsystem.
>  	 */
> -	for (i = irq_start; i < irq_limit; i++) {
> -		irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq);
> -		irq_set_chip_data(i, gic);
> -		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
> +	irq_domain_for_each_irq(domain, i, irq) {
> +		irq_set_chip_and_handler(irq, &gic_chip, handle_fasteoi_irq);
> +		irq_set_chip_data(irq, gic);
> +		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
>  	}
>  
>  	writel_relaxed(1, base + GIC_DIST_CTRL);
> @@ -535,23 +518,53 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
>  }
>  #endif
>  
> +const struct irq_domain_ops gic_irq_domain_ops = {
> +};
> +
>  void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
>  	void __iomem *dist_base, void __iomem *cpu_base)
>  {
>  	struct gic_chip_data *gic;
> +	struct irq_domain *domain;
> +	int gic_irqs;
>  
>  	BUG_ON(gic_nr >= MAX_GIC_NR);
>  
>  	gic = &gic_data[gic_nr];
> +	domain = &gic->domain;
>  	gic->dist_base = dist_base;
>  	gic->cpu_base = cpu_base;
> -	gic->irq_offset = (irq_start - 1) & ~31;
>  
> -	if (gic_nr == 0)
> +	/*
> +	 * For primary GICs, skip over SGIs.
> +	 * For secondary GICs, skip over PPIs, too.
> +	 */
> +	if (gic_nr == 0) {
>  		gic_cpu_base_addr = cpu_base;
> +		domain->hwirq_base = 16;
> +		irq_start = (irq_start & ~31) + 16;
> +	} else
> +		domain->hwirq_base = 32;
> +
> +	/*
> +	 * Find out how many interrupts are supported.
> +	 * The GIC only supports up to 1020 interrupt sources.
> +	 */
> +	gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
> +	gic_irqs = (gic_irqs + 1) * 32;
> +	if (gic_irqs > 1020)
> +		gic_irqs = 1020;
> +	gic->gic_irqs = gic_irqs;
> +
> +	domain->nr_irq = gic_irqs - domain->hwirq_base;
> +	domain->irq_base = irq_alloc_descs(-1, irq_start, domain->nr_irq,
> +					   numa_node_id());
> +	domain->priv = gic;
> +	domain->ops = &gic_irq_domain_ops;
> +	irq_domain_add(domain);
>  
>  	gic_chip.flags |= gic_arch_extn.flags;
> -	gic_dist_init(gic, irq_start);
> +	gic_dist_init(gic);
>  	gic_cpu_init(gic);
>  	gic_pm_init(gic);
>  }
> diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
> index c562705..ade84a4 100644
> --- a/arch/arm/include/asm/hardware/gic.h
> +++ b/arch/arm/include/asm/hardware/gic.h
> @@ -33,6 +33,8 @@
>  #define GIC_DIST_SOFTINT		0xf00
>  
>  #ifndef __ASSEMBLY__
> +#include <linux/irqdomain.h>
> +
>  extern void __iomem *gic_cpu_base_addr;
>  extern struct irq_chip gic_arch_extn;
>  
> @@ -43,7 +45,6 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
>  void gic_enable_ppi(unsigned int);
>  
>  struct gic_chip_data {
> -	unsigned int irq_offset;
>  	void __iomem *dist_base;
>  	void __iomem *cpu_base;
>  #ifdef CONFIG_CPU_PM
> @@ -53,6 +54,7 @@ struct gic_chip_data {
>  	u32 __percpu *saved_ppi_enable;
>  	u32 __percpu *saved_ppi_conf;
>  #endif
> +	struct irq_domain domain;
>  	unsigned int gic_irqs;
>  };
>  #endif
> -- 
> 1.7.5.4
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 2/3] ARM: gic: add irq_domain support
@ 2011-10-04 23:41     ` Grant Likely
  0 siblings, 0 replies; 68+ messages in thread
From: Grant Likely @ 2011-10-04 23:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Sep 30, 2011 at 02:27:59PM -0500, Rob Herring wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> Convert the gic interrupt controller to use irq domains in preparation
> for device-tree binding and MULTI_IRQ. This allows for translation between
> GIC interrupt IDs and Linux irq numbers.
> 
> The meaning of irq_offset has changed. It now is just the number of skipped
> GIC interrupt IDs for the controller. It will be 16 for primary GIC and 32
> for secondary GICs.
> 
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> ---
>  arch/arm/common/Kconfig             |    1 +
>  arch/arm/common/gic.c               |   81 ++++++++++++++++++++---------------
>  arch/arm/include/asm/hardware/gic.h |    4 +-
>  3 files changed, 51 insertions(+), 35 deletions(-)
> 
> diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
> index 4b71766..74df9ca 100644
> --- a/arch/arm/common/Kconfig
> +++ b/arch/arm/common/Kconfig
> @@ -1,4 +1,5 @@
>  config ARM_GIC
> +	select IRQ_DOMAIN
>  	bool
>  
>  config ARM_VIC
> diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
> index 8b5be72..6fbe1db 100644
> --- a/arch/arm/common/gic.c
> +++ b/arch/arm/common/gic.c
> @@ -29,6 +29,7 @@
>  #include <linux/cpu_pm.h>
>  #include <linux/cpumask.h>
>  #include <linux/io.h>
> +#include <linux/irqdomain.h>
>  
>  #include <asm/irq.h>
>  #include <asm/mach/irq.h>
> @@ -72,8 +73,7 @@ static inline void __iomem *gic_cpu_base(struct irq_data *d)
>  
>  static inline unsigned int gic_irq(struct irq_data *d)
>  {
> -	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
> -	return d->irq - gic_data->irq_offset;
> +	return d->hwirq;
>  }

Nit: Personally, I'd just drop gic_irq() entirely and reference
d->hwirq directly.  However, it isn't enough to withhold my a-b.

Acked-by: Grant Likely <grant.likely@secretlab.ca>

>  
>  /*
> @@ -81,7 +81,7 @@ static inline unsigned int gic_irq(struct irq_data *d)
>   */
>  static void gic_mask_irq(struct irq_data *d)
>  {
> -	u32 mask = 1 << (d->irq % 32);
> +	u32 mask = 1 << (gic_irq(d) % 32);
>  
>  	spin_lock(&irq_controller_lock);
>  	writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
> @@ -92,7 +92,7 @@ static void gic_mask_irq(struct irq_data *d)
>  
>  static void gic_unmask_irq(struct irq_data *d)
>  {
> -	u32 mask = 1 << (d->irq % 32);
> +	u32 mask = 1 << (gic_irq(d) % 32);
>  
>  	spin_lock(&irq_controller_lock);
>  	if (gic_arch_extn.irq_unmask)
> @@ -173,7 +173,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
>  			    bool force)
>  {
>  	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
> -	unsigned int shift = (d->irq % 4) * 8;
> +	unsigned int shift = (gic_irq(d) % 4) * 8;
>  	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
>  	u32 val, mask, bit;
>  
> @@ -224,7 +224,7 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
>  	if (gic_irq == 1023)
>  		goto out;
>  
> -	cascade_irq = gic_irq + chip_data->irq_offset;
> +	cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq);
>  	if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS))
>  		do_bad_IRQ(cascade_irq, desc);
>  	else
> @@ -256,10 +256,11 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
>  	irq_set_chained_handler(irq, gic_handle_cascade_irq);
>  }
>  
> -static void __init gic_dist_init(struct gic_chip_data *gic,
> -	unsigned int irq_start)
> +static void __init gic_dist_init(struct gic_chip_data *gic)
>  {
> -	unsigned int gic_irqs, irq_limit, i;
> +	unsigned int gic_irqs = gic->gic_irqs;
> +	struct irq_domain *domain = &gic->domain;
> +	unsigned int i, irq;
>  	u32 cpumask;
>  	void __iomem *base = gic->dist_base;
>  	u32 cpu = 0;
> @@ -275,17 +276,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
>  	writel_relaxed(0, base + GIC_DIST_CTRL);
>  
>  	/*
> -	 * Find out how many interrupts are supported.
> -	 * The GIC only supports up to 1020 interrupt sources.
> -	 */
> -	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
> -	gic_irqs = (gic_irqs + 1) * 32;
> -	if (gic_irqs > 1020)
> -		gic_irqs = 1020;
> -
> -	gic->gic_irqs = gic_irqs;
> -
> -	/*
>  	 * Set all global interrupts to be level triggered, active low.
>  	 */
>  	for (i = 32; i < gic_irqs; i += 16)
> @@ -311,19 +301,12 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
>  		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
>  
>  	/*
> -	 * Limit number of interrupts registered to the platform maximum
> -	 */
> -	irq_limit = gic->irq_offset + gic_irqs;
> -	if (WARN_ON(irq_limit > NR_IRQS))
> -		irq_limit = NR_IRQS;
> -
> -	/*
>  	 * Setup the Linux IRQ subsystem.
>  	 */
> -	for (i = irq_start; i < irq_limit; i++) {
> -		irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq);
> -		irq_set_chip_data(i, gic);
> -		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
> +	irq_domain_for_each_irq(domain, i, irq) {
> +		irq_set_chip_and_handler(irq, &gic_chip, handle_fasteoi_irq);
> +		irq_set_chip_data(irq, gic);
> +		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
>  	}
>  
>  	writel_relaxed(1, base + GIC_DIST_CTRL);
> @@ -535,23 +518,53 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
>  }
>  #endif
>  
> +const struct irq_domain_ops gic_irq_domain_ops = {
> +};
> +
>  void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
>  	void __iomem *dist_base, void __iomem *cpu_base)
>  {
>  	struct gic_chip_data *gic;
> +	struct irq_domain *domain;
> +	int gic_irqs;
>  
>  	BUG_ON(gic_nr >= MAX_GIC_NR);
>  
>  	gic = &gic_data[gic_nr];
> +	domain = &gic->domain;
>  	gic->dist_base = dist_base;
>  	gic->cpu_base = cpu_base;
> -	gic->irq_offset = (irq_start - 1) & ~31;
>  
> -	if (gic_nr == 0)
> +	/*
> +	 * For primary GICs, skip over SGIs.
> +	 * For secondary GICs, skip over PPIs, too.
> +	 */
> +	if (gic_nr == 0) {
>  		gic_cpu_base_addr = cpu_base;
> +		domain->hwirq_base = 16;
> +		irq_start = (irq_start & ~31) + 16;
> +	} else
> +		domain->hwirq_base = 32;
> +
> +	/*
> +	 * Find out how many interrupts are supported.
> +	 * The GIC only supports up to 1020 interrupt sources.
> +	 */
> +	gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
> +	gic_irqs = (gic_irqs + 1) * 32;
> +	if (gic_irqs > 1020)
> +		gic_irqs = 1020;
> +	gic->gic_irqs = gic_irqs;
> +
> +	domain->nr_irq = gic_irqs - domain->hwirq_base;
> +	domain->irq_base = irq_alloc_descs(-1, irq_start, domain->nr_irq,
> +					   numa_node_id());
> +	domain->priv = gic;
> +	domain->ops = &gic_irq_domain_ops;
> +	irq_domain_add(domain);
>  
>  	gic_chip.flags |= gic_arch_extn.flags;
> -	gic_dist_init(gic, irq_start);
> +	gic_dist_init(gic);
>  	gic_cpu_init(gic);
>  	gic_pm_init(gic);
>  }
> diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
> index c562705..ade84a4 100644
> --- a/arch/arm/include/asm/hardware/gic.h
> +++ b/arch/arm/include/asm/hardware/gic.h
> @@ -33,6 +33,8 @@
>  #define GIC_DIST_SOFTINT		0xf00
>  
>  #ifndef __ASSEMBLY__
> +#include <linux/irqdomain.h>
> +
>  extern void __iomem *gic_cpu_base_addr;
>  extern struct irq_chip gic_arch_extn;
>  
> @@ -43,7 +45,6 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
>  void gic_enable_ppi(unsigned int);
>  
>  struct gic_chip_data {
> -	unsigned int irq_offset;
>  	void __iomem *dist_base;
>  	void __iomem *cpu_base;
>  #ifdef CONFIG_CPU_PM
> @@ -53,6 +54,7 @@ struct gic_chip_data {
>  	u32 __percpu *saved_ppi_enable;
>  	u32 __percpu *saved_ppi_conf;
>  #endif
> +	struct irq_domain domain;
>  	unsigned int gic_irqs;
>  };
>  #endif
> -- 
> 1.7.5.4
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
  2011-09-30 19:28   ` Rob Herring
@ 2011-10-04 23:44     ` Grant Likely
  -1 siblings, 0 replies; 68+ messages in thread
From: Grant Likely @ 2011-10-04 23:44 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-arm-kernel, devicetree-discuss, linux-kernel, marc.zyngier,
	thomas.abraham, jamie, b-cousson, shawn.guo, Rob Herring

On Fri, Sep 30, 2011 at 02:28:00PM -0500, Rob Herring wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> This adds ARM gic interrupt controller initialization using device tree
> data.
> 
> The initialization function is intended to be called by of_irq_init
> function like this:
> 
> const static struct of_device_id irq_match[] = {
> 	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
> 	{}
> };
> 
> static void __init init_irqs(void)
> {
> 	of_irq_init(irq_match);
> }
> 
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>

Acked-by: Grant Likely <grant.likely@secretlab.ca>

I think this series is pretty much ready to be merged other than the
comment on patch 1.  It should go through either rmk's patch system or
the arm-soc tree, but you'll need an ack from tglx first.

g.


> ---
>  Documentation/devicetree/bindings/arm/gic.txt |   55 ++++++++++++++++++++++
>  arch/arm/common/gic.c                         |   61 +++++++++++++++++++++++++
>  arch/arm/include/asm/hardware/gic.h           |    1 +
>  3 files changed, 117 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/gic.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
> new file mode 100644
> index 0000000..52916b4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/gic.txt
> @@ -0,0 +1,55 @@
> +* ARM Generic Interrupt Controller
> +
> +ARM SMP cores are often associated with a GIC, providing per processor
> +interrupts (PPI), shared processor interrupts (SPI) and software
> +generated interrupts (SGI).
> +
> +Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
> +Secondary GICs are cascaded into the upward interrupt controller and do not
> +have PPIs or SGIs.
> +
> +Main node required properties:
> +
> +- compatible : should be one of:
> +	"arm,cortex-a9-gic"
> +	"arm,arm11mp-gic"
> +- interrupt-controller : Identifies the node as an interrupt controller
> +- #interrupt-cells : Specifies the number of cells needed to encode an
> +  interrupt source.  The type shall be a <u32> and the value shall be 3.
> +
> +  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
> +  interrupts.
> +
> +  The 2nd cell contains the interrupt number for the interrupt type.
> +  SPI interrupts are in the range [0-987].  PPI interrupts are in the
> +  range [0-15].
> +
> +  The 3rd cell is the flags, encoded as follows:
> +	bits[3:0] trigger type and level flags.
> +		1 = low-to-high edge triggered
> +		2 = high-to-low edge triggered
> +		4 = active high level-sensitive
> +		8 = active low level-sensitive
> +	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
> +	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
> +	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
> +
> +- reg : Specifies base physical address(s) and size of the GIC registers. The
> +  first region is the GIC distributor register base and size. The 2nd region is
> +  the GIC cpu interface register base and size.
> +
> +Optional
> +- interrupts	: Interrupt source of the parent interrupt controller. Only
> +  present on secondary GICs.
> +
> +Example:
> +
> +	intc: interrupt-controller@fff11000 {
> +		compatible = "arm,cortex-a9-gic";
> +		#interrupt-cells = <3>;
> +		#address-cells = <1>;
> +		interrupt-controller;
> +		reg = <0xfff11000 0x1000>,
> +		      <0xfff10100 0x100>;
> +	};
> +
> diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
> index 6fbe1db..3e67970 100644
> --- a/arch/arm/common/gic.c
> +++ b/arch/arm/common/gic.c
> @@ -29,6 +29,9 @@
>  #include <linux/cpu_pm.h>
>  #include <linux/cpumask.h>
>  #include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
>  #include <linux/irqdomain.h>
>  
>  #include <asm/irq.h>
> @@ -518,7 +521,33 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
>  }
>  #endif
>  
> +#ifdef CONFIG_OF
> +static int gic_irq_domain_dt_translate(struct irq_domain *d,
> +				       struct device_node *controller,
> +				       const u32 *intspec, unsigned int intsize,
> +				       unsigned long *out_hwirq, unsigned int *out_type)
> +{
> +	if (d->of_node != controller)
> +		return -EINVAL;
> +	if (intsize < 3)
> +		return -EINVAL;
> +
> +	/* Get the interrupt number and add 16 to skip over SGIs */
> +	*out_hwirq = intspec[1] + 16;
> +
> +	/* For SPIs, we need to add 16 more to get the GIC irq ID number */
> +	if (!intspec[0])
> +		*out_hwirq += 16;
> +
> +	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
> +	return 0;
> +}
> +#endif
> +
>  const struct irq_domain_ops gic_irq_domain_ops = {
> +#ifdef CONFIG_OF
> +	.dt_translate = gic_irq_domain_dt_translate,
> +#endif
>  };
>  
>  void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
> @@ -606,3 +635,35 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
>  	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
>  }
>  #endif
> +
> +#ifdef CONFIG_OF
> +static int gic_cnt __initdata = 0;
> +
> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
> +{
> +	void __iomem *cpu_base;
> +	void __iomem *dist_base;
> +	int irq;
> +	struct irq_domain *domain = &gic_data[gic_cnt].domain;
> +
> +	if (WARN_ON(!node))
> +		return -ENODEV;
> +
> +	dist_base = of_iomap(node, 0);
> +	WARN(!dist_base, "unable to map gic dist registers\n");
> +
> +	cpu_base = of_iomap(node, 1);
> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
> +
> +	domain->of_node = of_node_get(node);
> +
> +	gic_init(gic_cnt, 16, dist_base, cpu_base);
> +
> +	if (parent) {
> +		irq = irq_of_parse_and_map(node, 0);
> +		gic_cascade_irq(gic_cnt, irq);
> +	}
> +	gic_cnt++;
> +	return 0;
> +}
> +#endif
> diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
> index ade84a4..1a776a1 100644
> --- a/arch/arm/include/asm/hardware/gic.h
> +++ b/arch/arm/include/asm/hardware/gic.h
> @@ -39,6 +39,7 @@ extern void __iomem *gic_cpu_base_addr;
>  extern struct irq_chip gic_arch_extn;
>  
>  void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
> +int gic_of_init(struct device_node *node, struct device_node *parent);
>  void gic_secondary_init(unsigned int);
>  void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
>  void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
> -- 
> 1.7.5.4
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-10-04 23:44     ` Grant Likely
  0 siblings, 0 replies; 68+ messages in thread
From: Grant Likely @ 2011-10-04 23:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Sep 30, 2011 at 02:28:00PM -0500, Rob Herring wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> This adds ARM gic interrupt controller initialization using device tree
> data.
> 
> The initialization function is intended to be called by of_irq_init
> function like this:
> 
> const static struct of_device_id irq_match[] = {
> 	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
> 	{}
> };
> 
> static void __init init_irqs(void)
> {
> 	of_irq_init(irq_match);
> }
> 
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>

Acked-by: Grant Likely <grant.likely@secretlab.ca>

I think this series is pretty much ready to be merged other than the
comment on patch 1.  It should go through either rmk's patch system or
the arm-soc tree, but you'll need an ack from tglx first.

g.


> ---
>  Documentation/devicetree/bindings/arm/gic.txt |   55 ++++++++++++++++++++++
>  arch/arm/common/gic.c                         |   61 +++++++++++++++++++++++++
>  arch/arm/include/asm/hardware/gic.h           |    1 +
>  3 files changed, 117 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/gic.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
> new file mode 100644
> index 0000000..52916b4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/gic.txt
> @@ -0,0 +1,55 @@
> +* ARM Generic Interrupt Controller
> +
> +ARM SMP cores are often associated with a GIC, providing per processor
> +interrupts (PPI), shared processor interrupts (SPI) and software
> +generated interrupts (SGI).
> +
> +Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
> +Secondary GICs are cascaded into the upward interrupt controller and do not
> +have PPIs or SGIs.
> +
> +Main node required properties:
> +
> +- compatible : should be one of:
> +	"arm,cortex-a9-gic"
> +	"arm,arm11mp-gic"
> +- interrupt-controller : Identifies the node as an interrupt controller
> +- #interrupt-cells : Specifies the number of cells needed to encode an
> +  interrupt source.  The type shall be a <u32> and the value shall be 3.
> +
> +  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
> +  interrupts.
> +
> +  The 2nd cell contains the interrupt number for the interrupt type.
> +  SPI interrupts are in the range [0-987].  PPI interrupts are in the
> +  range [0-15].
> +
> +  The 3rd cell is the flags, encoded as follows:
> +	bits[3:0] trigger type and level flags.
> +		1 = low-to-high edge triggered
> +		2 = high-to-low edge triggered
> +		4 = active high level-sensitive
> +		8 = active low level-sensitive
> +	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
> +	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
> +	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
> +
> +- reg : Specifies base physical address(s) and size of the GIC registers. The
> +  first region is the GIC distributor register base and size. The 2nd region is
> +  the GIC cpu interface register base and size.
> +
> +Optional
> +- interrupts	: Interrupt source of the parent interrupt controller. Only
> +  present on secondary GICs.
> +
> +Example:
> +
> +	intc: interrupt-controller at fff11000 {
> +		compatible = "arm,cortex-a9-gic";
> +		#interrupt-cells = <3>;
> +		#address-cells = <1>;
> +		interrupt-controller;
> +		reg = <0xfff11000 0x1000>,
> +		      <0xfff10100 0x100>;
> +	};
> +
> diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
> index 6fbe1db..3e67970 100644
> --- a/arch/arm/common/gic.c
> +++ b/arch/arm/common/gic.c
> @@ -29,6 +29,9 @@
>  #include <linux/cpu_pm.h>
>  #include <linux/cpumask.h>
>  #include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
>  #include <linux/irqdomain.h>
>  
>  #include <asm/irq.h>
> @@ -518,7 +521,33 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
>  }
>  #endif
>  
> +#ifdef CONFIG_OF
> +static int gic_irq_domain_dt_translate(struct irq_domain *d,
> +				       struct device_node *controller,
> +				       const u32 *intspec, unsigned int intsize,
> +				       unsigned long *out_hwirq, unsigned int *out_type)
> +{
> +	if (d->of_node != controller)
> +		return -EINVAL;
> +	if (intsize < 3)
> +		return -EINVAL;
> +
> +	/* Get the interrupt number and add 16 to skip over SGIs */
> +	*out_hwirq = intspec[1] + 16;
> +
> +	/* For SPIs, we need to add 16 more to get the GIC irq ID number */
> +	if (!intspec[0])
> +		*out_hwirq += 16;
> +
> +	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
> +	return 0;
> +}
> +#endif
> +
>  const struct irq_domain_ops gic_irq_domain_ops = {
> +#ifdef CONFIG_OF
> +	.dt_translate = gic_irq_domain_dt_translate,
> +#endif
>  };
>  
>  void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
> @@ -606,3 +635,35 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
>  	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
>  }
>  #endif
> +
> +#ifdef CONFIG_OF
> +static int gic_cnt __initdata = 0;
> +
> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
> +{
> +	void __iomem *cpu_base;
> +	void __iomem *dist_base;
> +	int irq;
> +	struct irq_domain *domain = &gic_data[gic_cnt].domain;
> +
> +	if (WARN_ON(!node))
> +		return -ENODEV;
> +
> +	dist_base = of_iomap(node, 0);
> +	WARN(!dist_base, "unable to map gic dist registers\n");
> +
> +	cpu_base = of_iomap(node, 1);
> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
> +
> +	domain->of_node = of_node_get(node);
> +
> +	gic_init(gic_cnt, 16, dist_base, cpu_base);
> +
> +	if (parent) {
> +		irq = irq_of_parse_and_map(node, 0);
> +		gic_cascade_irq(gic_cnt, irq);
> +	}
> +	gic_cnt++;
> +	return 0;
> +}
> +#endif
> diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
> index ade84a4..1a776a1 100644
> --- a/arch/arm/include/asm/hardware/gic.h
> +++ b/arch/arm/include/asm/hardware/gic.h
> @@ -39,6 +39,7 @@ extern void __iomem *gic_cpu_base_addr;
>  extern struct irq_chip gic_arch_extn;
>  
>  void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
> +int gic_of_init(struct device_node *node, struct device_node *parent);
>  void gic_secondary_init(unsigned int);
>  void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
>  void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
> -- 
> 1.7.5.4
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH v2] irq: support domains with non-zero hwirq base
  2011-10-04 23:39     ` Grant Likely
@ 2011-10-05  2:56       ` Rob Herring
  -1 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-10-05  2:56 UTC (permalink / raw)
  To: grant.likely, Thomas Gleixner; +Cc: linux-arm-kernel, linux-kernel, Rob Herring

From: Rob Herring <rob.herring@calxeda.com>

Interrupt controllers can have non-zero starting value for h/w irq numbers.
Adding support in irq_domain allows the domain hwirq numbering to match
the interrupt controllers' numbering.

As this makes looping over irqs for a domain more complicated, add loop
iterators to iterate over all hwirqs and irqs for a domain.

Acked-by: Grant Likely <grant.likely@secretlab.ca>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
Thomas,

Please ack. I'm dependent on this for adding Calxeda highbank support, so
I'd like to take this thru arm-soc tree.

v2:
- Rebase to tglx's changes in my previous irq domain commit:
irq: Fix check for already initialized irq_domain in irq_domain_add
- drop NO_IRQ and add WARN_ON in irq_domain_to_irq

Rob

 include/linux/irqdomain.h |   16 +++++++++++++++-
 kernel/irq/irqdomain.c    |   12 ++++++------
 2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 3ad553e..99834e58 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -47,6 +47,7 @@ struct irq_domain_ops {
  *            of the irq_domain is responsible for allocating the array of
  *            irq_desc structures.
  * @nr_irq: Number of irqs managed by the irq domain
+ * @hwirq_base: Starting number for hwirqs managed by the irq domain
  * @ops: pointer to irq_domain methods
  * @priv: private data pointer for use by owner.  Not touched by irq_domain
  *        core code.
@@ -57,6 +58,7 @@ struct irq_domain {
 	struct list_head list;
 	unsigned int irq_base;
 	unsigned int nr_irq;
+	unsigned int hwirq_base;
 	const struct irq_domain_ops *ops;
 	void *priv;
 	struct device_node *of_node;
@@ -72,9 +74,21 @@ struct irq_domain {
 static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
 					     unsigned long hwirq)
 {
-	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
+	if (d->ops->to_irq)
+		return d->ops->to_irq(d, hwirq);
+	if (WARN_ON(hwirq < d->hwirq_base))
+		return 0;
+	return d->irq_base + hwirq - d->hwirq_base;
 }
 
+#define irq_domain_for_each_hwirq(d, hw) \
+	for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++)
+
+#define irq_domain_for_each_irq(d, hw, irq) \
+	for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \
+	     hw < d->hwirq_base + d->nr_irq; \
+	     hw++, irq = irq_domain_to_irq(d, hw))
+
 extern void irq_domain_add(struct irq_domain *domain);
 extern void irq_domain_del(struct irq_domain *domain);
 #endif /* CONFIG_IRQ_DOMAIN */
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index b57a377..200ce83 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -20,15 +20,15 @@ static DEFINE_MUTEX(irq_domain_mutex);
 void irq_domain_add(struct irq_domain *domain)
 {
 	struct irq_data *d;
-	int hwirq;
+	int hwirq, irq;
 
 	/*
 	 * This assumes that the irq_domain owner has already allocated
 	 * the irq_descs.  This block will be removed when support for dynamic
 	 * allocation of irq_descs is added to irq_domain.
 	 */
-	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
-		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+	irq_domain_for_each_irq(domain, hwirq, irq) {
+		d = irq_get_irq_data(irq);
 		if (!d) {
 			WARN(1, "error: assigning domain to non existant irq_desc");
 			return;
@@ -54,15 +54,15 @@ void irq_domain_add(struct irq_domain *domain)
 void irq_domain_del(struct irq_domain *domain)
 {
 	struct irq_data *d;
-	int hwirq;
+	int hwirq, irq;
 
 	mutex_lock(&irq_domain_mutex);
 	list_del(&domain->list);
 	mutex_unlock(&irq_domain_mutex);
 
 	/* Clear the irq_domain assignments */
-	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
-		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+	irq_domain_for_each_irq(domain, hwirq, irq) {
+		d = irq_get_irq_data(irq);
 		d->domain = NULL;
 	}
 }
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH v2] irq: support domains with non-zero hwirq base
@ 2011-10-05  2:56       ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-10-05  2:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Rob Herring <rob.herring@calxeda.com>

Interrupt controllers can have non-zero starting value for h/w irq numbers.
Adding support in irq_domain allows the domain hwirq numbering to match
the interrupt controllers' numbering.

As this makes looping over irqs for a domain more complicated, add loop
iterators to iterate over all hwirqs and irqs for a domain.

Acked-by: Grant Likely <grant.likely@secretlab.ca>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
Thomas,

Please ack. I'm dependent on this for adding Calxeda highbank support, so
I'd like to take this thru arm-soc tree.

v2:
- Rebase to tglx's changes in my previous irq domain commit:
irq: Fix check for already initialized irq_domain in irq_domain_add
- drop NO_IRQ and add WARN_ON in irq_domain_to_irq

Rob

 include/linux/irqdomain.h |   16 +++++++++++++++-
 kernel/irq/irqdomain.c    |   12 ++++++------
 2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 3ad553e..99834e58 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -47,6 +47,7 @@ struct irq_domain_ops {
  *            of the irq_domain is responsible for allocating the array of
  *            irq_desc structures.
  * @nr_irq: Number of irqs managed by the irq domain
+ * @hwirq_base: Starting number for hwirqs managed by the irq domain
  * @ops: pointer to irq_domain methods
  * @priv: private data pointer for use by owner.  Not touched by irq_domain
  *        core code.
@@ -57,6 +58,7 @@ struct irq_domain {
 	struct list_head list;
 	unsigned int irq_base;
 	unsigned int nr_irq;
+	unsigned int hwirq_base;
 	const struct irq_domain_ops *ops;
 	void *priv;
 	struct device_node *of_node;
@@ -72,9 +74,21 @@ struct irq_domain {
 static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
 					     unsigned long hwirq)
 {
-	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
+	if (d->ops->to_irq)
+		return d->ops->to_irq(d, hwirq);
+	if (WARN_ON(hwirq < d->hwirq_base))
+		return 0;
+	return d->irq_base + hwirq - d->hwirq_base;
 }
 
+#define irq_domain_for_each_hwirq(d, hw) \
+	for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++)
+
+#define irq_domain_for_each_irq(d, hw, irq) \
+	for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \
+	     hw < d->hwirq_base + d->nr_irq; \
+	     hw++, irq = irq_domain_to_irq(d, hw))
+
 extern void irq_domain_add(struct irq_domain *domain);
 extern void irq_domain_del(struct irq_domain *domain);
 #endif /* CONFIG_IRQ_DOMAIN */
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index b57a377..200ce83 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -20,15 +20,15 @@ static DEFINE_MUTEX(irq_domain_mutex);
 void irq_domain_add(struct irq_domain *domain)
 {
 	struct irq_data *d;
-	int hwirq;
+	int hwirq, irq;
 
 	/*
 	 * This assumes that the irq_domain owner has already allocated
 	 * the irq_descs.  This block will be removed when support for dynamic
 	 * allocation of irq_descs is added to irq_domain.
 	 */
-	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
-		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+	irq_domain_for_each_irq(domain, hwirq, irq) {
+		d = irq_get_irq_data(irq);
 		if (!d) {
 			WARN(1, "error: assigning domain to non existant irq_desc");
 			return;
@@ -54,15 +54,15 @@ void irq_domain_add(struct irq_domain *domain)
 void irq_domain_del(struct irq_domain *domain)
 {
 	struct irq_data *d;
-	int hwirq;
+	int hwirq, irq;
 
 	mutex_lock(&irq_domain_mutex);
 	list_del(&domain->list);
 	mutex_unlock(&irq_domain_mutex);
 
 	/* Clear the irq_domain assignments */
-	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
-		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+	irq_domain_for_each_irq(domain, hwirq, irq) {
+		d = irq_get_irq_data(irq);
 		d->domain = NULL;
 	}
 }
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* Re: [PATCH 0/3] GIC OF bindings
  2011-09-30 19:27 ` Rob Herring
@ 2011-10-08 14:04   ` Thomas Abraham
  -1 siblings, 0 replies; 68+ messages in thread
From: Thomas Abraham @ 2011-10-08 14:04 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-arm-kernel, devicetree-discuss, linux-kernel, grant.likely,
	marc.zyngier, jamie, b-cousson, shawn.guo, Rob Herring

On 1 October 2011 00:57, Rob Herring <robherring2@gmail.com> wrote:
> From: Rob Herring <rob.herring@calxeda.com>
>
> Another round of GIC devicetree support.
>
> This moves the tracking of the starting hwirq number into the irq domain
> code. Doing this makes hwirq == GIC interrupt ID and simplifies the GIC
> code removing irq_offset.
>
> The full series is available here. This includes Russell's devel-stable and
> for-next branches and Nico's vmalloc branch:
>
> git://git.jdl.com/software/linux-3.0.git gic-v2
>
> Tested on highbank and Realview 11MPCore qemu (2 GICs).
>
> Rob
>
> Rob Herring (3):
>  irq: support domains with non-zero hwirq base
>  ARM: gic: add irq_domain support
>  ARM: gic: add OF based initialization

For Exynos4 GIC and Interrupt Combiner Controllers:

Tested-by: Thomas Abraham <thomas.abraham@linaro.org>

>
>  Documentation/devicetree/bindings/arm/gic.txt |   55 ++++++++++
>  arch/arm/common/Kconfig                       |    1 +
>  arch/arm/common/gic.c                         |  142 +++++++++++++++++++------
>  arch/arm/include/asm/hardware/gic.h           |    5 +-
>  include/linux/irqdomain.h                     |   16 +++-
>  kernel/irq/irqdomain.c                        |   12 +-
>  6 files changed, 189 insertions(+), 42 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/gic.txt
>
> --
> 1.7.5.4
>
>

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 0/3] GIC OF bindings
@ 2011-10-08 14:04   ` Thomas Abraham
  0 siblings, 0 replies; 68+ messages in thread
From: Thomas Abraham @ 2011-10-08 14:04 UTC (permalink / raw)
  To: linux-arm-kernel

On 1 October 2011 00:57, Rob Herring <robherring2@gmail.com> wrote:
> From: Rob Herring <rob.herring@calxeda.com>
>
> Another round of GIC devicetree support.
>
> This moves the tracking of the starting hwirq number into the irq domain
> code. Doing this makes hwirq == GIC interrupt ID and simplifies the GIC
> code removing irq_offset.
>
> The full series is available here. This includes Russell's devel-stable and
> for-next branches and Nico's vmalloc branch:
>
> git://git.jdl.com/software/linux-3.0.git gic-v2
>
> Tested on highbank and Realview 11MPCore qemu (2 GICs).
>
> Rob
>
> Rob Herring (3):
> ?irq: support domains with non-zero hwirq base
> ?ARM: gic: add irq_domain support
> ?ARM: gic: add OF based initialization

For Exynos4 GIC and Interrupt Combiner Controllers:

Tested-by: Thomas Abraham <thomas.abraham@linaro.org>

>
> ?Documentation/devicetree/bindings/arm/gic.txt | ? 55 ++++++++++
> ?arch/arm/common/Kconfig ? ? ? ? ? ? ? ? ? ? ? | ? ?1 +
> ?arch/arm/common/gic.c ? ? ? ? ? ? ? ? ? ? ? ? | ?142 +++++++++++++++++++------
> ?arch/arm/include/asm/hardware/gic.h ? ? ? ? ? | ? ?5 +-
> ?include/linux/irqdomain.h ? ? ? ? ? ? ? ? ? ? | ? 16 +++-
> ?kernel/irq/irqdomain.c ? ? ? ? ? ? ? ? ? ? ? ?| ? 12 +-
> ?6 files changed, 189 insertions(+), 42 deletions(-)
> ?create mode 100644 Documentation/devicetree/bindings/arm/gic.txt
>
> --
> 1.7.5.4
>
>

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v2] irq: support domains with non-zero hwirq base
  2011-10-05  2:56       ` Rob Herring
@ 2011-10-11 13:18         ` Rob Herring
  -1 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-10-11 13:18 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: grant.likely, linux-arm-kernel, linux-kernel

Thomas,

On 10/04/2011 09:56 PM, Rob Herring wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> Interrupt controllers can have non-zero starting value for h/w irq numbers.
> Adding support in irq_domain allows the domain hwirq numbering to match
> the interrupt controllers' numbering.
> 
> As this makes looping over irqs for a domain more complicated, add loop
> iterators to iterate over all hwirqs and irqs for a domain.
> 
> Acked-by: Grant Likely <grant.likely@secretlab.ca>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> ---
> Thomas,
> 
> Please ack. I'm dependent on this for adding Calxeda highbank support, so
> I'd like to take this thru arm-soc tree.
> 

Can you please comment?

Rob

> v2:
> - Rebase to tglx's changes in my previous irq domain commit:
> irq: Fix check for already initialized irq_domain in irq_domain_add
> - drop NO_IRQ and add WARN_ON in irq_domain_to_irq
> 
> Rob
> 
>  include/linux/irqdomain.h |   16 +++++++++++++++-
>  kernel/irq/irqdomain.c    |   12 ++++++------
>  2 files changed, 21 insertions(+), 7 deletions(-)
> 
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index 3ad553e..99834e58 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -47,6 +47,7 @@ struct irq_domain_ops {
>   *            of the irq_domain is responsible for allocating the array of
>   *            irq_desc structures.
>   * @nr_irq: Number of irqs managed by the irq domain
> + * @hwirq_base: Starting number for hwirqs managed by the irq domain
>   * @ops: pointer to irq_domain methods
>   * @priv: private data pointer for use by owner.  Not touched by irq_domain
>   *        core code.
> @@ -57,6 +58,7 @@ struct irq_domain {
>  	struct list_head list;
>  	unsigned int irq_base;
>  	unsigned int nr_irq;
> +	unsigned int hwirq_base;
>  	const struct irq_domain_ops *ops;
>  	void *priv;
>  	struct device_node *of_node;
> @@ -72,9 +74,21 @@ struct irq_domain {
>  static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
>  					     unsigned long hwirq)
>  {
> -	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
> +	if (d->ops->to_irq)
> +		return d->ops->to_irq(d, hwirq);
> +	if (WARN_ON(hwirq < d->hwirq_base))
> +		return 0;
> +	return d->irq_base + hwirq - d->hwirq_base;
>  }
>  
> +#define irq_domain_for_each_hwirq(d, hw) \
> +	for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++)
> +
> +#define irq_domain_for_each_irq(d, hw, irq) \
> +	for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \
> +	     hw < d->hwirq_base + d->nr_irq; \
> +	     hw++, irq = irq_domain_to_irq(d, hw))
> +
>  extern void irq_domain_add(struct irq_domain *domain);
>  extern void irq_domain_del(struct irq_domain *domain);
>  #endif /* CONFIG_IRQ_DOMAIN */
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index b57a377..200ce83 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -20,15 +20,15 @@ static DEFINE_MUTEX(irq_domain_mutex);
>  void irq_domain_add(struct irq_domain *domain)
>  {
>  	struct irq_data *d;
> -	int hwirq;
> +	int hwirq, irq;
>  
>  	/*
>  	 * This assumes that the irq_domain owner has already allocated
>  	 * the irq_descs.  This block will be removed when support for dynamic
>  	 * allocation of irq_descs is added to irq_domain.
>  	 */
> -	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
> -		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
> +	irq_domain_for_each_irq(domain, hwirq, irq) {
> +		d = irq_get_irq_data(irq);
>  		if (!d) {
>  			WARN(1, "error: assigning domain to non existant irq_desc");
>  			return;
> @@ -54,15 +54,15 @@ void irq_domain_add(struct irq_domain *domain)
>  void irq_domain_del(struct irq_domain *domain)
>  {
>  	struct irq_data *d;
> -	int hwirq;
> +	int hwirq, irq;
>  
>  	mutex_lock(&irq_domain_mutex);
>  	list_del(&domain->list);
>  	mutex_unlock(&irq_domain_mutex);
>  
>  	/* Clear the irq_domain assignments */
> -	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
> -		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
> +	irq_domain_for_each_irq(domain, hwirq, irq) {
> +		d = irq_get_irq_data(irq);
>  		d->domain = NULL;
>  	}
>  }


^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH v2] irq: support domains with non-zero hwirq base
@ 2011-10-11 13:18         ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-10-11 13:18 UTC (permalink / raw)
  To: linux-arm-kernel

Thomas,

On 10/04/2011 09:56 PM, Rob Herring wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> Interrupt controllers can have non-zero starting value for h/w irq numbers.
> Adding support in irq_domain allows the domain hwirq numbering to match
> the interrupt controllers' numbering.
> 
> As this makes looping over irqs for a domain more complicated, add loop
> iterators to iterate over all hwirqs and irqs for a domain.
> 
> Acked-by: Grant Likely <grant.likely@secretlab.ca>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> ---
> Thomas,
> 
> Please ack. I'm dependent on this for adding Calxeda highbank support, so
> I'd like to take this thru arm-soc tree.
> 

Can you please comment?

Rob

> v2:
> - Rebase to tglx's changes in my previous irq domain commit:
> irq: Fix check for already initialized irq_domain in irq_domain_add
> - drop NO_IRQ and add WARN_ON in irq_domain_to_irq
> 
> Rob
> 
>  include/linux/irqdomain.h |   16 +++++++++++++++-
>  kernel/irq/irqdomain.c    |   12 ++++++------
>  2 files changed, 21 insertions(+), 7 deletions(-)
> 
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index 3ad553e..99834e58 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -47,6 +47,7 @@ struct irq_domain_ops {
>   *            of the irq_domain is responsible for allocating the array of
>   *            irq_desc structures.
>   * @nr_irq: Number of irqs managed by the irq domain
> + * @hwirq_base: Starting number for hwirqs managed by the irq domain
>   * @ops: pointer to irq_domain methods
>   * @priv: private data pointer for use by owner.  Not touched by irq_domain
>   *        core code.
> @@ -57,6 +58,7 @@ struct irq_domain {
>  	struct list_head list;
>  	unsigned int irq_base;
>  	unsigned int nr_irq;
> +	unsigned int hwirq_base;
>  	const struct irq_domain_ops *ops;
>  	void *priv;
>  	struct device_node *of_node;
> @@ -72,9 +74,21 @@ struct irq_domain {
>  static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
>  					     unsigned long hwirq)
>  {
> -	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
> +	if (d->ops->to_irq)
> +		return d->ops->to_irq(d, hwirq);
> +	if (WARN_ON(hwirq < d->hwirq_base))
> +		return 0;
> +	return d->irq_base + hwirq - d->hwirq_base;
>  }
>  
> +#define irq_domain_for_each_hwirq(d, hw) \
> +	for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++)
> +
> +#define irq_domain_for_each_irq(d, hw, irq) \
> +	for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \
> +	     hw < d->hwirq_base + d->nr_irq; \
> +	     hw++, irq = irq_domain_to_irq(d, hw))
> +
>  extern void irq_domain_add(struct irq_domain *domain);
>  extern void irq_domain_del(struct irq_domain *domain);
>  #endif /* CONFIG_IRQ_DOMAIN */
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index b57a377..200ce83 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -20,15 +20,15 @@ static DEFINE_MUTEX(irq_domain_mutex);
>  void irq_domain_add(struct irq_domain *domain)
>  {
>  	struct irq_data *d;
> -	int hwirq;
> +	int hwirq, irq;
>  
>  	/*
>  	 * This assumes that the irq_domain owner has already allocated
>  	 * the irq_descs.  This block will be removed when support for dynamic
>  	 * allocation of irq_descs is added to irq_domain.
>  	 */
> -	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
> -		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
> +	irq_domain_for_each_irq(domain, hwirq, irq) {
> +		d = irq_get_irq_data(irq);
>  		if (!d) {
>  			WARN(1, "error: assigning domain to non existant irq_desc");
>  			return;
> @@ -54,15 +54,15 @@ void irq_domain_add(struct irq_domain *domain)
>  void irq_domain_del(struct irq_domain *domain)
>  {
>  	struct irq_data *d;
> -	int hwirq;
> +	int hwirq, irq;
>  
>  	mutex_lock(&irq_domain_mutex);
>  	list_del(&domain->list);
>  	mutex_unlock(&irq_domain_mutex);
>  
>  	/* Clear the irq_domain assignments */
> -	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
> -		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
> +	irq_domain_for_each_irq(domain, hwirq, irq) {
> +		d = irq_get_irq_data(irq);
>  		d->domain = NULL;
>  	}
>  }

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v2] irq: support domains with non-zero hwirq base
  2011-10-11 13:18         ` Rob Herring
@ 2011-10-13 19:33           ` Grant Likely
  -1 siblings, 0 replies; 68+ messages in thread
From: Grant Likely @ 2011-10-13 19:33 UTC (permalink / raw)
  To: Rob Herring, Thomas Gleixner; +Cc: linux-arm-kernel, linux-kernel

Thomas, any objection to this patch?  It's entirely contained within
the irq_domain stuff, so it is pretty well isolated.

It can be merged via arm-soc since it is depended on by some of the
irq work.

g.

On Tue, Oct 11, 2011 at 08:18:58AM -0500, Rob Herring wrote:
> Thomas,
> 
> On 10/04/2011 09:56 PM, Rob Herring wrote:
> > From: Rob Herring <rob.herring@calxeda.com>
> > 
> > Interrupt controllers can have non-zero starting value for h/w irq numbers.
> > Adding support in irq_domain allows the domain hwirq numbering to match
> > the interrupt controllers' numbering.
> > 
> > As this makes looping over irqs for a domain more complicated, add loop
> > iterators to iterate over all hwirqs and irqs for a domain.
> > 
> > Acked-by: Grant Likely <grant.likely@secretlab.ca>
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> > ---
> > Thomas,
> > 
> > Please ack. I'm dependent on this for adding Calxeda highbank support, so
> > I'd like to take this thru arm-soc tree.
> > 
> 
> Can you please comment?
> 
> Rob
> 
> > v2:
> > - Rebase to tglx's changes in my previous irq domain commit:
> > irq: Fix check for already initialized irq_domain in irq_domain_add
> > - drop NO_IRQ and add WARN_ON in irq_domain_to_irq
> > 
> > Rob
> > 
> >  include/linux/irqdomain.h |   16 +++++++++++++++-
> >  kernel/irq/irqdomain.c    |   12 ++++++------
> >  2 files changed, 21 insertions(+), 7 deletions(-)
> > 
> > diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> > index 3ad553e..99834e58 100644
> > --- a/include/linux/irqdomain.h
> > +++ b/include/linux/irqdomain.h
> > @@ -47,6 +47,7 @@ struct irq_domain_ops {
> >   *            of the irq_domain is responsible for allocating the array of
> >   *            irq_desc structures.
> >   * @nr_irq: Number of irqs managed by the irq domain
> > + * @hwirq_base: Starting number for hwirqs managed by the irq domain
> >   * @ops: pointer to irq_domain methods
> >   * @priv: private data pointer for use by owner.  Not touched by irq_domain
> >   *        core code.
> > @@ -57,6 +58,7 @@ struct irq_domain {
> >  	struct list_head list;
> >  	unsigned int irq_base;
> >  	unsigned int nr_irq;
> > +	unsigned int hwirq_base;
> >  	const struct irq_domain_ops *ops;
> >  	void *priv;
> >  	struct device_node *of_node;
> > @@ -72,9 +74,21 @@ struct irq_domain {
> >  static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
> >  					     unsigned long hwirq)
> >  {
> > -	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
> > +	if (d->ops->to_irq)
> > +		return d->ops->to_irq(d, hwirq);
> > +	if (WARN_ON(hwirq < d->hwirq_base))
> > +		return 0;
> > +	return d->irq_base + hwirq - d->hwirq_base;
> >  }
> >  
> > +#define irq_domain_for_each_hwirq(d, hw) \
> > +	for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++)
> > +
> > +#define irq_domain_for_each_irq(d, hw, irq) \
> > +	for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \
> > +	     hw < d->hwirq_base + d->nr_irq; \
> > +	     hw++, irq = irq_domain_to_irq(d, hw))
> > +
> >  extern void irq_domain_add(struct irq_domain *domain);
> >  extern void irq_domain_del(struct irq_domain *domain);
> >  #endif /* CONFIG_IRQ_DOMAIN */
> > diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> > index b57a377..200ce83 100644
> > --- a/kernel/irq/irqdomain.c
> > +++ b/kernel/irq/irqdomain.c
> > @@ -20,15 +20,15 @@ static DEFINE_MUTEX(irq_domain_mutex);
> >  void irq_domain_add(struct irq_domain *domain)
> >  {
> >  	struct irq_data *d;
> > -	int hwirq;
> > +	int hwirq, irq;
> >  
> >  	/*
> >  	 * This assumes that the irq_domain owner has already allocated
> >  	 * the irq_descs.  This block will be removed when support for dynamic
> >  	 * allocation of irq_descs is added to irq_domain.
> >  	 */
> > -	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
> > -		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
> > +	irq_domain_for_each_irq(domain, hwirq, irq) {
> > +		d = irq_get_irq_data(irq);
> >  		if (!d) {
> >  			WARN(1, "error: assigning domain to non existant irq_desc");
> >  			return;
> > @@ -54,15 +54,15 @@ void irq_domain_add(struct irq_domain *domain)
> >  void irq_domain_del(struct irq_domain *domain)
> >  {
> >  	struct irq_data *d;
> > -	int hwirq;
> > +	int hwirq, irq;
> >  
> >  	mutex_lock(&irq_domain_mutex);
> >  	list_del(&domain->list);
> >  	mutex_unlock(&irq_domain_mutex);
> >  
> >  	/* Clear the irq_domain assignments */
> > -	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
> > -		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
> > +	irq_domain_for_each_irq(domain, hwirq, irq) {
> > +		d = irq_get_irq_data(irq);
> >  		d->domain = NULL;
> >  	}
> >  }
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH v2] irq: support domains with non-zero hwirq base
@ 2011-10-13 19:33           ` Grant Likely
  0 siblings, 0 replies; 68+ messages in thread
From: Grant Likely @ 2011-10-13 19:33 UTC (permalink / raw)
  To: linux-arm-kernel

Thomas, any objection to this patch?  It's entirely contained within
the irq_domain stuff, so it is pretty well isolated.

It can be merged via arm-soc since it is depended on by some of the
irq work.

g.

On Tue, Oct 11, 2011 at 08:18:58AM -0500, Rob Herring wrote:
> Thomas,
> 
> On 10/04/2011 09:56 PM, Rob Herring wrote:
> > From: Rob Herring <rob.herring@calxeda.com>
> > 
> > Interrupt controllers can have non-zero starting value for h/w irq numbers.
> > Adding support in irq_domain allows the domain hwirq numbering to match
> > the interrupt controllers' numbering.
> > 
> > As this makes looping over irqs for a domain more complicated, add loop
> > iterators to iterate over all hwirqs and irqs for a domain.
> > 
> > Acked-by: Grant Likely <grant.likely@secretlab.ca>
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> > ---
> > Thomas,
> > 
> > Please ack. I'm dependent on this for adding Calxeda highbank support, so
> > I'd like to take this thru arm-soc tree.
> > 
> 
> Can you please comment?
> 
> Rob
> 
> > v2:
> > - Rebase to tglx's changes in my previous irq domain commit:
> > irq: Fix check for already initialized irq_domain in irq_domain_add
> > - drop NO_IRQ and add WARN_ON in irq_domain_to_irq
> > 
> > Rob
> > 
> >  include/linux/irqdomain.h |   16 +++++++++++++++-
> >  kernel/irq/irqdomain.c    |   12 ++++++------
> >  2 files changed, 21 insertions(+), 7 deletions(-)
> > 
> > diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> > index 3ad553e..99834e58 100644
> > --- a/include/linux/irqdomain.h
> > +++ b/include/linux/irqdomain.h
> > @@ -47,6 +47,7 @@ struct irq_domain_ops {
> >   *            of the irq_domain is responsible for allocating the array of
> >   *            irq_desc structures.
> >   * @nr_irq: Number of irqs managed by the irq domain
> > + * @hwirq_base: Starting number for hwirqs managed by the irq domain
> >   * @ops: pointer to irq_domain methods
> >   * @priv: private data pointer for use by owner.  Not touched by irq_domain
> >   *        core code.
> > @@ -57,6 +58,7 @@ struct irq_domain {
> >  	struct list_head list;
> >  	unsigned int irq_base;
> >  	unsigned int nr_irq;
> > +	unsigned int hwirq_base;
> >  	const struct irq_domain_ops *ops;
> >  	void *priv;
> >  	struct device_node *of_node;
> > @@ -72,9 +74,21 @@ struct irq_domain {
> >  static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
> >  					     unsigned long hwirq)
> >  {
> > -	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
> > +	if (d->ops->to_irq)
> > +		return d->ops->to_irq(d, hwirq);
> > +	if (WARN_ON(hwirq < d->hwirq_base))
> > +		return 0;
> > +	return d->irq_base + hwirq - d->hwirq_base;
> >  }
> >  
> > +#define irq_domain_for_each_hwirq(d, hw) \
> > +	for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++)
> > +
> > +#define irq_domain_for_each_irq(d, hw, irq) \
> > +	for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \
> > +	     hw < d->hwirq_base + d->nr_irq; \
> > +	     hw++, irq = irq_domain_to_irq(d, hw))
> > +
> >  extern void irq_domain_add(struct irq_domain *domain);
> >  extern void irq_domain_del(struct irq_domain *domain);
> >  #endif /* CONFIG_IRQ_DOMAIN */
> > diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> > index b57a377..200ce83 100644
> > --- a/kernel/irq/irqdomain.c
> > +++ b/kernel/irq/irqdomain.c
> > @@ -20,15 +20,15 @@ static DEFINE_MUTEX(irq_domain_mutex);
> >  void irq_domain_add(struct irq_domain *domain)
> >  {
> >  	struct irq_data *d;
> > -	int hwirq;
> > +	int hwirq, irq;
> >  
> >  	/*
> >  	 * This assumes that the irq_domain owner has already allocated
> >  	 * the irq_descs.  This block will be removed when support for dynamic
> >  	 * allocation of irq_descs is added to irq_domain.
> >  	 */
> > -	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
> > -		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
> > +	irq_domain_for_each_irq(domain, hwirq, irq) {
> > +		d = irq_get_irq_data(irq);
> >  		if (!d) {
> >  			WARN(1, "error: assigning domain to non existant irq_desc");
> >  			return;
> > @@ -54,15 +54,15 @@ void irq_domain_add(struct irq_domain *domain)
> >  void irq_domain_del(struct irq_domain *domain)
> >  {
> >  	struct irq_data *d;
> > -	int hwirq;
> > +	int hwirq, irq;
> >  
> >  	mutex_lock(&irq_domain_mutex);
> >  	list_del(&domain->list);
> >  	mutex_unlock(&irq_domain_mutex);
> >  
> >  	/* Clear the irq_domain assignments */
> > -	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
> > -		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
> > +	irq_domain_for_each_irq(domain, hwirq, irq) {
> > +		d = irq_get_irq_data(irq);
> >  		d->domain = NULL;
> >  	}
> >  }
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH v2] irq: support domains with non-zero hwirq base
  2011-10-13 19:33           ` Grant Likely
@ 2011-10-13 20:12             ` Thomas Gleixner
  -1 siblings, 0 replies; 68+ messages in thread
From: Thomas Gleixner @ 2011-10-13 20:12 UTC (permalink / raw)
  To: Grant Likely; +Cc: Rob Herring, linux-arm-kernel, linux-kernel

On Thu, 13 Oct 2011, Grant Likely wrote:

> Thomas, any objection to this patch?  It's entirely contained within
> the irq_domain stuff, so it is pretty well isolated.
> 
> It can be merged via arm-soc since it is depended on by some of the
> irq work.
 
Acked-by-me

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH v2] irq: support domains with non-zero hwirq base
@ 2011-10-13 20:12             ` Thomas Gleixner
  0 siblings, 0 replies; 68+ messages in thread
From: Thomas Gleixner @ 2011-10-13 20:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 13 Oct 2011, Grant Likely wrote:

> Thomas, any objection to this patch?  It's entirely contained within
> the irq_domain stuff, so it is pretty well isolated.
> 
> It can be merged via arm-soc since it is depended on by some of the
> irq work.
 
Acked-by-me

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-26 22:29     ` Jamie Iles
  0 siblings, 0 replies; 68+ messages in thread
From: Jamie Iles @ 2011-09-26 22:29 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-arm-kernel, devicetree-discuss, linux-kernel, grant.likely,
	marc.zyngier, thomas.abraham, jamie, b-cousson, shawn.guo,
	dave.martin, linux, Rob Herring

Hi Rob,

Apologies for the noise!  One minor comment below.

Jamie

On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> This adds ARM gic interrupt controller initialization using device tree
> data.
> 
> The initialization function is intended to be called by of_irq_init
> function like this:
> 
> const static struct of_device_id irq_match[] = {
>         { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
>         {}
> };
> 
> static void __init init_irqs(void)
> {
>         of_irq_init(irq_match);
> }
> 
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> ---
[...]
> diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
> index 435d3f8..2862d0e 100644
> --- a/arch/arm/include/asm/hardware/gic.h
> +++ b/arch/arm/include/asm/hardware/gic.h
> @@ -33,10 +33,21 @@
>  #define GIC_DIST_SOFTINT		0xf00
>  
>  #ifndef __ASSEMBLY__
> +#include <linux/irqdomain.h>
> +
>  extern void __iomem *gic_cpu_base_addr;
>  extern struct irq_chip gic_arch_extn;
>  
>  void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
> +#ifdef CONFIG_OF
> +int gic_of_init(struct device_node *node, struct device_node *parent);
> +#else
> +static inline void gic_of_init(struct device_node *node,
> +			       struct device_node *parent)

This should return int?

> +{
> +	return -ENODEV;
> +}
> +#endif

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-26 22:29     ` Jamie Iles
  0 siblings, 0 replies; 68+ messages in thread
From: Jamie Iles @ 2011-09-26 22:29 UTC (permalink / raw)
  To: Rob Herring
  Cc: dave.martin-QSEj5FYQhm4dnm+yROfE0A, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi Rob,

Apologies for the noise!  One minor comment below.

Jamie

On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
> From: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
> 
> This adds ARM gic interrupt controller initialization using device tree
> data.
> 
> The initialization function is intended to be called by of_irq_init
> function like this:
> 
> const static struct of_device_id irq_match[] = {
>         { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
>         {}
> };
> 
> static void __init init_irqs(void)
> {
>         of_irq_init(irq_match);
> }
> 
> Signed-off-by: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
> ---
[...]
> diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
> index 435d3f8..2862d0e 100644
> --- a/arch/arm/include/asm/hardware/gic.h
> +++ b/arch/arm/include/asm/hardware/gic.h
> @@ -33,10 +33,21 @@
>  #define GIC_DIST_SOFTINT		0xf00
>  
>  #ifndef __ASSEMBLY__
> +#include <linux/irqdomain.h>
> +
>  extern void __iomem *gic_cpu_base_addr;
>  extern struct irq_chip gic_arch_extn;
>  
>  void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
> +#ifdef CONFIG_OF
> +int gic_of_init(struct device_node *node, struct device_node *parent);
> +#else
> +static inline void gic_of_init(struct device_node *node,
> +			       struct device_node *parent)

This should return int?

> +{
> +	return -ENODEV;
> +}
> +#endif

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-26 22:29     ` Jamie Iles
  0 siblings, 0 replies; 68+ messages in thread
From: Jamie Iles @ 2011-09-26 22:29 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Rob,

Apologies for the noise!  One minor comment below.

Jamie

On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> This adds ARM gic interrupt controller initialization using device tree
> data.
> 
> The initialization function is intended to be called by of_irq_init
> function like this:
> 
> const static struct of_device_id irq_match[] = {
>         { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
>         {}
> };
> 
> static void __init init_irqs(void)
> {
>         of_irq_init(irq_match);
> }
> 
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> ---
[...]
> diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
> index 435d3f8..2862d0e 100644
> --- a/arch/arm/include/asm/hardware/gic.h
> +++ b/arch/arm/include/asm/hardware/gic.h
> @@ -33,10 +33,21 @@
>  #define GIC_DIST_SOFTINT		0xf00
>  
>  #ifndef __ASSEMBLY__
> +#include <linux/irqdomain.h>
> +
>  extern void __iomem *gic_cpu_base_addr;
>  extern struct irq_chip gic_arch_extn;
>  
>  void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
> +#ifdef CONFIG_OF
> +int gic_of_init(struct device_node *node, struct device_node *parent);
> +#else
> +static inline void gic_of_init(struct device_node *node,
> +			       struct device_node *parent)

This should return int?

> +{
> +	return -ENODEV;
> +}
> +#endif

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
  2011-09-26 21:32           ` Rob Herring
@ 2011-09-26 22:00             ` Jamie Iles
  -1 siblings, 0 replies; 68+ messages in thread
From: Jamie Iles @ 2011-09-26 22:00 UTC (permalink / raw)
  To: Rob Herring
  Cc: Jamie Iles, linux-arm-kernel, devicetree-discuss, linux-kernel,
	grant.likely, marc.zyngier, thomas.abraham, b-cousson, shawn.guo,
	dave.martin, linux, Rob Herring

On Mon, Sep 26, 2011 at 04:32:17PM -0500, Rob Herring wrote:
> On 09/26/2011 04:11 PM, Jamie Iles wrote:
> > On Mon, Sep 26, 2011 at 03:49:11PM -0500, Rob Herring wrote:
> >> On 09/26/2011 02:57 PM, Jamie Iles wrote:
> >>> Hi Rob,
> >>>
> >>> On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
> >>> [...]
> >>>> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
> >>>> +{
> >>>> +	void __iomem *cpu_base;
> >>>> +	void __iomem *dist_base;
> >>>> +	int irq;
> >>>> +	struct irq_domain *domain = &gic_data[gic_cnt].domain;
> >>>> +
> >>>> +	if (WARN_ON(!node))
> >>>> +		return -ENODEV;
> >>>> +
> >>>> +	dist_base = of_iomap(node, 0);
> >>>> +	WARN(!dist_base, "unable to map gic dist registers\n");
> >>>> +
> >>>> +	cpu_base = of_iomap(node, 1);
> >>>> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
> >>>> +
> >>>> +	domain->nr_irq = gic_irq_count(dist_base);
> >>>> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
> >>>> +	if (parent)
> >>>> +		domain->nr_irq -= 32;
> >>>> +	else
> >>>> +		domain->nr_irq -= 16;
> >>>> +
> >>>> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
> >>>
> >>> The way I understand irq_alloc_descs() (probably not very well) is that 
> >>> having the irq parameter < 0 and the from parameter 16 means that it 
> >>> needs to find domain->nr_irq descs starting from at least 16.  But if 
> >>> the base is greater than 16, does this still work with the gic entry 
> >>> macros as they are?
> >>
> >> No, but that would only happen if a platform calls irq_alloc_descs prior
> >> to this code. The root controller must be initialized first (for other
> >> reasons as well). There are no calls to irq_alloc_descs in arch/arm.
> >>
> >> With the MULTI_IRQ GIC support Marc Z is working on, we could make the
> >> GIC irq mapping be completely dynamic. Although, there's probably not
> >> much reason to do so for the root controller.
> > 
> > OK, that makes sense.  I think that if you were to do 
> > irq_alloc_descs(16, 16, domain->nr_irqs, num_node_id()) then that will 
> > guarantee the descriptors start from 16 (if they are available) which is 
> > probably nicer.
> > 
> That would break secondary GICs though as it would always fail. For
> secondary GIC, we skip SGIs and PPIs and allocate the first available
> block of irq_desc's.

Ahh, OK that makes sense.  Thanks for the explanation Rob!  That'll 
hopefully help me with a common VIC binding.

Jamie

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-26 22:00             ` Jamie Iles
  0 siblings, 0 replies; 68+ messages in thread
From: Jamie Iles @ 2011-09-26 22:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Sep 26, 2011 at 04:32:17PM -0500, Rob Herring wrote:
> On 09/26/2011 04:11 PM, Jamie Iles wrote:
> > On Mon, Sep 26, 2011 at 03:49:11PM -0500, Rob Herring wrote:
> >> On 09/26/2011 02:57 PM, Jamie Iles wrote:
> >>> Hi Rob,
> >>>
> >>> On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
> >>> [...]
> >>>> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
> >>>> +{
> >>>> +	void __iomem *cpu_base;
> >>>> +	void __iomem *dist_base;
> >>>> +	int irq;
> >>>> +	struct irq_domain *domain = &gic_data[gic_cnt].domain;
> >>>> +
> >>>> +	if (WARN_ON(!node))
> >>>> +		return -ENODEV;
> >>>> +
> >>>> +	dist_base = of_iomap(node, 0);
> >>>> +	WARN(!dist_base, "unable to map gic dist registers\n");
> >>>> +
> >>>> +	cpu_base = of_iomap(node, 1);
> >>>> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
> >>>> +
> >>>> +	domain->nr_irq = gic_irq_count(dist_base);
> >>>> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
> >>>> +	if (parent)
> >>>> +		domain->nr_irq -= 32;
> >>>> +	else
> >>>> +		domain->nr_irq -= 16;
> >>>> +
> >>>> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
> >>>
> >>> The way I understand irq_alloc_descs() (probably not very well) is that 
> >>> having the irq parameter < 0 and the from parameter 16 means that it 
> >>> needs to find domain->nr_irq descs starting from at least 16.  But if 
> >>> the base is greater than 16, does this still work with the gic entry 
> >>> macros as they are?
> >>
> >> No, but that would only happen if a platform calls irq_alloc_descs prior
> >> to this code. The root controller must be initialized first (for other
> >> reasons as well). There are no calls to irq_alloc_descs in arch/arm.
> >>
> >> With the MULTI_IRQ GIC support Marc Z is working on, we could make the
> >> GIC irq mapping be completely dynamic. Although, there's probably not
> >> much reason to do so for the root controller.
> > 
> > OK, that makes sense.  I think that if you were to do 
> > irq_alloc_descs(16, 16, domain->nr_irqs, num_node_id()) then that will 
> > guarantee the descriptors start from 16 (if they are available) which is 
> > probably nicer.
> > 
> That would break secondary GICs though as it would always fail. For
> secondary GIC, we skip SGIs and PPIs and allocate the first available
> block of irq_desc's.

Ahh, OK that makes sense.  Thanks for the explanation Rob!  That'll 
hopefully help me with a common VIC binding.

Jamie

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
  2011-09-26 21:11         ` Jamie Iles
  (?)
@ 2011-09-26 21:32           ` Rob Herring
  -1 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-26 21:32 UTC (permalink / raw)
  To: Jamie Iles
  Cc: linux-arm-kernel, devicetree-discuss, linux-kernel, grant.likely,
	marc.zyngier, thomas.abraham, b-cousson, shawn.guo, dave.martin,
	linux, Rob Herring

On 09/26/2011 04:11 PM, Jamie Iles wrote:
> On Mon, Sep 26, 2011 at 03:49:11PM -0500, Rob Herring wrote:
>> On 09/26/2011 02:57 PM, Jamie Iles wrote:
>>> Hi Rob,
>>>
>>> On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
>>> [...]
>>>> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
>>>> +{
>>>> +	void __iomem *cpu_base;
>>>> +	void __iomem *dist_base;
>>>> +	int irq;
>>>> +	struct irq_domain *domain = &gic_data[gic_cnt].domain;
>>>> +
>>>> +	if (WARN_ON(!node))
>>>> +		return -ENODEV;
>>>> +
>>>> +	dist_base = of_iomap(node, 0);
>>>> +	WARN(!dist_base, "unable to map gic dist registers\n");
>>>> +
>>>> +	cpu_base = of_iomap(node, 1);
>>>> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
>>>> +
>>>> +	domain->nr_irq = gic_irq_count(dist_base);
>>>> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
>>>> +	if (parent)
>>>> +		domain->nr_irq -= 32;
>>>> +	else
>>>> +		domain->nr_irq -= 16;
>>>> +
>>>> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
>>>
>>> The way I understand irq_alloc_descs() (probably not very well) is that 
>>> having the irq parameter < 0 and the from parameter 16 means that it 
>>> needs to find domain->nr_irq descs starting from at least 16.  But if 
>>> the base is greater than 16, does this still work with the gic entry 
>>> macros as they are?
>>
>> No, but that would only happen if a platform calls irq_alloc_descs prior
>> to this code. The root controller must be initialized first (for other
>> reasons as well). There are no calls to irq_alloc_descs in arch/arm.
>>
>> With the MULTI_IRQ GIC support Marc Z is working on, we could make the
>> GIC irq mapping be completely dynamic. Although, there's probably not
>> much reason to do so for the root controller.
> 
> OK, that makes sense.  I think that if you were to do 
> irq_alloc_descs(16, 16, domain->nr_irqs, num_node_id()) then that will 
> guarantee the descriptors start from 16 (if they are available) which is 
> probably nicer.
> 
That would break secondary GICs though as it would always fail. For
secondary GIC, we skip SGIs and PPIs and allocate the first available
block of irq_desc's.

Rob

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-26 21:32           ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-26 21:32 UTC (permalink / raw)
  To: Jamie Iles
  Cc: dave.martin-QSEj5FYQhm4dnm+yROfE0A, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On 09/26/2011 04:11 PM, Jamie Iles wrote:
> On Mon, Sep 26, 2011 at 03:49:11PM -0500, Rob Herring wrote:
>> On 09/26/2011 02:57 PM, Jamie Iles wrote:
>>> Hi Rob,
>>>
>>> On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
>>> [...]
>>>> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
>>>> +{
>>>> +	void __iomem *cpu_base;
>>>> +	void __iomem *dist_base;
>>>> +	int irq;
>>>> +	struct irq_domain *domain = &gic_data[gic_cnt].domain;
>>>> +
>>>> +	if (WARN_ON(!node))
>>>> +		return -ENODEV;
>>>> +
>>>> +	dist_base = of_iomap(node, 0);
>>>> +	WARN(!dist_base, "unable to map gic dist registers\n");
>>>> +
>>>> +	cpu_base = of_iomap(node, 1);
>>>> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
>>>> +
>>>> +	domain->nr_irq = gic_irq_count(dist_base);
>>>> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
>>>> +	if (parent)
>>>> +		domain->nr_irq -= 32;
>>>> +	else
>>>> +		domain->nr_irq -= 16;
>>>> +
>>>> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
>>>
>>> The way I understand irq_alloc_descs() (probably not very well) is that 
>>> having the irq parameter < 0 and the from parameter 16 means that it 
>>> needs to find domain->nr_irq descs starting from at least 16.  But if 
>>> the base is greater than 16, does this still work with the gic entry 
>>> macros as they are?
>>
>> No, but that would only happen if a platform calls irq_alloc_descs prior
>> to this code. The root controller must be initialized first (for other
>> reasons as well). There are no calls to irq_alloc_descs in arch/arm.
>>
>> With the MULTI_IRQ GIC support Marc Z is working on, we could make the
>> GIC irq mapping be completely dynamic. Although, there's probably not
>> much reason to do so for the root controller.
> 
> OK, that makes sense.  I think that if you were to do 
> irq_alloc_descs(16, 16, domain->nr_irqs, num_node_id()) then that will 
> guarantee the descriptors start from 16 (if they are available) which is 
> probably nicer.
> 
That would break secondary GICs though as it would always fail. For
secondary GIC, we skip SGIs and PPIs and allocate the first available
block of irq_desc's.

Rob

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-26 21:32           ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-26 21:32 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/26/2011 04:11 PM, Jamie Iles wrote:
> On Mon, Sep 26, 2011 at 03:49:11PM -0500, Rob Herring wrote:
>> On 09/26/2011 02:57 PM, Jamie Iles wrote:
>>> Hi Rob,
>>>
>>> On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
>>> [...]
>>>> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
>>>> +{
>>>> +	void __iomem *cpu_base;
>>>> +	void __iomem *dist_base;
>>>> +	int irq;
>>>> +	struct irq_domain *domain = &gic_data[gic_cnt].domain;
>>>> +
>>>> +	if (WARN_ON(!node))
>>>> +		return -ENODEV;
>>>> +
>>>> +	dist_base = of_iomap(node, 0);
>>>> +	WARN(!dist_base, "unable to map gic dist registers\n");
>>>> +
>>>> +	cpu_base = of_iomap(node, 1);
>>>> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
>>>> +
>>>> +	domain->nr_irq = gic_irq_count(dist_base);
>>>> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
>>>> +	if (parent)
>>>> +		domain->nr_irq -= 32;
>>>> +	else
>>>> +		domain->nr_irq -= 16;
>>>> +
>>>> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
>>>
>>> The way I understand irq_alloc_descs() (probably not very well) is that 
>>> having the irq parameter < 0 and the from parameter 16 means that it 
>>> needs to find domain->nr_irq descs starting from at least 16.  But if 
>>> the base is greater than 16, does this still work with the gic entry 
>>> macros as they are?
>>
>> No, but that would only happen if a platform calls irq_alloc_descs prior
>> to this code. The root controller must be initialized first (for other
>> reasons as well). There are no calls to irq_alloc_descs in arch/arm.
>>
>> With the MULTI_IRQ GIC support Marc Z is working on, we could make the
>> GIC irq mapping be completely dynamic. Although, there's probably not
>> much reason to do so for the root controller.
> 
> OK, that makes sense.  I think that if you were to do 
> irq_alloc_descs(16, 16, domain->nr_irqs, num_node_id()) then that will 
> guarantee the descriptors start from 16 (if they are available) which is 
> probably nicer.
> 
That would break secondary GICs though as it would always fail. For
secondary GIC, we skip SGIs and PPIs and allocate the first available
block of irq_desc's.

Rob

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-26 21:11         ` Jamie Iles
  0 siblings, 0 replies; 68+ messages in thread
From: Jamie Iles @ 2011-09-26 21:11 UTC (permalink / raw)
  To: Rob Herring
  Cc: Jamie Iles, linux-arm-kernel, devicetree-discuss, linux-kernel,
	grant.likely, marc.zyngier, thomas.abraham, b-cousson, shawn.guo,
	dave.martin, linux, Rob Herring

On Mon, Sep 26, 2011 at 03:49:11PM -0500, Rob Herring wrote:
> On 09/26/2011 02:57 PM, Jamie Iles wrote:
> > Hi Rob,
> > 
> > On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
> > [...]
> >> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
> >> +{
> >> +	void __iomem *cpu_base;
> >> +	void __iomem *dist_base;
> >> +	int irq;
> >> +	struct irq_domain *domain = &gic_data[gic_cnt].domain;
> >> +
> >> +	if (WARN_ON(!node))
> >> +		return -ENODEV;
> >> +
> >> +	dist_base = of_iomap(node, 0);
> >> +	WARN(!dist_base, "unable to map gic dist registers\n");
> >> +
> >> +	cpu_base = of_iomap(node, 1);
> >> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
> >> +
> >> +	domain->nr_irq = gic_irq_count(dist_base);
> >> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
> >> +	if (parent)
> >> +		domain->nr_irq -= 32;
> >> +	else
> >> +		domain->nr_irq -= 16;
> >> +
> >> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
> > 
> > The way I understand irq_alloc_descs() (probably not very well) is that 
> > having the irq parameter < 0 and the from parameter 16 means that it 
> > needs to find domain->nr_irq descs starting from at least 16.  But if 
> > the base is greater than 16, does this still work with the gic entry 
> > macros as they are?
> 
> No, but that would only happen if a platform calls irq_alloc_descs prior
> to this code. The root controller must be initialized first (for other
> reasons as well). There are no calls to irq_alloc_descs in arch/arm.
> 
> With the MULTI_IRQ GIC support Marc Z is working on, we could make the
> GIC irq mapping be completely dynamic. Although, there's probably not
> much reason to do so for the root controller.

OK, that makes sense.  I think that if you were to do 
irq_alloc_descs(16, 16, domain->nr_irqs, num_node_id()) then that will 
guarantee the descriptors start from 16 (if they are available) which is 
probably nicer.

Jamie

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-26 21:11         ` Jamie Iles
  0 siblings, 0 replies; 68+ messages in thread
From: Jamie Iles @ 2011-09-26 21:11 UTC (permalink / raw)
  To: Rob Herring
  Cc: dave.martin-QSEj5FYQhm4dnm+yROfE0A, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On Mon, Sep 26, 2011 at 03:49:11PM -0500, Rob Herring wrote:
> On 09/26/2011 02:57 PM, Jamie Iles wrote:
> > Hi Rob,
> > 
> > On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
> > [...]
> >> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
> >> +{
> >> +	void __iomem *cpu_base;
> >> +	void __iomem *dist_base;
> >> +	int irq;
> >> +	struct irq_domain *domain = &gic_data[gic_cnt].domain;
> >> +
> >> +	if (WARN_ON(!node))
> >> +		return -ENODEV;
> >> +
> >> +	dist_base = of_iomap(node, 0);
> >> +	WARN(!dist_base, "unable to map gic dist registers\n");
> >> +
> >> +	cpu_base = of_iomap(node, 1);
> >> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
> >> +
> >> +	domain->nr_irq = gic_irq_count(dist_base);
> >> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
> >> +	if (parent)
> >> +		domain->nr_irq -= 32;
> >> +	else
> >> +		domain->nr_irq -= 16;
> >> +
> >> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
> > 
> > The way I understand irq_alloc_descs() (probably not very well) is that 
> > having the irq parameter < 0 and the from parameter 16 means that it 
> > needs to find domain->nr_irq descs starting from at least 16.  But if 
> > the base is greater than 16, does this still work with the gic entry 
> > macros as they are?
> 
> No, but that would only happen if a platform calls irq_alloc_descs prior
> to this code. The root controller must be initialized first (for other
> reasons as well). There are no calls to irq_alloc_descs in arch/arm.
> 
> With the MULTI_IRQ GIC support Marc Z is working on, we could make the
> GIC irq mapping be completely dynamic. Although, there's probably not
> much reason to do so for the root controller.

OK, that makes sense.  I think that if you were to do 
irq_alloc_descs(16, 16, domain->nr_irqs, num_node_id()) then that will 
guarantee the descriptors start from 16 (if they are available) which is 
probably nicer.

Jamie

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-26 21:11         ` Jamie Iles
  0 siblings, 0 replies; 68+ messages in thread
From: Jamie Iles @ 2011-09-26 21:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Sep 26, 2011 at 03:49:11PM -0500, Rob Herring wrote:
> On 09/26/2011 02:57 PM, Jamie Iles wrote:
> > Hi Rob,
> > 
> > On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
> > [...]
> >> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
> >> +{
> >> +	void __iomem *cpu_base;
> >> +	void __iomem *dist_base;
> >> +	int irq;
> >> +	struct irq_domain *domain = &gic_data[gic_cnt].domain;
> >> +
> >> +	if (WARN_ON(!node))
> >> +		return -ENODEV;
> >> +
> >> +	dist_base = of_iomap(node, 0);
> >> +	WARN(!dist_base, "unable to map gic dist registers\n");
> >> +
> >> +	cpu_base = of_iomap(node, 1);
> >> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
> >> +
> >> +	domain->nr_irq = gic_irq_count(dist_base);
> >> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
> >> +	if (parent)
> >> +		domain->nr_irq -= 32;
> >> +	else
> >> +		domain->nr_irq -= 16;
> >> +
> >> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
> > 
> > The way I understand irq_alloc_descs() (probably not very well) is that 
> > having the irq parameter < 0 and the from parameter 16 means that it 
> > needs to find domain->nr_irq descs starting from at least 16.  But if 
> > the base is greater than 16, does this still work with the gic entry 
> > macros as they are?
> 
> No, but that would only happen if a platform calls irq_alloc_descs prior
> to this code. The root controller must be initialized first (for other
> reasons as well). There are no calls to irq_alloc_descs in arch/arm.
> 
> With the MULTI_IRQ GIC support Marc Z is working on, we could make the
> GIC irq mapping be completely dynamic. Although, there's probably not
> much reason to do so for the root controller.

OK, that makes sense.  I think that if you were to do 
irq_alloc_descs(16, 16, domain->nr_irqs, num_node_id()) then that will 
guarantee the descriptors start from 16 (if they are available) which is 
probably nicer.

Jamie

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
  2011-09-26 19:57     ` Jamie Iles
  (?)
@ 2011-09-26 20:49       ` Rob Herring
  -1 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-26 20:49 UTC (permalink / raw)
  To: Jamie Iles
  Cc: linux-arm-kernel, devicetree-discuss, linux-kernel, grant.likely,
	marc.zyngier, thomas.abraham, b-cousson, shawn.guo, dave.martin,
	linux, Rob Herring

On 09/26/2011 02:57 PM, Jamie Iles wrote:
> Hi Rob,
> 
> On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
> [...]
>> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
>> +{
>> +	void __iomem *cpu_base;
>> +	void __iomem *dist_base;
>> +	int irq;
>> +	struct irq_domain *domain = &gic_data[gic_cnt].domain;
>> +
>> +	if (WARN_ON(!node))
>> +		return -ENODEV;
>> +
>> +	dist_base = of_iomap(node, 0);
>> +	WARN(!dist_base, "unable to map gic dist registers\n");
>> +
>> +	cpu_base = of_iomap(node, 1);
>> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
>> +
>> +	domain->nr_irq = gic_irq_count(dist_base);
>> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
>> +	if (parent)
>> +		domain->nr_irq -= 32;
>> +	else
>> +		domain->nr_irq -= 16;
>> +
>> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
> 
> The way I understand irq_alloc_descs() (probably not very well) is that 
> having the irq parameter < 0 and the from parameter 16 means that it 
> needs to find domain->nr_irq descs starting from at least 16.  But if 
> the base is greater than 16, does this still work with the gic entry 
> macros as they are?

No, but that would only happen if a platform calls irq_alloc_descs prior
to this code. The root controller must be initialized first (for other
reasons as well). There are no calls to irq_alloc_descs in arch/arm.

With the MULTI_IRQ GIC support Marc Z is working on, we could make the
GIC irq mapping be completely dynamic. Although, there's probably not
much reason to do so for the root controller.

Rob


^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-26 20:49       ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-26 20:49 UTC (permalink / raw)
  To: Jamie Iles
  Cc: dave.martin-QSEj5FYQhm4dnm+yROfE0A, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On 09/26/2011 02:57 PM, Jamie Iles wrote:
> Hi Rob,
> 
> On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
> [...]
>> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
>> +{
>> +	void __iomem *cpu_base;
>> +	void __iomem *dist_base;
>> +	int irq;
>> +	struct irq_domain *domain = &gic_data[gic_cnt].domain;
>> +
>> +	if (WARN_ON(!node))
>> +		return -ENODEV;
>> +
>> +	dist_base = of_iomap(node, 0);
>> +	WARN(!dist_base, "unable to map gic dist registers\n");
>> +
>> +	cpu_base = of_iomap(node, 1);
>> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
>> +
>> +	domain->nr_irq = gic_irq_count(dist_base);
>> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
>> +	if (parent)
>> +		domain->nr_irq -= 32;
>> +	else
>> +		domain->nr_irq -= 16;
>> +
>> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
> 
> The way I understand irq_alloc_descs() (probably not very well) is that 
> having the irq parameter < 0 and the from parameter 16 means that it 
> needs to find domain->nr_irq descs starting from at least 16.  But if 
> the base is greater than 16, does this still work with the gic entry 
> macros as they are?

No, but that would only happen if a platform calls irq_alloc_descs prior
to this code. The root controller must be initialized first (for other
reasons as well). There are no calls to irq_alloc_descs in arch/arm.

With the MULTI_IRQ GIC support Marc Z is working on, we could make the
GIC irq mapping be completely dynamic. Although, there's probably not
much reason to do so for the root controller.

Rob

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-26 20:49       ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-26 20:49 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/26/2011 02:57 PM, Jamie Iles wrote:
> Hi Rob,
> 
> On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
> [...]
>> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
>> +{
>> +	void __iomem *cpu_base;
>> +	void __iomem *dist_base;
>> +	int irq;
>> +	struct irq_domain *domain = &gic_data[gic_cnt].domain;
>> +
>> +	if (WARN_ON(!node))
>> +		return -ENODEV;
>> +
>> +	dist_base = of_iomap(node, 0);
>> +	WARN(!dist_base, "unable to map gic dist registers\n");
>> +
>> +	cpu_base = of_iomap(node, 1);
>> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
>> +
>> +	domain->nr_irq = gic_irq_count(dist_base);
>> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
>> +	if (parent)
>> +		domain->nr_irq -= 32;
>> +	else
>> +		domain->nr_irq -= 16;
>> +
>> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
> 
> The way I understand irq_alloc_descs() (probably not very well) is that 
> having the irq parameter < 0 and the from parameter 16 means that it 
> needs to find domain->nr_irq descs starting from at least 16.  But if 
> the base is greater than 16, does this still work with the gic entry 
> macros as they are?

No, but that would only happen if a platform calls irq_alloc_descs prior
to this code. The root controller must be initialized first (for other
reasons as well). There are no calls to irq_alloc_descs in arch/arm.

With the MULTI_IRQ GIC support Marc Z is working on, we could make the
GIC irq mapping be completely dynamic. Although, there's probably not
much reason to do so for the root controller.

Rob

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-26 19:57     ` Jamie Iles
  0 siblings, 0 replies; 68+ messages in thread
From: Jamie Iles @ 2011-09-26 19:57 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-arm-kernel, devicetree-discuss, linux-kernel, grant.likely,
	marc.zyngier, thomas.abraham, jamie, b-cousson, shawn.guo,
	dave.martin, linux, Rob Herring

Hi Rob,

On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
[...]
> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
> +{
> +	void __iomem *cpu_base;
> +	void __iomem *dist_base;
> +	int irq;
> +	struct irq_domain *domain = &gic_data[gic_cnt].domain;
> +
> +	if (WARN_ON(!node))
> +		return -ENODEV;
> +
> +	dist_base = of_iomap(node, 0);
> +	WARN(!dist_base, "unable to map gic dist registers\n");
> +
> +	cpu_base = of_iomap(node, 1);
> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
> +
> +	domain->nr_irq = gic_irq_count(dist_base);
> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
> +	if (parent)
> +		domain->nr_irq -= 32;
> +	else
> +		domain->nr_irq -= 16;
> +
> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());

The way I understand irq_alloc_descs() (probably not very well) is that 
having the irq parameter < 0 and the from parameter 16 means that it 
needs to find domain->nr_irq descs starting from at least 16.  But if 
the base is greater than 16, does this still work with the gic entry 
macros as they are?

Jamie

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-26 19:57     ` Jamie Iles
  0 siblings, 0 replies; 68+ messages in thread
From: Jamie Iles @ 2011-09-26 19:57 UTC (permalink / raw)
  To: Rob Herring
  Cc: dave.martin-QSEj5FYQhm4dnm+yROfE0A, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi Rob,

On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
[...]
> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
> +{
> +	void __iomem *cpu_base;
> +	void __iomem *dist_base;
> +	int irq;
> +	struct irq_domain *domain = &gic_data[gic_cnt].domain;
> +
> +	if (WARN_ON(!node))
> +		return -ENODEV;
> +
> +	dist_base = of_iomap(node, 0);
> +	WARN(!dist_base, "unable to map gic dist registers\n");
> +
> +	cpu_base = of_iomap(node, 1);
> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
> +
> +	domain->nr_irq = gic_irq_count(dist_base);
> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
> +	if (parent)
> +		domain->nr_irq -= 32;
> +	else
> +		domain->nr_irq -= 16;
> +
> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());

The way I understand irq_alloc_descs() (probably not very well) is that 
having the irq parameter < 0 and the from parameter 16 means that it 
needs to find domain->nr_irq descs starting from at least 16.  But if 
the base is greater than 16, does this still work with the gic entry 
macros as they are?

Jamie

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-26 19:57     ` Jamie Iles
  0 siblings, 0 replies; 68+ messages in thread
From: Jamie Iles @ 2011-09-26 19:57 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Rob,

On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
[...]
> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
> +{
> +	void __iomem *cpu_base;
> +	void __iomem *dist_base;
> +	int irq;
> +	struct irq_domain *domain = &gic_data[gic_cnt].domain;
> +
> +	if (WARN_ON(!node))
> +		return -ENODEV;
> +
> +	dist_base = of_iomap(node, 0);
> +	WARN(!dist_base, "unable to map gic dist registers\n");
> +
> +	cpu_base = of_iomap(node, 1);
> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
> +
> +	domain->nr_irq = gic_irq_count(dist_base);
> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
> +	if (parent)
> +		domain->nr_irq -= 32;
> +	else
> +		domain->nr_irq -= 16;
> +
> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());

The way I understand irq_alloc_descs() (probably not very well) is that 
having the irq parameter < 0 and the from parameter 16 means that it 
needs to find domain->nr_irq descs starting from at least 16.  But if 
the base is greater than 16, does this still work with the gic entry 
macros as they are?

Jamie

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-21 20:27           ` Cousson, Benoit
  0 siblings, 0 replies; 68+ messages in thread
From: Cousson, Benoit @ 2011-09-21 20:27 UTC (permalink / raw)
  To: Rob Herring
  Cc: dave.martin, linux, devicetree-discuss, linux-kernel,
	Rob Herring, linux-arm-kernel

On 9/21/2011 9:28 PM, Cousson, Benoit wrote:
> On 9/21/2011 7:55 PM, Rob Herring wrote:
>
> [...]
>
>> I fixed that in the prior series and tglx picked it up, so I did not
>> repost. It should hit mainline for 3.1, but I haven't verified if it is
>> in yet. Sorry for the confusion, I should have mentioned that.
>
> OK, I remember now as well that Thomas took patched 2 patches from your
> previous one. And I found it:
> https://lkml.org/lkml/2011/9/14/190
>
> Now, I have to find why the twl interrupt-controller is not working
> anymore even with that fix.

This is much better with the proper #interrupt-cells size:-)

> Almost-Tested-by: Benoit Cousson<b-cousson@ti.com>

Tested-by: Benoit Cousson<b-cousson@ti.com>

With a still very limited number of OMAP4 peripherals for the moment.

Regards,
Benoit


^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-21 20:27           ` Cousson, Benoit
  0 siblings, 0 replies; 68+ messages in thread
From: Cousson, Benoit @ 2011-09-21 20:27 UTC (permalink / raw)
  To: Rob Herring
  Cc: dave.martin-QSEj5FYQhm4dnm+yROfE0A, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On 9/21/2011 9:28 PM, Cousson, Benoit wrote:
> On 9/21/2011 7:55 PM, Rob Herring wrote:
>
> [...]
>
>> I fixed that in the prior series and tglx picked it up, so I did not
>> repost. It should hit mainline for 3.1, but I haven't verified if it is
>> in yet. Sorry for the confusion, I should have mentioned that.
>
> OK, I remember now as well that Thomas took patched 2 patches from your
> previous one. And I found it:
> https://lkml.org/lkml/2011/9/14/190
>
> Now, I have to find why the twl interrupt-controller is not working
> anymore even with that fix.

This is much better with the proper #interrupt-cells size:-)

> Almost-Tested-by: Benoit Cousson<b-cousson-l0cyMroinI0@public.gmane.org>

Tested-by: Benoit Cousson<b-cousson-l0cyMroinI0@public.gmane.org>

With a still very limited number of OMAP4 peripherals for the moment.

Regards,
Benoit

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-21 20:27           ` Cousson, Benoit
  0 siblings, 0 replies; 68+ messages in thread
From: Cousson, Benoit @ 2011-09-21 20:27 UTC (permalink / raw)
  To: linux-arm-kernel

On 9/21/2011 9:28 PM, Cousson, Benoit wrote:
> On 9/21/2011 7:55 PM, Rob Herring wrote:
>
> [...]
>
>> I fixed that in the prior series and tglx picked it up, so I did not
>> repost. It should hit mainline for 3.1, but I haven't verified if it is
>> in yet. Sorry for the confusion, I should have mentioned that.
>
> OK, I remember now as well that Thomas took patched 2 patches from your
> previous one. And I found it:
> https://lkml.org/lkml/2011/9/14/190
>
> Now, I have to find why the twl interrupt-controller is not working
> anymore even with that fix.

This is much better with the proper #interrupt-cells size:-)

> Almost-Tested-by: Benoit Cousson<b-cousson@ti.com>

Tested-by: Benoit Cousson<b-cousson@ti.com>

With a still very limited number of OMAP4 peripherals for the moment.

Regards,
Benoit

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-21 19:28         ` Cousson, Benoit
  0 siblings, 0 replies; 68+ messages in thread
From: Cousson, Benoit @ 2011-09-21 19:28 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-arm-kernel, devicetree-discuss, linux-kernel, grant.likely,
	marc.zyngier, thomas.abraham, jamie, shawn.guo, dave.martin,
	linux, Rob Herring

On 9/21/2011 7:55 PM, Rob Herring wrote:

[...]

> I fixed that in the prior series and tglx picked it up, so I did not
> repost. It should hit mainline for 3.1, but I haven't verified if it is
> in yet. Sorry for the confusion, I should have mentioned that.

OK, I remember now as well that Thomas took patched 2 patches from your 
previous one. And I found it:
https://lkml.org/lkml/2011/9/14/190

Now, I have to find why the twl interrupt-controller is not working 
anymore even with that fix.

Almost-Tested-by: Benoit Cousson <b-cousson@ti.com>

Thanks,
Benoit


^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-21 19:28         ` Cousson, Benoit
  0 siblings, 0 replies; 68+ messages in thread
From: Cousson, Benoit @ 2011-09-21 19:28 UTC (permalink / raw)
  To: Rob Herring
  Cc: dave.martin-QSEj5FYQhm4dnm+yROfE0A, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On 9/21/2011 7:55 PM, Rob Herring wrote:

[...]

> I fixed that in the prior series and tglx picked it up, so I did not
> repost. It should hit mainline for 3.1, but I haven't verified if it is
> in yet. Sorry for the confusion, I should have mentioned that.

OK, I remember now as well that Thomas took patched 2 patches from your 
previous one. And I found it:
https://lkml.org/lkml/2011/9/14/190

Now, I have to find why the twl interrupt-controller is not working 
anymore even with that fix.

Almost-Tested-by: Benoit Cousson <b-cousson-l0cyMroinI0@public.gmane.org>

Thanks,
Benoit

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-21 19:28         ` Cousson, Benoit
  0 siblings, 0 replies; 68+ messages in thread
From: Cousson, Benoit @ 2011-09-21 19:28 UTC (permalink / raw)
  To: linux-arm-kernel

On 9/21/2011 7:55 PM, Rob Herring wrote:

[...]

> I fixed that in the prior series and tglx picked it up, so I did not
> repost. It should hit mainline for 3.1, but I haven't verified if it is
> in yet. Sorry for the confusion, I should have mentioned that.

OK, I remember now as well that Thomas took patched 2 patches from your 
previous one. And I found it:
https://lkml.org/lkml/2011/9/14/190

Now, I have to find why the twl interrupt-controller is not working 
anymore even with that fix.

Almost-Tested-by: Benoit Cousson <b-cousson@ti.com>

Thanks,
Benoit

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-21 17:55       ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-21 17:55 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: linux-arm-kernel, devicetree-discuss, linux-kernel, grant.likely,
	marc.zyngier, thomas.abraham, jamie, shawn.guo, dave.martin,
	linux, Rob Herring

Benoit,

On 09/21/2011 12:15 PM, Cousson, Benoit wrote:
> Hi Rob,
> 
> I'm testing that series with OMAP4 but have some issues for the moment :-(
> 
> [    0.000000] WARNING: at kernel/irq/irqdomain.c:34 gic_of_init+0x10c/0x180()
> [    0.000000] error: irq_desc already assigned to a domain
> [    0.000000] Modules linked in:
> [    0.000000] [<c001b284>] (unwind_backtrace+0x0/0xf0) from [<c0051c34>] (warn_slowpath_common+0x4c/0x64)
> [    0.000000] [<c0051c34>] (warn_slowpath_common+0x4c/0x64) from [<c0051ce0>] (warn_slowpath_fmt+0x30/0x40)
> [    0.000000] [<c0051ce0>] (warn_slowpath_fmt+0x30/0x40) from [<c05f6874>] (gic_of_init+0x10c/0x180)
> [    0.000000] [<c05f6874>] (gic_of_init+0x10c/0x180) from [<c05fa2e0>] (omap_gic_of_init+0x8/0x28)
> [    0.000000] [<c05fa2e0>] (omap_gic_of_init+0x8/0x28) from [<c0616b44>] (of_irq_init+0x148/0x28c)
> [    0.000000] [<c0616b44>] (of_irq_init+0x148/0x28c) from [<c05f3074>] (init_IRQ+0x14/0x1c)
> [    0.000000] [<c05f3074>] (init_IRQ+0x14/0x1c) from [<c05f0650>] (start_kernel+0x184/0x2fc)
> [    0.000000] [<c05f0650>] (start_kernel+0x184/0x2fc) from [<80008040>] (0x80008040)
>  
> I'm not super familiar with all the irq stuff but I'm wondering if there is not something wrong with the test that print that message:
> 
> void irq_domain_add(struct irq_domain *domain)
> {
> 	struct irq_data *d;
> 	int hwirq;
> 
> 	/*
> 	 * This assumes that the irq_domain owner has already allocated
> 	 * the irq_descs.  This block will be removed when support for dynamic
> 	 * allocation of irq_descs is added to irq_domain.
> 	 */
> 	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
> 		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
> 		if (d || d->domain) {
> 			/* things are broken; just report, don't clean up */
> 			WARN(1, "error: irq_desc already assigned to a domain");
> 			return;
> 		}
> [...]
> 
> Is the (d || d->domain) correct? Shouldn't it be (d && d->domain)?
> 
> But since that used to work properly, I have some doubt. Moreover the driver will not even get the proper interrupt later...
> 
> Do you have any clue?

I fixed that in the prior series and tglx picked it up, so I did not
repost. It should hit mainline for 3.1, but I haven't verified if it is
in yet. Sorry for the confusion, I should have mentioned that.

Rob


^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-21 17:55       ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-21 17:55 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: dave.martin-QSEj5FYQhm4dnm+yROfE0A, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Benoit,

On 09/21/2011 12:15 PM, Cousson, Benoit wrote:
> Hi Rob,
> 
> I'm testing that series with OMAP4 but have some issues for the moment :-(
> 
> [    0.000000] WARNING: at kernel/irq/irqdomain.c:34 gic_of_init+0x10c/0x180()
> [    0.000000] error: irq_desc already assigned to a domain
> [    0.000000] Modules linked in:
> [    0.000000] [<c001b284>] (unwind_backtrace+0x0/0xf0) from [<c0051c34>] (warn_slowpath_common+0x4c/0x64)
> [    0.000000] [<c0051c34>] (warn_slowpath_common+0x4c/0x64) from [<c0051ce0>] (warn_slowpath_fmt+0x30/0x40)
> [    0.000000] [<c0051ce0>] (warn_slowpath_fmt+0x30/0x40) from [<c05f6874>] (gic_of_init+0x10c/0x180)
> [    0.000000] [<c05f6874>] (gic_of_init+0x10c/0x180) from [<c05fa2e0>] (omap_gic_of_init+0x8/0x28)
> [    0.000000] [<c05fa2e0>] (omap_gic_of_init+0x8/0x28) from [<c0616b44>] (of_irq_init+0x148/0x28c)
> [    0.000000] [<c0616b44>] (of_irq_init+0x148/0x28c) from [<c05f3074>] (init_IRQ+0x14/0x1c)
> [    0.000000] [<c05f3074>] (init_IRQ+0x14/0x1c) from [<c05f0650>] (start_kernel+0x184/0x2fc)
> [    0.000000] [<c05f0650>] (start_kernel+0x184/0x2fc) from [<80008040>] (0x80008040)
>  
> I'm not super familiar with all the irq stuff but I'm wondering if there is not something wrong with the test that print that message:
> 
> void irq_domain_add(struct irq_domain *domain)
> {
> 	struct irq_data *d;
> 	int hwirq;
> 
> 	/*
> 	 * This assumes that the irq_domain owner has already allocated
> 	 * the irq_descs.  This block will be removed when support for dynamic
> 	 * allocation of irq_descs is added to irq_domain.
> 	 */
> 	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
> 		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
> 		if (d || d->domain) {
> 			/* things are broken; just report, don't clean up */
> 			WARN(1, "error: irq_desc already assigned to a domain");
> 			return;
> 		}
> [...]
> 
> Is the (d || d->domain) correct? Shouldn't it be (d && d->domain)?
> 
> But since that used to work properly, I have some doubt. Moreover the driver will not even get the proper interrupt later...
> 
> Do you have any clue?

I fixed that in the prior series and tglx picked it up, so I did not
repost. It should hit mainline for 3.1, but I haven't verified if it is
in yet. Sorry for the confusion, I should have mentioned that.

Rob

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-21 17:55       ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-21 17:55 UTC (permalink / raw)
  To: linux-arm-kernel

Benoit,

On 09/21/2011 12:15 PM, Cousson, Benoit wrote:
> Hi Rob,
> 
> I'm testing that series with OMAP4 but have some issues for the moment :-(
> 
> [    0.000000] WARNING: at kernel/irq/irqdomain.c:34 gic_of_init+0x10c/0x180()
> [    0.000000] error: irq_desc already assigned to a domain
> [    0.000000] Modules linked in:
> [    0.000000] [<c001b284>] (unwind_backtrace+0x0/0xf0) from [<c0051c34>] (warn_slowpath_common+0x4c/0x64)
> [    0.000000] [<c0051c34>] (warn_slowpath_common+0x4c/0x64) from [<c0051ce0>] (warn_slowpath_fmt+0x30/0x40)
> [    0.000000] [<c0051ce0>] (warn_slowpath_fmt+0x30/0x40) from [<c05f6874>] (gic_of_init+0x10c/0x180)
> [    0.000000] [<c05f6874>] (gic_of_init+0x10c/0x180) from [<c05fa2e0>] (omap_gic_of_init+0x8/0x28)
> [    0.000000] [<c05fa2e0>] (omap_gic_of_init+0x8/0x28) from [<c0616b44>] (of_irq_init+0x148/0x28c)
> [    0.000000] [<c0616b44>] (of_irq_init+0x148/0x28c) from [<c05f3074>] (init_IRQ+0x14/0x1c)
> [    0.000000] [<c05f3074>] (init_IRQ+0x14/0x1c) from [<c05f0650>] (start_kernel+0x184/0x2fc)
> [    0.000000] [<c05f0650>] (start_kernel+0x184/0x2fc) from [<80008040>] (0x80008040)
>  
> I'm not super familiar with all the irq stuff but I'm wondering if there is not something wrong with the test that print that message:
> 
> void irq_domain_add(struct irq_domain *domain)
> {
> 	struct irq_data *d;
> 	int hwirq;
> 
> 	/*
> 	 * This assumes that the irq_domain owner has already allocated
> 	 * the irq_descs.  This block will be removed when support for dynamic
> 	 * allocation of irq_descs is added to irq_domain.
> 	 */
> 	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
> 		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
> 		if (d || d->domain) {
> 			/* things are broken; just report, don't clean up */
> 			WARN(1, "error: irq_desc already assigned to a domain");
> 			return;
> 		}
> [...]
> 
> Is the (d || d->domain) correct? Shouldn't it be (d && d->domain)?
> 
> But since that used to work properly, I have some doubt. Moreover the driver will not even get the proper interrupt later...
> 
> Do you have any clue?

I fixed that in the prior series and tglx picked it up, so I did not
repost. It should hit mainline for 3.1, but I haven't verified if it is
in yet. Sorry for the confusion, I should have mentioned that.

Rob

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-21 17:15     ` Cousson, Benoit
  0 siblings, 0 replies; 68+ messages in thread
From: Cousson, Benoit @ 2011-09-21 17:15 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-arm-kernel, devicetree-discuss, linux-kernel, grant.likely,
	marc.zyngier, thomas.abraham, jamie, shawn.guo, dave.martin,
	linux, Rob Herring

Hi Rob,

I'm testing that series with OMAP4 but have some issues for the moment :-(

[    0.000000] WARNING: at kernel/irq/irqdomain.c:34 gic_of_init+0x10c/0x180()
[    0.000000] error: irq_desc already assigned to a domain
[    0.000000] Modules linked in:
[    0.000000] [<c001b284>] (unwind_backtrace+0x0/0xf0) from [<c0051c34>] (warn_slowpath_common+0x4c/0x64)
[    0.000000] [<c0051c34>] (warn_slowpath_common+0x4c/0x64) from [<c0051ce0>] (warn_slowpath_fmt+0x30/0x40)
[    0.000000] [<c0051ce0>] (warn_slowpath_fmt+0x30/0x40) from [<c05f6874>] (gic_of_init+0x10c/0x180)
[    0.000000] [<c05f6874>] (gic_of_init+0x10c/0x180) from [<c05fa2e0>] (omap_gic_of_init+0x8/0x28)
[    0.000000] [<c05fa2e0>] (omap_gic_of_init+0x8/0x28) from [<c0616b44>] (of_irq_init+0x148/0x28c)
[    0.000000] [<c0616b44>] (of_irq_init+0x148/0x28c) from [<c05f3074>] (init_IRQ+0x14/0x1c)
[    0.000000] [<c05f3074>] (init_IRQ+0x14/0x1c) from [<c05f0650>] (start_kernel+0x184/0x2fc)
[    0.000000] [<c05f0650>] (start_kernel+0x184/0x2fc) from [<80008040>] (0x80008040)
 
I'm not super familiar with all the irq stuff but I'm wondering if there is not something wrong with the test that print that message:

void irq_domain_add(struct irq_domain *domain)
{
	struct irq_data *d;
	int hwirq;

	/*
	 * This assumes that the irq_domain owner has already allocated
	 * the irq_descs.  This block will be removed when support for dynamic
	 * allocation of irq_descs is added to irq_domain.
	 */
	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
		if (d || d->domain) {
			/* things are broken; just report, don't clean up */
			WARN(1, "error: irq_desc already assigned to a domain");
			return;
		}
[...]

Is the (d || d->domain) correct? Shouldn't it be (d && d->domain)?

But since that used to work properly, I have some doubt. Moreover the driver will not even get the proper interrupt later...

Do you have any clue?

Thanks,
Benoit


On 9/20/2011 10:24 PM, Rob Herring wrote:
> From: Rob Herring<rob.herring@calxeda.com>
> 
> This adds ARM gic interrupt controller initialization using device tree
> data.
> 
> The initialization function is intended to be called by of_irq_init
> function like this:
> 
> const static struct of_device_id irq_match[] = {
>          { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
>          {}
> };
> 
> static void __init init_irqs(void)
> {
>          of_irq_init(irq_match);
> }
> 
> Signed-off-by: Rob Herring<rob.herring@calxeda.com>
> ---
>   Documentation/devicetree/bindings/arm/gic.txt |   55 +++++++++++++++
>   arch/arm/common/gic.c                         |   89 +++++++++++++++++++++++-
>   arch/arm/include/asm/hardware/gic.h           |   12 ++++
>   3 files changed, 152 insertions(+), 4 deletions(-)
>   create mode 100644 Documentation/devicetree/bindings/arm/gic.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
> new file mode 100644
> index 0000000..52916b4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/gic.txt
> @@ -0,0 +1,55 @@
> +* ARM Generic Interrupt Controller
> +
> +ARM SMP cores are often associated with a GIC, providing per processor
> +interrupts (PPI), shared processor interrupts (SPI) and software
> +generated interrupts (SGI).
> +
> +Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
> +Secondary GICs are cascaded into the upward interrupt controller and do not
> +have PPIs or SGIs.
> +
> +Main node required properties:
> +
> +- compatible : should be one of:
> +	"arm,cortex-a9-gic"
> +	"arm,arm11mp-gic"
> +- interrupt-controller : Identifies the node as an interrupt controller
> +- #interrupt-cells : Specifies the number of cells needed to encode an
> +  interrupt source.  The type shall be a<u32>  and the value shall be 3.
> +
> +  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
> +  interrupts.
> +
> +  The 2nd cell contains the interrupt number for the interrupt type.
> +  SPI interrupts are in the range [0-987].  PPI interrupts are in the
> +  range [0-15].
> +
> +  The 3rd cell is the flags, encoded as follows:
> +	bits[3:0] trigger type and level flags.
> +		1 = low-to-high edge triggered
> +		2 = high-to-low edge triggered
> +		4 = active high level-sensitive
> +		8 = active low level-sensitive
> +	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
> +	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
> +	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
> +
> +- reg : Specifies base physical address(s) and size of the GIC registers. The
> +  first region is the GIC distributor register base and size. The 2nd region is
> +  the GIC cpu interface register base and size.
> +
> +Optional
> +- interrupts	: Interrupt source of the parent interrupt controller. Only
> +  present on secondary GICs.
> +
> +Example:
> +
> +	intc: interrupt-controller@fff11000 {
> +		compatible = "arm,cortex-a9-gic";
> +		#interrupt-cells =<3>;
> +		#address-cells =<1>;
> +		interrupt-controller;
> +		reg =<0xfff11000 0x1000>,
> +		<0xfff10100 0x100>;
> +	};
> +
> diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
> index 666b278..84e69a4 100644
> --- a/arch/arm/common/gic.c
> +++ b/arch/arm/common/gic.c
> @@ -28,6 +28,10 @@
>   #include<linux/smp.h>
>   #include<linux/cpumask.h>
>   #include<linux/io.h>
> +#include<linux/of.h>
> +#include<linux/of_address.h>
> +#include<linux/of_irq.h>
> +#include<linux/irqdomain.h>
> 
>   #include<asm/irq.h>
>   #include<asm/mach/irq.h>
> @@ -255,6 +259,15 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
>   	irq_set_chained_handler(irq, gic_handle_cascade_irq);
>   }
> 
> +static int gic_irq_count(void __iomem *dist_base)
> +{
> +	int gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR)&  0x1f;
> +	gic_irqs = (gic_irqs + 1) * 32;
> +	if (gic_irqs>  1020)
> +		gic_irqs = 1020;
> +	return gic_irqs;
> +}
> +
>   static void __init gic_dist_init(struct gic_chip_data *gic,
>   	unsigned int irq_start)
>   {
> @@ -277,10 +290,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
>   	 * Find out how many interrupts are supported.
>   	 * The GIC only supports up to 1020 interrupt sources.
>   	 */
> -	gic_irqs = readl_relaxed(base + GIC_DIST_CTR)&  0x1f;
> -	gic_irqs = (gic_irqs + 1) * 32;
> -	if (gic_irqs>  1020)
> -		gic_irqs = 1020;
> +	gic_irqs = gic_irq_count(base);
> 
>   	/*
>   	 * Set all global interrupts to be level triggered, active low.
> @@ -405,3 +415,74 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
>   	writel_relaxed(map<<  16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
>   }
>   #endif
> +
> +#ifdef CONFIG_OF
> +static int gic_cnt __initdata = 0;
> +
> +int gic_irq_domain_dt_translate(struct irq_domain *d,
> +			    struct device_node *controller,
> +			    const u32 *intspec, unsigned int intsize,
> +			    unsigned long *out_hwirq, unsigned int *out_type)
> +{
> +	struct gic_chip_data *gic_data = d->priv;
> +
> +	if (d->of_node != controller)
> +		return -EINVAL;
> +	if (intsize<  3)
> +		return -EINVAL;
> +
> +	*out_hwirq = intspec[1];
> +	/*
> +	 * We've already skipped over SGIs, so PPIs need no translation.
> +	 * For SPIs, we need to skip over 16 PPIs on primary GICs.
> +	 */
> +	if (!intspec[0]&&  !gic_data->irq_offset)
> +		*out_hwirq += 16;
> +
> +	*out_type = intspec[2]&  IRQ_TYPE_SENSE_MASK;
> +	return 0;
> +}
> +
> +struct irq_domain_ops gic_irq_domain_ops = {
> +	.dt_translate = gic_irq_domain_dt_translate,
> +};
> +
> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
> +{
> +	void __iomem *cpu_base;
> +	void __iomem *dist_base;
> +	int irq;
> +	struct irq_domain *domain =&gic_data[gic_cnt].domain;
> +
> +	if (WARN_ON(!node))
> +		return -ENODEV;
> +
> +	dist_base = of_iomap(node, 0);
> +	WARN(!dist_base, "unable to map gic dist registers\n");
> +
> +	cpu_base = of_iomap(node, 1);
> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
> +
> +	domain->nr_irq = gic_irq_count(dist_base);
> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
> +	if (parent)
> +		domain->nr_irq -= 32;
> +	else
> +		domain->nr_irq -= 16;
> +
> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
> +	domain->of_node = of_node_get(node);
> +	domain->ops =&gic_irq_domain_ops;
> +	domain->priv =&gic_data[gic_cnt];
> +	irq_domain_add(domain);
> +
> +	gic_init(gic_cnt, domain->irq_base, dist_base, cpu_base);
> +
> +	if (parent) {
> +		irq = irq_of_parse_and_map(node, 0);
> +		gic_cascade_irq(gic_cnt, irq);
> +	}
> +	gic_cnt++;
> +	return 0;
> +}
> +#endif
> diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
> index 435d3f8..2862d0e 100644
> --- a/arch/arm/include/asm/hardware/gic.h
> +++ b/arch/arm/include/asm/hardware/gic.h
> @@ -33,10 +33,21 @@
>   #define GIC_DIST_SOFTINT		0xf00
> 
>   #ifndef __ASSEMBLY__
> +#include<linux/irqdomain.h>
> +
>   extern void __iomem *gic_cpu_base_addr;
>   extern struct irq_chip gic_arch_extn;
> 
>   void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
> +#ifdef CONFIG_OF
> +int gic_of_init(struct device_node *node, struct device_node *parent);
> +#else
> +static inline void gic_of_init(struct device_node *node,
> +			       struct device_node *parent)
> +{
> +	return -ENODEV;
> +}
> +#endif
>   void gic_secondary_init(unsigned int);
>   void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
>   void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
> @@ -46,6 +57,7 @@ struct gic_chip_data {
>   	unsigned int irq_offset;
>   	void __iomem *dist_base;
>   	void __iomem *cpu_base;
> +	struct irq_domain domain;
>   };
>   #endif
> 


^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-21 17:15     ` Cousson, Benoit
  0 siblings, 0 replies; 68+ messages in thread
From: Cousson, Benoit @ 2011-09-21 17:15 UTC (permalink / raw)
  To: Rob Herring
  Cc: dave.martin-QSEj5FYQhm4dnm+yROfE0A, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

Hi Rob,

I'm testing that series with OMAP4 but have some issues for the moment :-(

[    0.000000] WARNING: at kernel/irq/irqdomain.c:34 gic_of_init+0x10c/0x180()
[    0.000000] error: irq_desc already assigned to a domain
[    0.000000] Modules linked in:
[    0.000000] [<c001b284>] (unwind_backtrace+0x0/0xf0) from [<c0051c34>] (warn_slowpath_common+0x4c/0x64)
[    0.000000] [<c0051c34>] (warn_slowpath_common+0x4c/0x64) from [<c0051ce0>] (warn_slowpath_fmt+0x30/0x40)
[    0.000000] [<c0051ce0>] (warn_slowpath_fmt+0x30/0x40) from [<c05f6874>] (gic_of_init+0x10c/0x180)
[    0.000000] [<c05f6874>] (gic_of_init+0x10c/0x180) from [<c05fa2e0>] (omap_gic_of_init+0x8/0x28)
[    0.000000] [<c05fa2e0>] (omap_gic_of_init+0x8/0x28) from [<c0616b44>] (of_irq_init+0x148/0x28c)
[    0.000000] [<c0616b44>] (of_irq_init+0x148/0x28c) from [<c05f3074>] (init_IRQ+0x14/0x1c)
[    0.000000] [<c05f3074>] (init_IRQ+0x14/0x1c) from [<c05f0650>] (start_kernel+0x184/0x2fc)
[    0.000000] [<c05f0650>] (start_kernel+0x184/0x2fc) from [<80008040>] (0x80008040)
 
I'm not super familiar with all the irq stuff but I'm wondering if there is not something wrong with the test that print that message:

void irq_domain_add(struct irq_domain *domain)
{
	struct irq_data *d;
	int hwirq;

	/*
	 * This assumes that the irq_domain owner has already allocated
	 * the irq_descs.  This block will be removed when support for dynamic
	 * allocation of irq_descs is added to irq_domain.
	 */
	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
		if (d || d->domain) {
			/* things are broken; just report, don't clean up */
			WARN(1, "error: irq_desc already assigned to a domain");
			return;
		}
[...]

Is the (d || d->domain) correct? Shouldn't it be (d && d->domain)?

But since that used to work properly, I have some doubt. Moreover the driver will not even get the proper interrupt later...

Do you have any clue?

Thanks,
Benoit


On 9/20/2011 10:24 PM, Rob Herring wrote:
> From: Rob Herring<rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
> 
> This adds ARM gic interrupt controller initialization using device tree
> data.
> 
> The initialization function is intended to be called by of_irq_init
> function like this:
> 
> const static struct of_device_id irq_match[] = {
>          { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
>          {}
> };
> 
> static void __init init_irqs(void)
> {
>          of_irq_init(irq_match);
> }
> 
> Signed-off-by: Rob Herring<rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
> ---
>   Documentation/devicetree/bindings/arm/gic.txt |   55 +++++++++++++++
>   arch/arm/common/gic.c                         |   89 +++++++++++++++++++++++-
>   arch/arm/include/asm/hardware/gic.h           |   12 ++++
>   3 files changed, 152 insertions(+), 4 deletions(-)
>   create mode 100644 Documentation/devicetree/bindings/arm/gic.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
> new file mode 100644
> index 0000000..52916b4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/gic.txt
> @@ -0,0 +1,55 @@
> +* ARM Generic Interrupt Controller
> +
> +ARM SMP cores are often associated with a GIC, providing per processor
> +interrupts (PPI), shared processor interrupts (SPI) and software
> +generated interrupts (SGI).
> +
> +Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
> +Secondary GICs are cascaded into the upward interrupt controller and do not
> +have PPIs or SGIs.
> +
> +Main node required properties:
> +
> +- compatible : should be one of:
> +	"arm,cortex-a9-gic"
> +	"arm,arm11mp-gic"
> +- interrupt-controller : Identifies the node as an interrupt controller
> +- #interrupt-cells : Specifies the number of cells needed to encode an
> +  interrupt source.  The type shall be a<u32>  and the value shall be 3.
> +
> +  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
> +  interrupts.
> +
> +  The 2nd cell contains the interrupt number for the interrupt type.
> +  SPI interrupts are in the range [0-987].  PPI interrupts are in the
> +  range [0-15].
> +
> +  The 3rd cell is the flags, encoded as follows:
> +	bits[3:0] trigger type and level flags.
> +		1 = low-to-high edge triggered
> +		2 = high-to-low edge triggered
> +		4 = active high level-sensitive
> +		8 = active low level-sensitive
> +	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
> +	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
> +	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
> +
> +- reg : Specifies base physical address(s) and size of the GIC registers. The
> +  first region is the GIC distributor register base and size. The 2nd region is
> +  the GIC cpu interface register base and size.
> +
> +Optional
> +- interrupts	: Interrupt source of the parent interrupt controller. Only
> +  present on secondary GICs.
> +
> +Example:
> +
> +	intc: interrupt-controller@fff11000 {
> +		compatible = "arm,cortex-a9-gic";
> +		#interrupt-cells =<3>;
> +		#address-cells =<1>;
> +		interrupt-controller;
> +		reg =<0xfff11000 0x1000>,
> +		<0xfff10100 0x100>;
> +	};
> +
> diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
> index 666b278..84e69a4 100644
> --- a/arch/arm/common/gic.c
> +++ b/arch/arm/common/gic.c
> @@ -28,6 +28,10 @@
>   #include<linux/smp.h>
>   #include<linux/cpumask.h>
>   #include<linux/io.h>
> +#include<linux/of.h>
> +#include<linux/of_address.h>
> +#include<linux/of_irq.h>
> +#include<linux/irqdomain.h>
> 
>   #include<asm/irq.h>
>   #include<asm/mach/irq.h>
> @@ -255,6 +259,15 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
>   	irq_set_chained_handler(irq, gic_handle_cascade_irq);
>   }
> 
> +static int gic_irq_count(void __iomem *dist_base)
> +{
> +	int gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR)&  0x1f;
> +	gic_irqs = (gic_irqs + 1) * 32;
> +	if (gic_irqs>  1020)
> +		gic_irqs = 1020;
> +	return gic_irqs;
> +}
> +
>   static void __init gic_dist_init(struct gic_chip_data *gic,
>   	unsigned int irq_start)
>   {
> @@ -277,10 +290,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
>   	 * Find out how many interrupts are supported.
>   	 * The GIC only supports up to 1020 interrupt sources.
>   	 */
> -	gic_irqs = readl_relaxed(base + GIC_DIST_CTR)&  0x1f;
> -	gic_irqs = (gic_irqs + 1) * 32;
> -	if (gic_irqs>  1020)
> -		gic_irqs = 1020;
> +	gic_irqs = gic_irq_count(base);
> 
>   	/*
>   	 * Set all global interrupts to be level triggered, active low.
> @@ -405,3 +415,74 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
>   	writel_relaxed(map<<  16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
>   }
>   #endif
> +
> +#ifdef CONFIG_OF
> +static int gic_cnt __initdata = 0;
> +
> +int gic_irq_domain_dt_translate(struct irq_domain *d,
> +			    struct device_node *controller,
> +			    const u32 *intspec, unsigned int intsize,
> +			    unsigned long *out_hwirq, unsigned int *out_type)
> +{
> +	struct gic_chip_data *gic_data = d->priv;
> +
> +	if (d->of_node != controller)
> +		return -EINVAL;
> +	if (intsize<  3)
> +		return -EINVAL;
> +
> +	*out_hwirq = intspec[1];
> +	/*
> +	 * We've already skipped over SGIs, so PPIs need no translation.
> +	 * For SPIs, we need to skip over 16 PPIs on primary GICs.
> +	 */
> +	if (!intspec[0]&&  !gic_data->irq_offset)
> +		*out_hwirq += 16;
> +
> +	*out_type = intspec[2]&  IRQ_TYPE_SENSE_MASK;
> +	return 0;
> +}
> +
> +struct irq_domain_ops gic_irq_domain_ops = {
> +	.dt_translate = gic_irq_domain_dt_translate,
> +};
> +
> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
> +{
> +	void __iomem *cpu_base;
> +	void __iomem *dist_base;
> +	int irq;
> +	struct irq_domain *domain =&gic_data[gic_cnt].domain;
> +
> +	if (WARN_ON(!node))
> +		return -ENODEV;
> +
> +	dist_base = of_iomap(node, 0);
> +	WARN(!dist_base, "unable to map gic dist registers\n");
> +
> +	cpu_base = of_iomap(node, 1);
> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
> +
> +	domain->nr_irq = gic_irq_count(dist_base);
> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
> +	if (parent)
> +		domain->nr_irq -= 32;
> +	else
> +		domain->nr_irq -= 16;
> +
> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
> +	domain->of_node = of_node_get(node);
> +	domain->ops =&gic_irq_domain_ops;
> +	domain->priv =&gic_data[gic_cnt];
> +	irq_domain_add(domain);
> +
> +	gic_init(gic_cnt, domain->irq_base, dist_base, cpu_base);
> +
> +	if (parent) {
> +		irq = irq_of_parse_and_map(node, 0);
> +		gic_cascade_irq(gic_cnt, irq);
> +	}
> +	gic_cnt++;
> +	return 0;
> +}
> +#endif
> diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
> index 435d3f8..2862d0e 100644
> --- a/arch/arm/include/asm/hardware/gic.h
> +++ b/arch/arm/include/asm/hardware/gic.h
> @@ -33,10 +33,21 @@
>   #define GIC_DIST_SOFTINT		0xf00
> 
>   #ifndef __ASSEMBLY__
> +#include<linux/irqdomain.h>
> +
>   extern void __iomem *gic_cpu_base_addr;
>   extern struct irq_chip gic_arch_extn;
> 
>   void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
> +#ifdef CONFIG_OF
> +int gic_of_init(struct device_node *node, struct device_node *parent);
> +#else
> +static inline void gic_of_init(struct device_node *node,
> +			       struct device_node *parent)
> +{
> +	return -ENODEV;
> +}
> +#endif
>   void gic_secondary_init(unsigned int);
>   void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
>   void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
> @@ -46,6 +57,7 @@ struct gic_chip_data {
>   	unsigned int irq_offset;
>   	void __iomem *dist_base;
>   	void __iomem *cpu_base;
> +	struct irq_domain domain;
>   };
>   #endif
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-21 17:15     ` Cousson, Benoit
  0 siblings, 0 replies; 68+ messages in thread
From: Cousson, Benoit @ 2011-09-21 17:15 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Rob,

I'm testing that series with OMAP4 but have some issues for the moment :-(

[    0.000000] WARNING: at kernel/irq/irqdomain.c:34 gic_of_init+0x10c/0x180()
[    0.000000] error: irq_desc already assigned to a domain
[    0.000000] Modules linked in:
[    0.000000] [<c001b284>] (unwind_backtrace+0x0/0xf0) from [<c0051c34>] (warn_slowpath_common+0x4c/0x64)
[    0.000000] [<c0051c34>] (warn_slowpath_common+0x4c/0x64) from [<c0051ce0>] (warn_slowpath_fmt+0x30/0x40)
[    0.000000] [<c0051ce0>] (warn_slowpath_fmt+0x30/0x40) from [<c05f6874>] (gic_of_init+0x10c/0x180)
[    0.000000] [<c05f6874>] (gic_of_init+0x10c/0x180) from [<c05fa2e0>] (omap_gic_of_init+0x8/0x28)
[    0.000000] [<c05fa2e0>] (omap_gic_of_init+0x8/0x28) from [<c0616b44>] (of_irq_init+0x148/0x28c)
[    0.000000] [<c0616b44>] (of_irq_init+0x148/0x28c) from [<c05f3074>] (init_IRQ+0x14/0x1c)
[    0.000000] [<c05f3074>] (init_IRQ+0x14/0x1c) from [<c05f0650>] (start_kernel+0x184/0x2fc)
[    0.000000] [<c05f0650>] (start_kernel+0x184/0x2fc) from [<80008040>] (0x80008040)
 
I'm not super familiar with all the irq stuff but I'm wondering if there is not something wrong with the test that print that message:

void irq_domain_add(struct irq_domain *domain)
{
	struct irq_data *d;
	int hwirq;

	/*
	 * This assumes that the irq_domain owner has already allocated
	 * the irq_descs.  This block will be removed when support for dynamic
	 * allocation of irq_descs is added to irq_domain.
	 */
	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
		if (d || d->domain) {
			/* things are broken; just report, don't clean up */
			WARN(1, "error: irq_desc already assigned to a domain");
			return;
		}
[...]

Is the (d || d->domain) correct? Shouldn't it be (d && d->domain)?

But since that used to work properly, I have some doubt. Moreover the driver will not even get the proper interrupt later...

Do you have any clue?

Thanks,
Benoit


On 9/20/2011 10:24 PM, Rob Herring wrote:
> From: Rob Herring<rob.herring@calxeda.com>
> 
> This adds ARM gic interrupt controller initialization using device tree
> data.
> 
> The initialization function is intended to be called by of_irq_init
> function like this:
> 
> const static struct of_device_id irq_match[] = {
>          { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
>          {}
> };
> 
> static void __init init_irqs(void)
> {
>          of_irq_init(irq_match);
> }
> 
> Signed-off-by: Rob Herring<rob.herring@calxeda.com>
> ---
>   Documentation/devicetree/bindings/arm/gic.txt |   55 +++++++++++++++
>   arch/arm/common/gic.c                         |   89 +++++++++++++++++++++++-
>   arch/arm/include/asm/hardware/gic.h           |   12 ++++
>   3 files changed, 152 insertions(+), 4 deletions(-)
>   create mode 100644 Documentation/devicetree/bindings/arm/gic.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
> new file mode 100644
> index 0000000..52916b4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/gic.txt
> @@ -0,0 +1,55 @@
> +* ARM Generic Interrupt Controller
> +
> +ARM SMP cores are often associated with a GIC, providing per processor
> +interrupts (PPI), shared processor interrupts (SPI) and software
> +generated interrupts (SGI).
> +
> +Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
> +Secondary GICs are cascaded into the upward interrupt controller and do not
> +have PPIs or SGIs.
> +
> +Main node required properties:
> +
> +- compatible : should be one of:
> +	"arm,cortex-a9-gic"
> +	"arm,arm11mp-gic"
> +- interrupt-controller : Identifies the node as an interrupt controller
> +- #interrupt-cells : Specifies the number of cells needed to encode an
> +  interrupt source.  The type shall be a<u32>  and the value shall be 3.
> +
> +  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
> +  interrupts.
> +
> +  The 2nd cell contains the interrupt number for the interrupt type.
> +  SPI interrupts are in the range [0-987].  PPI interrupts are in the
> +  range [0-15].
> +
> +  The 3rd cell is the flags, encoded as follows:
> +	bits[3:0] trigger type and level flags.
> +		1 = low-to-high edge triggered
> +		2 = high-to-low edge triggered
> +		4 = active high level-sensitive
> +		8 = active low level-sensitive
> +	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
> +	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
> +	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
> +
> +- reg : Specifies base physical address(s) and size of the GIC registers. The
> +  first region is the GIC distributor register base and size. The 2nd region is
> +  the GIC cpu interface register base and size.
> +
> +Optional
> +- interrupts	: Interrupt source of the parent interrupt controller. Only
> +  present on secondary GICs.
> +
> +Example:
> +
> +	intc: interrupt-controller at fff11000 {
> +		compatible = "arm,cortex-a9-gic";
> +		#interrupt-cells =<3>;
> +		#address-cells =<1>;
> +		interrupt-controller;
> +		reg =<0xfff11000 0x1000>,
> +		<0xfff10100 0x100>;
> +	};
> +
> diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
> index 666b278..84e69a4 100644
> --- a/arch/arm/common/gic.c
> +++ b/arch/arm/common/gic.c
> @@ -28,6 +28,10 @@
>   #include<linux/smp.h>
>   #include<linux/cpumask.h>
>   #include<linux/io.h>
> +#include<linux/of.h>
> +#include<linux/of_address.h>
> +#include<linux/of_irq.h>
> +#include<linux/irqdomain.h>
> 
>   #include<asm/irq.h>
>   #include<asm/mach/irq.h>
> @@ -255,6 +259,15 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
>   	irq_set_chained_handler(irq, gic_handle_cascade_irq);
>   }
> 
> +static int gic_irq_count(void __iomem *dist_base)
> +{
> +	int gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR)&  0x1f;
> +	gic_irqs = (gic_irqs + 1) * 32;
> +	if (gic_irqs>  1020)
> +		gic_irqs = 1020;
> +	return gic_irqs;
> +}
> +
>   static void __init gic_dist_init(struct gic_chip_data *gic,
>   	unsigned int irq_start)
>   {
> @@ -277,10 +290,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
>   	 * Find out how many interrupts are supported.
>   	 * The GIC only supports up to 1020 interrupt sources.
>   	 */
> -	gic_irqs = readl_relaxed(base + GIC_DIST_CTR)&  0x1f;
> -	gic_irqs = (gic_irqs + 1) * 32;
> -	if (gic_irqs>  1020)
> -		gic_irqs = 1020;
> +	gic_irqs = gic_irq_count(base);
> 
>   	/*
>   	 * Set all global interrupts to be level triggered, active low.
> @@ -405,3 +415,74 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
>   	writel_relaxed(map<<  16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
>   }
>   #endif
> +
> +#ifdef CONFIG_OF
> +static int gic_cnt __initdata = 0;
> +
> +int gic_irq_domain_dt_translate(struct irq_domain *d,
> +			    struct device_node *controller,
> +			    const u32 *intspec, unsigned int intsize,
> +			    unsigned long *out_hwirq, unsigned int *out_type)
> +{
> +	struct gic_chip_data *gic_data = d->priv;
> +
> +	if (d->of_node != controller)
> +		return -EINVAL;
> +	if (intsize<  3)
> +		return -EINVAL;
> +
> +	*out_hwirq = intspec[1];
> +	/*
> +	 * We've already skipped over SGIs, so PPIs need no translation.
> +	 * For SPIs, we need to skip over 16 PPIs on primary GICs.
> +	 */
> +	if (!intspec[0]&&  !gic_data->irq_offset)
> +		*out_hwirq += 16;
> +
> +	*out_type = intspec[2]&  IRQ_TYPE_SENSE_MASK;
> +	return 0;
> +}
> +
> +struct irq_domain_ops gic_irq_domain_ops = {
> +	.dt_translate = gic_irq_domain_dt_translate,
> +};
> +
> +int __init gic_of_init(struct device_node *node, struct device_node *parent)
> +{
> +	void __iomem *cpu_base;
> +	void __iomem *dist_base;
> +	int irq;
> +	struct irq_domain *domain =&gic_data[gic_cnt].domain;
> +
> +	if (WARN_ON(!node))
> +		return -ENODEV;
> +
> +	dist_base = of_iomap(node, 0);
> +	WARN(!dist_base, "unable to map gic dist registers\n");
> +
> +	cpu_base = of_iomap(node, 1);
> +	WARN(!cpu_base, "unable to map gic cpu registers\n");
> +
> +	domain->nr_irq = gic_irq_count(dist_base);
> +	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
> +	if (parent)
> +		domain->nr_irq -= 32;
> +	else
> +		domain->nr_irq -= 16;
> +
> +	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
> +	domain->of_node = of_node_get(node);
> +	domain->ops =&gic_irq_domain_ops;
> +	domain->priv =&gic_data[gic_cnt];
> +	irq_domain_add(domain);
> +
> +	gic_init(gic_cnt, domain->irq_base, dist_base, cpu_base);
> +
> +	if (parent) {
> +		irq = irq_of_parse_and_map(node, 0);
> +		gic_cascade_irq(gic_cnt, irq);
> +	}
> +	gic_cnt++;
> +	return 0;
> +}
> +#endif
> diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
> index 435d3f8..2862d0e 100644
> --- a/arch/arm/include/asm/hardware/gic.h
> +++ b/arch/arm/include/asm/hardware/gic.h
> @@ -33,10 +33,21 @@
>   #define GIC_DIST_SOFTINT		0xf00
> 
>   #ifndef __ASSEMBLY__
> +#include<linux/irqdomain.h>
> +
>   extern void __iomem *gic_cpu_base_addr;
>   extern struct irq_chip gic_arch_extn;
> 
>   void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
> +#ifdef CONFIG_OF
> +int gic_of_init(struct device_node *node, struct device_node *parent);
> +#else
> +static inline void gic_of_init(struct device_node *node,
> +			       struct device_node *parent)
> +{
> +	return -ENODEV;
> +}
> +#endif
>   void gic_secondary_init(unsigned int);
>   void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
>   void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
> @@ -46,6 +57,7 @@ struct gic_chip_data {
>   	unsigned int irq_offset;
>   	void __iomem *dist_base;
>   	void __iomem *cpu_base;
> +	struct irq_domain domain;
>   };
>   #endif
> 

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-21  1:54       ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-21  1:54 UTC (permalink / raw)
  To: Grant Likely
  Cc: linux-arm-kernel, devicetree-discuss, linux-kernel, marc.zyngier,
	thomas.abraham, jamie, b-cousson, shawn.guo, dave.martin, linux,
	Rob Herring

On 09/20/2011 06:08 PM, Grant Likely wrote:
> On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
>> From: Rob Herring <rob.herring@calxeda.com>
>>
>> This adds ARM gic interrupt controller initialization using device tree
>> data.
>>
>> The initialization function is intended to be called by of_irq_init
>> function like this:
>>
>> const static struct of_device_id irq_match[] = {
>>         { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
>>         {}
>> };
>>
>> static void __init init_irqs(void)
>> {
>>         of_irq_init(irq_match);
>> }
>>
>> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
>> ---
>>  Documentation/devicetree/bindings/arm/gic.txt |   55 +++++++++++++++
>>  arch/arm/common/gic.c                         |   89 +++++++++++++++++++++++-
>>  arch/arm/include/asm/hardware/gic.h           |   12 ++++
>>  3 files changed, 152 insertions(+), 4 deletions(-)
>>  create mode 100644 Documentation/devicetree/bindings/arm/gic.txt
>>
>> diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
>> new file mode 100644
>> index 0000000..52916b4
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/gic.txt
>> @@ -0,0 +1,55 @@
>> +* ARM Generic Interrupt Controller
>> +
>> +ARM SMP cores are often associated with a GIC, providing per processor
>> +interrupts (PPI), shared processor interrupts (SPI) and software
>> +generated interrupts (SGI).
>> +
>> +Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
>> +Secondary GICs are cascaded into the upward interrupt controller and do not
>> +have PPIs or SGIs.
>> +
>> +Main node required properties:
>> +
>> +- compatible : should be one of:
>> +	"arm,cortex-a9-gic"
>> +	"arm,arm11mp-gic"
>> +- interrupt-controller : Identifies the node as an interrupt controller
>> +- #interrupt-cells : Specifies the number of cells needed to encode an
>> +  interrupt source.  The type shall be a <u32> and the value shall be 3.
>> +
>> +  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
>> +  interrupts.
>> +
>> +  The 2nd cell contains the interrupt number for the interrupt type.
>> +  SPI interrupts are in the range [0-987].  PPI interrupts are in the
>> +  range [0-15].
>> +
>> +  The 3rd cell is the flags, encoded as follows:
>> +	bits[3:0] trigger type and level flags.
>> +		1 = low-to-high edge triggered
>> +		2 = high-to-low edge triggered
>> +		4 = active high level-sensitive
>> +		8 = active low level-sensitive
>> +	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
>> +	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
>> +	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
>> +
>> +- reg : Specifies base physical address(s) and size of the GIC registers. The
>> +  first region is the GIC distributor register base and size. The 2nd region is
>> +  the GIC cpu interface register base and size.
>> +
>> +Optional
>> +- interrupts	: Interrupt source of the parent interrupt controller. Only
>> +  present on secondary GICs.
>> +
>> +Example:
>> +
>> +	intc: interrupt-controller@fff11000 {
>> +		compatible = "arm,cortex-a9-gic";
>> +		#interrupt-cells = <3>;
>> +		#address-cells = <1>;
>> +		interrupt-controller;
>> +		reg = <0xfff11000 0x1000>,
>> +		      <0xfff10100 0x100>;
>> +	};
>> +
> 
> Ack on the binding.
> 
>> diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
>> index 666b278..84e69a4 100644
>> --- a/arch/arm/common/gic.c
>> +++ b/arch/arm/common/gic.c
>> @@ -28,6 +28,10 @@
>>  #include <linux/smp.h>
>>  #include <linux/cpumask.h>
>>  #include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_irq.h>
>> +#include <linux/irqdomain.h>
>>  
>>  #include <asm/irq.h>
>>  #include <asm/mach/irq.h>
>> @@ -255,6 +259,15 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
>>  	irq_set_chained_handler(irq, gic_handle_cascade_irq);
>>  }
>>  
>> +static int gic_irq_count(void __iomem *dist_base)
>> +{
>> +	int gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
>> +	gic_irqs = (gic_irqs + 1) * 32;
>> +	if (gic_irqs > 1020)
>> +		gic_irqs = 1020;
>> +	return gic_irqs;
>> +}
>> +
>>  static void __init gic_dist_init(struct gic_chip_data *gic,
>>  	unsigned int irq_start)
>>  {
>> @@ -277,10 +290,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
>>  	 * Find out how many interrupts are supported.
>>  	 * The GIC only supports up to 1020 interrupt sources.
>>  	 */
>> -	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
>> -	gic_irqs = (gic_irqs + 1) * 32;
>> -	if (gic_irqs > 1020)
>> -		gic_irqs = 1020;
>> +	gic_irqs = gic_irq_count(base);
>>  
>>  	/*
>>  	 * Set all global interrupts to be level triggered, active low.
>> @@ -405,3 +415,74 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
>>  	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
>>  }
>>  #endif
>> +
>> +#ifdef CONFIG_OF
>> +static int gic_cnt __initdata = 0;
>> +
>> +int gic_irq_domain_dt_translate(struct irq_domain *d,
>> +			    struct device_node *controller,
>> +			    const u32 *intspec, unsigned int intsize,
>> +			    unsigned long *out_hwirq, unsigned int *out_type)
>> +{
>> +	struct gic_chip_data *gic_data = d->priv;
>> +
>> +	if (d->of_node != controller)
>> +		return -EINVAL;
>> +	if (intsize < 3)
>> +		return -EINVAL;
>> +
>> +	*out_hwirq = intspec[1];
>> +	/*
>> +	 * We've already skipped over SGIs, so PPIs need no translation.
>> +	 * For SPIs, we need to skip over 16 PPIs on primary GICs.
>> +	 */
>> +	if (!intspec[0] && !gic_data->irq_offset)
>> +		*out_hwirq += 16;
> 
> I though that the offset was 32 to get from SPI number to Interrrupt
> ID?  And that PPI interrupts start at Interrupt ID 16?  Or am I
> mistaken about the hwirq number that this driver uses internally?
> 

There's basically 2 cases to handle: primary and secondary controllers.

For primary ctrlrs, the domain irq_base is already 16 to skip over SGIs
and legacy ISA interrupts. So PPIs don't need any conversion and SPIs
only need 16 more added. I misspoke previously as it's not quite
independent of virq numbering because entry-macro-gic.S is still fixed
GIC ID = Linux virq (or offset of 32 in Exynos case).

For secondary ctrlrs, the gic code already accounts for 32 offset in ID
to Linux virq with the irq_offset field which is set to Linux virq base
- 32. So in this case, no conversion is needed.

I don't really see a better way without breaking non-DT use of the gic.

Rob

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-21  1:54       ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-21  1:54 UTC (permalink / raw)
  To: Grant Likely
  Cc: dave.martin-QSEj5FYQhm4dnm+yROfE0A, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On 09/20/2011 06:08 PM, Grant Likely wrote:
> On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
>> From: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
>>
>> This adds ARM gic interrupt controller initialization using device tree
>> data.
>>
>> The initialization function is intended to be called by of_irq_init
>> function like this:
>>
>> const static struct of_device_id irq_match[] = {
>>         { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
>>         {}
>> };
>>
>> static void __init init_irqs(void)
>> {
>>         of_irq_init(irq_match);
>> }
>>
>> Signed-off-by: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
>> ---
>>  Documentation/devicetree/bindings/arm/gic.txt |   55 +++++++++++++++
>>  arch/arm/common/gic.c                         |   89 +++++++++++++++++++++++-
>>  arch/arm/include/asm/hardware/gic.h           |   12 ++++
>>  3 files changed, 152 insertions(+), 4 deletions(-)
>>  create mode 100644 Documentation/devicetree/bindings/arm/gic.txt
>>
>> diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
>> new file mode 100644
>> index 0000000..52916b4
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/gic.txt
>> @@ -0,0 +1,55 @@
>> +* ARM Generic Interrupt Controller
>> +
>> +ARM SMP cores are often associated with a GIC, providing per processor
>> +interrupts (PPI), shared processor interrupts (SPI) and software
>> +generated interrupts (SGI).
>> +
>> +Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
>> +Secondary GICs are cascaded into the upward interrupt controller and do not
>> +have PPIs or SGIs.
>> +
>> +Main node required properties:
>> +
>> +- compatible : should be one of:
>> +	"arm,cortex-a9-gic"
>> +	"arm,arm11mp-gic"
>> +- interrupt-controller : Identifies the node as an interrupt controller
>> +- #interrupt-cells : Specifies the number of cells needed to encode an
>> +  interrupt source.  The type shall be a <u32> and the value shall be 3.
>> +
>> +  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
>> +  interrupts.
>> +
>> +  The 2nd cell contains the interrupt number for the interrupt type.
>> +  SPI interrupts are in the range [0-987].  PPI interrupts are in the
>> +  range [0-15].
>> +
>> +  The 3rd cell is the flags, encoded as follows:
>> +	bits[3:0] trigger type and level flags.
>> +		1 = low-to-high edge triggered
>> +		2 = high-to-low edge triggered
>> +		4 = active high level-sensitive
>> +		8 = active low level-sensitive
>> +	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
>> +	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
>> +	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
>> +
>> +- reg : Specifies base physical address(s) and size of the GIC registers. The
>> +  first region is the GIC distributor register base and size. The 2nd region is
>> +  the GIC cpu interface register base and size.
>> +
>> +Optional
>> +- interrupts	: Interrupt source of the parent interrupt controller. Only
>> +  present on secondary GICs.
>> +
>> +Example:
>> +
>> +	intc: interrupt-controller@fff11000 {
>> +		compatible = "arm,cortex-a9-gic";
>> +		#interrupt-cells = <3>;
>> +		#address-cells = <1>;
>> +		interrupt-controller;
>> +		reg = <0xfff11000 0x1000>,
>> +		      <0xfff10100 0x100>;
>> +	};
>> +
> 
> Ack on the binding.
> 
>> diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
>> index 666b278..84e69a4 100644
>> --- a/arch/arm/common/gic.c
>> +++ b/arch/arm/common/gic.c
>> @@ -28,6 +28,10 @@
>>  #include <linux/smp.h>
>>  #include <linux/cpumask.h>
>>  #include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_irq.h>
>> +#include <linux/irqdomain.h>
>>  
>>  #include <asm/irq.h>
>>  #include <asm/mach/irq.h>
>> @@ -255,6 +259,15 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
>>  	irq_set_chained_handler(irq, gic_handle_cascade_irq);
>>  }
>>  
>> +static int gic_irq_count(void __iomem *dist_base)
>> +{
>> +	int gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
>> +	gic_irqs = (gic_irqs + 1) * 32;
>> +	if (gic_irqs > 1020)
>> +		gic_irqs = 1020;
>> +	return gic_irqs;
>> +}
>> +
>>  static void __init gic_dist_init(struct gic_chip_data *gic,
>>  	unsigned int irq_start)
>>  {
>> @@ -277,10 +290,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
>>  	 * Find out how many interrupts are supported.
>>  	 * The GIC only supports up to 1020 interrupt sources.
>>  	 */
>> -	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
>> -	gic_irqs = (gic_irqs + 1) * 32;
>> -	if (gic_irqs > 1020)
>> -		gic_irqs = 1020;
>> +	gic_irqs = gic_irq_count(base);
>>  
>>  	/*
>>  	 * Set all global interrupts to be level triggered, active low.
>> @@ -405,3 +415,74 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
>>  	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
>>  }
>>  #endif
>> +
>> +#ifdef CONFIG_OF
>> +static int gic_cnt __initdata = 0;
>> +
>> +int gic_irq_domain_dt_translate(struct irq_domain *d,
>> +			    struct device_node *controller,
>> +			    const u32 *intspec, unsigned int intsize,
>> +			    unsigned long *out_hwirq, unsigned int *out_type)
>> +{
>> +	struct gic_chip_data *gic_data = d->priv;
>> +
>> +	if (d->of_node != controller)
>> +		return -EINVAL;
>> +	if (intsize < 3)
>> +		return -EINVAL;
>> +
>> +	*out_hwirq = intspec[1];
>> +	/*
>> +	 * We've already skipped over SGIs, so PPIs need no translation.
>> +	 * For SPIs, we need to skip over 16 PPIs on primary GICs.
>> +	 */
>> +	if (!intspec[0] && !gic_data->irq_offset)
>> +		*out_hwirq += 16;
> 
> I though that the offset was 32 to get from SPI number to Interrrupt
> ID?  And that PPI interrupts start at Interrupt ID 16?  Or am I
> mistaken about the hwirq number that this driver uses internally?
> 

There's basically 2 cases to handle: primary and secondary controllers.

For primary ctrlrs, the domain irq_base is already 16 to skip over SGIs
and legacy ISA interrupts. So PPIs don't need any conversion and SPIs
only need 16 more added. I misspoke previously as it's not quite
independent of virq numbering because entry-macro-gic.S is still fixed
GIC ID = Linux virq (or offset of 32 in Exynos case).

For secondary ctrlrs, the gic code already accounts for 32 offset in ID
to Linux virq with the irq_offset field which is set to Linux virq base
- 32. So in this case, no conversion is needed.

I don't really see a better way without breaking non-DT use of the gic.

Rob

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-21  1:54       ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-21  1:54 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/20/2011 06:08 PM, Grant Likely wrote:
> On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
>> From: Rob Herring <rob.herring@calxeda.com>
>>
>> This adds ARM gic interrupt controller initialization using device tree
>> data.
>>
>> The initialization function is intended to be called by of_irq_init
>> function like this:
>>
>> const static struct of_device_id irq_match[] = {
>>         { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
>>         {}
>> };
>>
>> static void __init init_irqs(void)
>> {
>>         of_irq_init(irq_match);
>> }
>>
>> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
>> ---
>>  Documentation/devicetree/bindings/arm/gic.txt |   55 +++++++++++++++
>>  arch/arm/common/gic.c                         |   89 +++++++++++++++++++++++-
>>  arch/arm/include/asm/hardware/gic.h           |   12 ++++
>>  3 files changed, 152 insertions(+), 4 deletions(-)
>>  create mode 100644 Documentation/devicetree/bindings/arm/gic.txt
>>
>> diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
>> new file mode 100644
>> index 0000000..52916b4
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/gic.txt
>> @@ -0,0 +1,55 @@
>> +* ARM Generic Interrupt Controller
>> +
>> +ARM SMP cores are often associated with a GIC, providing per processor
>> +interrupts (PPI), shared processor interrupts (SPI) and software
>> +generated interrupts (SGI).
>> +
>> +Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
>> +Secondary GICs are cascaded into the upward interrupt controller and do not
>> +have PPIs or SGIs.
>> +
>> +Main node required properties:
>> +
>> +- compatible : should be one of:
>> +	"arm,cortex-a9-gic"
>> +	"arm,arm11mp-gic"
>> +- interrupt-controller : Identifies the node as an interrupt controller
>> +- #interrupt-cells : Specifies the number of cells needed to encode an
>> +  interrupt source.  The type shall be a <u32> and the value shall be 3.
>> +
>> +  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
>> +  interrupts.
>> +
>> +  The 2nd cell contains the interrupt number for the interrupt type.
>> +  SPI interrupts are in the range [0-987].  PPI interrupts are in the
>> +  range [0-15].
>> +
>> +  The 3rd cell is the flags, encoded as follows:
>> +	bits[3:0] trigger type and level flags.
>> +		1 = low-to-high edge triggered
>> +		2 = high-to-low edge triggered
>> +		4 = active high level-sensitive
>> +		8 = active low level-sensitive
>> +	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
>> +	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
>> +	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
>> +
>> +- reg : Specifies base physical address(s) and size of the GIC registers. The
>> +  first region is the GIC distributor register base and size. The 2nd region is
>> +  the GIC cpu interface register base and size.
>> +
>> +Optional
>> +- interrupts	: Interrupt source of the parent interrupt controller. Only
>> +  present on secondary GICs.
>> +
>> +Example:
>> +
>> +	intc: interrupt-controller at fff11000 {
>> +		compatible = "arm,cortex-a9-gic";
>> +		#interrupt-cells = <3>;
>> +		#address-cells = <1>;
>> +		interrupt-controller;
>> +		reg = <0xfff11000 0x1000>,
>> +		      <0xfff10100 0x100>;
>> +	};
>> +
> 
> Ack on the binding.
> 
>> diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
>> index 666b278..84e69a4 100644
>> --- a/arch/arm/common/gic.c
>> +++ b/arch/arm/common/gic.c
>> @@ -28,6 +28,10 @@
>>  #include <linux/smp.h>
>>  #include <linux/cpumask.h>
>>  #include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_irq.h>
>> +#include <linux/irqdomain.h>
>>  
>>  #include <asm/irq.h>
>>  #include <asm/mach/irq.h>
>> @@ -255,6 +259,15 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
>>  	irq_set_chained_handler(irq, gic_handle_cascade_irq);
>>  }
>>  
>> +static int gic_irq_count(void __iomem *dist_base)
>> +{
>> +	int gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
>> +	gic_irqs = (gic_irqs + 1) * 32;
>> +	if (gic_irqs > 1020)
>> +		gic_irqs = 1020;
>> +	return gic_irqs;
>> +}
>> +
>>  static void __init gic_dist_init(struct gic_chip_data *gic,
>>  	unsigned int irq_start)
>>  {
>> @@ -277,10 +290,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
>>  	 * Find out how many interrupts are supported.
>>  	 * The GIC only supports up to 1020 interrupt sources.
>>  	 */
>> -	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
>> -	gic_irqs = (gic_irqs + 1) * 32;
>> -	if (gic_irqs > 1020)
>> -		gic_irqs = 1020;
>> +	gic_irqs = gic_irq_count(base);
>>  
>>  	/*
>>  	 * Set all global interrupts to be level triggered, active low.
>> @@ -405,3 +415,74 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
>>  	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
>>  }
>>  #endif
>> +
>> +#ifdef CONFIG_OF
>> +static int gic_cnt __initdata = 0;
>> +
>> +int gic_irq_domain_dt_translate(struct irq_domain *d,
>> +			    struct device_node *controller,
>> +			    const u32 *intspec, unsigned int intsize,
>> +			    unsigned long *out_hwirq, unsigned int *out_type)
>> +{
>> +	struct gic_chip_data *gic_data = d->priv;
>> +
>> +	if (d->of_node != controller)
>> +		return -EINVAL;
>> +	if (intsize < 3)
>> +		return -EINVAL;
>> +
>> +	*out_hwirq = intspec[1];
>> +	/*
>> +	 * We've already skipped over SGIs, so PPIs need no translation.
>> +	 * For SPIs, we need to skip over 16 PPIs on primary GICs.
>> +	 */
>> +	if (!intspec[0] && !gic_data->irq_offset)
>> +		*out_hwirq += 16;
> 
> I though that the offset was 32 to get from SPI number to Interrrupt
> ID?  And that PPI interrupts start at Interrupt ID 16?  Or am I
> mistaken about the hwirq number that this driver uses internally?
> 

There's basically 2 cases to handle: primary and secondary controllers.

For primary ctrlrs, the domain irq_base is already 16 to skip over SGIs
and legacy ISA interrupts. So PPIs don't need any conversion and SPIs
only need 16 more added. I misspoke previously as it's not quite
independent of virq numbering because entry-macro-gic.S is still fixed
GIC ID = Linux virq (or offset of 32 in Exynos case).

For secondary ctrlrs, the gic code already accounts for 32 offset in ID
to Linux virq with the irq_offset field which is set to Linux virq base
- 32. So in this case, no conversion is needed.

I don't really see a better way without breaking non-DT use of the gic.

Rob

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-20 23:08     ` Grant Likely
  0 siblings, 0 replies; 68+ messages in thread
From: Grant Likely @ 2011-09-20 23:08 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-arm-kernel, devicetree-discuss, linux-kernel, marc.zyngier,
	thomas.abraham, jamie, b-cousson, shawn.guo, dave.martin, linux,
	Rob Herring

On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> This adds ARM gic interrupt controller initialization using device tree
> data.
> 
> The initialization function is intended to be called by of_irq_init
> function like this:
> 
> const static struct of_device_id irq_match[] = {
>         { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
>         {}
> };
> 
> static void __init init_irqs(void)
> {
>         of_irq_init(irq_match);
> }
> 
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> ---
>  Documentation/devicetree/bindings/arm/gic.txt |   55 +++++++++++++++
>  arch/arm/common/gic.c                         |   89 +++++++++++++++++++++++-
>  arch/arm/include/asm/hardware/gic.h           |   12 ++++
>  3 files changed, 152 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/gic.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
> new file mode 100644
> index 0000000..52916b4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/gic.txt
> @@ -0,0 +1,55 @@
> +* ARM Generic Interrupt Controller
> +
> +ARM SMP cores are often associated with a GIC, providing per processor
> +interrupts (PPI), shared processor interrupts (SPI) and software
> +generated interrupts (SGI).
> +
> +Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
> +Secondary GICs are cascaded into the upward interrupt controller and do not
> +have PPIs or SGIs.
> +
> +Main node required properties:
> +
> +- compatible : should be one of:
> +	"arm,cortex-a9-gic"
> +	"arm,arm11mp-gic"
> +- interrupt-controller : Identifies the node as an interrupt controller
> +- #interrupt-cells : Specifies the number of cells needed to encode an
> +  interrupt source.  The type shall be a <u32> and the value shall be 3.
> +
> +  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
> +  interrupts.
> +
> +  The 2nd cell contains the interrupt number for the interrupt type.
> +  SPI interrupts are in the range [0-987].  PPI interrupts are in the
> +  range [0-15].
> +
> +  The 3rd cell is the flags, encoded as follows:
> +	bits[3:0] trigger type and level flags.
> +		1 = low-to-high edge triggered
> +		2 = high-to-low edge triggered
> +		4 = active high level-sensitive
> +		8 = active low level-sensitive
> +	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
> +	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
> +	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
> +
> +- reg : Specifies base physical address(s) and size of the GIC registers. The
> +  first region is the GIC distributor register base and size. The 2nd region is
> +  the GIC cpu interface register base and size.
> +
> +Optional
> +- interrupts	: Interrupt source of the parent interrupt controller. Only
> +  present on secondary GICs.
> +
> +Example:
> +
> +	intc: interrupt-controller@fff11000 {
> +		compatible = "arm,cortex-a9-gic";
> +		#interrupt-cells = <3>;
> +		#address-cells = <1>;
> +		interrupt-controller;
> +		reg = <0xfff11000 0x1000>,
> +		      <0xfff10100 0x100>;
> +	};
> +

Ack on the binding.

> diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
> index 666b278..84e69a4 100644
> --- a/arch/arm/common/gic.c
> +++ b/arch/arm/common/gic.c
> @@ -28,6 +28,10 @@
>  #include <linux/smp.h>
>  #include <linux/cpumask.h>
>  #include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/irqdomain.h>
>  
>  #include <asm/irq.h>
>  #include <asm/mach/irq.h>
> @@ -255,6 +259,15 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
>  	irq_set_chained_handler(irq, gic_handle_cascade_irq);
>  }
>  
> +static int gic_irq_count(void __iomem *dist_base)
> +{
> +	int gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
> +	gic_irqs = (gic_irqs + 1) * 32;
> +	if (gic_irqs > 1020)
> +		gic_irqs = 1020;
> +	return gic_irqs;
> +}
> +
>  static void __init gic_dist_init(struct gic_chip_data *gic,
>  	unsigned int irq_start)
>  {
> @@ -277,10 +290,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
>  	 * Find out how many interrupts are supported.
>  	 * The GIC only supports up to 1020 interrupt sources.
>  	 */
> -	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
> -	gic_irqs = (gic_irqs + 1) * 32;
> -	if (gic_irqs > 1020)
> -		gic_irqs = 1020;
> +	gic_irqs = gic_irq_count(base);
>  
>  	/*
>  	 * Set all global interrupts to be level triggered, active low.
> @@ -405,3 +415,74 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
>  	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
>  }
>  #endif
> +
> +#ifdef CONFIG_OF
> +static int gic_cnt __initdata = 0;
> +
> +int gic_irq_domain_dt_translate(struct irq_domain *d,
> +			    struct device_node *controller,
> +			    const u32 *intspec, unsigned int intsize,
> +			    unsigned long *out_hwirq, unsigned int *out_type)
> +{
> +	struct gic_chip_data *gic_data = d->priv;
> +
> +	if (d->of_node != controller)
> +		return -EINVAL;
> +	if (intsize < 3)
> +		return -EINVAL;
> +
> +	*out_hwirq = intspec[1];
> +	/*
> +	 * We've already skipped over SGIs, so PPIs need no translation.
> +	 * For SPIs, we need to skip over 16 PPIs on primary GICs.
> +	 */
> +	if (!intspec[0] && !gic_data->irq_offset)
> +		*out_hwirq += 16;

I though that the offset was 32 to get from SPI number to Interrrupt
ID?  And that PPI interrupts start at Interrupt ID 16?  Or am I
mistaken about the hwirq number that this driver uses internally?

Otherwise, the change looks about right to me.

g.

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-20 23:08     ` Grant Likely
  0 siblings, 0 replies; 68+ messages in thread
From: Grant Likely @ 2011-09-20 23:08 UTC (permalink / raw)
  To: Rob Herring
  Cc: dave.martin-QSEj5FYQhm4dnm+yROfE0A, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
> From: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
> 
> This adds ARM gic interrupt controller initialization using device tree
> data.
> 
> The initialization function is intended to be called by of_irq_init
> function like this:
> 
> const static struct of_device_id irq_match[] = {
>         { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
>         {}
> };
> 
> static void __init init_irqs(void)
> {
>         of_irq_init(irq_match);
> }
> 
> Signed-off-by: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/arm/gic.txt |   55 +++++++++++++++
>  arch/arm/common/gic.c                         |   89 +++++++++++++++++++++++-
>  arch/arm/include/asm/hardware/gic.h           |   12 ++++
>  3 files changed, 152 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/gic.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
> new file mode 100644
> index 0000000..52916b4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/gic.txt
> @@ -0,0 +1,55 @@
> +* ARM Generic Interrupt Controller
> +
> +ARM SMP cores are often associated with a GIC, providing per processor
> +interrupts (PPI), shared processor interrupts (SPI) and software
> +generated interrupts (SGI).
> +
> +Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
> +Secondary GICs are cascaded into the upward interrupt controller and do not
> +have PPIs or SGIs.
> +
> +Main node required properties:
> +
> +- compatible : should be one of:
> +	"arm,cortex-a9-gic"
> +	"arm,arm11mp-gic"
> +- interrupt-controller : Identifies the node as an interrupt controller
> +- #interrupt-cells : Specifies the number of cells needed to encode an
> +  interrupt source.  The type shall be a <u32> and the value shall be 3.
> +
> +  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
> +  interrupts.
> +
> +  The 2nd cell contains the interrupt number for the interrupt type.
> +  SPI interrupts are in the range [0-987].  PPI interrupts are in the
> +  range [0-15].
> +
> +  The 3rd cell is the flags, encoded as follows:
> +	bits[3:0] trigger type and level flags.
> +		1 = low-to-high edge triggered
> +		2 = high-to-low edge triggered
> +		4 = active high level-sensitive
> +		8 = active low level-sensitive
> +	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
> +	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
> +	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
> +
> +- reg : Specifies base physical address(s) and size of the GIC registers. The
> +  first region is the GIC distributor register base and size. The 2nd region is
> +  the GIC cpu interface register base and size.
> +
> +Optional
> +- interrupts	: Interrupt source of the parent interrupt controller. Only
> +  present on secondary GICs.
> +
> +Example:
> +
> +	intc: interrupt-controller@fff11000 {
> +		compatible = "arm,cortex-a9-gic";
> +		#interrupt-cells = <3>;
> +		#address-cells = <1>;
> +		interrupt-controller;
> +		reg = <0xfff11000 0x1000>,
> +		      <0xfff10100 0x100>;
> +	};
> +

Ack on the binding.

> diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
> index 666b278..84e69a4 100644
> --- a/arch/arm/common/gic.c
> +++ b/arch/arm/common/gic.c
> @@ -28,6 +28,10 @@
>  #include <linux/smp.h>
>  #include <linux/cpumask.h>
>  #include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/irqdomain.h>
>  
>  #include <asm/irq.h>
>  #include <asm/mach/irq.h>
> @@ -255,6 +259,15 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
>  	irq_set_chained_handler(irq, gic_handle_cascade_irq);
>  }
>  
> +static int gic_irq_count(void __iomem *dist_base)
> +{
> +	int gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
> +	gic_irqs = (gic_irqs + 1) * 32;
> +	if (gic_irqs > 1020)
> +		gic_irqs = 1020;
> +	return gic_irqs;
> +}
> +
>  static void __init gic_dist_init(struct gic_chip_data *gic,
>  	unsigned int irq_start)
>  {
> @@ -277,10 +290,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
>  	 * Find out how many interrupts are supported.
>  	 * The GIC only supports up to 1020 interrupt sources.
>  	 */
> -	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
> -	gic_irqs = (gic_irqs + 1) * 32;
> -	if (gic_irqs > 1020)
> -		gic_irqs = 1020;
> +	gic_irqs = gic_irq_count(base);
>  
>  	/*
>  	 * Set all global interrupts to be level triggered, active low.
> @@ -405,3 +415,74 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
>  	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
>  }
>  #endif
> +
> +#ifdef CONFIG_OF
> +static int gic_cnt __initdata = 0;
> +
> +int gic_irq_domain_dt_translate(struct irq_domain *d,
> +			    struct device_node *controller,
> +			    const u32 *intspec, unsigned int intsize,
> +			    unsigned long *out_hwirq, unsigned int *out_type)
> +{
> +	struct gic_chip_data *gic_data = d->priv;
> +
> +	if (d->of_node != controller)
> +		return -EINVAL;
> +	if (intsize < 3)
> +		return -EINVAL;
> +
> +	*out_hwirq = intspec[1];
> +	/*
> +	 * We've already skipped over SGIs, so PPIs need no translation.
> +	 * For SPIs, we need to skip over 16 PPIs on primary GICs.
> +	 */
> +	if (!intspec[0] && !gic_data->irq_offset)
> +		*out_hwirq += 16;

I though that the offset was 32 to get from SPI number to Interrrupt
ID?  And that PPI interrupts start at Interrupt ID 16?  Or am I
mistaken about the hwirq number that this driver uses internally?

Otherwise, the change looks about right to me.

g.

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-20 23:08     ` Grant Likely
  0 siblings, 0 replies; 68+ messages in thread
From: Grant Likely @ 2011-09-20 23:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Sep 20, 2011 at 03:24:04PM -0500, Rob Herring wrote:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> This adds ARM gic interrupt controller initialization using device tree
> data.
> 
> The initialization function is intended to be called by of_irq_init
> function like this:
> 
> const static struct of_device_id irq_match[] = {
>         { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
>         {}
> };
> 
> static void __init init_irqs(void)
> {
>         of_irq_init(irq_match);
> }
> 
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> ---
>  Documentation/devicetree/bindings/arm/gic.txt |   55 +++++++++++++++
>  arch/arm/common/gic.c                         |   89 +++++++++++++++++++++++-
>  arch/arm/include/asm/hardware/gic.h           |   12 ++++
>  3 files changed, 152 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/arm/gic.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
> new file mode 100644
> index 0000000..52916b4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/gic.txt
> @@ -0,0 +1,55 @@
> +* ARM Generic Interrupt Controller
> +
> +ARM SMP cores are often associated with a GIC, providing per processor
> +interrupts (PPI), shared processor interrupts (SPI) and software
> +generated interrupts (SGI).
> +
> +Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
> +Secondary GICs are cascaded into the upward interrupt controller and do not
> +have PPIs or SGIs.
> +
> +Main node required properties:
> +
> +- compatible : should be one of:
> +	"arm,cortex-a9-gic"
> +	"arm,arm11mp-gic"
> +- interrupt-controller : Identifies the node as an interrupt controller
> +- #interrupt-cells : Specifies the number of cells needed to encode an
> +  interrupt source.  The type shall be a <u32> and the value shall be 3.
> +
> +  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
> +  interrupts.
> +
> +  The 2nd cell contains the interrupt number for the interrupt type.
> +  SPI interrupts are in the range [0-987].  PPI interrupts are in the
> +  range [0-15].
> +
> +  The 3rd cell is the flags, encoded as follows:
> +	bits[3:0] trigger type and level flags.
> +		1 = low-to-high edge triggered
> +		2 = high-to-low edge triggered
> +		4 = active high level-sensitive
> +		8 = active low level-sensitive
> +	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
> +	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
> +	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
> +
> +- reg : Specifies base physical address(s) and size of the GIC registers. The
> +  first region is the GIC distributor register base and size. The 2nd region is
> +  the GIC cpu interface register base and size.
> +
> +Optional
> +- interrupts	: Interrupt source of the parent interrupt controller. Only
> +  present on secondary GICs.
> +
> +Example:
> +
> +	intc: interrupt-controller at fff11000 {
> +		compatible = "arm,cortex-a9-gic";
> +		#interrupt-cells = <3>;
> +		#address-cells = <1>;
> +		interrupt-controller;
> +		reg = <0xfff11000 0x1000>,
> +		      <0xfff10100 0x100>;
> +	};
> +

Ack on the binding.

> diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
> index 666b278..84e69a4 100644
> --- a/arch/arm/common/gic.c
> +++ b/arch/arm/common/gic.c
> @@ -28,6 +28,10 @@
>  #include <linux/smp.h>
>  #include <linux/cpumask.h>
>  #include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/irqdomain.h>
>  
>  #include <asm/irq.h>
>  #include <asm/mach/irq.h>
> @@ -255,6 +259,15 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
>  	irq_set_chained_handler(irq, gic_handle_cascade_irq);
>  }
>  
> +static int gic_irq_count(void __iomem *dist_base)
> +{
> +	int gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
> +	gic_irqs = (gic_irqs + 1) * 32;
> +	if (gic_irqs > 1020)
> +		gic_irqs = 1020;
> +	return gic_irqs;
> +}
> +
>  static void __init gic_dist_init(struct gic_chip_data *gic,
>  	unsigned int irq_start)
>  {
> @@ -277,10 +290,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
>  	 * Find out how many interrupts are supported.
>  	 * The GIC only supports up to 1020 interrupt sources.
>  	 */
> -	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
> -	gic_irqs = (gic_irqs + 1) * 32;
> -	if (gic_irqs > 1020)
> -		gic_irqs = 1020;
> +	gic_irqs = gic_irq_count(base);
>  
>  	/*
>  	 * Set all global interrupts to be level triggered, active low.
> @@ -405,3 +415,74 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
>  	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
>  }
>  #endif
> +
> +#ifdef CONFIG_OF
> +static int gic_cnt __initdata = 0;
> +
> +int gic_irq_domain_dt_translate(struct irq_domain *d,
> +			    struct device_node *controller,
> +			    const u32 *intspec, unsigned int intsize,
> +			    unsigned long *out_hwirq, unsigned int *out_type)
> +{
> +	struct gic_chip_data *gic_data = d->priv;
> +
> +	if (d->of_node != controller)
> +		return -EINVAL;
> +	if (intsize < 3)
> +		return -EINVAL;
> +
> +	*out_hwirq = intspec[1];
> +	/*
> +	 * We've already skipped over SGIs, so PPIs need no translation.
> +	 * For SPIs, we need to skip over 16 PPIs on primary GICs.
> +	 */
> +	if (!intspec[0] && !gic_data->irq_offset)
> +		*out_hwirq += 16;

I though that the offset was 32 to get from SPI number to Interrrupt
ID?  And that PPI interrupts start at Interrupt ID 16?  Or am I
mistaken about the hwirq number that this driver uses internally?

Otherwise, the change looks about right to me.

g.

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-20 20:24   ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-20 20:24 UTC (permalink / raw)
  To: linux-arm-kernel, devicetree-discuss, linux-kernel
  Cc: grant.likely, marc.zyngier, thomas.abraham, jamie, b-cousson,
	shawn.guo, dave.martin, linux, Rob Herring

From: Rob Herring <rob.herring@calxeda.com>

This adds ARM gic interrupt controller initialization using device tree
data.

The initialization function is intended to be called by of_irq_init
function like this:

const static struct of_device_id irq_match[] = {
        { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
        {}
};

static void __init init_irqs(void)
{
        of_irq_init(irq_match);
}

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 Documentation/devicetree/bindings/arm/gic.txt |   55 +++++++++++++++
 arch/arm/common/gic.c                         |   89 +++++++++++++++++++++++-
 arch/arm/include/asm/hardware/gic.h           |   12 ++++
 3 files changed, 152 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/gic.txt

diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
new file mode 100644
index 0000000..52916b4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/gic.txt
@@ -0,0 +1,55 @@
+* ARM Generic Interrupt Controller
+
+ARM SMP cores are often associated with a GIC, providing per processor
+interrupts (PPI), shared processor interrupts (SPI) and software
+generated interrupts (SGI).
+
+Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
+Secondary GICs are cascaded into the upward interrupt controller and do not
+have PPIs or SGIs.
+
+Main node required properties:
+
+- compatible : should be one of:
+	"arm,cortex-a9-gic"
+	"arm,arm11mp-gic"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source.  The type shall be a <u32> and the value shall be 3.
+
+  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
+  interrupts.
+
+  The 2nd cell contains the interrupt number for the interrupt type.
+  SPI interrupts are in the range [0-987].  PPI interrupts are in the
+  range [0-15].
+
+  The 3rd cell is the flags, encoded as follows:
+	bits[3:0] trigger type and level flags.
+		1 = low-to-high edge triggered
+		2 = high-to-low edge triggered
+		4 = active high level-sensitive
+		8 = active low level-sensitive
+	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
+	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
+	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
+
+- reg : Specifies base physical address(s) and size of the GIC registers. The
+  first region is the GIC distributor register base and size. The 2nd region is
+  the GIC cpu interface register base and size.
+
+Optional
+- interrupts	: Interrupt source of the parent interrupt controller. Only
+  present on secondary GICs.
+
+Example:
+
+	intc: interrupt-controller@fff11000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <1>;
+		interrupt-controller;
+		reg = <0xfff11000 0x1000>,
+		      <0xfff10100 0x100>;
+	};
+
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 666b278..84e69a4 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -28,6 +28,10 @@
 #include <linux/smp.h>
 #include <linux/cpumask.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
 
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
@@ -255,6 +259,15 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 	irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
+static int gic_irq_count(void __iomem *dist_base)
+{
+	int gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
+	gic_irqs = (gic_irqs + 1) * 32;
+	if (gic_irqs > 1020)
+		gic_irqs = 1020;
+	return gic_irqs;
+}
+
 static void __init gic_dist_init(struct gic_chip_data *gic,
 	unsigned int irq_start)
 {
@@ -277,10 +290,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 	 * Find out how many interrupts are supported.
 	 * The GIC only supports up to 1020 interrupt sources.
 	 */
-	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
-	gic_irqs = (gic_irqs + 1) * 32;
-	if (gic_irqs > 1020)
-		gic_irqs = 1020;
+	gic_irqs = gic_irq_count(base);
 
 	/*
 	 * Set all global interrupts to be level triggered, active low.
@@ -405,3 +415,74 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
 }
 #endif
+
+#ifdef CONFIG_OF
+static int gic_cnt __initdata = 0;
+
+int gic_irq_domain_dt_translate(struct irq_domain *d,
+			    struct device_node *controller,
+			    const u32 *intspec, unsigned int intsize,
+			    unsigned long *out_hwirq, unsigned int *out_type)
+{
+	struct gic_chip_data *gic_data = d->priv;
+
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 3)
+		return -EINVAL;
+
+	*out_hwirq = intspec[1];
+	/*
+	 * We've already skipped over SGIs, so PPIs need no translation.
+	 * For SPIs, we need to skip over 16 PPIs on primary GICs.
+	 */
+	if (!intspec[0] && !gic_data->irq_offset)
+		*out_hwirq += 16;
+
+	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+
+struct irq_domain_ops gic_irq_domain_ops = {
+	.dt_translate = gic_irq_domain_dt_translate,
+};
+
+int __init gic_of_init(struct device_node *node, struct device_node *parent)
+{
+	void __iomem *cpu_base;
+	void __iomem *dist_base;
+	int irq;
+	struct irq_domain *domain = &gic_data[gic_cnt].domain;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	dist_base = of_iomap(node, 0);
+	WARN(!dist_base, "unable to map gic dist registers\n");
+
+	cpu_base = of_iomap(node, 1);
+	WARN(!cpu_base, "unable to map gic cpu registers\n");
+
+	domain->nr_irq = gic_irq_count(dist_base);
+	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
+	if (parent)
+		domain->nr_irq -= 32;
+	else
+		domain->nr_irq -= 16;
+
+	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
+	domain->of_node = of_node_get(node);
+	domain->ops = &gic_irq_domain_ops;
+	domain->priv = &gic_data[gic_cnt];
+	irq_domain_add(domain);
+
+	gic_init(gic_cnt, domain->irq_base, dist_base, cpu_base);
+
+	if (parent) {
+		irq = irq_of_parse_and_map(node, 0);
+		gic_cascade_irq(gic_cnt, irq);
+	}
+	gic_cnt++;
+	return 0;
+}
+#endif
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 435d3f8..2862d0e 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -33,10 +33,21 @@
 #define GIC_DIST_SOFTINT		0xf00
 
 #ifndef __ASSEMBLY__
+#include <linux/irqdomain.h>
+
 extern void __iomem *gic_cpu_base_addr;
 extern struct irq_chip gic_arch_extn;
 
 void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
+#ifdef CONFIG_OF
+int gic_of_init(struct device_node *node, struct device_node *parent);
+#else
+static inline void gic_of_init(struct device_node *node,
+			       struct device_node *parent)
+{
+	return -ENODEV;
+}
+#endif
 void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
@@ -46,6 +57,7 @@ struct gic_chip_data {
 	unsigned int irq_offset;
 	void __iomem *dist_base;
 	void __iomem *cpu_base;
+	struct irq_domain domain;
 };
 #endif
 
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-20 20:24   ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-20 20:24 UTC (permalink / raw)
  To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
  Cc: dave.martin-QSEj5FYQhm4dnm+yROfE0A, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	Rob Herring

From: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>

This adds ARM gic interrupt controller initialization using device tree
data.

The initialization function is intended to be called by of_irq_init
function like this:

const static struct of_device_id irq_match[] = {
        { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
        {}
};

static void __init init_irqs(void)
{
        of_irq_init(irq_match);
}

Signed-off-by: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
---
 Documentation/devicetree/bindings/arm/gic.txt |   55 +++++++++++++++
 arch/arm/common/gic.c                         |   89 +++++++++++++++++++++++-
 arch/arm/include/asm/hardware/gic.h           |   12 ++++
 3 files changed, 152 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/gic.txt

diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
new file mode 100644
index 0000000..52916b4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/gic.txt
@@ -0,0 +1,55 @@
+* ARM Generic Interrupt Controller
+
+ARM SMP cores are often associated with a GIC, providing per processor
+interrupts (PPI), shared processor interrupts (SPI) and software
+generated interrupts (SGI).
+
+Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
+Secondary GICs are cascaded into the upward interrupt controller and do not
+have PPIs or SGIs.
+
+Main node required properties:
+
+- compatible : should be one of:
+	"arm,cortex-a9-gic"
+	"arm,arm11mp-gic"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source.  The type shall be a <u32> and the value shall be 3.
+
+  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
+  interrupts.
+
+  The 2nd cell contains the interrupt number for the interrupt type.
+  SPI interrupts are in the range [0-987].  PPI interrupts are in the
+  range [0-15].
+
+  The 3rd cell is the flags, encoded as follows:
+	bits[3:0] trigger type and level flags.
+		1 = low-to-high edge triggered
+		2 = high-to-low edge triggered
+		4 = active high level-sensitive
+		8 = active low level-sensitive
+	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
+	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
+	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
+
+- reg : Specifies base physical address(s) and size of the GIC registers. The
+  first region is the GIC distributor register base and size. The 2nd region is
+  the GIC cpu interface register base and size.
+
+Optional
+- interrupts	: Interrupt source of the parent interrupt controller. Only
+  present on secondary GICs.
+
+Example:
+
+	intc: interrupt-controller@fff11000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <1>;
+		interrupt-controller;
+		reg = <0xfff11000 0x1000>,
+		      <0xfff10100 0x100>;
+	};
+
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 666b278..84e69a4 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -28,6 +28,10 @@
 #include <linux/smp.h>
 #include <linux/cpumask.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
 
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
@@ -255,6 +259,15 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 	irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
+static int gic_irq_count(void __iomem *dist_base)
+{
+	int gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
+	gic_irqs = (gic_irqs + 1) * 32;
+	if (gic_irqs > 1020)
+		gic_irqs = 1020;
+	return gic_irqs;
+}
+
 static void __init gic_dist_init(struct gic_chip_data *gic,
 	unsigned int irq_start)
 {
@@ -277,10 +290,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 	 * Find out how many interrupts are supported.
 	 * The GIC only supports up to 1020 interrupt sources.
 	 */
-	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
-	gic_irqs = (gic_irqs + 1) * 32;
-	if (gic_irqs > 1020)
-		gic_irqs = 1020;
+	gic_irqs = gic_irq_count(base);
 
 	/*
 	 * Set all global interrupts to be level triggered, active low.
@@ -405,3 +415,74 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
 }
 #endif
+
+#ifdef CONFIG_OF
+static int gic_cnt __initdata = 0;
+
+int gic_irq_domain_dt_translate(struct irq_domain *d,
+			    struct device_node *controller,
+			    const u32 *intspec, unsigned int intsize,
+			    unsigned long *out_hwirq, unsigned int *out_type)
+{
+	struct gic_chip_data *gic_data = d->priv;
+
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 3)
+		return -EINVAL;
+
+	*out_hwirq = intspec[1];
+	/*
+	 * We've already skipped over SGIs, so PPIs need no translation.
+	 * For SPIs, we need to skip over 16 PPIs on primary GICs.
+	 */
+	if (!intspec[0] && !gic_data->irq_offset)
+		*out_hwirq += 16;
+
+	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+
+struct irq_domain_ops gic_irq_domain_ops = {
+	.dt_translate = gic_irq_domain_dt_translate,
+};
+
+int __init gic_of_init(struct device_node *node, struct device_node *parent)
+{
+	void __iomem *cpu_base;
+	void __iomem *dist_base;
+	int irq;
+	struct irq_domain *domain = &gic_data[gic_cnt].domain;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	dist_base = of_iomap(node, 0);
+	WARN(!dist_base, "unable to map gic dist registers\n");
+
+	cpu_base = of_iomap(node, 1);
+	WARN(!cpu_base, "unable to map gic cpu registers\n");
+
+	domain->nr_irq = gic_irq_count(dist_base);
+	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
+	if (parent)
+		domain->nr_irq -= 32;
+	else
+		domain->nr_irq -= 16;
+
+	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
+	domain->of_node = of_node_get(node);
+	domain->ops = &gic_irq_domain_ops;
+	domain->priv = &gic_data[gic_cnt];
+	irq_domain_add(domain);
+
+	gic_init(gic_cnt, domain->irq_base, dist_base, cpu_base);
+
+	if (parent) {
+		irq = irq_of_parse_and_map(node, 0);
+		gic_cascade_irq(gic_cnt, irq);
+	}
+	gic_cnt++;
+	return 0;
+}
+#endif
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 435d3f8..2862d0e 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -33,10 +33,21 @@
 #define GIC_DIST_SOFTINT		0xf00
 
 #ifndef __ASSEMBLY__
+#include <linux/irqdomain.h>
+
 extern void __iomem *gic_cpu_base_addr;
 extern struct irq_chip gic_arch_extn;
 
 void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
+#ifdef CONFIG_OF
+int gic_of_init(struct device_node *node, struct device_node *parent);
+#else
+static inline void gic_of_init(struct device_node *node,
+			       struct device_node *parent)
+{
+	return -ENODEV;
+}
+#endif
 void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
@@ -46,6 +57,7 @@ struct gic_chip_data {
 	unsigned int irq_offset;
 	void __iomem *dist_base;
 	void __iomem *cpu_base;
+	struct irq_domain domain;
 };
 #endif
 
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 3/3] ARM: gic: add OF based initialization
@ 2011-09-20 20:24   ` Rob Herring
  0 siblings, 0 replies; 68+ messages in thread
From: Rob Herring @ 2011-09-20 20:24 UTC (permalink / raw)
  To: linux-arm-kernel

From: Rob Herring <rob.herring@calxeda.com>

This adds ARM gic interrupt controller initialization using device tree
data.

The initialization function is intended to be called by of_irq_init
function like this:

const static struct of_device_id irq_match[] = {
        { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
        {}
};

static void __init init_irqs(void)
{
        of_irq_init(irq_match);
}

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
 Documentation/devicetree/bindings/arm/gic.txt |   55 +++++++++++++++
 arch/arm/common/gic.c                         |   89 +++++++++++++++++++++++-
 arch/arm/include/asm/hardware/gic.h           |   12 ++++
 3 files changed, 152 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/gic.txt

diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
new file mode 100644
index 0000000..52916b4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/gic.txt
@@ -0,0 +1,55 @@
+* ARM Generic Interrupt Controller
+
+ARM SMP cores are often associated with a GIC, providing per processor
+interrupts (PPI), shared processor interrupts (SPI) and software
+generated interrupts (SGI).
+
+Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.
+Secondary GICs are cascaded into the upward interrupt controller and do not
+have PPIs or SGIs.
+
+Main node required properties:
+
+- compatible : should be one of:
+	"arm,cortex-a9-gic"
+	"arm,arm11mp-gic"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source.  The type shall be a <u32> and the value shall be 3.
+
+  The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
+  interrupts.
+
+  The 2nd cell contains the interrupt number for the interrupt type.
+  SPI interrupts are in the range [0-987].  PPI interrupts are in the
+  range [0-15].
+
+  The 3rd cell is the flags, encoded as follows:
+	bits[3:0] trigger type and level flags.
+		1 = low-to-high edge triggered
+		2 = high-to-low edge triggered
+		4 = active high level-sensitive
+		8 = active low level-sensitive
+	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
+	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
+	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
+
+- reg : Specifies base physical address(s) and size of the GIC registers. The
+  first region is the GIC distributor register base and size. The 2nd region is
+  the GIC cpu interface register base and size.
+
+Optional
+- interrupts	: Interrupt source of the parent interrupt controller. Only
+  present on secondary GICs.
+
+Example:
+
+	intc: interrupt-controller at fff11000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <1>;
+		interrupt-controller;
+		reg = <0xfff11000 0x1000>,
+		      <0xfff10100 0x100>;
+	};
+
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 666b278..84e69a4 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -28,6 +28,10 @@
 #include <linux/smp.h>
 #include <linux/cpumask.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
 
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
@@ -255,6 +259,15 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 	irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
+static int gic_irq_count(void __iomem *dist_base)
+{
+	int gic_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x1f;
+	gic_irqs = (gic_irqs + 1) * 32;
+	if (gic_irqs > 1020)
+		gic_irqs = 1020;
+	return gic_irqs;
+}
+
 static void __init gic_dist_init(struct gic_chip_data *gic,
 	unsigned int irq_start)
 {
@@ -277,10 +290,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
 	 * Find out how many interrupts are supported.
 	 * The GIC only supports up to 1020 interrupt sources.
 	 */
-	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
-	gic_irqs = (gic_irqs + 1) * 32;
-	if (gic_irqs > 1020)
-		gic_irqs = 1020;
+	gic_irqs = gic_irq_count(base);
 
 	/*
 	 * Set all global interrupts to be level triggered, active low.
@@ -405,3 +415,74 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
 }
 #endif
+
+#ifdef CONFIG_OF
+static int gic_cnt __initdata = 0;
+
+int gic_irq_domain_dt_translate(struct irq_domain *d,
+			    struct device_node *controller,
+			    const u32 *intspec, unsigned int intsize,
+			    unsigned long *out_hwirq, unsigned int *out_type)
+{
+	struct gic_chip_data *gic_data = d->priv;
+
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 3)
+		return -EINVAL;
+
+	*out_hwirq = intspec[1];
+	/*
+	 * We've already skipped over SGIs, so PPIs need no translation.
+	 * For SPIs, we need to skip over 16 PPIs on primary GICs.
+	 */
+	if (!intspec[0] && !gic_data->irq_offset)
+		*out_hwirq += 16;
+
+	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+
+struct irq_domain_ops gic_irq_domain_ops = {
+	.dt_translate = gic_irq_domain_dt_translate,
+};
+
+int __init gic_of_init(struct device_node *node, struct device_node *parent)
+{
+	void __iomem *cpu_base;
+	void __iomem *dist_base;
+	int irq;
+	struct irq_domain *domain = &gic_data[gic_cnt].domain;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	dist_base = of_iomap(node, 0);
+	WARN(!dist_base, "unable to map gic dist registers\n");
+
+	cpu_base = of_iomap(node, 1);
+	WARN(!cpu_base, "unable to map gic cpu registers\n");
+
+	domain->nr_irq = gic_irq_count(dist_base);
+	/* subtract off SGIs. Also subtract off PPIs for secondary GICs */
+	if (parent)
+		domain->nr_irq -= 32;
+	else
+		domain->nr_irq -= 16;
+
+	domain->irq_base = irq_alloc_descs(-1, 16, domain->nr_irq, numa_node_id());
+	domain->of_node = of_node_get(node);
+	domain->ops = &gic_irq_domain_ops;
+	domain->priv = &gic_data[gic_cnt];
+	irq_domain_add(domain);
+
+	gic_init(gic_cnt, domain->irq_base, dist_base, cpu_base);
+
+	if (parent) {
+		irq = irq_of_parse_and_map(node, 0);
+		gic_cascade_irq(gic_cnt, irq);
+	}
+	gic_cnt++;
+	return 0;
+}
+#endif
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 435d3f8..2862d0e 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -33,10 +33,21 @@
 #define GIC_DIST_SOFTINT		0xf00
 
 #ifndef __ASSEMBLY__
+#include <linux/irqdomain.h>
+
 extern void __iomem *gic_cpu_base_addr;
 extern struct irq_chip gic_arch_extn;
 
 void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
+#ifdef CONFIG_OF
+int gic_of_init(struct device_node *node, struct device_node *parent);
+#else
+static inline void gic_of_init(struct device_node *node,
+			       struct device_node *parent)
+{
+	return -ENODEV;
+}
+#endif
 void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
@@ -46,6 +57,7 @@ struct gic_chip_data {
 	unsigned int irq_offset;
 	void __iomem *dist_base;
 	void __iomem *cpu_base;
+	struct irq_domain domain;
 };
 #endif
 
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

end of thread, other threads:[~2011-10-13 20:12 UTC | newest]

Thread overview: 68+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-30 19:27 [PATCH 0/3] GIC OF bindings Rob Herring
2011-09-30 19:27 ` Rob Herring
2011-09-30 19:27 ` [PATCH 1/3] irq: support domains with non-zero hwirq base Rob Herring
2011-09-30 19:27   ` Rob Herring
2011-09-30 19:27   ` Rob Herring
2011-10-04 23:39   ` Grant Likely
2011-10-04 23:39     ` Grant Likely
2011-10-05  2:56     ` [PATCH v2] " Rob Herring
2011-10-05  2:56       ` Rob Herring
2011-10-11 13:18       ` Rob Herring
2011-10-11 13:18         ` Rob Herring
2011-10-13 19:33         ` Grant Likely
2011-10-13 19:33           ` Grant Likely
2011-10-13 20:12           ` Thomas Gleixner
2011-10-13 20:12             ` Thomas Gleixner
2011-09-30 19:27 ` [PATCH 2/3] ARM: gic: add irq_domain support Rob Herring
2011-09-30 19:27   ` Rob Herring
2011-09-30 19:27   ` Rob Herring
2011-10-04 23:41   ` Grant Likely
2011-10-04 23:41     ` Grant Likely
2011-09-30 19:28 ` [PATCH 3/3] ARM: gic: add OF based initialization Rob Herring
2011-09-30 19:28   ` Rob Herring
2011-09-30 19:28   ` Rob Herring
2011-10-04 23:44   ` Grant Likely
2011-10-04 23:44     ` Grant Likely
2011-10-04 16:15 ` [PATCH 0/3] GIC OF bindings Rob Herring
2011-10-04 16:15   ` Rob Herring
2011-10-04 16:15   ` Rob Herring
2011-10-08 14:04 ` Thomas Abraham
2011-10-08 14:04   ` Thomas Abraham
  -- strict thread matches above, loose matches on Subject: below --
2011-09-20 20:24 Rob Herring
2011-09-20 20:24 ` [PATCH 3/3] ARM: gic: add OF based initialization Rob Herring
2011-09-20 20:24   ` Rob Herring
2011-09-20 20:24   ` Rob Herring
2011-09-20 23:08   ` Grant Likely
2011-09-20 23:08     ` Grant Likely
2011-09-20 23:08     ` Grant Likely
2011-09-21  1:54     ` Rob Herring
2011-09-21  1:54       ` Rob Herring
2011-09-21  1:54       ` Rob Herring
2011-09-21 17:15   ` Cousson, Benoit
2011-09-21 17:15     ` Cousson, Benoit
2011-09-21 17:15     ` Cousson, Benoit
2011-09-21 17:55     ` Rob Herring
2011-09-21 17:55       ` Rob Herring
2011-09-21 17:55       ` Rob Herring
2011-09-21 19:28       ` Cousson, Benoit
2011-09-21 19:28         ` Cousson, Benoit
2011-09-21 19:28         ` Cousson, Benoit
2011-09-21 20:27         ` Cousson, Benoit
2011-09-21 20:27           ` Cousson, Benoit
2011-09-21 20:27           ` Cousson, Benoit
2011-09-26 19:57   ` Jamie Iles
2011-09-26 19:57     ` Jamie Iles
2011-09-26 19:57     ` Jamie Iles
2011-09-26 20:49     ` Rob Herring
2011-09-26 20:49       ` Rob Herring
2011-09-26 20:49       ` Rob Herring
2011-09-26 21:11       ` Jamie Iles
2011-09-26 21:11         ` Jamie Iles
2011-09-26 21:11         ` Jamie Iles
2011-09-26 21:32         ` Rob Herring
2011-09-26 21:32           ` Rob Herring
2011-09-26 21:32           ` Rob Herring
2011-09-26 22:00           ` Jamie Iles
2011-09-26 22:00             ` Jamie Iles
2011-09-26 22:29   ` Jamie Iles
2011-09-26 22:29     ` Jamie Iles
2011-09-26 22:29     ` Jamie Iles

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.