From patchwork Sat Mar 24 09:41:13 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: 7443 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 C6AC923E0C for ; Sat, 24 Mar 2012 09:36:38 +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 75F48A18691 for ; Sat, 24 Mar 2012 09:36:38 +0000 (UTC) Received: by mail-iy0-f180.google.com with SMTP id e36so7727536iag.11 for ; Sat, 24 Mar 2012 02:36:38 -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=YajaY+EkT/VtvV40EznUDGdyvG8o9YIB8nGFDXgxH8M=; b=YzYlA7j6kDUXe39dLI/5qyQmNKfWhHwkmTAUcoUFT77bnJSpSt5lcSRE0FYKGdYXYB fafnELVWT8MQC3B+/h47kldqXxg2INaNSCmTuxm7ykghlpKkGbNzlYW92gX/4ldWwJgw kS8EXVkHR1R6YLQihHHVMmTYrQjZHPU58TL9iYbgW+6EOQwcnP2fksi1hNeSin0ByP/d mXYQ+cUJqZ9/DaUht5jDDaBiYsVOXesI8MtyraNWEbrwPSMRAYBzu1DXN/ac69nU5Zie wvs2kV3OHT0EnrWO6SoT5NTqou0sfjg4CB7fTcFET0VTxWY7Yss7ymga+JrpcbP/yYU1 lqaQ== MIME-Version: 1.0 Received: by 10.50.214.36 with SMTP id nx4mr1140457igc.2.1332581798253; Sat, 24 Mar 2012 02:36:38 -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 fh15csp43516ibb; Sat, 24 Mar 2012 02:36:37 -0700 (PDT) Received: by 10.68.229.169 with SMTP id sr9mr35895242pbc.164.1332581797168; Sat, 24 Mar 2012 02:36:37 -0700 (PDT) Received: from mailout3.samsung.com (mailout3.samsung.com. [203.254.224.33]) by mx.google.com with ESMTP id g9si12008182pbd.101.2012.03.24.02.36.36; Sat, 24 Mar 2012 02:36:37 -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:36 +0900 (KST) X-AuditID: cbfee61b-b7baeae000004fa7-c5-4f6d95a4e428 Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (MMPCPMTA) with SMTP id 09.79.20391.4A59D6F4; Sat, 24 Mar 2012 18:36:36 +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:36 +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 2/4] ARM: Exynos: Add irq_domain support for gpio wakeup interrupts Date: Sat, 24 Mar 2012 15:11:13 +0530 Message-id: <1332582075-16204-3-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: ALoCoQlxAnfinwIRYk+gNyhJ7sPpVTkVRltnmv0g9EUX2QovUpsOQXftYTM+97TnMJMVNS1UrYri 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 Signed-off-by: Thomas Abraham Acked-by: Rob Herring --- 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 #include -#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)