* [PATCH v4 0/4] ARM: Exynos4: Add irq domain and device tree support for wakeup interrupts
@ 2012-03-24 9:41 Thomas Abraham
2012-03-24 9:41 ` [PATCH v4 1/4] ARM: Exynos: Simplify the wakeup interrupt setup code Thomas Abraham
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Thomas Abraham @ 2012-03-24 9:41 UTC (permalink / raw)
To: linux-samsung-soc
Cc: devicetree-discuss, linux-arm-kernel, grant.likely, rob.herring,
kgene.kim, patches
Changes since v3:
- Rebased the patches to the latest kgene/for-next branch which now includes
Exynos5 support as well. In this process, there are some significant changes,
when compared to v3 version of this patchset, related to device tree support
in patch 4/4 and code simplification in patch 1/4. Since v3 of this series
was acked by Rob Herring, I have added the his Ack for patches 2/4 and
3/4 but not in patches 1/4 and 4/4 (due to the new set of changes).
- Patch 4/4 includes modifications which are required to support Exynos5
wakeup interrupt controller that has two interrupt parents (gic and
interrupt combiner).
Changes since v2:
- Reworked irq domain support based on v5 of the irq_domain generalization
patches.
Changes since v1: (only patch 4/4 has changes)
- Fixes based on Rob's comments:
a. Fixed the function prototype of exynos4_init_irq_eint(void)
b. Included interrupt-parent as an optional property for wakeup interrupt
controller node.
Samsung Exynos4 includes 32 external wakeup interrupt sources. The first 16
of these interrupts are connected to GIC SPI[31:16]. The last 16 of these
interrupts are grouped together into one interrupt and connected to GIC
SPI[32].
Samsung Exynos5 also includes 32 external wakeup interrupt sources. The first
16 of these interrupts are connected to interrupt combiner controller. The
last 16 of these interrupts are grouped together into one interrupt and
connected to GIC SPI[32].
This patchset adds irq domain and device tree support for these interrupts.
Since there are users of fixed linux irq numbers of the external wakeup
interrupts, the legacy mapping is used for the irq domain.
This patchset is based on
http://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git [for-next]
with all patches merged from
http://git.secretlab.ca/git/linux-2.6.git [irqdomain/next]
This patchset should be applied after applying the following patch.
[PATCH v5] ARM: Exynos: Add irq domain and device tree support for interrupt combiner
Thomas Abraham (4):
ARM: Exynos: Simplify the wakeup interrupt setup code
ARM: Exynos: Add irq_domain support for gpio wakeup interrupts
ARM: Exynos: Remove arch_initcall for wakeup interrupt initialization
ARM: Exynos: Add device tree support for gpio wakeup interrupt controller
.../bindings/arm/samsung/wakeup-eint.txt | 152 ++++++++++++++++++++
arch/arm/mach-exynos/common.c | 138 ++++++++++++------
arch/arm/mach-exynos/include/mach/regs-gpio.h | 4 +-
3 files changed, 247 insertions(+), 47 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/samsung/wakeup-eint.txt
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v4 1/4] ARM: Exynos: Simplify the wakeup interrupt setup code
2012-03-24 9:41 [PATCH v4 0/4] ARM: Exynos4: Add irq domain and device tree support for wakeup interrupts Thomas Abraham
@ 2012-03-24 9:41 ` Thomas Abraham
2012-03-24 9:41 ` [PATCH v4 2/4] ARM: Exynos: Add irq_domain support for gpio wakeup interrupts Thomas Abraham
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Thomas Abraham @ 2012-03-24 9:41 UTC (permalink / raw)
To: linux-samsung-soc
Cc: devicetree-discuss, linux-arm-kernel, grant.likely, rob.herring,
kgene.kim, patches
Simplify the wakeup interrupt setup code in order to add irq domain
and device tree support.
Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
arch/arm/mach-exynos/common.c | 32 +++++++++++---------------------
1 files changed, 11 insertions(+), 21 deletions(-)
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 36b5837..3768efa 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -995,16 +995,14 @@ static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
static int __init exynos_init_irq_eint(void)
{
- int irq;
+ int irq, *src_int;
+ unsigned int paddr;
- if (soc_is_exynos5250())
- exynos_eint_base = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
- else
- exynos_eint_base = ioremap(EXYNOS4_PA_GPIO2, SZ_4K);
-
- if (exynos_eint_base == NULL) {
+ paddr = soc_is_exynos5250() ? EXYNOS5_PA_GPIO1 : EXYNOS4_PA_GPIO2;
+ exynos_eint_base = ioremap(paddr, SZ_4K);
+ if (!exynos_eint_base) {
pr_err("unable to ioremap for EINT base address\n");
- return -ENOMEM;
+ return -ENXIO;
}
for (irq = 0 ; irq <= 31 ; irq++) {
@@ -1015,20 +1013,12 @@ static int __init exynos_init_irq_eint(void)
irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos_irq_demux_eint16_31);
- for (irq = 0 ; irq <= 15 ; irq++) {
+ for (irq = 0 ; irq <= 15; irq++) {
eint0_15_data[irq] = IRQ_EINT(irq);
-
- if (soc_is_exynos5250()) {
- irq_set_handler_data(exynos5_eint0_15_src_int[irq],
- &eint0_15_data[irq]);
- irq_set_chained_handler(exynos5_eint0_15_src_int[irq],
- exynos_irq_eint0_15);
- } else {
- irq_set_handler_data(exynos4_eint0_15_src_int[irq],
- &eint0_15_data[irq]);
- irq_set_chained_handler(exynos4_eint0_15_src_int[irq],
- exynos_irq_eint0_15);
- }
+ src_int = soc_is_exynos5250() ? exynos5_eint0_15_src_int :
+ exynos4_eint0_15_src_int;
+ irq_set_handler_data(src_int[irq], &eint0_15_data[irq]);
+ irq_set_chained_handler(src_int[irq], exynos_irq_eint0_15);
}
return 0;
--
1.6.6.rc2
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 2/4] ARM: Exynos: Add irq_domain support for gpio wakeup interrupts
2012-03-24 9:41 [PATCH v4 0/4] ARM: Exynos4: Add irq domain and device tree support for wakeup interrupts Thomas Abraham
2012-03-24 9:41 ` [PATCH v4 1/4] ARM: Exynos: Simplify the wakeup interrupt setup code Thomas Abraham
@ 2012-03-24 9:41 ` Thomas Abraham
2012-03-24 9:41 ` [PATCH v4 3/4] ARM: Exynos: Remove arch_initcall for wakeup interrupt initialization Thomas Abraham
2012-03-24 9:41 ` [PATCH v4 4/4] ARM: Exynos: Add device tree support for gpio wakeup interrupt controller Thomas Abraham
3 siblings, 0 replies; 5+ messages in thread
From: Thomas Abraham @ 2012-03-24 9:41 UTC (permalink / raw)
To: linux-samsung-soc
Cc: devicetree-discuss, linux-arm-kernel, grant.likely, rob.herring,
kgene.kim, patches
Add a irq_domain for all the 32 gpio external wakeup interrupt sources.
Since there are users of fixed linux irq numbers of the external wakeup
interrupts, the legacy mapping is used for the irq domain. The fixups
required to use irq domain based interrupt mapping is also included.
Cc: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
Acked-by: Rob Herring <rob.herring@calxeda.com>
---
arch/arm/mach-exynos/common.c | 67 +++++++++++++++++--------
arch/arm/mach-exynos/include/mach/regs-gpio.h | 4 +-
2 files changed, 48 insertions(+), 23 deletions(-)
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 3768efa..b69f36a 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -759,6 +759,9 @@ static DEFINE_SPINLOCK(eint_lock);
static unsigned int eint0_15_data[16];
+#define EXYNOS_EINT_NR 32
+static struct irq_domain *irq_domain;
+
static inline int exynos4_irq_to_gpio(unsigned int irq)
{
if (irq < IRQ_EINT(0))
@@ -849,9 +852,9 @@ static inline void exynos_irq_eint_mask(struct irq_data *data)
u32 mask;
spin_lock(&eint_lock);
- mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq));
- mask |= EINT_OFFSET_BIT(data->irq);
- __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq));
+ mask = __raw_readl(EINT_MASK(exynos_eint_base, data->hwirq));
+ mask |= EINT_OFFSET_BIT(data->hwirq);
+ __raw_writel(mask, EINT_MASK(exynos_eint_base, data->hwirq));
spin_unlock(&eint_lock);
}
@@ -860,16 +863,16 @@ static void exynos_irq_eint_unmask(struct irq_data *data)
u32 mask;
spin_lock(&eint_lock);
- mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq));
- mask &= ~(EINT_OFFSET_BIT(data->irq));
- __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq));
+ mask = __raw_readl(EINT_MASK(exynos_eint_base, data->hwirq));
+ mask &= ~(EINT_OFFSET_BIT(data->hwirq));
+ __raw_writel(mask, EINT_MASK(exynos_eint_base, data->hwirq));
spin_unlock(&eint_lock);
}
static inline void exynos_irq_eint_ack(struct irq_data *data)
{
- __raw_writel(EINT_OFFSET_BIT(data->irq),
- EINT_PEND(exynos_eint_base, data->irq));
+ __raw_writel(EINT_OFFSET_BIT(data->hwirq),
+ EINT_PEND(exynos_eint_base, data->hwirq));
}
static void exynos_irq_eint_maskack(struct irq_data *data)
@@ -880,7 +883,7 @@ static void exynos_irq_eint_maskack(struct irq_data *data)
static int exynos_irq_eint_set_type(struct irq_data *data, unsigned int type)
{
- int offs = EINT_OFFSET(data->irq);
+ int offs = data->hwirq;
int shift;
u32 ctrl, mask;
u32 newvalue = 0;
@@ -915,10 +918,10 @@ static int exynos_irq_eint_set_type(struct irq_data *data, unsigned int type)
mask = 0x7 << shift;
spin_lock(&eint_lock);
- ctrl = __raw_readl(EINT_CON(exynos_eint_base, data->irq));
+ ctrl = __raw_readl(EINT_CON(exynos_eint_base, data->hwirq));
ctrl &= ~mask;
ctrl |= newvalue << shift;
- __raw_writel(ctrl, EINT_CON(exynos_eint_base, data->irq));
+ __raw_writel(ctrl, EINT_CON(exynos_eint_base, data->hwirq));
spin_unlock(&eint_lock);
if (soc_is_exynos5250())
@@ -962,7 +965,7 @@ static inline void exynos_irq_demux_eint(unsigned int start)
while (status) {
irq = fls(status) - 1;
- generic_handle_irq(irq + start);
+ generic_handle_irq(irq_find_mapping(irq_domain, irq + start));
status &= ~(1 << irq);
}
}
@@ -971,8 +974,8 @@ static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
{
struct irq_chip *chip = irq_get_chip(irq);
chained_irq_enter(chip, desc);
- exynos_irq_demux_eint(IRQ_EINT(16));
- exynos_irq_demux_eint(IRQ_EINT(24));
+ exynos_irq_demux_eint(16);
+ exynos_irq_demux_eint(24);
chained_irq_exit(chip, desc);
}
@@ -980,6 +983,7 @@ static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
{
u32 *irq_data = irq_get_handler_data(irq);
struct irq_chip *chip = irq_get_chip(irq);
+ int eint_irq;
chained_irq_enter(chip, desc);
chip->irq_mask(&desc->irq_data);
@@ -987,15 +991,28 @@ static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
if (chip->irq_ack)
chip->irq_ack(&desc->irq_data);
- generic_handle_irq(*irq_data);
+ eint_irq = irq_find_mapping(irq_domain, *irq_data);
+ generic_handle_irq(eint_irq);
chip->irq_unmask(&desc->irq_data);
chained_irq_exit(chip, desc);
}
+static int exynos_eint_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(irq, &exynos_irq_eint, handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID);
+ return 0;
+}
+
+static struct irq_domain_ops exynos_eint_irq_domain_ops = {
+ .map = exynos_eint_irq_domain_map,
+};
+
static int __init exynos_init_irq_eint(void)
{
- int irq, *src_int;
+ int irq, *src_int, irq_base;
unsigned int paddr;
paddr = soc_is_exynos5250() ? EXYNOS5_PA_GPIO1 : EXYNOS4_PA_GPIO2;
@@ -1005,16 +1022,24 @@ static int __init exynos_init_irq_eint(void)
return -ENXIO;
}
- for (irq = 0 ; irq <= 31 ; irq++) {
- irq_set_chip_and_handler(IRQ_EINT(irq), &exynos_irq_eint,
- handle_level_irq);
- set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
+ irq_base = irq_alloc_descs(IRQ_EINT(0), 1, EXYNOS_EINT_NR, 0);
+ if (IS_ERR_VALUE(irq_base)) {
+ irq_base = IRQ_EINT(0);
+ pr_warning("%s: irq desc alloc failed. Continuing with %d as "
+ "linux irq base\n", __func__, irq_base);
+ }
+
+ irq_domain = irq_domain_add_legacy(NULL, EXYNOS_EINT_NR, irq_base, 0,
+ &exynos_eint_irq_domain_ops, NULL);
+ if (WARN_ON(!irq_domain)) {
+ pr_warning("%s: irq domain init failed\n", __func__);
+ return 0;
}
irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos_irq_demux_eint16_31);
for (irq = 0 ; irq <= 15; irq++) {
- eint0_15_data[irq] = IRQ_EINT(irq);
+ eint0_15_data[irq] = irq;
src_int = soc_is_exynos5250() ? exynos5_eint0_15_src_int :
exynos4_eint0_15_src_int;
irq_set_handler_data(src_int[irq], &eint0_15_data[irq]);
diff --git a/arch/arm/mach-exynos/include/mach/regs-gpio.h b/arch/arm/mach-exynos/include/mach/regs-gpio.h
index e4b5b60..24bf4ec 100644
--- a/arch/arm/mach-exynos/include/mach/regs-gpio.h
+++ b/arch/arm/mach-exynos/include/mach/regs-gpio.h
@@ -16,13 +16,13 @@
#include <mach/map.h>
#include <mach/irqs.h>
-#define EINT_REG_NR(x) (EINT_OFFSET(x) >> 3)
+#define EINT_REG_NR(x) ((x) >> 3)
#define EINT_CON(b, x) (b + 0xE00 + (EINT_REG_NR(x) * 4))
#define EINT_FLTCON(b, x) (b + 0xE80 + (EINT_REG_NR(x) * 4))
#define EINT_MASK(b, x) (b + 0xF00 + (EINT_REG_NR(x) * 4))
#define EINT_PEND(b, x) (b + 0xF40 + (EINT_REG_NR(x) * 4))
-#define EINT_OFFSET_BIT(x) (1 << (EINT_OFFSET(x) & 0x7))
+#define EINT_OFFSET_BIT(x) (1 << ((x) & 0x7))
/* compatibility for plat-s5p/irq-pm.c */
#define EXYNOS4_EINT40CON (S5P_VA_GPIO2 + 0xE00)
--
1.6.6.rc2
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 3/4] ARM: Exynos: Remove arch_initcall for wakeup interrupt initialization
2012-03-24 9:41 [PATCH v4 0/4] ARM: Exynos4: Add irq domain and device tree support for wakeup interrupts Thomas Abraham
2012-03-24 9:41 ` [PATCH v4 1/4] ARM: Exynos: Simplify the wakeup interrupt setup code Thomas Abraham
2012-03-24 9:41 ` [PATCH v4 2/4] ARM: Exynos: Add irq_domain support for gpio wakeup interrupts Thomas Abraham
@ 2012-03-24 9:41 ` Thomas Abraham
2012-03-24 9:41 ` [PATCH v4 4/4] ARM: Exynos: Add device tree support for gpio wakeup interrupt controller Thomas Abraham
3 siblings, 0 replies; 5+ messages in thread
From: Thomas Abraham @ 2012-03-24 9:41 UTC (permalink / raw)
To: linux-samsung-soc
Cc: devicetree-discuss, linux-arm-kernel, grant.likely, rob.herring,
kgene.kim, patches
The of_irq_init function would be setup to invoke the exynos4_init_irq_eint
function when booting using device tree. The arch_initcall for
exynos4_init_irq_eint would duplicate its invocation in that case. Hence,
arch_initcall for exynos4_init_irq_eint is removed and this function is invoked
from the exynos4_init_irq for non-dt case.
Moreover, with single kernel image build, the exynos4_init_irq_eint has no checks
to ensure that it is running on a exynos4 platform. So it would be appropriate
to invoke it from exynos4_init_irq.
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
Acked-by: Rob Herring <rob.herring@calxeda.com>
---
arch/arm/mach-exynos/common.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index b69f36a..7aa1919 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -64,6 +64,7 @@ static void exynos4_init_clocks(int xtal);
static void exynos5_init_clocks(int xtal);
static void exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no);
static int exynos_init(void);
+static int exynos_init_irq_eint(void);
static struct cpu_table cpu_ids[] __initdata = {
{
@@ -608,6 +609,7 @@ void __init exynos4_init_irq(void)
* uses GIC instead of VIC.
*/
s5p_init_irq(NULL, 0);
+ exynos_init_irq_eint();
}
void __init exynos5_init_irq(void)
@@ -620,6 +622,7 @@ void __init exynos5_init_irq(void)
* uses GIC instead of VIC.
*/
s5p_init_irq(NULL, 0);
+ exynos_init_irq_eint();
}
struct bus_type exynos4_subsys = {
@@ -1048,4 +1051,3 @@ static int __init exynos_init_irq_eint(void)
return 0;
}
-arch_initcall(exynos_init_irq_eint);
--
1.6.6.rc2
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 4/4] ARM: Exynos: Add device tree support for gpio wakeup interrupt controller
2012-03-24 9:41 [PATCH v4 0/4] ARM: Exynos4: Add irq domain and device tree support for wakeup interrupts Thomas Abraham
` (2 preceding siblings ...)
2012-03-24 9:41 ` [PATCH v4 3/4] ARM: Exynos: Remove arch_initcall for wakeup interrupt initialization Thomas Abraham
@ 2012-03-24 9:41 ` Thomas Abraham
3 siblings, 0 replies; 5+ messages in thread
From: Thomas Abraham @ 2012-03-24 9:41 UTC (permalink / raw)
To: linux-samsung-soc
Cc: devicetree-discuss, linux-arm-kernel, grant.likely, rob.herring,
kgene.kim, patches
Add device tree support for gpio wakeup source interrupt controller for
Exynos platforms.
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
.../bindings/arm/samsung/wakeup-eint.txt | 152 ++++++++++++++++++++
arch/arm/mach-exynos/common.c | 55 ++++++--
2 files changed, 195 insertions(+), 12 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/samsung/wakeup-eint.txt
diff --git a/Documentation/devicetree/bindings/arm/samsung/wakeup-eint.txt b/Documentation/devicetree/bindings/arm/samsung/wakeup-eint.txt
new file mode 100644
index 0000000..04bbf25
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/samsung/wakeup-eint.txt
@@ -0,0 +1,152 @@
+* Samsung GPIO Wakeup Interrupt Controller
+
+This document is split into following sections.
+
+[1] Samsung Exynos4 GPIO Wakeup Interrupt Source Controller
+[2] Samsung Exynos5 GPIO Wakeup Interrupt Source Controller
+
+
+[1] Samsung Exynos4 GPIO Wakeup Interrupt Source Controller
+
+Samsung Exynos4 processor supports 32 external wakeup interrupt sources. First
+16 of these interrupts are directly connected to GIC and the rest 16 of the
+interrupts are grouped together to deliver a single interrupt to GIC.
+
+Required properties:
+
+ - compatible: should be "samsung,exynos4210-wakeup-eint".
+
+ - reg: physical base address of the controller and length of memory
+ mapped region.
+
+ - interrupt-controller: Identifies the node as an interrupt controller.
+
+ - interrupt-cells: Specifies the number of cells required to specify the
+ interrupt source number. The value of should be <2>. The first cell
+ represents the wakeup interrupt source number and the second cell
+ should be zero (currently unused).
+
+ - interrupts: List of interrupts generated by the gpio wakeup interrupt
+ controller which are connected to a parent interrupt controller. The
+ format of the interrupt specifier depends on the interrupt parent
+ controller.
+
+Optional properties:
+
+ - interrupt-parent: phandle of the parent interrupt controller, required
+ if not inheriting the interrupt parent from the parent node.
+
+Example:
+
+ The following example is from the Exynos4210 dtsi file.
+
+ wakeup_eint: interrupt-controller-wakeup-eint {
+ compatible = "samsung,exynos4210-wakeup-eint";
+ reg = <0x11000000 0x1000>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+ <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
+ <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+ <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>,
+ <0 32 0>;
+ };
+
+
+[2] Samsung Exynos5 GPIO Wakeup Interrupt Source Controller
+
+Samsung Exynos5 processor supports 32 external wakeup interrupt sources. First
+16 of these interrupts are directly connected to GIC and the rest 16 of the
+interrupts are grouped together to deliver a single interrupt to interrupt
+combiner controller.
+
+Since the wakeup interrupts has two interrupt parents, a interrupt nexus
+child node is used that includes a interrupt-map used to translate wakeup
+interrupt specifiers into gic and combiner domain interrupts.
+
+Required properties:
+
+ - compatible: should be "samsung,exynos5210-wakeup-eint".
+
+ - reg: physical base address of the controller and length of memory
+ mapped region.
+
+ - interrupt-controller: Identifies the node as an interrupt controller.
+
+ - interrupt-cells: Specifies the number of cells required to specify the
+ interrupt source number. The value of should be <2>. The first cell
+ represents the wakeup interrupt source number and the second cell
+ should be zero (currently unused).
+
+ - interrupts: List of interrupts generated by the gpio wakeup interrupt
+ controller. Since both gic and combiner controllers are interrupt
+ parents, a interrupt nexus child node is used to translate the interrupt
+ specifiers into respective gic and combiner interrupt domains (see below).
+ The interrupt specifier should be two cells - the first cell should be the
+ interrupt number originating from the wakeup controller and the second
+ cell should be zero (unused).
+
+ - interrupt-parent: The phandle of the interrupt nexus child node.
+
+ - interrupt-nexus child node: This node is used to translate the interrupt
+ specifiers of the wakeup interrupt controller node to the respecitive
+ gic or combiner interrupt domain. The interrupt nexus node should include
+ the following properties.
+
+ - interrupt-cells: Specifies the number of cells required to specify the
+ interrupt source number. The value of should be <2>. The first cell
+ represents the wakeup interrupt source number and the second cell
+ should be zero (currently unused).
+
+ - #address-cells: value of this property should be zero.
+
+ - #size-cells: value of this property should be zero.
+
+ - interrupt-map: The interrpt-map specifies how interrupt specifiers are
+ translated. There should be a interrupt-map entry for each interrupt
+ generated by the wakeup interrupt controller. The format of each entry
+ in the interrupt map should be
+
+ <#intr 0 parent-phandle parent-interrupt-specifier>
+
+ where #intr is one of the entries in the 'interrupts' property of the
+ parent node.
+
+
+Example:
+
+ wakeup_eint: interrupt-controller@11400000 {
+ compatible = "samsung,exynos5210-wakeup-eint";
+ reg = <0x11400000 0x1000>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&eint_nexus>;
+ interrupts = <0x0 0>, <0x1 0>, <0x2 0>, <0x3 0>,
+ <0x4 0>, <0x5 0>, <0x6 0>, <0x7 0>,
+ <0x8 0>, <0x9 0>, <0xa 0>, <0xb 0>,
+ <0xc 0>, <0xd 0>, <0xe 0>, <0xf 0>,
+ <0x10 0>;
+
+ wakeup_map: interrupt-map {
+ #interrupt-cells = <2>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ interrupt-map = <0x0 0 &combiner 23 0>,
+ <0x1 0 &combiner 24 0>,
+ <0x2 0 &combiner 25 0>,
+ <0x3 0 &combiner 25 1>,
+ <0x4 0 &combiner 26 0>,
+ <0x5 0 &combiner 26 1>,
+ <0x6 0 &combiner 27 0>,
+ <0x7 0 &combiner 27 1>,
+ <0x8 0 &combiner 28 0>,
+ <0x9 0 &combiner 28 1>,
+ <0xa 0 &combiner 29 0>,
+ <0xb 0 &combiner 29 1>,
+ <0xc 0 &combiner 30 0>,
+ <0xd 0 &combiner 30 1>,
+ <0xe 0 &combiner 31 0>,
+ <0xf 0 &combiner 31 1>,
+ <0x10 0 &gic 0 32 0>;
+ };
+ };
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 7aa1919..d7a321f 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -64,7 +64,8 @@ static void exynos4_init_clocks(int xtal);
static void exynos5_init_clocks(int xtal);
static void exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no);
static int exynos_init(void);
-static int exynos_init_irq_eint(void);
+static int exynos_init_irq_eint(struct device_node *np,
+ struct device_node *parent);
static struct cpu_table cpu_ids[] __initdata = {
{
@@ -583,6 +584,8 @@ static const struct of_device_id exynos4_dt_irq_match[] = {
{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
{ .compatible = "samsung,exynos4210-combiner",
.data = combiner_of_init, },
+ { .compatible = "samsung,exynos4210-wakeup-eint",
+ .data = exynos_init_irq_eint, },
{},
};
#endif
@@ -600,8 +603,10 @@ void __init exynos4_init_irq(void)
of_irq_init(exynos4_dt_irq_match);
#endif
- if (!of_have_populated_dt())
+ if (!of_have_populated_dt()) {
combiner_init(S5P_VA_COMBINER_BASE, NULL);
+ exynos_init_irq_eint(NULL, NULL);
+ }
/*
* The parameters of s5p_init_irq() are for VIC init.
@@ -609,20 +614,38 @@ void __init exynos4_init_irq(void)
* uses GIC instead of VIC.
*/
s5p_init_irq(NULL, 0);
- exynos_init_irq_eint();
}
void __init exynos5_init_irq(void)
{
+ struct device_node *np;
+
gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
/*
+ * The Exynos5 wakeup interrupt controller has two-interrupt parents,
+ * gic and combiner. Hence, a interrupt nexus node is used to translate
+ * interrupt specifers for the interrupts which wakeup interrupt
+ * controller deliver to the gic and combiner.
+ *
+ * When using a interrupt nexus node (which is child node of the wakeup
+ * controller node), the interrupt parent of the wakeup controller node
+ * is set as the nexus node and the nexus node does not have a
+ * 'interrupt-controller' property. Hence, the of_irq_init function
+ * will not be able to invoke the intializer function for wakeup
+ * interrupt controller. So call the initiazer explicitly here.
+ */
+ np = of_find_compatible_node(NULL, NULL,
+ "samsung,exynos5210-wakeup-eint");
+ if (np)
+ exynos_init_irq_eint(np, NULL);
+
+ /*
* The parameters of s5p_init_irq() are for VIC init.
* Theses parameters should be NULL and 0 because EXYNOS4
* uses GIC instead of VIC.
*/
s5p_init_irq(NULL, 0);
- exynos_init_irq_eint();
}
struct bus_type exynos4_subsys = {
@@ -1013,13 +1036,19 @@ static struct irq_domain_ops exynos_eint_irq_domain_ops = {
.map = exynos_eint_irq_domain_map,
};
-static int __init exynos_init_irq_eint(void)
+static int __init exynos_init_irq_eint(struct device_node *np,
+ struct device_node *parent)
{
- int irq, *src_int, irq_base;
+ int irq, *src_int, irq_base, irq_eint;
unsigned int paddr;
- paddr = soc_is_exynos5250() ? EXYNOS5_PA_GPIO1 : EXYNOS4_PA_GPIO2;
- exynos_eint_base = ioremap(paddr, SZ_4K);
+ if (!np) {
+ paddr = soc_is_exynos5250() ? EXYNOS5_PA_GPIO1 :
+ EXYNOS4_PA_GPIO2;
+ exynos_eint_base = ioremap(paddr, SZ_4K);
+ } else {
+ exynos_eint_base = of_iomap(np, 0);
+ }
if (!exynos_eint_base) {
pr_err("unable to ioremap for EINT base address\n");
return -ENXIO;
@@ -1032,21 +1061,23 @@ static int __init exynos_init_irq_eint(void)
"linux irq base\n", __func__, irq_base);
}
- irq_domain = irq_domain_add_legacy(NULL, EXYNOS_EINT_NR, irq_base, 0,
+ irq_domain = irq_domain_add_legacy(np, EXYNOS_EINT_NR, irq_base, 0,
&exynos_eint_irq_domain_ops, NULL);
if (WARN_ON(!irq_domain)) {
pr_warning("%s: irq domain init failed\n", __func__);
return 0;
}
- irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos_irq_demux_eint16_31);
+ irq_eint = np ? irq_of_parse_and_map(np, 16) : EXYNOS_IRQ_EINT16_31;
+ irq_set_chained_handler(irq_eint, exynos_irq_demux_eint16_31);
for (irq = 0 ; irq <= 15; irq++) {
eint0_15_data[irq] = irq;
src_int = soc_is_exynos5250() ? exynos5_eint0_15_src_int :
exynos4_eint0_15_src_int;
- irq_set_handler_data(src_int[irq], &eint0_15_data[irq]);
- irq_set_chained_handler(src_int[irq], exynos_irq_eint0_15);
+ irq_eint = np ? irq_of_parse_and_map(np, irq) : src_int[irq];
+ irq_set_handler_data(irq_eint, &eint0_15_data[irq]);
+ irq_set_chained_handler(irq_eint, exynos_irq_eint0_15);
}
return 0;
--
1.6.6.rc2
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-03-24 9:41 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-24 9:41 [PATCH v4 0/4] ARM: Exynos4: Add irq domain and device tree support for wakeup interrupts Thomas Abraham
2012-03-24 9:41 ` [PATCH v4 1/4] ARM: Exynos: Simplify the wakeup interrupt setup code Thomas Abraham
2012-03-24 9:41 ` [PATCH v4 2/4] ARM: Exynos: Add irq_domain support for gpio wakeup interrupts Thomas Abraham
2012-03-24 9:41 ` [PATCH v4 3/4] ARM: Exynos: Remove arch_initcall for wakeup interrupt initialization Thomas Abraham
2012-03-24 9:41 ` [PATCH v4 4/4] ARM: Exynos: Add device tree support for gpio wakeup interrupt controller Thomas Abraham
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).