diff options
Diffstat (limited to 'arch/sh/boards/mach-x3proto/gpio.c')
| -rw-r--r-- | arch/sh/boards/mach-x3proto/gpio.c | 61 | 
1 files changed, 33 insertions, 28 deletions
diff --git a/arch/sh/boards/mach-x3proto/gpio.c b/arch/sh/boards/mach-x3proto/gpio.c index 239e7406625..3ea65e9b56e 100644 --- a/arch/sh/boards/mach-x3proto/gpio.c +++ b/arch/sh/boards/mach-x3proto/gpio.c @@ -3,7 +3,7 @@   *   * Renesas SH-X3 Prototype Baseboard GPIO Support.   * - * Copyright (C) 2010  Paul Mundt + * Copyright (C) 2010 - 2012  Paul Mundt   *   * This file is subject to the terms and conditions of the GNU General Public   * License.  See the file "COPYING" in the main directory of this archive @@ -17,6 +17,7 @@  #include <linux/irq.h>  #include <linux/kernel.h>  #include <linux/spinlock.h> +#include <linux/irqdomain.h>  #include <linux/io.h>  #include <mach/ilsel.h>  #include <mach/hardware.h> @@ -26,7 +27,7 @@  #define KEYDETR 0xb81c0004  static DEFINE_SPINLOCK(x3proto_gpio_lock); -static unsigned int x3proto_gpio_irq_map[NR_BASEBOARD_GPIOS] = { 0, }; +static struct irq_domain *x3proto_irq_domain;  static int x3proto_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)  { @@ -49,7 +50,14 @@ static int x3proto_gpio_get(struct gpio_chip *chip, unsigned gpio)  static int x3proto_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)  { -	return x3proto_gpio_irq_map[gpio]; +	int virq; + +	if (gpio < chip->ngpio) +		virq = irq_create_mapping(x3proto_irq_domain, gpio); +	else +		virq = -ENXIO; + +	return virq;  }  static void x3proto_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) @@ -62,9 +70,8 @@ static void x3proto_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)  	chip->irq_mask_ack(data);  	mask = __raw_readw(KEYDETR); -  	for_each_set_bit(pin, &mask, NR_BASEBOARD_GPIOS) -		generic_handle_irq(x3proto_gpio_to_irq(NULL, pin)); +		generic_handle_irq(irq_linear_revmap(x3proto_irq_domain, pin));  	chip->irq_unmask(data);  } @@ -78,10 +85,23 @@ struct gpio_chip x3proto_gpio_chip = {  	.ngpio			= NR_BASEBOARD_GPIOS,  }; +static int x3proto_gpio_irq_map(struct irq_domain *domain, unsigned int virq, +				irq_hw_number_t hwirq) +{ +	irq_set_chip_and_handler_name(virq, &dummy_irq_chip, handle_simple_irq, +				      "gpio"); + +	return 0; +} + +static struct irq_domain_ops x3proto_gpio_irq_ops = { +	.map	= x3proto_gpio_irq_map, +	.xlate	= irq_domain_xlate_twocell, +}; +  int __init x3proto_gpio_setup(void)  { -	int ilsel; -	int ret, i; +	int ilsel, ret;  	ilsel = ilsel_enable(ILSEL_KEY);  	if (unlikely(ilsel < 0)) @@ -91,21 +111,10 @@ int __init x3proto_gpio_setup(void)  	if (unlikely(ret))  		goto err_gpio; -	for (i = 0; i < NR_BASEBOARD_GPIOS; i++) { -		unsigned long flags; -		int irq = create_irq(); - -		if (unlikely(irq < 0)) { -			ret = -EINVAL; -			goto err_irq; -		} - -		spin_lock_irqsave(&x3proto_gpio_lock, flags); -		x3proto_gpio_irq_map[i] = irq; -		set_irq_chip_and_handler_name(irq, &dummy_irq_chip, -					handle_simple_irq, "gpio"); -		spin_unlock_irqrestore(&x3proto_gpio_lock, flags); -	} +	x3proto_irq_domain = irq_domain_add_linear(NULL, NR_BASEBOARD_GPIOS, +						   &x3proto_gpio_irq_ops, NULL); +	if (unlikely(!x3proto_irq_domain)) +		goto err_irq;  	pr_info("registering '%s' support, handling GPIOs %u -> %u, "  		"bound to IRQ %u\n", @@ -113,16 +122,12 @@ int __init x3proto_gpio_setup(void)  		x3proto_gpio_chip.base + x3proto_gpio_chip.ngpio,  		ilsel); -	set_irq_chained_handler(ilsel, x3proto_gpio_irq_handler); -	set_irq_wake(ilsel, 1); +	irq_set_chained_handler(ilsel, x3proto_gpio_irq_handler); +	irq_set_irq_wake(ilsel, 1);  	return 0;  err_irq: -	for (; i >= 0; --i) -		if (x3proto_gpio_irq_map[i]) -			destroy_irq(x3proto_gpio_irq_map[i]); -  	ret = gpiochip_remove(&x3proto_gpio_chip);  	if (unlikely(ret))  		pr_err("Failed deregistering GPIO\n");  | 
