aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/cell/spider-pic.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-07-03 05:32:51 -0400
committerPaul Mackerras <paulus@samba.org>2006-07-03 05:55:12 -0400
commitb9e5b4e6a991a5a6d521f2e20a65835404b4169f (patch)
treea0ac972faae4bf9133f576d842667bb134190341 /arch/powerpc/platforms/cell/spider-pic.c
parent5a43a066b11ac2fe84cf67307f20b83bea390f83 (diff)
[POWERPC] Use the genirq framework
This adapts the generic powerpc interrupt handling code, and all of the platforms except for the embedded 6xx machines, to use the new genirq framework. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/cell/spider-pic.c')
-rw-r--r--arch/powerpc/platforms/cell/spider-pic.c173
1 files changed, 76 insertions, 97 deletions
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 7c3a0b6d34f..98425acb6cd 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -82,17 +82,20 @@ static void __iomem *spider_get_irq_config(int irq)
82 return pic + TIR_CFGA + 8 * spider_get_nr(irq); 82 return pic + TIR_CFGA + 8 * spider_get_nr(irq);
83} 83}
84 84
85static void spider_enable_irq(unsigned int irq) 85static void spider_unmask_irq(unsigned int irq)
86{ 86{
87 int nodeid = (irq / IIC_NODE_STRIDE) * 0x10; 87 int nodeid = (irq / IIC_NODE_STRIDE) * 0x10;
88 void __iomem *cfg = spider_get_irq_config(irq); 88 void __iomem *cfg = spider_get_irq_config(irq);
89 irq = spider_get_nr(irq); 89 irq = spider_get_nr(irq);
90 90
91 /* FIXME: Most of that is configuration and has nothing to do with enabling/disable,
92 * besides, it's also partially bogus.
93 */
91 out_be32(cfg, (in_be32(cfg) & ~0xf0)| 0x3107000eu | nodeid); 94 out_be32(cfg, (in_be32(cfg) & ~0xf0)| 0x3107000eu | nodeid);
92 out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); 95 out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq);
93} 96}
94 97
95static void spider_disable_irq(unsigned int irq) 98static void spider_mask_irq(unsigned int irq)
96{ 99{
97 void __iomem *cfg = spider_get_irq_config(irq); 100 void __iomem *cfg = spider_get_irq_config(irq);
98 irq = spider_get_nr(irq); 101 irq = spider_get_nr(irq);
@@ -100,39 +103,21 @@ static void spider_disable_irq(unsigned int irq)
100 out_be32(cfg, in_be32(cfg) & ~0x30000000u); 103 out_be32(cfg, in_be32(cfg) & ~0x30000000u);
101} 104}
102 105
103static unsigned int spider_startup_irq(unsigned int irq)
104{
105 spider_enable_irq(irq);
106 return 0;
107}
108
109static void spider_shutdown_irq(unsigned int irq)
110{
111 spider_disable_irq(irq);
112}
113
114static void spider_end_irq(unsigned int irq)
115{
116 spider_enable_irq(irq);
117}
118
119static void spider_ack_irq(unsigned int irq) 106static void spider_ack_irq(unsigned int irq)
120{ 107{
121 spider_disable_irq(irq); 108 /* Should reset edge detection logic but we don't configure any edge interrupt
122 iic_local_enable(); 109 * at the moment.
110 */
123} 111}
124 112
125static struct hw_interrupt_type spider_pic = { 113static struct irq_chip spider_pic = {
126 .typename = " SPIDER ", 114 .typename = " SPIDER ",
127 .startup = spider_startup_irq, 115 .unmask = spider_unmask_irq,
128 .shutdown = spider_shutdown_irq, 116 .mask = spider_mask_irq,
129 .enable = spider_enable_irq,
130 .disable = spider_disable_irq,
131 .ack = spider_ack_irq, 117 .ack = spider_ack_irq,
132 .end = spider_end_irq,
133}; 118};
134 119
135int spider_get_irq(int node) 120static int spider_get_irq(int node)
136{ 121{
137 unsigned long cs; 122 unsigned long cs;
138 void __iomem *regs = spider_pics[node]; 123 void __iomem *regs = spider_pics[node];
@@ -145,95 +130,89 @@ int spider_get_irq(int node)
145 return cs; 130 return cs;
146} 131}
147 132
133static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc,
134 struct pt_regs *regs)
135{
136 int node = (int)(long)desc->handler_data;
137 int cascade_irq;
138
139 cascade_irq = spider_get_irq(node);
140 generic_handle_irq(cascade_irq, regs);
141 desc->chip->eoi(irq);
142}
143
148/* hardcoded part to be compatible with older firmware */ 144/* hardcoded part to be compatible with older firmware */
149 145
150void spider_init_IRQ_hardcoded(void) 146static void __init spider_init_one(int node, unsigned long addr)
151{ 147{
152 int node; 148 int n, irq;
153 long spiderpic; 149
154 long pics[] = { 0x24000008000, 0x34000008000 }; 150 spider_pics[node] = ioremap(addr, 0x800);
155 int n; 151 if (spider_pics[node] == NULL)
156 152 panic("spider_pic: can't map registers !");
157 pr_debug("%s(%d): Using hardcoded defaults\n", __FUNCTION__, __LINE__); 153
158 154 printk(KERN_INFO "spider_pic: mapped for node %d, addr: 0x%lx mapped to %p\n",
159 for (node = 0; node < num_present_cpus()/2; node++) { 155 node, addr, spider_pics[node]);
160 spiderpic = pics[node]; 156
161 printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic); 157 for (n = 0; n < IIC_NUM_EXT; n++) {
162 spider_pics[node] = ioremap(spiderpic, 0x800); 158 if (n == IIC_EXT_CASCADE)
163 for (n = 0; n < IIC_NUM_EXT; n++) { 159 continue;
164 int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; 160 irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE;
165 get_irq_desc(irq)->chip = &spider_pic; 161 set_irq_chip_and_handler(irq, &spider_pic, handle_level_irq);
166 } 162 get_irq_desc(irq)->status |= IRQ_LEVEL;
167
168 /* do not mask any interrupts because of level */
169 out_be32(spider_pics[node] + TIR_MSK, 0x0);
170
171 /* disable edge detection clear */
172 /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */
173
174 /* enable interrupt packets to be output */
175 out_be32(spider_pics[node] + TIR_PIEN,
176 in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
177
178 /* Enable the interrupt detection enable bit. Do this last! */
179 out_be32(spider_pics[node] + TIR_DEN,
180 in_be32(spider_pics[node] + TIR_DEN) | 0x1);
181 } 163 }
164
165 /* do not mask any interrupts because of level */
166 out_be32(spider_pics[node] + TIR_MSK, 0x0);
167
168 /* disable edge detection clear */
169 /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */
170
171 /* enable interrupt packets to be output */
172 out_be32(spider_pics[node] + TIR_PIEN,
173 in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
174
175 /* Hook up cascade */
176 irq = IIC_EXT_CASCADE + node * IIC_NODE_STRIDE;
177 set_irq_data(irq, (void *)(long)node);
178 set_irq_chained_handler(irq, spider_irq_cascade);
179
180 /* Enable the interrupt detection enable bit. Do this last! */
181 out_be32(spider_pics[node] + TIR_DEN,
182 in_be32(spider_pics[node] + TIR_DEN) | 0x1);
182} 183}
183 184
184void spider_init_IRQ(void) 185void __init spider_init_IRQ(void)
185{ 186{
186 long spider_reg; 187 unsigned long *spider_reg;
187 struct device_node *dn; 188 struct device_node *dn;
188 char *compatible; 189 char *compatible;
189 int n, node = 0; 190 int node = 0;
190 191
192 /* XXX node numbers are totally bogus. We _hope_ we get the device nodes in the right
193 * order here but that's definitely not guaranteed, we need to get the node from the
194 * device tree instead. There is currently no proper property for it (but our whole
195 * device-tree is bogus anyway) so all we can do is pray or maybe test the address
196 * and deduce the node-id
197 */
191 for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) { 198 for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) {
192 compatible = (char *)get_property(dn, "compatible", NULL); 199 compatible = (char *)get_property(dn, "compatible", NULL);
193 200
194 if (!compatible) 201 if (!compatible)
195 continue; 202 continue;
196 203
197 if (strstr(compatible, "CBEA,platform-spider-pic")) 204 if (strstr(compatible, "CBEA,platform-spider-pic"))
198 spider_reg = *(long *)get_property(dn,"reg", NULL); 205 spider_reg = (unsigned long *)get_property(dn, "reg", NULL);
199 else if (strstr(compatible, "sti,platform-spider-pic")) { 206 else if (strstr(compatible, "sti,platform-spider-pic") && (node < 2)) {
200 spider_init_IRQ_hardcoded(); 207 static long hard_coded_pics[] = { 0x24000008000, 0x34000008000 };
201 return; 208 spider_reg = &hard_coded_pics[node];
202 } else 209 } else
203 continue; 210 continue;
204 211
205 if (!spider_reg) 212 if (spider_reg == NULL)
206 printk("interrupt controller does not have reg property !\n"); 213 printk(KERN_ERR "spider_pic: No address for node %d\n", node);
207
208 n = prom_n_addr_cells(dn);
209
210 if ( n != 2)
211 printk("reg property with invalid number of elements \n");
212
213 spider_pics[node] = ioremap(spider_reg, 0x800);
214
215 printk("SPIDER addr: %lx with %i addr_cells mapped to %p\n",
216 spider_reg, n, spider_pics[node]);
217
218 for (n = 0; n < IIC_NUM_EXT; n++) {
219 int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE;
220 get_irq_desc(irq)->chip = &spider_pic;
221 }
222
223 /* do not mask any interrupts because of level */
224 out_be32(spider_pics[node] + TIR_MSK, 0x0);
225
226 /* disable edge detection clear */
227 /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */
228
229 /* enable interrupt packets to be output */
230 out_be32(spider_pics[node] + TIR_PIEN,
231 in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
232
233 /* Enable the interrupt detection enable bit. Do this last! */
234 out_be32(spider_pics[node] + TIR_DEN,
235 in_be32(spider_pics[node] + TIR_DEN) | 0x1);
236 214
215 spider_init_one(node, *spider_reg);
237 node++; 216 node++;
238 } 217 }
239} 218}