1 /*
2  * Cell Internal Interrupt Controller
3  *
4  * Copyright (C) 2006 Benjamin Herrenschmidt (benh@kernel.crashing.org)
5  *                    IBM, Corp.
6  *
7  * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
8  *
9  * Author: Arnd Bergmann <arndb@de.ibm.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2, or (at your option)
14  * any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25 
26 #include <linux/interrupt.h>
27 #include <linux/irq.h>
28 #include <linux/module.h>
29 #include <linux/percpu.h>
30 #include <linux/types.h>
31 #include <linux/ioport.h>
32 
33 #include <asm/io.h>
34 #include <asm/pgtable.h>
35 #include <asm/prom.h>
36 #include <asm/ptrace.h>
37 #include <asm/machdep.h>
38 
39 #include "interrupt.h"
40 #include "cbe_regs.h"
41 
42 struct iic {
43 	struct cbe_iic_thread_regs __iomem *regs;
44 	u8 target_id;
45 	u8 eoi_stack[16];
46 	int eoi_ptr;
47 	struct irq_host *host;
48 };
49 
50 static DEFINE_PER_CPU(struct iic, iic);
51 #define IIC_NODE_COUNT	2
52 static struct irq_host *iic_hosts[IIC_NODE_COUNT];
53 
54 /* Convert between "pending" bits and hw irq number */
55 static irq_hw_number_t iic_pending_to_hwnum(struct cbe_iic_pending_bits bits)
56 {
57 	unsigned char unit = bits.source & 0xf;
58 
59 	if (bits.flags & CBE_IIC_IRQ_IPI)
60 		return IIC_IRQ_IPI0 | (bits.prio >> 4);
61 	else if (bits.class <= 3)
62 		return (bits.class << 4) | unit;
63 	else
64 		return IIC_IRQ_INVALID;
65 }
66 
67 static void iic_mask(unsigned int irq)
68 {
69 }
70 
71 static void iic_unmask(unsigned int irq)
72 {
73 }
74 
75 static void iic_eoi(unsigned int irq)
76 {
77 	struct iic *iic = &__get_cpu_var(iic);
78 	out_be64(&iic->regs->prio, iic->eoi_stack[--iic->eoi_ptr]);
79 	BUG_ON(iic->eoi_ptr < 0);
80 }
81 
82 static struct irq_chip iic_chip = {
83 	.typename = " CELL-IIC ",
84 	.mask = iic_mask,
85 	.unmask = iic_unmask,
86 	.eoi = iic_eoi,
87 };
88 
89 /* Get an IRQ number from the pending state register of the IIC */
90 static unsigned int iic_get_irq(struct pt_regs *regs)
91 {
92   	struct cbe_iic_pending_bits pending;
93  	struct iic *iic;
94 
95  	iic = &__get_cpu_var(iic);
96  	*(unsigned long *) &pending =
97  		in_be64((unsigned long __iomem *) &iic->regs->pending_destr);
98  	iic->eoi_stack[++iic->eoi_ptr] = pending.prio;
99  	BUG_ON(iic->eoi_ptr > 15);
100 	if (pending.flags & CBE_IIC_IRQ_VALID)
101 		return irq_linear_revmap(iic->host,
102  					 iic_pending_to_hwnum(pending));
103 	return NO_IRQ;
104 }
105 
106 #ifdef CONFIG_SMP
107 
108 /* Use the highest interrupt priorities for IPI */
109 static inline int iic_ipi_to_irq(int ipi)
110 {
111 	return IIC_IRQ_IPI0 + IIC_NUM_IPIS - 1 - ipi;
112 }
113 
114 static inline int iic_irq_to_ipi(int irq)
115 {
116 	return IIC_NUM_IPIS - 1 - (irq - IIC_IRQ_IPI0);
117 }
118 
119 void iic_setup_cpu(void)
120 {
121 	out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
122 }
123 
124 void iic_cause_IPI(int cpu, int mesg)
125 {
126 	out_be64(&per_cpu(iic, cpu).regs->generate, (IIC_NUM_IPIS - 1 - mesg) << 4);
127 }
128 
129 u8 iic_get_target_id(int cpu)
130 {
131 	return per_cpu(iic, cpu).target_id;
132 }
133 EXPORT_SYMBOL_GPL(iic_get_target_id);
134 
135 struct irq_host *iic_get_irq_host(int node)
136 {
137 	if (node < 0 || node >= IIC_NODE_COUNT)
138 		return NULL;
139 	return iic_hosts[node];
140 }
141 EXPORT_SYMBOL_GPL(iic_get_irq_host);
142 
143 
144 static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
145 {
146 	int ipi = (int)(long)dev_id;
147 
148 	smp_message_recv(ipi, regs);
149 
150 	return IRQ_HANDLED;
151 }
152 
153 static void iic_request_ipi(int ipi, const char *name)
154 {
155 	int node, virq;
156 
157 	for (node = 0; node < IIC_NODE_COUNT; node++) {
158 		char *rname;
159 		if (iic_hosts[node] == NULL)
160 			continue;
161 		virq = irq_create_mapping(iic_hosts[node],
162 					  iic_ipi_to_irq(ipi));
163 		if (virq == NO_IRQ) {
164 			printk(KERN_ERR
165 			       "iic: failed to map IPI %s on node %d\n",
166 			       name, node);
167 			continue;
168 		}
169 		rname = kzalloc(strlen(name) + 16, GFP_KERNEL);
170 		if (rname)
171 			sprintf(rname, "%s node %d", name, node);
172 		else
173 			rname = (char *)name;
174 		if (request_irq(virq, iic_ipi_action, IRQF_DISABLED,
175 				rname, (void *)(long)ipi))
176 			printk(KERN_ERR
177 			       "iic: failed to request IPI %s on node %d\n",
178 			       name, node);
179 	}
180 }
181 
182 void iic_request_IPIs(void)
183 {
184 	iic_request_ipi(PPC_MSG_CALL_FUNCTION, "IPI-call");
185 	iic_request_ipi(PPC_MSG_RESCHEDULE, "IPI-resched");
186 #ifdef CONFIG_DEBUGGER
187 	iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug");
188 #endif /* CONFIG_DEBUGGER */
189 }
190 
191 #endif /* CONFIG_SMP */
192 
193 
194 static int iic_host_match(struct irq_host *h, struct device_node *node)
195 {
196 	return h->host_data != NULL && node == h->host_data;
197 }
198 
199 static int iic_host_map(struct irq_host *h, unsigned int virq,
200 			irq_hw_number_t hw)
201 {
202 	if (hw < IIC_IRQ_IPI0)
203 		set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq);
204 	else
205 		set_irq_chip_and_handler(virq, &iic_chip, handle_percpu_irq);
206 	return 0;
207 }
208 
209 static int iic_host_xlate(struct irq_host *h, struct device_node *ct,
210 			   u32 *intspec, unsigned int intsize,
211 			   irq_hw_number_t *out_hwirq, unsigned int *out_flags)
212 
213 {
214 	/* Currently, we don't translate anything. That needs to be fixed as
215 	 * we get better defined device-trees. iic interrupts have to be
216 	 * explicitely mapped by whoever needs them
217 	 */
218 	return -ENODEV;
219 }
220 
221 static struct irq_host_ops iic_host_ops = {
222 	.match = iic_host_match,
223 	.map = iic_host_map,
224 	.xlate = iic_host_xlate,
225 };
226 
227 static void __init init_one_iic(unsigned int hw_cpu, unsigned long addr,
228 				struct irq_host *host)
229 {
230 	/* XXX FIXME: should locate the linux CPU number from the HW cpu
231 	 * number properly. We are lucky for now
232 	 */
233 	struct iic *iic = &per_cpu(iic, hw_cpu);
234 
235 	iic->regs = ioremap(addr, sizeof(struct cbe_iic_thread_regs));
236 	BUG_ON(iic->regs == NULL);
237 
238 	iic->target_id = ((hw_cpu & 2) << 3) | ((hw_cpu & 1) ? 0xf : 0xe);
239 	iic->eoi_stack[0] = 0xff;
240 	iic->host = host;
241 	out_be64(&iic->regs->prio, 0);
242 
243 	printk(KERN_INFO "IIC for CPU %d at %lx mapped to %p, target id 0x%x\n",
244 	       hw_cpu, addr, iic->regs, iic->target_id);
245 }
246 
247 static int __init setup_iic(void)
248 {
249 	struct device_node *dn;
250 	struct resource r0, r1;
251 	struct irq_host *host;
252 	int found = 0;
253  	const u32 *np;
254 
255 	for (dn = NULL;
256 	     (dn = of_find_node_by_name(dn,"interrupt-controller")) != NULL;) {
257 		if (!device_is_compatible(dn,
258 				     "IBM,CBEA-Internal-Interrupt-Controller"))
259 			continue;
260 		np = get_property(dn, "ibm,interrupt-server-ranges", NULL);
261  		if (np == NULL) {
262 			printk(KERN_WARNING "IIC: CPU association not found\n");
263 			of_node_put(dn);
264 			return -ENODEV;
265 		}
266 		if (of_address_to_resource(dn, 0, &r0) ||
267 		    of_address_to_resource(dn, 1, &r1)) {
268 			printk(KERN_WARNING "IIC: Can't resolve addresses\n");
269 			of_node_put(dn);
270 			return -ENODEV;
271 		}
272 		host = NULL;
273 		if (found < IIC_NODE_COUNT) {
274 			host = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
275 					      IIC_SOURCE_COUNT,
276 					      &iic_host_ops,
277 					      IIC_IRQ_INVALID);
278 			iic_hosts[found] = host;
279 			BUG_ON(iic_hosts[found] == NULL);
280 			iic_hosts[found]->host_data = of_node_get(dn);
281 			found++;
282 		}
283 		init_one_iic(np[0], r0.start, host);
284 		init_one_iic(np[1], r1.start, host);
285 	}
286 
287 	if (found)
288 		return 0;
289 	else
290 		return -ENODEV;
291 }
292 
293 void __init iic_init_IRQ(void)
294 {
295 	/* Discover and initialize iics */
296 	if (setup_iic() < 0)
297 		panic("IIC: Failed to initialize !\n");
298 
299 	/* Set master interrupt handling function */
300 	ppc_md.get_irq = iic_get_irq;
301 
302 	/* Enable on current CPU */
303 	iic_setup_cpu();
304 }
305