1 /*
2  *  Copyright (C) 2008 Ilya Yanok, Emcraft Systems
3  *
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  */
10 
11 #include <linux/irq.h>
12 #include <linux/of_platform.h>
13 #include <linux/io.h>
14 
15 /*
16  * The FPGA supports 9 interrupt sources, which can be routed to 3
17  * interrupt request lines of the MPIC. The line to be used can be
18  * specified through the third cell of FDT property  "interrupts".
19  */
20 
21 #define SOCRATES_FPGA_NUM_IRQS	9
22 
23 #define FPGA_PIC_IRQCFG		(0x0)
24 #define FPGA_PIC_IRQMASK(n)	(0x4 + 0x4 * (n))
25 
26 #define SOCRATES_FPGA_IRQ_MASK	((1 << SOCRATES_FPGA_NUM_IRQS) - 1)
27 
28 struct socrates_fpga_irq_info {
29 	unsigned int irq_line;
30 	int type;
31 };
32 
33 /*
34  * Interrupt routing and type table
35  *
36  * IRQ_TYPE_NONE means the interrupt type is configurable,
37  * otherwise it's fixed to the specified value.
38  */
39 static struct socrates_fpga_irq_info fpga_irqs[SOCRATES_FPGA_NUM_IRQS] = {
40 	[0] = {0, IRQ_TYPE_NONE},
41 	[1] = {0, IRQ_TYPE_LEVEL_HIGH},
42 	[2] = {0, IRQ_TYPE_LEVEL_LOW},
43 	[3] = {0, IRQ_TYPE_NONE},
44 	[4] = {0, IRQ_TYPE_NONE},
45 	[5] = {0, IRQ_TYPE_NONE},
46 	[6] = {0, IRQ_TYPE_NONE},
47 	[7] = {0, IRQ_TYPE_NONE},
48 	[8] = {0, IRQ_TYPE_LEVEL_HIGH},
49 };
50 
51 #define socrates_fpga_irq_to_hw(virq)    ((unsigned int)irq_map[virq].hwirq)
52 
53 static DEFINE_RAW_SPINLOCK(socrates_fpga_pic_lock);
54 
55 static void __iomem *socrates_fpga_pic_iobase;
56 static struct irq_host *socrates_fpga_pic_irq_host;
57 static unsigned int socrates_fpga_irqs[3];
58 
59 static inline uint32_t socrates_fpga_pic_read(int reg)
60 {
61 	return in_be32(socrates_fpga_pic_iobase + reg);
62 }
63 
64 static inline void socrates_fpga_pic_write(int reg, uint32_t val)
65 {
66 	out_be32(socrates_fpga_pic_iobase + reg, val);
67 }
68 
69 static inline unsigned int socrates_fpga_pic_get_irq(unsigned int irq)
70 {
71 	uint32_t cause;
72 	unsigned long flags;
73 	int i;
74 
75 	/* Check irq line routed to the MPIC */
76 	for (i = 0; i < 3; i++) {
77 		if (irq == socrates_fpga_irqs[i])
78 			break;
79 	}
80 	if (i == 3)
81 		return NO_IRQ;
82 
83 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
84 	cause = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(i));
85 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
86 	for (i = SOCRATES_FPGA_NUM_IRQS - 1; i >= 0; i--) {
87 		if (cause >> (i + 16))
88 			break;
89 	}
90 	return irq_linear_revmap(socrates_fpga_pic_irq_host,
91 			(irq_hw_number_t)i);
92 }
93 
94 void socrates_fpga_pic_cascade(unsigned int irq, struct irq_desc *desc)
95 {
96 	unsigned int cascade_irq;
97 
98 	/*
99 	 * See if we actually have an interrupt, call generic handling code if
100 	 * we do.
101 	 */
102 	cascade_irq = socrates_fpga_pic_get_irq(irq);
103 
104 	if (cascade_irq != NO_IRQ)
105 		generic_handle_irq(cascade_irq);
106 	desc->chip->eoi(irq);
107 
108 }
109 
110 static void socrates_fpga_pic_ack(unsigned int virq)
111 {
112 	unsigned long flags;
113 	unsigned int hwirq, irq_line;
114 	uint32_t mask;
115 
116 	hwirq = socrates_fpga_irq_to_hw(virq);
117 
118 	irq_line = fpga_irqs[hwirq].irq_line;
119 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
120 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
121 		& SOCRATES_FPGA_IRQ_MASK;
122 	mask |= (1 << (hwirq + 16));
123 	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
124 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
125 }
126 
127 static void socrates_fpga_pic_mask(unsigned int virq)
128 {
129 	unsigned long flags;
130 	unsigned int hwirq;
131 	int irq_line;
132 	u32 mask;
133 
134 	hwirq = socrates_fpga_irq_to_hw(virq);
135 
136 	irq_line = fpga_irqs[hwirq].irq_line;
137 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
138 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
139 		& SOCRATES_FPGA_IRQ_MASK;
140 	mask &= ~(1 << hwirq);
141 	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
142 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
143 }
144 
145 static void socrates_fpga_pic_mask_ack(unsigned int virq)
146 {
147 	unsigned long flags;
148 	unsigned int hwirq;
149 	int irq_line;
150 	u32 mask;
151 
152 	hwirq = socrates_fpga_irq_to_hw(virq);
153 
154 	irq_line = fpga_irqs[hwirq].irq_line;
155 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
156 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
157 		& SOCRATES_FPGA_IRQ_MASK;
158 	mask &= ~(1 << hwirq);
159 	mask |= (1 << (hwirq + 16));
160 	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
161 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
162 }
163 
164 static void socrates_fpga_pic_unmask(unsigned int virq)
165 {
166 	unsigned long flags;
167 	unsigned int hwirq;
168 	int irq_line;
169 	u32 mask;
170 
171 	hwirq = socrates_fpga_irq_to_hw(virq);
172 
173 	irq_line = fpga_irqs[hwirq].irq_line;
174 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
175 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
176 		& SOCRATES_FPGA_IRQ_MASK;
177 	mask |= (1 << hwirq);
178 	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
179 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
180 }
181 
182 static void socrates_fpga_pic_eoi(unsigned int virq)
183 {
184 	unsigned long flags;
185 	unsigned int hwirq;
186 	int irq_line;
187 	u32 mask;
188 
189 	hwirq = socrates_fpga_irq_to_hw(virq);
190 
191 	irq_line = fpga_irqs[hwirq].irq_line;
192 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
193 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
194 		& SOCRATES_FPGA_IRQ_MASK;
195 	mask |= (1 << (hwirq + 16));
196 	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
197 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
198 }
199 
200 static int socrates_fpga_pic_set_type(unsigned int virq,
201 		unsigned int flow_type)
202 {
203 	unsigned long flags;
204 	unsigned int hwirq;
205 	int polarity;
206 	u32 mask;
207 
208 	hwirq = socrates_fpga_irq_to_hw(virq);
209 
210 	if (fpga_irqs[hwirq].type != IRQ_TYPE_NONE)
211 		return -EINVAL;
212 
213 	switch (flow_type & IRQ_TYPE_SENSE_MASK) {
214 	case IRQ_TYPE_LEVEL_HIGH:
215 		polarity = 1;
216 		break;
217 	case IRQ_TYPE_LEVEL_LOW:
218 		polarity = 0;
219 		break;
220 	default:
221 		return -EINVAL;
222 	}
223 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
224 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQCFG);
225 	if (polarity)
226 		mask |= (1 << hwirq);
227 	else
228 		mask &= ~(1 << hwirq);
229 	socrates_fpga_pic_write(FPGA_PIC_IRQCFG, mask);
230 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
231 	return 0;
232 }
233 
234 static struct irq_chip socrates_fpga_pic_chip = {
235 	.name		= "FPGA-PIC",
236 	.ack		= socrates_fpga_pic_ack,
237 	.mask           = socrates_fpga_pic_mask,
238 	.mask_ack       = socrates_fpga_pic_mask_ack,
239 	.unmask         = socrates_fpga_pic_unmask,
240 	.eoi		= socrates_fpga_pic_eoi,
241 	.set_type	= socrates_fpga_pic_set_type,
242 };
243 
244 static int socrates_fpga_pic_host_map(struct irq_host *h, unsigned int virq,
245 		irq_hw_number_t hwirq)
246 {
247 	/* All interrupts are LEVEL sensitive */
248 	irq_to_desc(virq)->status |= IRQ_LEVEL;
249 	set_irq_chip_and_handler(virq, &socrates_fpga_pic_chip,
250 			handle_fasteoi_irq);
251 
252 	return 0;
253 }
254 
255 static int socrates_fpga_pic_host_xlate(struct irq_host *h,
256 		struct device_node *ct,	const u32 *intspec, unsigned int intsize,
257 		irq_hw_number_t *out_hwirq, unsigned int *out_flags)
258 {
259 	struct socrates_fpga_irq_info *fpga_irq = &fpga_irqs[intspec[0]];
260 
261 	*out_hwirq = intspec[0];
262 	if  (fpga_irq->type == IRQ_TYPE_NONE) {
263 		/* type is configurable */
264 		if (intspec[1] != IRQ_TYPE_LEVEL_LOW &&
265 		    intspec[1] != IRQ_TYPE_LEVEL_HIGH) {
266 			pr_warning("FPGA PIC: invalid irq type, "
267 				   "setting default active low\n");
268 			*out_flags = IRQ_TYPE_LEVEL_LOW;
269 		} else {
270 			*out_flags = intspec[1];
271 		}
272 	} else {
273 		/* type is fixed */
274 		*out_flags = fpga_irq->type;
275 	}
276 
277 	/* Use specified interrupt routing */
278 	if (intspec[2] <= 2)
279 		fpga_irq->irq_line = intspec[2];
280 	else
281 		pr_warning("FPGA PIC: invalid irq routing\n");
282 
283 	return 0;
284 }
285 
286 static struct irq_host_ops socrates_fpga_pic_host_ops = {
287 	.map    = socrates_fpga_pic_host_map,
288 	.xlate  = socrates_fpga_pic_host_xlate,
289 };
290 
291 void socrates_fpga_pic_init(struct device_node *pic)
292 {
293 	unsigned long flags;
294 	int i;
295 
296 	/* Setup an irq_host structure */
297 	socrates_fpga_pic_irq_host = irq_alloc_host(pic, IRQ_HOST_MAP_LINEAR,
298 			SOCRATES_FPGA_NUM_IRQS,	&socrates_fpga_pic_host_ops,
299 			SOCRATES_FPGA_NUM_IRQS);
300 	if (socrates_fpga_pic_irq_host == NULL) {
301 		pr_err("FPGA PIC: Unable to allocate host\n");
302 		return;
303 	}
304 
305 	for (i = 0; i < 3; i++) {
306 		socrates_fpga_irqs[i] = irq_of_parse_and_map(pic, i);
307 		if (socrates_fpga_irqs[i] == NO_IRQ) {
308 			pr_warning("FPGA PIC: can't get irq%d.\n", i);
309 			continue;
310 		}
311 		set_irq_chained_handler(socrates_fpga_irqs[i],
312 				socrates_fpga_pic_cascade);
313 	}
314 
315 	socrates_fpga_pic_iobase = of_iomap(pic, 0);
316 
317 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
318 	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(0),
319 			SOCRATES_FPGA_IRQ_MASK << 16);
320 	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(1),
321 			SOCRATES_FPGA_IRQ_MASK << 16);
322 	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(2),
323 			SOCRATES_FPGA_IRQ_MASK << 16);
324 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
325 
326 	pr_info("FPGA PIC: Setting up Socrates FPGA PIC\n");
327 }
328