From patchwork Tue Jun 7 08:25:37 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shawn Guo X-Patchwork-Id: 1765 Return-Path: Delivered-To: unknown Received: from imap.gmail.com (74.125.159.109) by localhost6.localdomain6 with IMAP4-SSL; 08 Jun 2011 14:55:38 -0000 Delivered-To: patches@linaro.org Received: by 10.52.181.10 with SMTP id ds10cs86068vdc; Tue, 7 Jun 2011 01:17:22 -0700 (PDT) Received: by 10.42.239.6 with SMTP id ku6mr9180199icb.189.1307434641902; Tue, 07 Jun 2011 01:17:21 -0700 (PDT) Received: from mail-px0-f172.google.com (mail-px0-f172.google.com [209.85.212.172]) by mx.google.com with ESMTPS id i6si34784125icv.94.2011.06.07.01.17.21 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 07 Jun 2011 01:17:21 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.212.172 is neither permitted nor denied by best guess record for domain of shawn.guo@linaro.org) client-ip=209.85.212.172; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.172 is neither permitted nor denied by best guess record for domain of shawn.guo@linaro.org) smtp.mail=shawn.guo@linaro.org Received: by pxi6 with SMTP id 6so3097731pxi.17 for ; Tue, 07 Jun 2011 01:17:21 -0700 (PDT) Received: by 10.68.36.231 with SMTP id t7mr76580pbj.507.1307434641109; Tue, 07 Jun 2011 01:17:21 -0700 (PDT) Received: from localhost.localdomain ([114.216.150.149]) by mx.google.com with ESMTPS id x1sm4293467pbb.34.2011.06.07.01.17.09 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 07 Jun 2011 01:17:20 -0700 (PDT) From: Shawn Guo To: linux-arm-kernel@lists.infradead.org Cc: grant.likely@secretlab.ca, tglx@linutronix.de, kernel@pengutronix.de, patches@linaro.org, Shawn Guo Subject: [PATCH] gpio/mxc: convert gpio-mxc to use generic irq chip Date: Tue, 7 Jun 2011 16:25:37 +0800 Message-Id: <1307435137-31439-1-git-send-email-shawn.guo@linaro.org> X-Mailer: git-send-email 1.7.4.1 The patch converts gpio-mxc driver to use generic irq chip. Signed-off-by: Shawn Guo Acked-by: Sascha Hauer --- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-mxc.c | 90 +++++++++++++++-------------------------------- 2 files changed, 30 insertions(+), 61 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index d973abd..ee8802f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -97,6 +97,7 @@ config GPIO_MXC def_bool y depends on ARCH_MXC select GPIO_BASIC_MMIO_CORE + select GENERIC_IRQ_CHIP config GPIO_PLAT_SAMSUNG bool "Samsung SoCs GPIO library support" diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index b351952893..950e53a 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -65,46 +65,11 @@ static LIST_HEAD(mxc_gpio_ports); /* Note: This driver assumes 32 GPIOs are handled in one register */ -static void _clear_gpio_irqstatus(struct mxc_gpio_port *port, u32 index) -{ - writel(1 << index, port->base + GPIO_ISR); -} - -static void _set_gpio_irqenable(struct mxc_gpio_port *port, u32 index, - int enable) -{ - u32 l; - - l = readl(port->base + GPIO_IMR); - l = (l & (~(1 << index))) | (!!enable << index); - writel(l, port->base + GPIO_IMR); -} - -static void gpio_ack_irq(struct irq_data *d) -{ - struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d); - u32 gpio = irq_to_gpio(d->irq); - _clear_gpio_irqstatus(port, gpio & 0x1f); -} - -static void gpio_mask_irq(struct irq_data *d) -{ - struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d); - u32 gpio = irq_to_gpio(d->irq); - _set_gpio_irqenable(port, gpio & 0x1f, 0); -} - -static void gpio_unmask_irq(struct irq_data *d) -{ - struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d); - u32 gpio = irq_to_gpio(d->irq); - _set_gpio_irqenable(port, gpio & 0x1f, 1); -} - static int gpio_set_irq_type(struct irq_data *d, u32 type) { u32 gpio = irq_to_gpio(d->irq); - struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d); + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct mxc_gpio_port *port = gc->private; u32 bit, val; int edge; void __iomem *reg = port->base; @@ -142,7 +107,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) bit = gpio & 0xf; val = readl(reg) & ~(0x3 << (bit << 1)); writel(val | (edge << (bit << 1)), reg); - _clear_gpio_irqstatus(port, gpio & 0x1f); + writel(1 << (gpio & 0x1f), port->base + GPIO_ISR); return 0; } @@ -231,7 +196,8 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable) { u32 gpio = irq_to_gpio(d->irq); u32 gpio_idx = gpio & 0x1F; - struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d); + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct mxc_gpio_port *port = gc->private; if (enable) { if (port->irq_high && (gpio_idx >= 16)) @@ -248,26 +214,33 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable) return 0; } -static struct irq_chip gpio_irq_chip = { - .name = "GPIO", - .irq_ack = gpio_ack_irq, - .irq_mask = gpio_mask_irq, - .irq_unmask = gpio_unmask_irq, - .irq_set_type = gpio_set_irq_type, - .irq_set_wake = gpio_set_wake_irq, -}; - -/* - * This lock class tells lockdep that GPIO irqs are in a different - * category than their parents, so it won't report false recursion. - */ -static struct lock_class_key gpio_lock_class; +static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port) +{ + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + + gc = irq_alloc_generic_chip("gpio-mxc", 1, port->virtual_irq_start, + port->base, handle_level_irq); + gc->private = port; + + ct = gc->chip_types; + ct->chip.irq_ack = irq_gc_ack, + ct->chip.irq_mask = irq_gc_mask_clr_bit; + ct->chip.irq_unmask = irq_gc_mask_set_bit; + ct->chip.irq_set_type = gpio_set_irq_type; + ct->chip.irq_set_wake = gpio_set_wake_irq, + ct->regs.ack = GPIO_ISR; + ct->regs.mask = GPIO_IMR; + + irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK, + IRQ_NOREQUEST, 0); +} static int __devinit mxc_gpio_probe(struct platform_device *pdev) { struct mxc_gpio_port *port; struct resource *iores; - int err, i; + int err; port = kzalloc(sizeof(struct mxc_gpio_port), GFP_KERNEL); if (!port) @@ -304,13 +277,8 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev) writel(0, port->base + GPIO_IMR); writel(~0, port->base + GPIO_ISR); - for (i = port->virtual_irq_start; - i < port->virtual_irq_start + 32; i++) { - irq_set_lockdep_class(i, &gpio_lock_class); - irq_set_chip_and_handler(i, &gpio_irq_chip, handle_level_irq); - set_irq_flags(i, IRQF_VALID); - irq_set_chip_data(i, port); - } + /* gpio-mxc can be a generic irq chip */ + mxc_gpio_init_gc(port); if (cpu_is_mx2()) { /* setup one handler for all GPIO interrupts */