1/*
2 * arch/ppc/syslib/ipic.c
3 *
4 * IPIC routines implementations.
5 *
6 * Copyright 2005 Freescale Semiconductor, Inc.
7 *
8 * This program is free software; you can redistribute  it and/or modify it
9 * under  the terms of  the GNU General  Public License as published by the
10 * Free Software Foundation;  either version 2 of the  License, or (at your
11 * option) any later version.
12 */
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/errno.h>
16#include <linux/reboot.h>
17#include <linux/slab.h>
18#include <linux/stddef.h>
19#include <linux/sched.h>
20#include <linux/signal.h>
21#include <linux/sysdev.h>
22#include <asm/irq.h>
23#include <asm/io.h>
24#include <asm/ipic.h>
25#include <asm/mpc83xx.h>
26
27#include "ipic.h"
28
29static struct ipic p_ipic;
30static struct ipic * primary_ipic;
31
32static struct ipic_info ipic_info[] = {
33	[9] = {
34		.pend	= IPIC_SIPNR_H,
35		.mask	= IPIC_SIMSR_H,
36		.prio	= IPIC_SIPRR_D,
37		.force	= IPIC_SIFCR_H,
38		.bit	= 24,
39		.prio_mask = 0,
40	},
41	[10] = {
42		.pend	= IPIC_SIPNR_H,
43		.mask	= IPIC_SIMSR_H,
44		.prio	= IPIC_SIPRR_D,
45		.force	= IPIC_SIFCR_H,
46		.bit	= 25,
47		.prio_mask = 1,
48	},
49	[11] = {
50		.pend	= IPIC_SIPNR_H,
51		.mask	= IPIC_SIMSR_H,
52		.prio	= IPIC_SIPRR_D,
53		.force	= IPIC_SIFCR_H,
54		.bit	= 26,
55		.prio_mask = 2,
56	},
57	[14] = {
58		.pend	= IPIC_SIPNR_H,
59		.mask	= IPIC_SIMSR_H,
60		.prio	= IPIC_SIPRR_D,
61		.force	= IPIC_SIFCR_H,
62		.bit	= 29,
63		.prio_mask = 5,
64	},
65	[15] = {
66		.pend	= IPIC_SIPNR_H,
67		.mask	= IPIC_SIMSR_H,
68		.prio	= IPIC_SIPRR_D,
69		.force	= IPIC_SIFCR_H,
70		.bit	= 30,
71		.prio_mask = 6,
72	},
73	[16] = {
74		.pend	= IPIC_SIPNR_H,
75		.mask	= IPIC_SIMSR_H,
76		.prio	= IPIC_SIPRR_D,
77		.force	= IPIC_SIFCR_H,
78		.bit	= 31,
79		.prio_mask = 7,
80	},
81	[17] = {
82		.pend	= IPIC_SEPNR,
83		.mask	= IPIC_SEMSR,
84		.prio	= IPIC_SMPRR_A,
85		.force	= IPIC_SEFCR,
86		.bit	= 1,
87		.prio_mask = 5,
88	},
89	[18] = {
90		.pend	= IPIC_SEPNR,
91		.mask	= IPIC_SEMSR,
92		.prio	= IPIC_SMPRR_A,
93		.force	= IPIC_SEFCR,
94		.bit	= 2,
95		.prio_mask = 6,
96	},
97	[19] = {
98		.pend	= IPIC_SEPNR,
99		.mask	= IPIC_SEMSR,
100		.prio	= IPIC_SMPRR_A,
101		.force	= IPIC_SEFCR,
102		.bit	= 3,
103		.prio_mask = 7,
104	},
105	[20] = {
106		.pend	= IPIC_SEPNR,
107		.mask	= IPIC_SEMSR,
108		.prio	= IPIC_SMPRR_B,
109		.force	= IPIC_SEFCR,
110		.bit	= 4,
111		.prio_mask = 4,
112	},
113	[21] = {
114		.pend	= IPIC_SEPNR,
115		.mask	= IPIC_SEMSR,
116		.prio	= IPIC_SMPRR_B,
117		.force	= IPIC_SEFCR,
118		.bit	= 5,
119		.prio_mask = 5,
120	},
121	[22] = {
122		.pend	= IPIC_SEPNR,
123		.mask	= IPIC_SEMSR,
124		.prio	= IPIC_SMPRR_B,
125		.force	= IPIC_SEFCR,
126		.bit	= 6,
127		.prio_mask = 6,
128	},
129	[23] = {
130		.pend	= IPIC_SEPNR,
131		.mask	= IPIC_SEMSR,
132		.prio	= IPIC_SMPRR_B,
133		.force	= IPIC_SEFCR,
134		.bit	= 7,
135		.prio_mask = 7,
136	},
137	[32] = {
138		.pend	= IPIC_SIPNR_H,
139		.mask	= IPIC_SIMSR_H,
140		.prio	= IPIC_SIPRR_A,
141		.force	= IPIC_SIFCR_H,
142		.bit	= 0,
143		.prio_mask = 0,
144	},
145	[33] = {
146		.pend	= IPIC_SIPNR_H,
147		.mask	= IPIC_SIMSR_H,
148		.prio	= IPIC_SIPRR_A,
149		.force	= IPIC_SIFCR_H,
150		.bit	= 1,
151		.prio_mask = 1,
152	},
153	[34] = {
154		.pend	= IPIC_SIPNR_H,
155		.mask	= IPIC_SIMSR_H,
156		.prio	= IPIC_SIPRR_A,
157		.force	= IPIC_SIFCR_H,
158		.bit	= 2,
159		.prio_mask = 2,
160	},
161	[35] = {
162		.pend	= IPIC_SIPNR_H,
163		.mask	= IPIC_SIMSR_H,
164		.prio	= IPIC_SIPRR_A,
165		.force	= IPIC_SIFCR_H,
166		.bit	= 3,
167		.prio_mask = 3,
168	},
169	[36] = {
170		.pend	= IPIC_SIPNR_H,
171		.mask	= IPIC_SIMSR_H,
172		.prio	= IPIC_SIPRR_A,
173		.force	= IPIC_SIFCR_H,
174		.bit	= 4,
175		.prio_mask = 4,
176	},
177	[37] = {
178		.pend	= IPIC_SIPNR_H,
179		.mask	= IPIC_SIMSR_H,
180		.prio	= IPIC_SIPRR_A,
181		.force	= IPIC_SIFCR_H,
182		.bit	= 5,
183		.prio_mask = 5,
184	},
185	[38] = {
186		.pend	= IPIC_SIPNR_H,
187		.mask	= IPIC_SIMSR_H,
188		.prio	= IPIC_SIPRR_A,
189		.force	= IPIC_SIFCR_H,
190		.bit	= 6,
191		.prio_mask = 6,
192	},
193	[39] = {
194		.pend	= IPIC_SIPNR_H,
195		.mask	= IPIC_SIMSR_H,
196		.prio	= IPIC_SIPRR_A,
197		.force	= IPIC_SIFCR_H,
198		.bit	= 7,
199		.prio_mask = 7,
200	},
201	[48] = {
202		.pend	= IPIC_SEPNR,
203		.mask	= IPIC_SEMSR,
204		.prio	= IPIC_SMPRR_A,
205		.force	= IPIC_SEFCR,
206		.bit	= 0,
207		.prio_mask = 4,
208	},
209	[64] = {
210		.pend	= IPIC_SIPNR_H,
211		.mask	= IPIC_SIMSR_L,
212		.prio	= IPIC_SMPRR_A,
213		.force	= IPIC_SIFCR_L,
214		.bit	= 0,
215		.prio_mask = 0,
216	},
217	[65] = {
218		.pend	= IPIC_SIPNR_H,
219		.mask	= IPIC_SIMSR_L,
220		.prio	= IPIC_SMPRR_A,
221		.force	= IPIC_SIFCR_L,
222		.bit	= 1,
223		.prio_mask = 1,
224	},
225	[66] = {
226		.pend	= IPIC_SIPNR_H,
227		.mask	= IPIC_SIMSR_L,
228		.prio	= IPIC_SMPRR_A,
229		.force	= IPIC_SIFCR_L,
230		.bit	= 2,
231		.prio_mask = 2,
232	},
233	[67] = {
234		.pend	= IPIC_SIPNR_H,
235		.mask	= IPIC_SIMSR_L,
236		.prio	= IPIC_SMPRR_A,
237		.force	= IPIC_SIFCR_L,
238		.bit	= 3,
239		.prio_mask = 3,
240	},
241	[68] = {
242		.pend	= IPIC_SIPNR_H,
243		.mask	= IPIC_SIMSR_L,
244		.prio	= IPIC_SMPRR_B,
245		.force	= IPIC_SIFCR_L,
246		.bit	= 4,
247		.prio_mask = 0,
248	},
249	[69] = {
250		.pend	= IPIC_SIPNR_H,
251		.mask	= IPIC_SIMSR_L,
252		.prio	= IPIC_SMPRR_B,
253		.force	= IPIC_SIFCR_L,
254		.bit	= 5,
255		.prio_mask = 1,
256	},
257	[70] = {
258		.pend	= IPIC_SIPNR_H,
259		.mask	= IPIC_SIMSR_L,
260		.prio	= IPIC_SMPRR_B,
261		.force	= IPIC_SIFCR_L,
262		.bit	= 6,
263		.prio_mask = 2,
264	},
265	[71] = {
266		.pend	= IPIC_SIPNR_H,
267		.mask	= IPIC_SIMSR_L,
268		.prio	= IPIC_SMPRR_B,
269		.force	= IPIC_SIFCR_L,
270		.bit	= 7,
271		.prio_mask = 3,
272	},
273	[72] = {
274		.pend	= IPIC_SIPNR_H,
275		.mask	= IPIC_SIMSR_L,
276		.prio	= 0,
277		.force	= IPIC_SIFCR_L,
278		.bit	= 8,
279	},
280	[73] = {
281		.pend	= IPIC_SIPNR_H,
282		.mask	= IPIC_SIMSR_L,
283		.prio	= 0,
284		.force	= IPIC_SIFCR_L,
285		.bit	= 9,
286	},
287	[74] = {
288		.pend	= IPIC_SIPNR_H,
289		.mask	= IPIC_SIMSR_L,
290		.prio	= 0,
291		.force	= IPIC_SIFCR_L,
292		.bit	= 10,
293	},
294	[75] = {
295		.pend	= IPIC_SIPNR_H,
296		.mask	= IPIC_SIMSR_L,
297		.prio	= 0,
298		.force	= IPIC_SIFCR_L,
299		.bit	= 11,
300	},
301	[76] = {
302		.pend	= IPIC_SIPNR_H,
303		.mask	= IPIC_SIMSR_L,
304		.prio	= 0,
305		.force	= IPIC_SIFCR_L,
306		.bit	= 12,
307	},
308	[77] = {
309		.pend	= IPIC_SIPNR_H,
310		.mask	= IPIC_SIMSR_L,
311		.prio	= 0,
312		.force	= IPIC_SIFCR_L,
313		.bit	= 13,
314	},
315	[78] = {
316		.pend	= IPIC_SIPNR_H,
317		.mask	= IPIC_SIMSR_L,
318		.prio	= 0,
319		.force	= IPIC_SIFCR_L,
320		.bit	= 14,
321	},
322	[79] = {
323		.pend	= IPIC_SIPNR_H,
324		.mask	= IPIC_SIMSR_L,
325		.prio	= 0,
326		.force	= IPIC_SIFCR_L,
327		.bit	= 15,
328	},
329	[80] = {
330		.pend	= IPIC_SIPNR_H,
331		.mask	= IPIC_SIMSR_L,
332		.prio	= 0,
333		.force	= IPIC_SIFCR_L,
334		.bit	= 16,
335	},
336	[84] = {
337		.pend	= IPIC_SIPNR_H,
338		.mask	= IPIC_SIMSR_L,
339		.prio	= 0,
340		.force	= IPIC_SIFCR_L,
341		.bit	= 20,
342	},
343	[85] = {
344		.pend	= IPIC_SIPNR_H,
345		.mask	= IPIC_SIMSR_L,
346		.prio	= 0,
347		.force	= IPIC_SIFCR_L,
348		.bit	= 21,
349	},
350	[90] = {
351		.pend	= IPIC_SIPNR_H,
352		.mask	= IPIC_SIMSR_L,
353		.prio	= 0,
354		.force	= IPIC_SIFCR_L,
355		.bit	= 26,
356	},
357	[91] = {
358		.pend	= IPIC_SIPNR_H,
359		.mask	= IPIC_SIMSR_L,
360		.prio	= 0,
361		.force	= IPIC_SIFCR_L,
362		.bit	= 27,
363	},
364};
365
366static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
367{
368	return in_be32(base + (reg >> 2));
369}
370
371static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
372{
373	out_be32(base + (reg >> 2), value);
374}
375
376static inline struct ipic * ipic_from_irq(unsigned int irq)
377{
378	return primary_ipic;
379}
380
381static void ipic_enable_irq(unsigned int irq)
382{
383	struct ipic *ipic = ipic_from_irq(irq);
384	unsigned int src = irq - ipic->irq_offset;
385	u32 temp;
386
387	temp = ipic_read(ipic->regs, ipic_info[src].mask);
388	temp |= (1 << (31 - ipic_info[src].bit));
389	ipic_write(ipic->regs, ipic_info[src].mask, temp);
390}
391
392static void ipic_disable_irq(unsigned int irq)
393{
394	struct ipic *ipic = ipic_from_irq(irq);
395	unsigned int src = irq - ipic->irq_offset;
396	u32 temp;
397
398	temp = ipic_read(ipic->regs, ipic_info[src].mask);
399	temp &= ~(1 << (31 - ipic_info[src].bit));
400	ipic_write(ipic->regs, ipic_info[src].mask, temp);
401}
402
403static void ipic_disable_irq_and_ack(unsigned int irq)
404{
405	struct ipic *ipic = ipic_from_irq(irq);
406	unsigned int src = irq - ipic->irq_offset;
407	u32 temp;
408
409	ipic_disable_irq(irq);
410
411	temp = ipic_read(ipic->regs, ipic_info[src].pend);
412	temp |= (1 << (31 - ipic_info[src].bit));
413	ipic_write(ipic->regs, ipic_info[src].pend, temp);
414}
415
416static void ipic_end_irq(unsigned int irq)
417{
418	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
419		ipic_enable_irq(irq);
420}
421
422struct hw_interrupt_type ipic = {
423	.typename = " IPIC  ",
424	.enable = ipic_enable_irq,
425	.disable = ipic_disable_irq,
426	.ack = ipic_disable_irq_and_ack,
427	.end = ipic_end_irq,
428};
429
430void __init ipic_init(phys_addr_t phys_addr,
431		unsigned int flags,
432		unsigned int irq_offset,
433		unsigned char *senses,
434		unsigned int senses_count)
435{
436	u32 i, temp = 0;
437
438	primary_ipic = &p_ipic;
439	primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
440
441	primary_ipic->irq_offset = irq_offset;
442
443	ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
444
445	/* default priority scheme is grouped. If spread mode is required
446	 * configure SICFR accordingly */
447	if (flags & IPIC_SPREADMODE_GRP_A)
448		temp |= SICFR_IPSA;
449	if (flags & IPIC_SPREADMODE_GRP_D)
450		temp |= SICFR_IPSD;
451	if (flags & IPIC_SPREADMODE_MIX_A)
452		temp |= SICFR_MPSA;
453	if (flags & IPIC_SPREADMODE_MIX_B)
454		temp |= SICFR_MPSB;
455
456	ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
457
458	/* handle MCP route */
459	temp = 0;
460	if (flags & IPIC_DISABLE_MCP_OUT)
461		temp = SERCR_MCPR;
462	ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
463
464	/* handle routing of IRQ0 to MCP */
465	temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
466
467	if (flags & IPIC_IRQ0_MCP)
468		temp |= SEMSR_SIRQ0;
469	else
470		temp &= ~SEMSR_SIRQ0;
471
472	ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
473
474	for (i = 0 ; i < NR_IPIC_INTS ; i++) {
475		irq_desc[i+irq_offset].chip = &ipic;
476		irq_desc[i+irq_offset].status = IRQ_LEVEL;
477	}
478
479	temp = 0;
480	for (i = 0 ; i < senses_count ; i++) {
481		if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
482			temp |= 1 << (15 - i);
483			if (i != 0)
484				irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
485			else
486				irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
487		}
488	}
489	ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
490
491	printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
492			senses_count, primary_ipic->regs);
493}
494
495int ipic_set_priority(unsigned int irq, unsigned int priority)
496{
497	struct ipic *ipic = ipic_from_irq(irq);
498	unsigned int src = irq - ipic->irq_offset;
499	u32 temp;
500
501	if (priority > 7)
502		return -EINVAL;
503	if (src > 127)
504		return -EINVAL;
505	if (ipic_info[src].prio == 0)
506		return -EINVAL;
507
508	temp = ipic_read(ipic->regs, ipic_info[src].prio);
509
510	if (priority < 4) {
511		temp &= ~(0x7 << (20 + (3 - priority) * 3));
512		temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
513	} else {
514		temp &= ~(0x7 << (4 + (7 - priority) * 3));
515		temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
516	}
517
518	ipic_write(ipic->regs, ipic_info[src].prio, temp);
519
520	return 0;
521}
522
523void ipic_set_highest_priority(unsigned int irq)
524{
525	struct ipic *ipic = ipic_from_irq(irq);
526	unsigned int src = irq - ipic->irq_offset;
527	u32 temp;
528
529	temp = ipic_read(ipic->regs, IPIC_SICFR);
530
531	/* clear and set HPI */
532	temp &= 0x7f000000;
533	temp |= (src & 0x7f) << 24;
534
535	ipic_write(ipic->regs, IPIC_SICFR, temp);
536}
537
538void ipic_set_default_priority(void)
539{
540	ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
541	ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
542	ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
543	ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
544	ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
545	ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
546	ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
547	ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
548
549	ipic_set_priority(MPC83xx_IRQ_UART1, 0);
550	ipic_set_priority(MPC83xx_IRQ_UART2, 1);
551	ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
552	ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
553	ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
554	ipic_set_priority(MPC83xx_IRQ_SPI, 7);
555	ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
556	ipic_set_priority(MPC83xx_IRQ_PIT, 1);
557	ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
558	ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
559	ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
560	ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
561	ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
562	ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
563	ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
564	ipic_set_priority(MPC83xx_IRQ_MU, 1);
565	ipic_set_priority(MPC83xx_IRQ_SBA, 2);
566	ipic_set_priority(MPC83xx_IRQ_DMA, 3);
567	ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
568	ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
569	ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
570	ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
571}
572
573void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
574{
575	struct ipic *ipic = primary_ipic;
576	u32 temp;
577
578	temp = ipic_read(ipic->regs, IPIC_SERMR);
579	temp |= (1 << (31 - mcp_irq));
580	ipic_write(ipic->regs, IPIC_SERMR, temp);
581}
582
583void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
584{
585	struct ipic *ipic = primary_ipic;
586	u32 temp;
587
588	temp = ipic_read(ipic->regs, IPIC_SERMR);
589	temp &= (1 << (31 - mcp_irq));
590	ipic_write(ipic->regs, IPIC_SERMR, temp);
591}
592
593u32 ipic_get_mcp_status(void)
594{
595	return ipic_read(primary_ipic->regs, IPIC_SERMR);
596}
597
598void ipic_clear_mcp_status(u32 mask)
599{
600	ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
601}
602
603/* Return an interrupt vector or -1 if no interrupt is pending. */
604int ipic_get_irq(void)
605{
606	int irq;
607
608	irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
609
610	if (irq == 0)    /* 0 --> no irq is pending */
611		irq = -1;
612
613	return irq;
614}
615
616static struct sysdev_class ipic_sysclass = {
617	set_kset_name("ipic"),
618};
619
620static struct sys_device device_ipic = {
621	.id		= 0,
622	.cls		= &ipic_sysclass,
623};
624
625static int __init init_ipic_sysfs(void)
626{
627	int rc;
628
629	if (!primary_ipic->regs)
630		return -ENODEV;
631	printk(KERN_DEBUG "Registering ipic with sysfs...\n");
632
633	rc = sysdev_class_register(&ipic_sysclass);
634	if (rc) {
635		printk(KERN_ERR "Failed registering ipic sys class\n");
636		return -ENODEV;
637	}
638	rc = sysdev_register(&device_ipic);
639	if (rc) {
640		printk(KERN_ERR "Failed registering ipic sys device\n");
641		return -ENODEV;
642	}
643	return 0;
644}
645
646subsys_initcall(init_ipic_sysfs);
647