From patchwork Sat Mar 24 09:41:15 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: thomas.abraham@linaro.org X-Patchwork-Id: 7445 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id BB05B23E0C for ; Sat, 24 Mar 2012 09:36:42 +0000 (UTC) Received: from mail-iy0-f180.google.com (mail-iy0-f180.google.com [209.85.210.180]) by fiordland.canonical.com (Postfix) with ESMTP id 633C2A18691 for ; Sat, 24 Mar 2012 09:36:42 +0000 (UTC) Received: by mail-iy0-f180.google.com with SMTP id e36so7727536iag.11 for ; Sat, 24 Mar 2012 02:36:42 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:x-forwarded-to:x-forwarded-for:delivered-to :received-spf:x-auditid:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references:x-brightmail-tracker:x-tm-as-mml :x-gm-message-state; bh=joJzBgVon4AgicQRKvm7kyBUygESmQFUkg7f5fj26CU=; b=jl24sERmgDEpcMRZoyZrEzLJ5mwbUeuC8BgvTODxT5aayO2gr7HZt/AVxAwOGyCtbI iBEnqfe/qciLKUzcksfpviRCDa1AbZsBveFPa8i/GVnIErc3Hrflk9eeClu8H4W3A2tS jV7qWN3JQ7yTdv/jpf7dPttco4/jgqUS+XxbrD0GhGO8/2cTC3BT/b95vcW8Y74HF62b 0ZPaSg8T0v0+6lHpsBNACAkklsvkO+wWc18EyWKgJ2+Mj3RSErIworvQDCOPxwcKyEnT eNwJsYUjenNguaPuUiwgImVmgoyNcyfOhxkrwv/3F7WHs7F8f60VyzCwgMRwjltfyWQJ YXVQ== MIME-Version: 1.0 Received: by 10.50.214.36 with SMTP id nx4mr1140568igc.2.1332581802184; Sat, 24 Mar 2012 02:36:42 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.203.79 with SMTP id fh15csp43518ibb; Sat, 24 Mar 2012 02:36:41 -0700 (PDT) Received: by 10.68.201.6 with SMTP id jw6mr36679898pbc.92.1332581801450; Sat, 24 Mar 2012 02:36:41 -0700 (PDT) Received: from mailout3.samsung.com (mailout3.samsung.com. [203.254.224.33]) by mx.google.com with ESMTP id x8si11963915pbi.336.2012.03.24.02.36.40; Sat, 24 Mar 2012 02:36:41 -0700 (PDT) Received-SPF: neutral (google.com: 203.254.224.33 is neither permitted nor denied by best guess record for domain of thomas.abraham@linaro.org) client-ip=203.254.224.33; Authentication-Results: mx.google.com; spf=neutral (google.com: 203.254.224.33 is neither permitted nor denied by best guess record for domain of thomas.abraham@linaro.org) smtp.mail=thomas.abraham@linaro.org Received: from epcpsbgm2.samsung.com (mailout3.samsung.com [203.254.224.33]) by mailout3.samsung.com (Oracle Communications Messaging Exchange Server 7u4-19.01 64bit (built Sep 7 2010)) with ESMTP id <0M1D006OVUOYDWE0@mailout3.samsung.com> for patches@linaro.org; Sat, 24 Mar 2012 18:36:40 +0900 (KST) X-AuditID: cbfee61b-b7baeae000004fa7-d0-4f6d95a8085b Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (MMPCPMTA) with SMTP id 7A.79.20391.8A59D6F4; Sat, 24 Mar 2012 18:36:40 +0900 (KST) Received: from localhost.localdomain ([107.108.73.37]) by mmp1.samsung.com (Oracle Communications Messaging Exchange Server 7u4-19.01 64bit (built Sep 7 2010)) with ESMTPA id <0M1D00D9XUORGL60@mmp1.samsung.com> for patches@linaro.org; Sat, 24 Mar 2012 18:36:40 +0900 (KST) From: Thomas Abraham To: linux-samsung-soc@vger.kernel.org Cc: devicetree-discuss@lists.ozlabs.org, linux-arm-kernel@lists.infradead.org, grant.likely@secretlab.ca, rob.herring@calxeda.com, kgene.kim@samsung.com, patches@linaro.org Subject: [PATCH v4 4/4] ARM: Exynos: Add device tree support for gpio wakeup interrupt controller Date: Sat, 24 Mar 2012 15:11:15 +0530 Message-id: <1332582075-16204-5-git-send-email-thomas.abraham@linaro.org> X-Mailer: git-send-email 1.6.6.rc2 In-reply-to: <1332582075-16204-1-git-send-email-thomas.abraham@linaro.org> References: <1332582075-16204-1-git-send-email-thomas.abraham@linaro.org> X-Brightmail-Tracker: AAAAAA== X-TM-AS-MML: No X-Gm-Message-State: ALoCoQneoDmsp2yYh3EYdO9+Qj0PBukB+j7/Dekg+LBjIwMGTA3UUNArdg4hbI1ylP70ImpKwHRR Add device tree support for gpio wakeup source interrupt controller for Exynos platforms. Cc: Rob Herring Cc: Grant Likely Signed-off-by: Thomas Abraham --- .../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;