diff options
Diffstat (limited to 'arch/sh/boards')
-rw-r--r-- | arch/sh/boards/Kconfig | 5 | ||||
-rw-r--r-- | arch/sh/boards/board-polaris.c | 2 | ||||
-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-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, 244 insertions, 168 deletions
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index 1f56b35d3248..7048c03490d9 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig | |||
@@ -44,6 +44,8 @@ config SH_7721_SOLUTION_ENGINE | |||
44 | config SH_7722_SOLUTION_ENGINE | 44 | config SH_7722_SOLUTION_ENGINE |
45 | bool "SolutionEngine7722" | 45 | bool "SolutionEngine7722" |
46 | select SOLUTION_ENGINE | 46 | select SOLUTION_ENGINE |
47 | select GENERIC_IRQ_CHIP | ||
48 | select IRQ_DOMAIN | ||
47 | depends on CPU_SUBTYPE_SH7722 | 49 | depends on CPU_SUBTYPE_SH7722 |
48 | help | 50 | help |
49 | Select 7722 SolutionEngine if configuring for a Hitachi SH772 | 51 | Select 7722 SolutionEngine if configuring for a Hitachi SH772 |
@@ -80,6 +82,8 @@ config SH_7780_SOLUTION_ENGINE | |||
80 | config SH_7343_SOLUTION_ENGINE | 82 | config SH_7343_SOLUTION_ENGINE |
81 | bool "SolutionEngine7343" | 83 | bool "SolutionEngine7343" |
82 | select SOLUTION_ENGINE | 84 | select SOLUTION_ENGINE |
85 | select GENERIC_IRQ_CHIP | ||
86 | select IRQ_DOMAIN | ||
83 | depends on CPU_SUBTYPE_SH7343 | 87 | depends on CPU_SUBTYPE_SH7343 |
84 | help | 88 | help |
85 | Select 7343 SolutionEngine if configuring for a Hitachi | 89 | Select 7343 SolutionEngine if configuring for a Hitachi |
@@ -295,6 +299,7 @@ config SH_X3PROTO | |||
295 | bool "SH-X3 Prototype board" | 299 | bool "SH-X3 Prototype board" |
296 | depends on CPU_SUBTYPE_SHX3 | 300 | depends on CPU_SUBTYPE_SHX3 |
297 | select NO_IOPORT if !PCI | 301 | select NO_IOPORT if !PCI |
302 | select IRQ_DOMAIN | ||
298 | 303 | ||
299 | config SH_MAGIC_PANEL_R2 | 304 | config SH_MAGIC_PANEL_R2 |
300 | bool "Magic Panel R2" | 305 | bool "Magic Panel R2" |
diff --git a/arch/sh/boards/board-polaris.c b/arch/sh/boards/board-polaris.c index 37d03c097ae9..0978ae2e4847 100644 --- a/arch/sh/boards/board-polaris.c +++ b/arch/sh/boards/board-polaris.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * June 2006 steve.glendinning@smsc.com | 2 | * June 2006 Steve Glendinning <steve.glendinning@shawell.net> |
3 | * | 3 | * |
4 | * Polaris-specific resource declaration | 4 | * Polaris-specific resource declaration |
5 | * | 5 | * |
diff --git a/arch/sh/boards/mach-dreamcast/irq.c b/arch/sh/boards/mach-dreamcast/irq.c index f63d323f411f..2789647abebe 100644 --- a/arch/sh/boards/mach-dreamcast/irq.c +++ b/arch/sh/boards/mach-dreamcast/irq.c | |||
@@ -8,10 +8,11 @@ | |||
8 | * This file is part of the LinuxDC project (www.linuxdc.org) | 8 | * This file is part of the LinuxDC project (www.linuxdc.org) |
9 | * Released under the terms of the GNU GPL v2.0 | 9 | * Released under the terms of the GNU GPL v2.0 |
10 | */ | 10 | */ |
11 | |||
12 | #include <linux/irq.h> | 11 | #include <linux/irq.h> |
13 | #include <linux/io.h> | 12 | #include <linux/io.h> |
14 | #include <asm/irq.h> | 13 | #include <linux/irq.h> |
14 | #include <linux/export.h> | ||
15 | #include <linux/err.h> | ||
15 | #include <mach/sysasic.h> | 16 | #include <mach/sysasic.h> |
16 | 17 | ||
17 | /* | 18 | /* |
@@ -141,26 +142,15 @@ int systemasic_irq_demux(int irq) | |||
141 | 142 | ||
142 | void systemasic_irq_init(void) | 143 | void systemasic_irq_init(void) |
143 | { | 144 | { |
144 | int i, nid = cpu_to_node(boot_cpu_data); | 145 | int irq_base, i; |
145 | |||
146 | /* Assign all virtual IRQs to the System ASIC int. handler */ | ||
147 | for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++) { | ||
148 | unsigned int irq; | ||
149 | |||
150 | irq = create_irq_nr(i, nid); | ||
151 | if (unlikely(irq == 0)) { | ||
152 | pr_err("%s: failed hooking irq %d for systemasic\n", | ||
153 | __func__, i); | ||
154 | return; | ||
155 | } | ||
156 | 146 | ||
157 | if (unlikely(irq != i)) { | 147 | irq_base = irq_alloc_descs(HW_EVENT_IRQ_BASE, HW_EVENT_IRQ_BASE, |
158 | pr_err("%s: got irq %d but wanted %d, bailing.\n", | 148 | HW_EVENT_IRQ_MAX - HW_EVENT_IRQ_BASE, -1); |
159 | __func__, irq, i); | 149 | if (IS_ERR_VALUE(irq_base)) { |
160 | destroy_irq(irq); | 150 | pr_err("%s: failed hooking irqs\n", __func__); |
161 | return; | 151 | return; |
162 | } | 152 | } |
163 | 153 | ||
154 | for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++) | ||
164 | irq_set_chip_and_handler(i, &systemasic_int, handle_level_irq); | 155 | irq_set_chip_and_handler(i, &systemasic_int, handle_level_irq); |
165 | } | ||
166 | } | 156 | } |
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c index 158c9176e42a..43a179ce9afc 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[] = { | |||
201 | .flags = IORESOURCE_MEM, | 201 | .flags = IORESOURCE_MEM, |
202 | }, | 202 | }, |
203 | [1] = { | 203 | [1] = { |
204 | .start = evtirq(0xa20), | 204 | .start = evt2irq(0xa20), |
205 | .end = evtirq(0xa20), | 205 | .end = evt2irq(0xa20), |
206 | .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW, | 206 | .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW, |
207 | }, | 207 | }, |
208 | }; | 208 | }; |
diff --git a/arch/sh/boards/mach-se/7343/irq.c b/arch/sh/boards/mach-se/7343/irq.c index fd45ffc48340..7646bf0486c2 100644 --- a/arch/sh/boards/mach-se/7343/irq.c +++ b/arch/sh/boards/mach-se/7343/irq.c | |||
@@ -1,86 +1,129 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/sh/boards/se/7343/irq.c | 2 | * Hitachi UL SolutionEngine 7343 FPGA IRQ Support. |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Yoshihiro Shimoda | 4 | * Copyright (C) 2008 Yoshihiro Shimoda |
5 | * Copyright (C) 2012 Paul Mundt | ||
5 | * | 6 | * |
6 | * Based on linux/arch/sh/boards/se/7722/irq.c | 7 | * Based on linux/arch/sh/boards/se/7343/irq.c |
7 | * Copyright (C) 2007 Nobuhiro Iwamatsu | 8 | * Copyright (C) 2007 Nobuhiro Iwamatsu |
8 | * | 9 | * |
9 | * This file is subject to the terms and conditions of the GNU General Public | 10 | * This file is subject to the terms and conditions of the GNU General Public |
10 | * License. See the file "COPYING" in the main directory of this archive | 11 | * License. See the file "COPYING" in the main directory of this archive |
11 | * for more details. | 12 | * for more details. |
12 | */ | 13 | */ |
14 | #define DRV_NAME "SE7343-FPGA" | ||
15 | #define pr_fmt(fmt) DRV_NAME ": " fmt | ||
16 | |||
17 | #define irq_reg_readl ioread16 | ||
18 | #define irq_reg_writel iowrite16 | ||
19 | |||
13 | #include <linux/init.h> | 20 | #include <linux/init.h> |
14 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
15 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/irqdomain.h> | ||
16 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | #include <asm/sizes.h> | ||
17 | #include <mach-se/mach/se7343.h> | 26 | #include <mach-se/mach/se7343.h> |
18 | 27 | ||
19 | unsigned int se7343_fpga_irq[SE7343_FPGA_IRQ_NR] = { 0, }; | 28 | #define PA_CPLD_BASE_ADDR 0x11400000 |
29 | #define PA_CPLD_ST_REG 0x08 /* CPLD Interrupt status register */ | ||
30 | #define PA_CPLD_IMSK_REG 0x0a /* CPLD Interrupt mask register */ | ||
20 | 31 | ||
21 | static void disable_se7343_irq(struct irq_data *data) | 32 | static void __iomem *se7343_irq_regs; |
22 | { | 33 | struct irq_domain *se7343_irq_domain; |
23 | unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data); | ||
24 | __raw_writew(__raw_readw(PA_CPLD_IMSK) | 1 << bit, PA_CPLD_IMSK); | ||
25 | } | ||
26 | 34 | ||
27 | static void enable_se7343_irq(struct irq_data *data) | 35 | static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc) |
28 | { | 36 | { |
29 | unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data); | 37 | struct irq_data *data = irq_get_irq_data(irq); |
30 | __raw_writew(__raw_readw(PA_CPLD_IMSK) & ~(1 << bit), PA_CPLD_IMSK); | 38 | struct irq_chip *chip = irq_data_get_irq_chip(data); |
31 | } | 39 | unsigned long mask; |
40 | int bit; | ||
32 | 41 | ||
33 | static struct irq_chip se7343_irq_chip __read_mostly = { | 42 | chip->irq_mask_ack(data); |
34 | .name = "SE7343-FPGA", | ||
35 | .irq_mask = disable_se7343_irq, | ||
36 | .irq_unmask = enable_se7343_irq, | ||
37 | }; | ||
38 | 43 | ||
39 | static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc) | 44 | mask = ioread16(se7343_irq_regs + PA_CPLD_ST_REG); |
45 | |||
46 | for_each_set_bit(bit, &mask, SE7343_FPGA_IRQ_NR) | ||
47 | generic_handle_irq(irq_linear_revmap(se7343_irq_domain, bit)); | ||
48 | |||
49 | chip->irq_unmask(data); | ||
50 | } | ||
51 | |||
52 | static void __init se7343_domain_init(void) | ||
40 | { | 53 | { |
41 | unsigned short intv = __raw_readw(PA_CPLD_ST); | 54 | int i; |
42 | unsigned int ext_irq = 0; | ||
43 | 55 | ||
44 | intv &= (1 << SE7343_FPGA_IRQ_NR) - 1; | 56 | se7343_irq_domain = irq_domain_add_linear(NULL, SE7343_FPGA_IRQ_NR, |
57 | &irq_domain_simple_ops, NULL); | ||
58 | if (unlikely(!se7343_irq_domain)) { | ||
59 | printk("Failed to get IRQ domain\n"); | ||
60 | return; | ||
61 | } | ||
45 | 62 | ||
46 | for (; intv; intv >>= 1, ext_irq++) { | 63 | for (i = 0; i < SE7343_FPGA_IRQ_NR; i++) { |
47 | if (!(intv & 1)) | 64 | int irq = irq_create_mapping(se7343_irq_domain, i); |
48 | continue; | ||
49 | 65 | ||
50 | generic_handle_irq(se7343_fpga_irq[ext_irq]); | 66 | if (unlikely(irq == 0)) { |
67 | printk("Failed to allocate IRQ %d\n", i); | ||
68 | return; | ||
69 | } | ||
51 | } | 70 | } |
52 | } | 71 | } |
53 | 72 | ||
54 | /* | 73 | static void __init se7343_gc_init(void) |
55 | * Initialize IRQ setting | ||
56 | */ | ||
57 | void __init init_7343se_IRQ(void) | ||
58 | { | 74 | { |
59 | int i, irq; | 75 | struct irq_chip_generic *gc; |
76 | struct irq_chip_type *ct; | ||
77 | unsigned int irq_base; | ||
60 | 78 | ||
61 | __raw_writew(0, PA_CPLD_IMSK); /* disable all irqs */ | 79 | irq_base = irq_linear_revmap(se7343_irq_domain, 0); |
62 | __raw_writew(0x2000, 0xb03fffec); /* mrshpc irq enable */ | ||
63 | 80 | ||
64 | for (i = 0; i < SE7343_FPGA_IRQ_NR; i++) { | 81 | gc = irq_alloc_generic_chip(DRV_NAME, 1, irq_base, se7343_irq_regs, |
65 | irq = create_irq(); | 82 | handle_level_irq); |
66 | if (irq < 0) | 83 | if (unlikely(!gc)) |
67 | return; | 84 | return; |
68 | se7343_fpga_irq[i] = irq; | ||
69 | 85 | ||
70 | irq_set_chip_and_handler_name(se7343_fpga_irq[i], | 86 | ct = gc->chip_types; |
71 | &se7343_irq_chip, | 87 | ct->chip.irq_mask = irq_gc_mask_set_bit; |
72 | handle_level_irq, | 88 | ct->chip.irq_unmask = irq_gc_mask_clr_bit; |
73 | "level"); | ||
74 | 89 | ||
75 | irq_set_chip_data(se7343_fpga_irq[i], (void *)i); | 90 | ct->regs.mask = PA_CPLD_IMSK_REG; |
76 | } | 91 | |
92 | irq_setup_generic_chip(gc, IRQ_MSK(SE7343_FPGA_IRQ_NR), | ||
93 | IRQ_GC_INIT_MASK_CACHE, | ||
94 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); | ||
77 | 95 | ||
78 | irq_set_chained_handler(IRQ0_IRQ, se7343_irq_demux); | 96 | irq_set_chained_handler(IRQ0_IRQ, se7343_irq_demux); |
79 | irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW); | 97 | irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW); |
98 | |||
80 | irq_set_chained_handler(IRQ1_IRQ, se7343_irq_demux); | 99 | irq_set_chained_handler(IRQ1_IRQ, se7343_irq_demux); |
81 | irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW); | 100 | irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW); |
101 | |||
82 | irq_set_chained_handler(IRQ4_IRQ, se7343_irq_demux); | 102 | irq_set_chained_handler(IRQ4_IRQ, se7343_irq_demux); |
83 | irq_set_irq_type(IRQ4_IRQ, IRQ_TYPE_LEVEL_LOW); | 103 | irq_set_irq_type(IRQ4_IRQ, IRQ_TYPE_LEVEL_LOW); |
104 | |||
84 | irq_set_chained_handler(IRQ5_IRQ, se7343_irq_demux); | 105 | irq_set_chained_handler(IRQ5_IRQ, se7343_irq_demux); |
85 | irq_set_irq_type(IRQ5_IRQ, IRQ_TYPE_LEVEL_LOW); | 106 | irq_set_irq_type(IRQ5_IRQ, IRQ_TYPE_LEVEL_LOW); |
86 | } | 107 | } |
108 | |||
109 | /* | ||
110 | * Initialize IRQ setting | ||
111 | */ | ||
112 | void __init init_7343se_IRQ(void) | ||
113 | { | ||
114 | se7343_irq_regs = ioremap(PA_CPLD_BASE_ADDR, SZ_16); | ||
115 | if (unlikely(!se7343_irq_regs)) { | ||
116 | pr_err("Failed to remap CPLD\n"); | ||
117 | return; | ||
118 | } | ||
119 | |||
120 | /* | ||
121 | * All FPGA IRQs disabled by default | ||
122 | */ | ||
123 | iowrite16(0, se7343_irq_regs + PA_CPLD_IMSK_REG); | ||
124 | |||
125 | __raw_writew(0x2000, 0xb03fffec); /* mrshpc irq enable */ | ||
126 | |||
127 | se7343_domain_init(); | ||
128 | se7343_gc_init(); | ||
129 | } | ||
diff --git a/arch/sh/boards/mach-se/7343/setup.c b/arch/sh/boards/mach-se/7343/setup.c index d2370af56d77..8ce4f2a202a8 100644 --- a/arch/sh/boards/mach-se/7343/setup.c +++ b/arch/sh/boards/mach-se/7343/setup.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/serial_reg.h> | 5 | #include <linux/serial_reg.h> |
6 | #include <linux/usb/isp116x.h> | 6 | #include <linux/usb/isp116x.h> |
7 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
8 | #include <linux/irqdomain.h> | ||
8 | #include <asm/machvec.h> | 9 | #include <asm/machvec.h> |
9 | #include <mach-se/mach/se7343.h> | 10 | #include <mach-se/mach/se7343.h> |
10 | #include <asm/heartbeat.h> | 11 | #include <asm/heartbeat.h> |
@@ -145,11 +146,12 @@ static struct platform_device *sh7343se_platform_devices[] __initdata = { | |||
145 | static int __init sh7343se_devices_setup(void) | 146 | static int __init sh7343se_devices_setup(void) |
146 | { | 147 | { |
147 | /* Wire-up dynamic vectors */ | 148 | /* Wire-up dynamic vectors */ |
148 | serial_platform_data[0].irq = se7343_fpga_irq[SE7343_FPGA_IRQ_UARTA]; | 149 | serial_platform_data[0].irq = irq_find_mapping(se7343_irq_domain, |
149 | serial_platform_data[1].irq = se7343_fpga_irq[SE7343_FPGA_IRQ_UARTB]; | 150 | SE7343_FPGA_IRQ_UARTA); |
150 | 151 | serial_platform_data[1].irq = irq_find_mapping(se7343_irq_domain, | |
152 | SE7343_FPGA_IRQ_UARTB); | ||
151 | usb_resources[2].start = usb_resources[2].end = | 153 | usb_resources[2].start = usb_resources[2].end = |
152 | se7343_fpga_irq[SE7343_FPGA_IRQ_USB]; | 154 | irq_find_mapping(se7343_irq_domain, SE7343_FPGA_IRQ_USB); |
153 | 155 | ||
154 | return platform_add_devices(sh7343se_platform_devices, | 156 | return platform_add_devices(sh7343se_platform_devices, |
155 | ARRAY_SIZE(sh7343se_platform_devices)); | 157 | 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 aac92f21ebd2..f5e2af1bf040 100644 --- a/arch/sh/boards/mach-se/7722/irq.c +++ b/arch/sh/boards/mach-se/7722/irq.c | |||
@@ -1,79 +1,96 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/sh/boards/se/7722/irq.c | 2 | * Hitachi UL SolutionEngine 7722 FPGA IRQ Support. |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Nobuhiro Iwamatsu | 4 | * Copyright (C) 2007 Nobuhiro Iwamatsu |
5 | * | 5 | * Copyright (C) 2012 Paul Mundt |
6 | * Hitachi UL SolutionEngine 7722 Support. | ||
7 | * | 6 | * |
8 | * This file is subject to the terms and conditions of the GNU General Public | 7 | * This file is subject to the terms and conditions of the GNU General Public |
9 | * License. See the file "COPYING" in the main directory of this archive | 8 | * License. See the file "COPYING" in the main directory of this archive |
10 | * for more details. | 9 | * for more details. |
11 | */ | 10 | */ |
11 | #define DRV_NAME "SE7722-FPGA" | ||
12 | #define pr_fmt(fmt) DRV_NAME ": " fmt | ||
13 | |||
14 | #define irq_reg_readl ioread16 | ||
15 | #define irq_reg_writel iowrite16 | ||
16 | |||
12 | #include <linux/init.h> | 17 | #include <linux/init.h> |
13 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
14 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
15 | #include <asm/irq.h> | 20 | #include <linux/irqdomain.h> |
16 | #include <asm/io.h> | 21 | #include <linux/io.h> |
22 | #include <linux/err.h> | ||
23 | #include <asm/sizes.h> | ||
17 | #include <mach-se/mach/se7722.h> | 24 | #include <mach-se/mach/se7722.h> |
18 | 25 | ||
19 | unsigned int se7722_fpga_irq[SE7722_FPGA_IRQ_NR] = { 0, }; | 26 | #define IRQ01_BASE_ADDR 0x11800000 |
27 | #define IRQ01_MODE_REG 0 | ||
28 | #define IRQ01_STS_REG 4 | ||
29 | #define IRQ01_MASK_REG 8 | ||
20 | 30 | ||
21 | static void disable_se7722_irq(struct irq_data *data) | 31 | static void __iomem *se7722_irq_regs; |
22 | { | 32 | struct irq_domain *se7722_irq_domain; |
23 | unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data); | ||
24 | __raw_writew(__raw_readw(IRQ01_MASK) | 1 << bit, IRQ01_MASK); | ||
25 | } | ||
26 | 33 | ||
27 | static void enable_se7722_irq(struct irq_data *data) | 34 | static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc) |
28 | { | 35 | { |
29 | unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data); | 36 | struct irq_data *data = irq_get_irq_data(irq); |
30 | __raw_writew(__raw_readw(IRQ01_MASK) & ~(1 << bit), IRQ01_MASK); | 37 | struct irq_chip *chip = irq_data_get_irq_chip(data); |
31 | } | 38 | unsigned long mask; |
39 | int bit; | ||
32 | 40 | ||
33 | static struct irq_chip se7722_irq_chip __read_mostly = { | 41 | chip->irq_mask_ack(data); |
34 | .name = "SE7722-FPGA", | ||
35 | .irq_mask = disable_se7722_irq, | ||
36 | .irq_unmask = enable_se7722_irq, | ||
37 | }; | ||
38 | 42 | ||
39 | static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc) | 43 | mask = ioread16(se7722_irq_regs + IRQ01_STS_REG); |
44 | |||
45 | for_each_set_bit(bit, &mask, SE7722_FPGA_IRQ_NR) | ||
46 | generic_handle_irq(irq_linear_revmap(se7722_irq_domain, bit)); | ||
47 | |||
48 | chip->irq_unmask(data); | ||
49 | } | ||
50 | |||
51 | static void __init se7722_domain_init(void) | ||
40 | { | 52 | { |
41 | unsigned short intv = __raw_readw(IRQ01_STS); | 53 | int i; |
42 | unsigned int ext_irq = 0; | ||
43 | 54 | ||
44 | intv &= (1 << SE7722_FPGA_IRQ_NR) - 1; | 55 | se7722_irq_domain = irq_domain_add_linear(NULL, SE7722_FPGA_IRQ_NR, |
56 | &irq_domain_simple_ops, NULL); | ||
57 | if (unlikely(!se7722_irq_domain)) { | ||
58 | printk("Failed to get IRQ domain\n"); | ||
59 | return; | ||
60 | } | ||
45 | 61 | ||
46 | for (; intv; intv >>= 1, ext_irq++) { | 62 | for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) { |
47 | if (!(intv & 1)) | 63 | int irq = irq_create_mapping(se7722_irq_domain, i); |
48 | continue; | ||
49 | 64 | ||
50 | generic_handle_irq(se7722_fpga_irq[ext_irq]); | 65 | if (unlikely(irq == 0)) { |
66 | printk("Failed to allocate IRQ %d\n", i); | ||
67 | return; | ||
68 | } | ||
51 | } | 69 | } |
52 | } | 70 | } |
53 | 71 | ||
54 | /* | 72 | static void __init se7722_gc_init(void) |
55 | * Initialize IRQ setting | ||
56 | */ | ||
57 | void __init init_se7722_IRQ(void) | ||
58 | { | 73 | { |
59 | int i, irq; | 74 | struct irq_chip_generic *gc; |
75 | struct irq_chip_type *ct; | ||
76 | unsigned int irq_base; | ||
60 | 77 | ||
61 | __raw_writew(0, IRQ01_MASK); /* disable all irqs */ | 78 | irq_base = irq_linear_revmap(se7722_irq_domain, 0); |
62 | __raw_writew(0x2000, 0xb03fffec); /* mrshpc irq enable */ | ||
63 | 79 | ||
64 | for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) { | 80 | gc = irq_alloc_generic_chip(DRV_NAME, 1, irq_base, se7722_irq_regs, |
65 | irq = create_irq(); | 81 | handle_level_irq); |
66 | if (irq < 0) | 82 | if (unlikely(!gc)) |
67 | return; | 83 | return; |
68 | se7722_fpga_irq[i] = irq; | ||
69 | 84 | ||
70 | irq_set_chip_and_handler_name(se7722_fpga_irq[i], | 85 | ct = gc->chip_types; |
71 | &se7722_irq_chip, | 86 | ct->chip.irq_mask = irq_gc_mask_set_bit; |
72 | handle_level_irq, | 87 | ct->chip.irq_unmask = irq_gc_mask_clr_bit; |
73 | "level"); | ||
74 | 88 | ||
75 | irq_set_chip_data(se7722_fpga_irq[i], (void *)i); | 89 | ct->regs.mask = IRQ01_MASK_REG; |
76 | } | 90 | |
91 | irq_setup_generic_chip(gc, IRQ_MSK(SE7722_FPGA_IRQ_NR), | ||
92 | IRQ_GC_INIT_MASK_CACHE, | ||
93 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); | ||
77 | 94 | ||
78 | irq_set_chained_handler(IRQ0_IRQ, se7722_irq_demux); | 95 | irq_set_chained_handler(IRQ0_IRQ, se7722_irq_demux); |
79 | irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW); | 96 | irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW); |
@@ -81,3 +98,25 @@ void __init init_se7722_IRQ(void) | |||
81 | irq_set_chained_handler(IRQ1_IRQ, se7722_irq_demux); | 98 | irq_set_chained_handler(IRQ1_IRQ, se7722_irq_demux); |
82 | irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW); | 99 | irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW); |
83 | } | 100 | } |
101 | |||
102 | /* | ||
103 | * Initialize FPGA IRQs | ||
104 | */ | ||
105 | void __init init_se7722_IRQ(void) | ||
106 | { | ||
107 | se7722_irq_regs = ioremap(IRQ01_BASE_ADDR, SZ_16); | ||
108 | if (unlikely(!se7722_irq_regs)) { | ||
109 | printk("Failed to remap IRQ01 regs\n"); | ||
110 | return; | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * All FPGA IRQs disabled by default | ||
115 | */ | ||
116 | iowrite16(0, se7722_irq_regs + IRQ01_MASK_REG); | ||
117 | |||
118 | __raw_writew(0x2000, 0xb03fffec); /* mrshpc irq enable */ | ||
119 | |||
120 | se7722_domain_init(); | ||
121 | se7722_gc_init(); | ||
122 | } | ||
diff --git a/arch/sh/boards/mach-se/7722/setup.c b/arch/sh/boards/mach-se/7722/setup.c index 8f7f0550cfde..e04e2bc46984 100644 --- a/arch/sh/boards/mach-se/7722/setup.c +++ b/arch/sh/boards/mach-se/7722/setup.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * linux/arch/sh/boards/se/7722/setup.c | 2 | * linux/arch/sh/boards/se/7722/setup.c |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Nobuhiro Iwamatsu | 4 | * Copyright (C) 2007 Nobuhiro Iwamatsu |
5 | * Copyright (C) 2012 Paul Mundt | ||
5 | * | 6 | * |
6 | * Hitachi UL SolutionEngine 7722 Support. | 7 | * Hitachi UL SolutionEngine 7722 Support. |
7 | * | 8 | * |
@@ -15,6 +16,7 @@ | |||
15 | #include <linux/ata_platform.h> | 16 | #include <linux/ata_platform.h> |
16 | #include <linux/input.h> | 17 | #include <linux/input.h> |
17 | #include <linux/input/sh_keysc.h> | 18 | #include <linux/input/sh_keysc.h> |
19 | #include <linux/irqdomain.h> | ||
18 | #include <linux/smc91x.h> | 20 | #include <linux/smc91x.h> |
19 | #include <linux/sh_intc.h> | 21 | #include <linux/sh_intc.h> |
20 | #include <mach-se/mach/se7722.h> | 22 | #include <mach-se/mach/se7722.h> |
@@ -143,10 +145,10 @@ static int __init se7722_devices_setup(void) | |||
143 | 145 | ||
144 | /* Wire-up dynamic vectors */ | 146 | /* Wire-up dynamic vectors */ |
145 | cf_ide_resources[2].start = cf_ide_resources[2].end = | 147 | cf_ide_resources[2].start = cf_ide_resources[2].end = |
146 | se7722_fpga_irq[SE7722_FPGA_IRQ_MRSHPC0]; | 148 | irq_find_mapping(se7722_irq_domain, SE7722_FPGA_IRQ_MRSHPC0); |
147 | 149 | ||
148 | smc91x_eth_resources[1].start = smc91x_eth_resources[1].end = | 150 | smc91x_eth_resources[1].start = smc91x_eth_resources[1].end = |
149 | se7722_fpga_irq[SE7722_FPGA_IRQ_SMC]; | 151 | irq_find_mapping(se7722_irq_domain, SE7722_FPGA_IRQ_SMC); |
150 | 152 | ||
151 | return platform_add_devices(se7722_devices, ARRAY_SIZE(se7722_devices)); | 153 | return platform_add_devices(se7722_devices, ARRAY_SIZE(se7722_devices)); |
152 | } | 154 | } |
diff --git a/arch/sh/boards/mach-se/7724/irq.c b/arch/sh/boards/mach-se/7724/irq.c index c6342ce7768d..5d1d3ec9a6cd 100644 --- a/arch/sh/boards/mach-se/7724/irq.c +++ b/arch/sh/boards/mach-se/7724/irq.c | |||
@@ -17,8 +17,10 @@ | |||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <asm/irq.h> | 20 | #include <linux/export.h> |
21 | #include <asm/io.h> | 21 | #include <linux/topology.h> |
22 | #include <linux/io.h> | ||
23 | #include <linux/err.h> | ||
22 | #include <mach-se/mach/se7724.h> | 24 | #include <mach-se/mach/se7724.h> |
23 | 25 | ||
24 | struct fpga_irq { | 26 | struct fpga_irq { |
@@ -111,7 +113,7 @@ static void se7724_irq_demux(unsigned int irq, struct irq_desc *desc) | |||
111 | */ | 113 | */ |
112 | void __init init_se7724_IRQ(void) | 114 | void __init init_se7724_IRQ(void) |
113 | { | 115 | { |
114 | int i, nid = cpu_to_node(boot_cpu_data); | 116 | int irq_base, i; |
115 | 117 | ||
116 | __raw_writew(0xffff, IRQ0_MR); /* mask all */ | 118 | __raw_writew(0xffff, IRQ0_MR); /* mask all */ |
117 | __raw_writew(0xffff, IRQ1_MR); /* mask all */ | 119 | __raw_writew(0xffff, IRQ1_MR); /* mask all */ |
@@ -121,28 +123,16 @@ void __init init_se7724_IRQ(void) | |||
121 | __raw_writew(0x0000, IRQ2_SR); /* clear irq */ | 123 | __raw_writew(0x0000, IRQ2_SR); /* clear irq */ |
122 | __raw_writew(0x002a, IRQ_MODE); /* set irq type */ | 124 | __raw_writew(0x002a, IRQ_MODE); /* set irq type */ |
123 | 125 | ||
124 | for (i = 0; i < SE7724_FPGA_IRQ_NR; i++) { | 126 | irq_base = irq_alloc_descs(SE7724_FPGA_IRQ_BASE, SE7724_FPGA_IRQ_BASE, |
125 | int irq, wanted; | 127 | SE7724_FPGA_IRQ_NR, numa_node_id()); |
126 | 128 | if (IS_ERR_VALUE(irq_base)) { | |
127 | wanted = SE7724_FPGA_IRQ_BASE + i; | 129 | pr_err("%s: failed hooking irqs for FPGA\n", __func__); |
128 | 130 | return; | |
129 | irq = create_irq_nr(wanted, nid); | 131 | } |
130 | if (unlikely(irq == 0)) { | ||
131 | pr_err("%s: failed hooking irq %d for FPGA\n", | ||
132 | __func__, wanted); | ||
133 | return; | ||
134 | } | ||
135 | |||
136 | if (unlikely(irq != wanted)) { | ||
137 | pr_err("%s: got irq %d but wanted %d, bailing.\n", | ||
138 | __func__, irq, wanted); | ||
139 | destroy_irq(irq); | ||
140 | return; | ||
141 | } | ||
142 | 132 | ||
143 | irq_set_chip_and_handler_name(irq, &se7724_irq_chip, | 133 | for (i = 0; i < SE7724_FPGA_IRQ_NR; i++) |
134 | irq_set_chip_and_handler_name(irq_base + i, &se7724_irq_chip, | ||
144 | handle_level_irq, "level"); | 135 | handle_level_irq, "level"); |
145 | } | ||
146 | 136 | ||
147 | irq_set_chained_handler(IRQ0_IRQ, se7724_irq_demux); | 137 | irq_set_chained_handler(IRQ0_IRQ, se7724_irq_demux); |
148 | irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW); | 138 | 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 f33b2b57019c..3ea65e9b56e8 100644 --- a/arch/sh/boards/mach-x3proto/gpio.c +++ b/arch/sh/boards/mach-x3proto/gpio.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Renesas SH-X3 Prototype Baseboard GPIO Support. | 4 | * Renesas SH-X3 Prototype Baseboard GPIO Support. |
5 | * | 5 | * |
6 | * Copyright (C) 2010 Paul Mundt | 6 | * Copyright (C) 2010 - 2012 Paul Mundt |
7 | * | 7 | * |
8 | * This file is subject to the terms and conditions of the GNU General Public | 8 | * This file is subject to the terms and conditions of the GNU General Public |
9 | * License. See the file "COPYING" in the main directory of this archive | 9 | * License. See the file "COPYING" in the main directory of this archive |
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/irq.h> | 17 | #include <linux/irq.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
20 | #include <linux/irqdomain.h> | ||
20 | #include <linux/io.h> | 21 | #include <linux/io.h> |
21 | #include <mach/ilsel.h> | 22 | #include <mach/ilsel.h> |
22 | #include <mach/hardware.h> | 23 | #include <mach/hardware.h> |
@@ -26,7 +27,7 @@ | |||
26 | #define KEYDETR 0xb81c0004 | 27 | #define KEYDETR 0xb81c0004 |
27 | 28 | ||
28 | static DEFINE_SPINLOCK(x3proto_gpio_lock); | 29 | static DEFINE_SPINLOCK(x3proto_gpio_lock); |
29 | static unsigned int x3proto_gpio_irq_map[NR_BASEBOARD_GPIOS] = { 0, }; | 30 | static struct irq_domain *x3proto_irq_domain; |
30 | 31 | ||
31 | static int x3proto_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) | 32 | static int x3proto_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) |
32 | { | 33 | { |
@@ -49,7 +50,14 @@ static int x3proto_gpio_get(struct gpio_chip *chip, unsigned gpio) | |||
49 | 50 | ||
50 | static int x3proto_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) | 51 | static int x3proto_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) |
51 | { | 52 | { |
52 | return x3proto_gpio_irq_map[gpio]; | 53 | int virq; |
54 | |||
55 | if (gpio < chip->ngpio) | ||
56 | virq = irq_create_mapping(x3proto_irq_domain, gpio); | ||
57 | else | ||
58 | virq = -ENXIO; | ||
59 | |||
60 | return virq; | ||
53 | } | 61 | } |
54 | 62 | ||
55 | static void x3proto_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | 63 | 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) | |||
62 | chip->irq_mask_ack(data); | 70 | chip->irq_mask_ack(data); |
63 | 71 | ||
64 | mask = __raw_readw(KEYDETR); | 72 | mask = __raw_readw(KEYDETR); |
65 | |||
66 | for_each_set_bit(pin, &mask, NR_BASEBOARD_GPIOS) | 73 | for_each_set_bit(pin, &mask, NR_BASEBOARD_GPIOS) |
67 | generic_handle_irq(x3proto_gpio_to_irq(NULL, pin)); | 74 | generic_handle_irq(irq_linear_revmap(x3proto_irq_domain, pin)); |
68 | 75 | ||
69 | chip->irq_unmask(data); | 76 | chip->irq_unmask(data); |
70 | } | 77 | } |
@@ -78,10 +85,23 @@ struct gpio_chip x3proto_gpio_chip = { | |||
78 | .ngpio = NR_BASEBOARD_GPIOS, | 85 | .ngpio = NR_BASEBOARD_GPIOS, |
79 | }; | 86 | }; |
80 | 87 | ||
88 | static int x3proto_gpio_irq_map(struct irq_domain *domain, unsigned int virq, | ||
89 | irq_hw_number_t hwirq) | ||
90 | { | ||
91 | irq_set_chip_and_handler_name(virq, &dummy_irq_chip, handle_simple_irq, | ||
92 | "gpio"); | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static struct irq_domain_ops x3proto_gpio_irq_ops = { | ||
98 | .map = x3proto_gpio_irq_map, | ||
99 | .xlate = irq_domain_xlate_twocell, | ||
100 | }; | ||
101 | |||
81 | int __init x3proto_gpio_setup(void) | 102 | int __init x3proto_gpio_setup(void) |
82 | { | 103 | { |
83 | int ilsel; | 104 | int ilsel, ret; |
84 | int ret, i; | ||
85 | 105 | ||
86 | ilsel = ilsel_enable(ILSEL_KEY); | 106 | ilsel = ilsel_enable(ILSEL_KEY); |
87 | if (unlikely(ilsel < 0)) | 107 | if (unlikely(ilsel < 0)) |
@@ -91,21 +111,10 @@ int __init x3proto_gpio_setup(void) | |||
91 | if (unlikely(ret)) | 111 | if (unlikely(ret)) |
92 | goto err_gpio; | 112 | goto err_gpio; |
93 | 113 | ||
94 | for (i = 0; i < NR_BASEBOARD_GPIOS; i++) { | 114 | x3proto_irq_domain = irq_domain_add_linear(NULL, NR_BASEBOARD_GPIOS, |
95 | unsigned long flags; | 115 | &x3proto_gpio_irq_ops, NULL); |
96 | int irq = create_irq(); | 116 | if (unlikely(!x3proto_irq_domain)) |
97 | 117 | goto err_irq; | |
98 | if (unlikely(irq < 0)) { | ||
99 | ret = -EINVAL; | ||
100 | goto err_irq; | ||
101 | } | ||
102 | |||
103 | spin_lock_irqsave(&x3proto_gpio_lock, flags); | ||
104 | x3proto_gpio_irq_map[i] = irq; | ||
105 | irq_set_chip_and_handler_name(irq, &dummy_irq_chip, | ||
106 | handle_simple_irq, "gpio"); | ||
107 | spin_unlock_irqrestore(&x3proto_gpio_lock, flags); | ||
108 | } | ||
109 | 118 | ||
110 | pr_info("registering '%s' support, handling GPIOs %u -> %u, " | 119 | pr_info("registering '%s' support, handling GPIOs %u -> %u, " |
111 | "bound to IRQ %u\n", | 120 | "bound to IRQ %u\n", |
@@ -119,10 +128,6 @@ int __init x3proto_gpio_setup(void) | |||
119 | return 0; | 128 | return 0; |
120 | 129 | ||
121 | err_irq: | 130 | err_irq: |
122 | for (; i >= 0; --i) | ||
123 | if (x3proto_gpio_irq_map[i]) | ||
124 | destroy_irq(x3proto_gpio_irq_map[i]); | ||
125 | |||
126 | ret = gpiochip_remove(&x3proto_gpio_chip); | 131 | ret = gpiochip_remove(&x3proto_gpio_chip); |
127 | if (unlikely(ret)) | 132 | if (unlikely(ret)) |
128 | pr_err("Failed deregistering GPIO\n"); | 133 | pr_err("Failed deregistering GPIO\n"); |