From patchwork Fri Jan 30 20:01:05 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 5752701 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.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id ECDBEBF440 for ; Fri, 30 Jan 2015 20:04:26 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id EF6C420263 for ; Fri, 30 Jan 2015 20:04:25 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 02D4B20265 for ; Fri, 30 Jan 2015 20:04:25 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YHHm3-00047M-F8; Fri, 30 Jan 2015 20:02:39 +0000 Received: from mail-pa0-x230.google.com ([2607:f8b0:400e:c03::230]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YHHlO-0003jl-6y for linux-arm-kernel@lists.infradead.org; Fri, 30 Jan 2015 20:01:59 +0000 Received: by mail-pa0-f48.google.com with SMTP id ey11so56207190pad.7 for ; Fri, 30 Jan 2015 12:01:36 -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=AbrKeTNggOKMES5MDXKvZvEpLd43nl8o1Q2P82b1l7c=; b=A64LtzEu2lO3BvKLUccR4YtR5LYZre/HrFE52xn50NpxC04mksORa8pONytuwtJ29Z f+lTbWi3QTUZVQEMlXCwoHxX1+zejUMjjVT06cAMBHe4WQPr+Iizf5Il1UgBdBCP2lj4 E4nsW6Dp8WPX0II53oKdYdf+H+D/xJwSZHbW1xVWpKPhnLf8Kuco+4fcjXVBQ1E00fUr Ssiq/aPf0lQw1nzuThj+jD+Ggiij5fvGfPX6Xlm9vG8l/uqd3iknYPwbYHDbwtmGZ+fT sbrRASjPCcDvfAU42y+7h2+mdTQ4g3vDDffOjaJ8Q+pgfFLQRCmj8JoyYfxvryO9ST8q O7Jg== X-Received: by 10.68.109.227 with SMTP id hv3mr7495799pbb.84.1422648096826; Fri, 30 Jan 2015 12:01:36 -0800 (PST) Received: from fangorn.rup.mentorg.com (nat-min.mentorg.com. [139.181.32.34]) by mx.google.com with ESMTPSA id b15sm11585829pdl.60.2015.01.30.12.01.34 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 30 Jan 2015 12:01:36 -0800 (PST) From: Dmitry Eremin-Solenikov To: Russell King , Thomas Gleixner , Jason Cooper Subject: [PATCH v2 4/5] irqchip: add sa1100 driver Date: Fri, 30 Jan 2015 23:01:05 +0300 Message-Id: <1422648066-7897-5-git-send-email-dbaryshkov@gmail.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1422648066-7897-1-git-send-email-dbaryshkov@gmail.com> References: <1422648066-7897-1-git-send-email-dbaryshkov@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150130_120158_323268_245B143A X-CRM114-Status: GOOD ( 18.14 ) X-Spam-Score: -0.8 (/) Cc: Linus Walleij , Andrea Adami , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 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=-4.1 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable 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 Add an irqchip driver for Intel StrongARM SA-11x0 family of chips. For now it is just a copy of the current arch/arm/mach-sa1100/irq.c driver. Signed-off-by: Dmitry Eremin-Solenikov --- drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-sa11x0.c | 176 +++++++++++++++++++++++++++++++++++++ include/linux/irqchip/irq-sa11x0.h | 16 ++++ 3 files changed, 193 insertions(+) create mode 100644 drivers/irqchip/irq-sa11x0.c create mode 100644 include/linux/irqchip/irq-sa11x0.h diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 9516a32..b0d1dde 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -42,3 +42,4 @@ obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o obj-$(CONFIG_MIPS_GIC) += irq-mips-gic.o obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o +obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o diff --git a/drivers/irqchip/irq-sa11x0.c b/drivers/irqchip/irq-sa11x0.c new file mode 100644 index 0000000..76b8c1d --- /dev/null +++ b/drivers/irqchip/irq-sa11x0.c @@ -0,0 +1,176 @@ +/* + * drivers/irqchip/irq-sa11x0.c + * + * Copyright (C) 1999-2001 Nicolas Pitre + * + * Generic IRQ handling for the SA11x0. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#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. */ + +static void __iomem *iobase; + +/* + * We don't need to ACK IRQs on the SA1100 unless they're GPIOs + * this is for internal IRQs i.e. from IRQ LCD to RTCAlrm. + */ +static void sa1100_mask_irq(struct irq_data *d) +{ + u32 reg; + + reg = readl_relaxed(iobase + ICMR); + reg &= ~BIT(d->hwirq); + writel_relaxed(reg, iobase + ICMR); +} + +static void sa1100_unmask_irq(struct irq_data *d) +{ + u32 reg; + + reg = readl_relaxed(iobase + ICMR); + reg |= BIT(d->hwirq); + writel_relaxed(reg, iobase + ICMR); +} + +static int sa1100_set_wake(struct irq_data *d, unsigned int on) +{ + return sa11x0_sc_set_wake(d->hwirq, on); +} + +static struct irq_chip sa1100_normal_chip = { + .name = "SC", + .irq_ack = sa1100_mask_irq, + .irq_mask = sa1100_mask_irq, + .irq_unmask = sa1100_unmask_irq, + .irq_set_wake = sa1100_set_wake, +}; + +static int sa1100_normal_irqdomain_map(struct irq_domain *d, + unsigned int irq, irq_hw_number_t hwirq) +{ + 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_normal_irqdomain_ops = { + .map = sa1100_normal_irqdomain_map, + .xlate = irq_domain_xlate_onetwocell, +}; + +static struct irq_domain *sa1100_normal_irqdomain; + +static struct sa1100irq_state { + unsigned int saved; + unsigned int icmr; + unsigned int iclr; + unsigned int iccr; +} sa1100irq_state; + +static int sa1100irq_suspend(void) +{ + struct sa1100irq_state *st = &sa1100irq_state; + + st->saved = 1; + st->icmr = readl_relaxed(iobase + ICMR); + st->iclr = readl_relaxed(iobase + ICLR); + st->iccr = readl_relaxed(iobase + ICCR); + + /* + * Disable all GPIO-based interrupts. + */ + writel_relaxed(st->icmr & 0xfffff000, iobase + ICMR); + + return 0; +} + +static void sa1100irq_resume(void) +{ + struct sa1100irq_state *st = &sa1100irq_state; + + if (st->saved) { + writel_relaxed(st->iccr, iobase + ICCR); + writel_relaxed(st->iclr, iobase + ICLR); + + writel_relaxed(st->icmr, iobase + ICMR); + } +} + +static struct syscore_ops sa1100irq_syscore_ops = { + .suspend = sa1100irq_suspend, + .resume = sa1100irq_resume, +}; + +static int __init sa1100irq_init_devicefs(void) +{ + register_syscore_ops(&sa1100irq_syscore_ops); + return 0; +} + +device_initcall(sa1100irq_init_devicefs); + +static asmlinkage void __exception_irq_entry +sa1100_handle_irq(struct pt_regs *regs) +{ + uint32_t icip, icmr, mask; + + do { + icip = readl_relaxed(iobase + ICIP); + icmr = readl_relaxed(iobase + ICMR); + mask = icip & icmr; + + if (mask == 0) + break; + + handle_domain_irq(sa1100_normal_irqdomain, + ffs(mask) - 1, regs); + } while (1); +} + +void __init sa11x0_init_irq_nodt(int irq_start, resource_size_t io_start) +{ + iobase = ioremap(io_start, SZ_64K); + if (WARN_ON(!iobase)) + return; + + /* disable all IRQs */ + writel_relaxed(0, iobase + ICMR); + + /* all IRQs are IRQ, not FIQ */ + writel_relaxed(0, iobase + 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. + */ + writel_relaxed(1, iobase + ICCR); + + sa1100_normal_irqdomain = irq_domain_add_simple(NULL, + 32, irq_start, + &sa1100_normal_irqdomain_ops, NULL); + + set_handle_irq(sa1100_handle_irq); +} diff --git a/include/linux/irqchip/irq-sa11x0.h b/include/linux/irqchip/irq-sa11x0.h new file mode 100644 index 0000000..2f66eca --- /dev/null +++ b/include/linux/irqchip/irq-sa11x0.h @@ -0,0 +1,16 @@ +/* + * Generic IRQ handling for the SA11x0. + * + * Copyright (C) 1999-2001 Nicolas Pitre + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_SA11x0_H +#define __INCLUDE_LINUX_IRQCHIP_IRQ_SA11x0_H + +void __init sa11x0_init_irq_nodt(int irq_start, resource_size_t io_start); + +#endif