aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2012-05-24 05:24:32 -0400
committerPaul Mundt <lethal@linux-sh.org>2012-05-24 05:24:32 -0400
commit5df38b9b7676e4e46c5c13e75f023ffb82542980 (patch)
treec7a21ff99ec07365dcc3f55de6f09b6261cfdcde
parentb98b35815f40f01337e25e3f0d10d57b7cec5126 (diff)
sh: se722: Move FPGA IRQs to irqdomain and generic irq chip.
This implements a total rewrite of the rather buggy SE7722 FPGA IRQ code, utilizing a linear irq domain as well as the generic irq chip type. While the interaction between the two APIs is a bit clunky (ie, revmap lookup for gc irq_base), they work well enough together that it's easy enough to work with going forward. While we're at it, deal with irq_mask_ack/unmask of the chained IRQ in the demux handler to prevent smc91x screaming about spurious interrupts. There's also some more improvement that can be made to the irqdomain code to create backing irqdescs for the entire linear range in one bang instead of iterating over the number of hwirqs and doing it irq-at-a-time. This is easily dealt with at a later point, though. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--arch/sh/boards/Kconfig2
-rw-r--r--arch/sh/boards/mach-se/7722/irq.c131
-rw-r--r--arch/sh/boards/mach-se/7722/setup.c6
-rw-r--r--arch/sh/include/mach-se/mach/se7722.h10
4 files changed, 94 insertions, 55 deletions
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index f2024a91319f..525b9e32cd14 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -44,6 +44,8 @@ config SH_7721_SOLUTION_ENGINE
44config SH_7722_SOLUTION_ENGINE 44config 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
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
19unsigned 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
21static void disable_se7722_irq(struct irq_data *data) 31static void __iomem *se7722_irq_regs;
22{ 32struct 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
27static void enable_se7722_irq(struct irq_data *data) 34static 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
33static 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
39static 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
51static 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/* 72static void __init se7722_gc_init(void)
55 * Initialize IRQ setting
56 */
57void __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 */
105void __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 e1963fecd761..2ec0111fdf9b 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 <mach-se/mach/se7722.h> 21#include <mach-se/mach/se7722.h>
20#include <mach-se/mach/mrshpc.h> 22#include <mach-se/mach/mrshpc.h>
@@ -142,10 +144,10 @@ static int __init se7722_devices_setup(void)
142 144
143 /* Wire-up dynamic vectors */ 145 /* Wire-up dynamic vectors */
144 cf_ide_resources[2].start = cf_ide_resources[2].end = 146 cf_ide_resources[2].start = cf_ide_resources[2].end =
145 se7722_fpga_irq[SE7722_FPGA_IRQ_MRSHPC0]; 147 irq_find_mapping(se7722_irq_domain, SE7722_FPGA_IRQ_MRSHPC0);
146 148
147 smc91x_eth_resources[1].start = smc91x_eth_resources[1].end = 149 smc91x_eth_resources[1].start = smc91x_eth_resources[1].end =
148 se7722_fpga_irq[SE7722_FPGA_IRQ_SMC]; 150 irq_find_mapping(se7722_irq_domain, SE7722_FPGA_IRQ_SMC);
149 151
150 return platform_add_devices(se7722_devices, ARRAY_SIZE(se7722_devices)); 152 return platform_add_devices(se7722_devices, ARRAY_SIZE(se7722_devices));
151} 153}
diff --git a/arch/sh/include/mach-se/mach/se7722.h b/arch/sh/include/mach-se/mach/se7722.h
index 16505bfb8a9e..5508dc42e4d2 100644
--- a/arch/sh/include/mach-se/mach/se7722.h
+++ b/arch/sh/include/mach-se/mach/se7722.h
@@ -80,12 +80,6 @@
80#define IRQ0_IRQ 32 80#define IRQ0_IRQ 32
81#define IRQ1_IRQ 33 81#define IRQ1_IRQ 33
82 82
83#define IRQ01_MODE 0xb1800000
84#define IRQ01_STS 0xb1800004
85#define IRQ01_MASK 0xb1800008
86
87/* Bits in IRQ01_* registers */
88
89#define SE7722_FPGA_IRQ_USB 0 /* IRQ0 */ 83#define SE7722_FPGA_IRQ_USB 0 /* IRQ0 */
90#define SE7722_FPGA_IRQ_SMC 1 /* IRQ0 */ 84#define SE7722_FPGA_IRQ_SMC 1 /* IRQ0 */
91#define SE7722_FPGA_IRQ_MRSHPC0 2 /* IRQ1 */ 85#define SE7722_FPGA_IRQ_MRSHPC0 2 /* IRQ1 */
@@ -94,8 +88,10 @@
94#define SE7722_FPGA_IRQ_MRSHPC3 5 /* IRQ1 */ 88#define SE7722_FPGA_IRQ_MRSHPC3 5 /* IRQ1 */
95#define SE7722_FPGA_IRQ_NR 6 89#define SE7722_FPGA_IRQ_NR 6
96 90
91struct irq_domain;
92
97/* arch/sh/boards/se/7722/irq.c */ 93/* arch/sh/boards/se/7722/irq.c */
98extern unsigned int se7722_fpga_irq[]; 94extern struct irq_domain *se7722_irq_domain;
99 95
100void init_se7722_IRQ(void); 96void init_se7722_IRQ(void);
101 97