From patchwork Fri Nov 15 08:48:00 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 3187311 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 85100C045B for ; Fri, 15 Nov 2013 09:04:51 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 29AB72097E for ; Fri, 15 Nov 2013 09:04:50 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4393820967 for ; Fri, 15 Nov 2013 09:04:45 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VhF7L-0007Or-E3; Fri, 15 Nov 2013 08:51:10 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VhF6U-0001fO-Cd; Fri, 15 Nov 2013 08:50:14 +0000 Received: from mail-we0-x236.google.com ([2a00:1450:400c:c03::236]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VhF5C-0001VJ-1a for linux-arm-kernel@lists.infradead.org; Fri, 15 Nov 2013 08:48:58 +0000 Received: by mail-we0-f182.google.com with SMTP id q59so1177580wes.27 for ; Fri, 15 Nov 2013 00:48:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=s8O4nMt2R5I1qXqM2GVf6tTTHU7hTvuR1+Nk4kxMVl8=; b=Ks2scz76T3aFDXNXWgp8qXY7k71fbB/Tv/uHxAVS1EKQkJA3+UdICwKp7KC5wjIBmQ FLp+akXnSkz+FKenL53OMh2YpNRcbRQOiydeCNt6xaNoD8Nrubq8p5kRgvCOmCzw/bCg tcY7ohiy692+My+LiJwQleAnhJ8NOJodFQMuT/AvnR//WVdLIstVFAz0DxgehqJiXH7x W0rtJuYICasrvgX41tsURrEkJPP3QnVyHIp8Ci7KI8WU487Bf7e2vH9vHhEupIvTb7yI VLRcd6m3SbAMSwlGFt/SFS5qDGNhCAjM+f9nLDj6o8K+mtZLwEmsuj+isKHmArya/e8H x2yw== X-Received: by 10.180.102.97 with SMTP id fn1mr6389466wib.32.1384505312368; Fri, 15 Nov 2013 00:48:32 -0800 (PST) Received: from fangorn.rup.mentorg.com (nat-min.mentorg.com. [139.181.32.34]) by mx.google.com with ESMTPSA id qc10sm2856890wic.9.2013.11.15.00.48.31 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 15 Nov 2013 00:48:31 -0800 (PST) From: Dmitry Eremin-Solenikov To: linux-arm-kernel@lists.infradead.org, linux-gpio@vger.kernel.org Subject: [PATCH 9/9] ARM: sa1100: refactor irq driver Date: Fri, 15 Nov 2013 12:48:00 +0400 Message-Id: <1384505280-25389-10-git-send-email-dbaryshkov@gmail.com> X-Mailer: git-send-email 1.8.4.2 In-Reply-To: <1384505280-25389-1-git-send-email-dbaryshkov@gmail.com> References: <1384505280-25389-1-git-send-email-dbaryshkov@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20131115_034854_411769_73534C00 X-CRM114-Status: GOOD ( 19.35 ) X-Spam-Score: 0.5 (/) Cc: Linus Walleij , Russell King , Dmitry Artamonow X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-1.6 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, SUSPICIOUS_RECIPS, T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP * Replace direct-mapped access with proper ioremap. * Introduce irq domain for system controller irqs * Merge "save" state to common newly create private data. Signed-off-by: Dmitry Eremin-Solenikov --- arch/arm/mach-sa1100/irq.c | 111 +++++++++++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 40 deletions(-) diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c index d96f65f..a26a6a2 100644 --- a/arch/arm/mach-sa1100/irq.c +++ b/arch/arm/mach-sa1100/irq.c @@ -14,26 +14,50 @@ #include #include #include +#include #include #include -#include #include #include "generic.h" +#define ICIP 0x00 /* IC IRQ Pending reg. */ +#define ICMR 0x04 /* IC Mask Reg. */ +#define ICLR 0x08 /* IC Level Reg. */ +#define ICCR 0x0C /* IC Control Reg. */ +#define ICFP 0x10 /* IC FIQ Pending reg. */ +#define ICPR 0x20 /* IC Pending Reg. */ + +struct sa1100_sc { + struct irq_domain *domain; + void __iomem *regbase; + + unsigned int saved_icmr; + unsigned int saved_iclr; + unsigned int saved_iccr; +}; + /* * We don't need to ACK IRQs on the SA1100 unless they're GPIOs * this is for internal IRQs i.e. from 11 to 31. */ static void sa1100_mask_irq(struct irq_data *d) { - ICMR &= ~(1 << d->irq); + struct sa1100_sc *sc = irq_data_get_irq_chip_data(d); + uint32_t icmr = readl_relaxed(sc->regbase + ICMR); + + icmr &= ~BIT(d->hwirq); + writel_relaxed(icmr, sc->regbase + ICMR); } static void sa1100_unmask_irq(struct irq_data *d) { - ICMR |= (1 << d->irq); + struct sa1100_sc *sc = irq_data_get_irq_chip_data(d); + uint32_t icmr = readl_relaxed(sc->regbase + ICMR); + + icmr |= BIT(d->hwirq); + writel_relaxed(icmr, sc->regbase + ICMR); } /* @@ -41,7 +65,7 @@ static void sa1100_unmask_irq(struct irq_data *d) */ static int sa1100_set_wake(struct irq_data *d, unsigned int on) { - return sa11x0_sc_set_wake(d->irq, on); + return sa11x0_sc_set_wake(d->hwirq, on); } static struct irq_chip sa1100_normal_chip = { @@ -55,28 +79,37 @@ static struct irq_chip sa1100_normal_chip = { static struct resource irq_resource = DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs"); -static struct sa1100irq_state { - unsigned int saved; - unsigned int icmr; - unsigned int iclr; - unsigned int iccr; -} sa1100irq_state; +static int sa1100_irqdomain_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hwirq) +{ + struct sa1100_sc *sc = d->host_data; + + irq_set_chip_data(irq, sc); + irq_set_chip_and_handler(irq, &sa1100_normal_chip, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + + return 0; +} + +static struct irq_domain_ops sa1100_irqdomain_ops = { + .map = sa1100_irqdomain_map, + .xlate = irq_domain_xlate_onetwocell, +}; + +static struct sa1100_sc state; static int sa1100irq_suspend(void) { - struct sa1100irq_state *st = &sa1100irq_state; + struct sa1100_sc *sc = &state; - st->saved = 1; - st->icmr = ICMR; - st->iclr = ICLR; - st->iccr = ICCR; + sc->saved_icmr = readl_relaxed(sc->regbase + ICMR); + sc->saved_iclr = readl_relaxed(sc->regbase + ICLR); + sc->saved_iccr = readl_relaxed(sc->regbase + ICCR); /* * Disable all GPIO-based interrupts. */ - ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7| - IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2| - IC_GPIO1|IC_GPIO0); + writel_relaxed(sc->saved_icmr & ~0xFFF, sc->regbase + ICMR); return 0; @@ -84,13 +117,11 @@ static int sa1100irq_suspend(void) static void sa1100irq_resume(void) { - struct sa1100irq_state *st = &sa1100irq_state; + struct sa1100_sc *sc = &state; - if (st->saved) { - ICCR = st->iccr; - ICLR = st->iclr; - ICMR = st->icmr; - } + writel_relaxed(sc->saved_iccr, sc->regbase + ICCR); + writel_relaxed(sc->saved_iclr, sc->regbase + ICLR); + writel_relaxed(sc->saved_icmr, sc->regbase + ICMR); } static struct syscore_ops sa1100irq_syscore_ops = { @@ -110,42 +141,42 @@ static asmlinkage void __exception_irq_entry sa1100_handle_irq(struct pt_regs *regs) { uint32_t icip, icmr, mask; + int irq; - do { - icip = (ICIP); - icmr = (ICMR); + while (1) { + icip = readl_relaxed(state.regbase + ICIP); + icmr = readl_relaxed(state.regbase + ICMR); mask = icip & icmr; if (mask == 0) break; - handle_IRQ(fls(mask) - 1, regs); - } while (1); + irq = fls(mask) - 1; + handle_IRQ(irq_find_mapping(state.domain, irq), regs); + } } void __init sa1100_init_irq(void) { - unsigned int irq; - request_resource(&iomem_resource, &irq_resource); + state.regbase = ioremap(irq_resource.start, + resource_size(&irq_resource)); + /* disable all IRQs */ - ICMR = 0; + writel_relaxed(0, state.regbase + ICMR); /* all IRQs are IRQ, not FIQ */ - ICLR = 0; + writel_relaxed(0, state.regbase + ICLR); /* * Whatever the doc says, this has to be set for the wait-on-irq - * instruction to work... on a SA1100 rev 9 at least. + * instruction to work... on a SA1100 rev 9 at leastate. */ - ICCR = 1; + writel_relaxed(1, state.regbase + ICCR); - for (irq = 0; irq <= 31; irq++) { - irq_set_chip_and_handler(irq, &sa1100_normal_chip, - handle_level_irq); - set_irq_flags(irq, IRQF_VALID); - } + state.domain = irq_domain_add_legacy(NULL, 32, 0, 0, + &sa1100_irqdomain_ops, &state); set_handle_irq(sa1100_handle_irq); }