diff options
Diffstat (limited to 'arch/sh/boards')
| -rw-r--r-- | arch/sh/boards/Kconfig | 5 | ||||
| -rw-r--r-- | arch/sh/boards/mach-dreamcast/irq.c | 32 | ||||
| -rw-r--r-- | arch/sh/boards/mach-kfr2r09/setup.c | 4 | ||||
| -rw-r--r-- | arch/sh/boards/mach-migor/setup.c | 1 | ||||
| -rw-r--r-- | arch/sh/boards/mach-se/7343/irq.c | 129 | ||||
| -rw-r--r-- | arch/sh/boards/mach-se/7343/setup.c | 10 | ||||
| -rw-r--r-- | arch/sh/boards/mach-se/7722/irq.c | 131 | ||||
| -rw-r--r-- | arch/sh/boards/mach-se/7722/setup.c | 6 | ||||
| -rw-r--r-- | arch/sh/boards/mach-se/7724/irq.c | 36 | ||||
| -rw-r--r-- | arch/sh/boards/mach-x3proto/gpio.c | 57 | 
10 files changed, 243 insertions, 168 deletions
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index 1f56b35d324..7048c03490d 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -44,6 +44,8 @@ config SH_7721_SOLUTION_ENGINE  config SH_7722_SOLUTION_ENGINE  	bool "SolutionEngine7722"  	select SOLUTION_ENGINE +	select GENERIC_IRQ_CHIP +	select IRQ_DOMAIN  	depends on CPU_SUBTYPE_SH7722  	help  	  Select 7722 SolutionEngine if configuring for a Hitachi SH772 @@ -80,6 +82,8 @@ config SH_7780_SOLUTION_ENGINE  config SH_7343_SOLUTION_ENGINE  	bool "SolutionEngine7343"  	select SOLUTION_ENGINE +	select GENERIC_IRQ_CHIP +	select IRQ_DOMAIN  	depends on CPU_SUBTYPE_SH7343  	help  	  Select 7343 SolutionEngine if configuring for a Hitachi @@ -295,6 +299,7 @@ config SH_X3PROTO  	bool "SH-X3 Prototype board"  	depends on CPU_SUBTYPE_SHX3  	select NO_IOPORT if !PCI +	select IRQ_DOMAIN  config SH_MAGIC_PANEL_R2  	bool "Magic Panel R2" diff --git a/arch/sh/boards/mach-dreamcast/irq.c b/arch/sh/boards/mach-dreamcast/irq.c index f63d323f411..2789647abeb 100644 --- a/arch/sh/boards/mach-dreamcast/irq.c +++ b/arch/sh/boards/mach-dreamcast/irq.c @@ -8,10 +8,11 @@   * This file is part of the LinuxDC project (www.linuxdc.org)   * Released under the terms of the GNU GPL v2.0   */ -  #include <linux/irq.h>  #include <linux/io.h> -#include <asm/irq.h> +#include <linux/irq.h> +#include <linux/export.h> +#include <linux/err.h>  #include <mach/sysasic.h>  /* @@ -141,26 +142,15 @@ int systemasic_irq_demux(int irq)  void systemasic_irq_init(void)  { -	int i, nid = cpu_to_node(boot_cpu_data); - -	/* Assign all virtual IRQs to the System ASIC int. handler */ -	for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++) { -		unsigned int irq; - -		irq = create_irq_nr(i, nid); -		if (unlikely(irq == 0)) { -			pr_err("%s: failed hooking irq %d for systemasic\n", -			       __func__, i); -			return; -		} +	int irq_base, i; -		if (unlikely(irq != i)) { -			pr_err("%s: got irq %d but wanted %d, bailing.\n", -			       __func__, irq, i); -			destroy_irq(irq); -			return; -		} +	irq_base = irq_alloc_descs(HW_EVENT_IRQ_BASE, HW_EVENT_IRQ_BASE, +				   HW_EVENT_IRQ_MAX - HW_EVENT_IRQ_BASE, -1); +	if (IS_ERR_VALUE(irq_base)) { +		pr_err("%s: failed hooking irqs\n", __func__); +		return; +	} +	for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++)  		irq_set_chip_and_handler(i, &systemasic_int, handle_level_irq); -	}  } diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c index 158c9176e42..43a179ce9af 100644 --- a/arch/sh/boards/mach-kfr2r09/setup.c +++ b/arch/sh/boards/mach-kfr2r09/setup.c @@ -201,8 +201,8 @@ static struct resource kfr2r09_usb0_gadget_resources[] = {  		.flags	= IORESOURCE_MEM,  	},  	[1] = { -		.start	= evtirq(0xa20), -		.end	= evtirq(0xa20), +		.start	= evt2irq(0xa20), +		.end	= evt2irq(0xa20),  		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,  	},  }; diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index 34cd0c5ff2e..a8a1ca741c8 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c @@ -188,7 +188,6 @@ static struct platform_nand_data migor_nand_flash_data = {  		.partitions = migor_nand_flash_partitions,  		.nr_partitions = ARRAY_SIZE(migor_nand_flash_partitions),  		.chip_delay = 20, -		.part_probe_types = (const char *[]) { "cmdlinepart", NULL },  	},  	.ctrl = {  		.dev_ready = migor_nand_flash_ready, diff --git a/arch/sh/boards/mach-se/7343/irq.c b/arch/sh/boards/mach-se/7343/irq.c index fd45ffc4834..7646bf0486c 100644 --- a/arch/sh/boards/mach-se/7343/irq.c +++ b/arch/sh/boards/mach-se/7343/irq.c @@ -1,86 +1,129 @@  /* - * linux/arch/sh/boards/se/7343/irq.c + * Hitachi UL SolutionEngine 7343 FPGA IRQ Support.   *   * Copyright (C) 2008  Yoshihiro Shimoda + * Copyright (C) 2012  Paul Mundt   * - * Based on linux/arch/sh/boards/se/7722/irq.c + * Based on linux/arch/sh/boards/se/7343/irq.c   * Copyright (C) 2007  Nobuhiro Iwamatsu   *   * 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   * for more details.   */ +#define DRV_NAME "SE7343-FPGA" +#define pr_fmt(fmt) DRV_NAME ": " fmt + +#define irq_reg_readl	ioread16 +#define irq_reg_writel	iowrite16 +  #include <linux/init.h>  #include <linux/irq.h>  #include <linux/interrupt.h> +#include <linux/irqdomain.h>  #include <linux/io.h> +#include <asm/sizes.h>  #include <mach-se/mach/se7343.h> -unsigned int se7343_fpga_irq[SE7343_FPGA_IRQ_NR] = { 0, }; +#define PA_CPLD_BASE_ADDR	0x11400000 +#define PA_CPLD_ST_REG		0x08	/* CPLD Interrupt status register */ +#define PA_CPLD_IMSK_REG	0x0a	/* CPLD Interrupt mask register */ -static void disable_se7343_irq(struct irq_data *data) -{ -	unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data); -	__raw_writew(__raw_readw(PA_CPLD_IMSK) | 1 << bit, PA_CPLD_IMSK); -} +static void __iomem *se7343_irq_regs; +struct irq_domain *se7343_irq_domain; -static void enable_se7343_irq(struct irq_data *data) +static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc)  { -	unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data); -	__raw_writew(__raw_readw(PA_CPLD_IMSK) & ~(1 << bit), PA_CPLD_IMSK); -} +	struct irq_data *data = irq_get_irq_data(irq); +	struct irq_chip *chip = irq_data_get_irq_chip(data); +	unsigned long mask; +	int bit; -static struct irq_chip se7343_irq_chip __read_mostly = { -	.name		= "SE7343-FPGA", -	.irq_mask	= disable_se7343_irq, -	.irq_unmask	= enable_se7343_irq, -}; +	chip->irq_mask_ack(data); -static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc) +	mask = ioread16(se7343_irq_regs + PA_CPLD_ST_REG); + +	for_each_set_bit(bit, &mask, SE7343_FPGA_IRQ_NR) +		generic_handle_irq(irq_linear_revmap(se7343_irq_domain, bit)); + +	chip->irq_unmask(data); +} + +static void __init se7343_domain_init(void)  { -	unsigned short intv = __raw_readw(PA_CPLD_ST); -	unsigned int ext_irq = 0; +	int i; -	intv &= (1 << SE7343_FPGA_IRQ_NR) - 1; +	se7343_irq_domain = irq_domain_add_linear(NULL, SE7343_FPGA_IRQ_NR, +						  &irq_domain_simple_ops, NULL); +	if (unlikely(!se7343_irq_domain)) { +		printk("Failed to get IRQ domain\n"); +		return; +	} -	for (; intv; intv >>= 1, ext_irq++) { -		if (!(intv & 1)) -			continue; +	for (i = 0; i < SE7343_FPGA_IRQ_NR; i++) { +		int irq = irq_create_mapping(se7343_irq_domain, i); -		generic_handle_irq(se7343_fpga_irq[ext_irq]); +		if (unlikely(irq == 0)) { +			printk("Failed to allocate IRQ %d\n", i); +			return; +		}  	}  } -/* - * Initialize IRQ setting - */ -void __init init_7343se_IRQ(void) +static void __init se7343_gc_init(void)  { -	int i, irq; +	struct irq_chip_generic *gc; +	struct irq_chip_type *ct; +	unsigned int irq_base; -	__raw_writew(0, PA_CPLD_IMSK);	/* disable all irqs */ -	__raw_writew(0x2000, 0xb03fffec);	/* mrshpc irq enable */ +	irq_base = irq_linear_revmap(se7343_irq_domain, 0); -	for (i = 0; i < SE7343_FPGA_IRQ_NR; i++) { -		irq = create_irq(); -		if (irq < 0) -			return; -		se7343_fpga_irq[i] = irq; +	gc = irq_alloc_generic_chip(DRV_NAME, 1, irq_base, se7343_irq_regs, +				    handle_level_irq); +	if (unlikely(!gc)) +		return; -		irq_set_chip_and_handler_name(se7343_fpga_irq[i], -					      &se7343_irq_chip, -					      handle_level_irq, -					      "level"); +	ct = gc->chip_types; +	ct->chip.irq_mask = irq_gc_mask_set_bit; +	ct->chip.irq_unmask = irq_gc_mask_clr_bit; -		irq_set_chip_data(se7343_fpga_irq[i], (void *)i); -	} +	ct->regs.mask = PA_CPLD_IMSK_REG; + +	irq_setup_generic_chip(gc, IRQ_MSK(SE7343_FPGA_IRQ_NR), +			       IRQ_GC_INIT_MASK_CACHE, +			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);  	irq_set_chained_handler(IRQ0_IRQ, se7343_irq_demux);  	irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW); +  	irq_set_chained_handler(IRQ1_IRQ, se7343_irq_demux);  	irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW); +  	irq_set_chained_handler(IRQ4_IRQ, se7343_irq_demux);  	irq_set_irq_type(IRQ4_IRQ, IRQ_TYPE_LEVEL_LOW); +  	irq_set_chained_handler(IRQ5_IRQ, se7343_irq_demux);  	irq_set_irq_type(IRQ5_IRQ, IRQ_TYPE_LEVEL_LOW);  } + +/* + * Initialize IRQ setting + */ +void __init init_7343se_IRQ(void) +{ +	se7343_irq_regs = ioremap(PA_CPLD_BASE_ADDR, SZ_16); +	if (unlikely(!se7343_irq_regs)) { +		pr_err("Failed to remap CPLD\n"); +		return; +	} + +	/* +	 * All FPGA IRQs disabled by default +	 */ +	iowrite16(0, se7343_irq_regs + PA_CPLD_IMSK_REG); + +	__raw_writew(0x2000, 0xb03fffec);	/* mrshpc irq enable */ + +	se7343_domain_init(); +	se7343_gc_init(); +} diff --git a/arch/sh/boards/mach-se/7343/setup.c b/arch/sh/boards/mach-se/7343/setup.c index d2370af56d7..8ce4f2a202a 100644 --- a/arch/sh/boards/mach-se/7343/setup.c +++ b/arch/sh/boards/mach-se/7343/setup.c @@ -5,6 +5,7 @@  #include <linux/serial_reg.h>  #include <linux/usb/isp116x.h>  #include <linux/delay.h> +#include <linux/irqdomain.h>  #include <asm/machvec.h>  #include <mach-se/mach/se7343.h>  #include <asm/heartbeat.h> @@ -145,11 +146,12 @@ static struct platform_device *sh7343se_platform_devices[] __initdata = {  static int __init sh7343se_devices_setup(void)  {  	/* Wire-up dynamic vectors */ -	serial_platform_data[0].irq = se7343_fpga_irq[SE7343_FPGA_IRQ_UARTA]; -	serial_platform_data[1].irq = se7343_fpga_irq[SE7343_FPGA_IRQ_UARTB]; - +	serial_platform_data[0].irq = irq_find_mapping(se7343_irq_domain, +						       SE7343_FPGA_IRQ_UARTA); +	serial_platform_data[1].irq = irq_find_mapping(se7343_irq_domain, +						       SE7343_FPGA_IRQ_UARTB);  	usb_resources[2].start = usb_resources[2].end = -		se7343_fpga_irq[SE7343_FPGA_IRQ_USB]; +		irq_find_mapping(se7343_irq_domain, SE7343_FPGA_IRQ_USB);  	return platform_add_devices(sh7343se_platform_devices,  				    ARRAY_SIZE(sh7343se_platform_devices)); diff --git a/arch/sh/boards/mach-se/7722/irq.c b/arch/sh/boards/mach-se/7722/irq.c index aac92f21ebd..f5e2af1bf04 100644 --- a/arch/sh/boards/mach-se/7722/irq.c +++ b/arch/sh/boards/mach-se/7722/irq.c @@ -1,79 +1,96 @@  /* - * linux/arch/sh/boards/se/7722/irq.c + * Hitachi UL SolutionEngine 7722 FPGA IRQ Support.   *   * Copyright (C) 2007  Nobuhiro Iwamatsu - * - * Hitachi UL SolutionEngine 7722 Support. + * Copyright (C) 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   * for more details.   */ +#define DRV_NAME "SE7722-FPGA" +#define pr_fmt(fmt) DRV_NAME ": " fmt + +#define irq_reg_readl	ioread16 +#define irq_reg_writel	iowrite16 +  #include <linux/init.h>  #include <linux/irq.h>  #include <linux/interrupt.h> -#include <asm/irq.h> -#include <asm/io.h> +#include <linux/irqdomain.h> +#include <linux/io.h> +#include <linux/err.h> +#include <asm/sizes.h>  #include <mach-se/mach/se7722.h> -unsigned int se7722_fpga_irq[SE7722_FPGA_IRQ_NR] = { 0, }; +#define IRQ01_BASE_ADDR	0x11800000 +#define IRQ01_MODE_REG	0 +#define IRQ01_STS_REG	4 +#define IRQ01_MASK_REG	8 -static void disable_se7722_irq(struct irq_data *data) -{ -	unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data); -	__raw_writew(__raw_readw(IRQ01_MASK) | 1 << bit, IRQ01_MASK); -} +static void __iomem *se7722_irq_regs; +struct irq_domain *se7722_irq_domain; -static void enable_se7722_irq(struct irq_data *data) +static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc)  { -	unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data); -	__raw_writew(__raw_readw(IRQ01_MASK) & ~(1 << bit), IRQ01_MASK); -} +	struct irq_data *data = irq_get_irq_data(irq); +	struct irq_chip *chip = irq_data_get_irq_chip(data); +	unsigned long mask; +	int bit; -static struct irq_chip se7722_irq_chip __read_mostly = { -	.name		= "SE7722-FPGA", -	.irq_mask	= disable_se7722_irq, -	.irq_unmask	= enable_se7722_irq, -}; +	chip->irq_mask_ack(data); -static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc) +	mask = ioread16(se7722_irq_regs + IRQ01_STS_REG); + +	for_each_set_bit(bit, &mask, SE7722_FPGA_IRQ_NR) +		generic_handle_irq(irq_linear_revmap(se7722_irq_domain, bit)); + +	chip->irq_unmask(data); +} + +static void __init se7722_domain_init(void)  { -	unsigned short intv = __raw_readw(IRQ01_STS); -	unsigned int ext_irq = 0; +	int i; -	intv &= (1 << SE7722_FPGA_IRQ_NR) - 1; +	se7722_irq_domain = irq_domain_add_linear(NULL, SE7722_FPGA_IRQ_NR, +						  &irq_domain_simple_ops, NULL); +	if (unlikely(!se7722_irq_domain)) { +		printk("Failed to get IRQ domain\n"); +		return; +	} -	for (; intv; intv >>= 1, ext_irq++) { -		if (!(intv & 1)) -			continue; +	for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) { +		int irq = irq_create_mapping(se7722_irq_domain, i); -		generic_handle_irq(se7722_fpga_irq[ext_irq]); +		if (unlikely(irq == 0)) { +			printk("Failed to allocate IRQ %d\n", i); +			return; +		}  	}  } -/* - * Initialize IRQ setting - */ -void __init init_se7722_IRQ(void) +static void __init se7722_gc_init(void)  { -	int i, irq; +	struct irq_chip_generic *gc; +	struct irq_chip_type *ct; +	unsigned int irq_base; -	__raw_writew(0, IRQ01_MASK);       /* disable all irqs */ -	__raw_writew(0x2000, 0xb03fffec);  /* mrshpc irq enable */ +	irq_base = irq_linear_revmap(se7722_irq_domain, 0); -	for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) { -		irq = create_irq(); -		if (irq < 0) -			return; -		se7722_fpga_irq[i] = irq; +	gc = irq_alloc_generic_chip(DRV_NAME, 1, irq_base, se7722_irq_regs, +				    handle_level_irq); +	if (unlikely(!gc)) +		return; -		irq_set_chip_and_handler_name(se7722_fpga_irq[i], -					      &se7722_irq_chip, -					      handle_level_irq, -					      "level"); +	ct = gc->chip_types; +	ct->chip.irq_mask = irq_gc_mask_set_bit; +	ct->chip.irq_unmask = irq_gc_mask_clr_bit; -		irq_set_chip_data(se7722_fpga_irq[i], (void *)i); -	} +	ct->regs.mask = IRQ01_MASK_REG; + +	irq_setup_generic_chip(gc, IRQ_MSK(SE7722_FPGA_IRQ_NR), +			       IRQ_GC_INIT_MASK_CACHE, +			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);  	irq_set_chained_handler(IRQ0_IRQ, se7722_irq_demux);  	irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW); @@ -81,3 +98,25 @@ void __init init_se7722_IRQ(void)  	irq_set_chained_handler(IRQ1_IRQ, se7722_irq_demux);  	irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);  } + +/* + * Initialize FPGA IRQs + */ +void __init init_se7722_IRQ(void) +{ +	se7722_irq_regs = ioremap(IRQ01_BASE_ADDR, SZ_16); +	if (unlikely(!se7722_irq_regs)) { +		printk("Failed to remap IRQ01 regs\n"); +		return; +	} + +	/* +	 * All FPGA IRQs disabled by default +	 */ +	iowrite16(0, se7722_irq_regs + IRQ01_MASK_REG); + +	__raw_writew(0x2000, 0xb03fffec);  /* mrshpc irq enable */ + +	se7722_domain_init(); +	se7722_gc_init(); +} diff --git a/arch/sh/boards/mach-se/7722/setup.c b/arch/sh/boards/mach-se/7722/setup.c index 8f7f0550cfd..e04e2bc4698 100644 --- a/arch/sh/boards/mach-se/7722/setup.c +++ b/arch/sh/boards/mach-se/7722/setup.c @@ -2,6 +2,7 @@   * linux/arch/sh/boards/se/7722/setup.c   *   * Copyright (C) 2007 Nobuhiro Iwamatsu + * Copyright (C) 2012 Paul Mundt   *   * Hitachi UL SolutionEngine 7722 Support.   * @@ -15,6 +16,7 @@  #include <linux/ata_platform.h>  #include <linux/input.h>  #include <linux/input/sh_keysc.h> +#include <linux/irqdomain.h>  #include <linux/smc91x.h>  #include <linux/sh_intc.h>  #include <mach-se/mach/se7722.h> @@ -143,10 +145,10 @@ static int __init se7722_devices_setup(void)  	/* Wire-up dynamic vectors */  	cf_ide_resources[2].start = cf_ide_resources[2].end = -		se7722_fpga_irq[SE7722_FPGA_IRQ_MRSHPC0]; +		irq_find_mapping(se7722_irq_domain, SE7722_FPGA_IRQ_MRSHPC0);  	smc91x_eth_resources[1].start = smc91x_eth_resources[1].end = -		se7722_fpga_irq[SE7722_FPGA_IRQ_SMC]; +		irq_find_mapping(se7722_irq_domain, SE7722_FPGA_IRQ_SMC);  	return platform_add_devices(se7722_devices, ARRAY_SIZE(se7722_devices));  } diff --git a/arch/sh/boards/mach-se/7724/irq.c b/arch/sh/boards/mach-se/7724/irq.c index c6342ce7768..5d1d3ec9a6c 100644 --- a/arch/sh/boards/mach-se/7724/irq.c +++ b/arch/sh/boards/mach-se/7724/irq.c @@ -17,8 +17,10 @@  #include <linux/init.h>  #include <linux/irq.h>  #include <linux/interrupt.h> -#include <asm/irq.h> -#include <asm/io.h> +#include <linux/export.h> +#include <linux/topology.h> +#include <linux/io.h> +#include <linux/err.h>  #include <mach-se/mach/se7724.h>  struct fpga_irq { @@ -111,7 +113,7 @@ static void se7724_irq_demux(unsigned int irq, struct irq_desc *desc)   */  void __init init_se7724_IRQ(void)  { -	int i, nid = cpu_to_node(boot_cpu_data); +	int irq_base, i;  	__raw_writew(0xffff, IRQ0_MR);  /* mask all */  	__raw_writew(0xffff, IRQ1_MR);  /* mask all */ @@ -121,28 +123,16 @@ void __init init_se7724_IRQ(void)  	__raw_writew(0x0000, IRQ2_SR);  /* clear irq */  	__raw_writew(0x002a, IRQ_MODE); /* set irq type */ -	for (i = 0; i < SE7724_FPGA_IRQ_NR; i++) { -		int irq, wanted; - -		wanted = SE7724_FPGA_IRQ_BASE + i; - -		irq = create_irq_nr(wanted, nid); -		if (unlikely(irq == 0)) { -			pr_err("%s: failed hooking irq %d for FPGA\n", -			       __func__, wanted); -			return; -		} - -		if (unlikely(irq != wanted)) { -			pr_err("%s: got irq %d but wanted %d, bailing.\n", -			       __func__, irq, wanted); -			destroy_irq(irq); -			return; -		} +	irq_base = irq_alloc_descs(SE7724_FPGA_IRQ_BASE, SE7724_FPGA_IRQ_BASE, +				   SE7724_FPGA_IRQ_NR, numa_node_id()); +	if (IS_ERR_VALUE(irq_base)) { +		pr_err("%s: failed hooking irqs for FPGA\n", __func__); +		return; +	} -		irq_set_chip_and_handler_name(irq, &se7724_irq_chip, +	for (i = 0; i < SE7724_FPGA_IRQ_NR; i++) +		irq_set_chip_and_handler_name(irq_base + i, &se7724_irq_chip,  					      handle_level_irq, "level"); -	}  	irq_set_chained_handler(IRQ0_IRQ, se7724_irq_demux);  	irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW); diff --git a/arch/sh/boards/mach-x3proto/gpio.c b/arch/sh/boards/mach-x3proto/gpio.c index f33b2b57019..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; -		irq_set_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", @@ -119,10 +128,6 @@ int __init x3proto_gpio_setup(void)  	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");  |