xref: /linux/arch/powerpc/sysdev/ipic.c (revision 77d4309e19b1a7ab3286cd741e924894fc329986)
11cd8e506SKumar Gala /*
2f30c2269SUwe Zeisberger  * arch/powerpc/sysdev/ipic.c
31cd8e506SKumar Gala  *
41cd8e506SKumar Gala  * IPIC routines implementations.
51cd8e506SKumar Gala  *
61cd8e506SKumar Gala  * Copyright 2005 Freescale Semiconductor, Inc.
71cd8e506SKumar Gala  *
81cd8e506SKumar Gala  * This program is free software; you can redistribute  it and/or modify it
91cd8e506SKumar Gala  * under  the terms of  the GNU General  Public License as published by the
101cd8e506SKumar Gala  * Free Software Foundation;  either version 2 of the  License, or (at your
111cd8e506SKumar Gala  * option) any later version.
121cd8e506SKumar Gala  */
131cd8e506SKumar Gala #include <linux/kernel.h>
141cd8e506SKumar Gala #include <linux/init.h>
151cd8e506SKumar Gala #include <linux/errno.h>
161cd8e506SKumar Gala #include <linux/reboot.h>
171cd8e506SKumar Gala #include <linux/slab.h>
181cd8e506SKumar Gala #include <linux/stddef.h>
191cd8e506SKumar Gala #include <linux/sched.h>
201cd8e506SKumar Gala #include <linux/signal.h>
211cd8e506SKumar Gala #include <linux/sysdev.h>
22b9f0f1bbSKim Phillips #include <linux/device.h>
23b9f0f1bbSKim Phillips #include <linux/bootmem.h>
24b9f0f1bbSKim Phillips #include <linux/spinlock.h>
251cd8e506SKumar Gala #include <asm/irq.h>
261cd8e506SKumar Gala #include <asm/io.h>
27b9f0f1bbSKim Phillips #include <asm/prom.h>
281cd8e506SKumar Gala #include <asm/ipic.h>
291cd8e506SKumar Gala 
301cd8e506SKumar Gala #include "ipic.h"
311cd8e506SKumar Gala 
321cd8e506SKumar Gala static struct ipic * primary_ipic;
33*77d4309eSLi Yang static struct irq_chip ipic_level_irq_chip, ipic_edge_irq_chip;
34b9f0f1bbSKim Phillips static DEFINE_SPINLOCK(ipic_lock);
351cd8e506SKumar Gala 
361cd8e506SKumar Gala static struct ipic_info ipic_info[] = {
37f03ca957SLi Yang 	[1] = {
38f03ca957SLi Yang 		.mask	= IPIC_SIMSR_H,
39f03ca957SLi Yang 		.prio	= IPIC_SIPRR_C,
40f03ca957SLi Yang 		.force	= IPIC_SIFCR_H,
41f03ca957SLi Yang 		.bit	= 16,
42f03ca957SLi Yang 		.prio_mask = 0,
43f03ca957SLi Yang 	},
44f03ca957SLi Yang 	[2] = {
45f03ca957SLi Yang 		.mask	= IPIC_SIMSR_H,
46f03ca957SLi Yang 		.prio	= IPIC_SIPRR_C,
47f03ca957SLi Yang 		.force	= IPIC_SIFCR_H,
48f03ca957SLi Yang 		.bit	= 17,
49f03ca957SLi Yang 		.prio_mask = 1,
50f03ca957SLi Yang 	},
51f03ca957SLi Yang 	[4] = {
52f03ca957SLi Yang 		.mask	= IPIC_SIMSR_H,
53f03ca957SLi Yang 		.prio	= IPIC_SIPRR_C,
54f03ca957SLi Yang 		.force	= IPIC_SIFCR_H,
55f03ca957SLi Yang 		.bit	= 19,
56f03ca957SLi Yang 		.prio_mask = 3,
57f03ca957SLi Yang 	},
581cd8e506SKumar Gala 	[9] = {
591cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_H,
601cd8e506SKumar Gala 		.prio	= IPIC_SIPRR_D,
611cd8e506SKumar Gala 		.force	= IPIC_SIFCR_H,
621cd8e506SKumar Gala 		.bit	= 24,
631cd8e506SKumar Gala 		.prio_mask = 0,
641cd8e506SKumar Gala 	},
651cd8e506SKumar Gala 	[10] = {
661cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_H,
671cd8e506SKumar Gala 		.prio	= IPIC_SIPRR_D,
681cd8e506SKumar Gala 		.force	= IPIC_SIFCR_H,
691cd8e506SKumar Gala 		.bit	= 25,
701cd8e506SKumar Gala 		.prio_mask = 1,
711cd8e506SKumar Gala 	},
721cd8e506SKumar Gala 	[11] = {
731cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_H,
741cd8e506SKumar Gala 		.prio	= IPIC_SIPRR_D,
751cd8e506SKumar Gala 		.force	= IPIC_SIFCR_H,
761cd8e506SKumar Gala 		.bit	= 26,
771cd8e506SKumar Gala 		.prio_mask = 2,
781cd8e506SKumar Gala 	},
79f03ca957SLi Yang 	[12] = {
80f03ca957SLi Yang 		.mask	= IPIC_SIMSR_H,
81f03ca957SLi Yang 		.prio	= IPIC_SIPRR_D,
82f03ca957SLi Yang 		.force	= IPIC_SIFCR_H,
83f03ca957SLi Yang 		.bit	= 27,
84f03ca957SLi Yang 		.prio_mask = 3,
85f03ca957SLi Yang 	},
86f03ca957SLi Yang 	[13] = {
87f03ca957SLi Yang 		.mask	= IPIC_SIMSR_H,
88f03ca957SLi Yang 		.prio	= IPIC_SIPRR_D,
89f03ca957SLi Yang 		.force	= IPIC_SIFCR_H,
90f03ca957SLi Yang 		.bit	= 28,
91f03ca957SLi Yang 		.prio_mask = 4,
92f03ca957SLi Yang 	},
931cd8e506SKumar Gala 	[14] = {
941cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_H,
951cd8e506SKumar Gala 		.prio	= IPIC_SIPRR_D,
961cd8e506SKumar Gala 		.force	= IPIC_SIFCR_H,
971cd8e506SKumar Gala 		.bit	= 29,
981cd8e506SKumar Gala 		.prio_mask = 5,
991cd8e506SKumar Gala 	},
1001cd8e506SKumar Gala 	[15] = {
1011cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_H,
1021cd8e506SKumar Gala 		.prio	= IPIC_SIPRR_D,
1031cd8e506SKumar Gala 		.force	= IPIC_SIFCR_H,
1041cd8e506SKumar Gala 		.bit	= 30,
1051cd8e506SKumar Gala 		.prio_mask = 6,
1061cd8e506SKumar Gala 	},
1071cd8e506SKumar Gala 	[16] = {
1081cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_H,
1091cd8e506SKumar Gala 		.prio	= IPIC_SIPRR_D,
1101cd8e506SKumar Gala 		.force	= IPIC_SIFCR_H,
1111cd8e506SKumar Gala 		.bit	= 31,
1121cd8e506SKumar Gala 		.prio_mask = 7,
1131cd8e506SKumar Gala 	},
1141cd8e506SKumar Gala 	[17] = {
115*77d4309eSLi Yang 		.ack	= IPIC_SEPNR,
1161cd8e506SKumar Gala 		.mask	= IPIC_SEMSR,
1171cd8e506SKumar Gala 		.prio	= IPIC_SMPRR_A,
1181cd8e506SKumar Gala 		.force	= IPIC_SEFCR,
1191cd8e506SKumar Gala 		.bit	= 1,
1201cd8e506SKumar Gala 		.prio_mask = 5,
1211cd8e506SKumar Gala 	},
1221cd8e506SKumar Gala 	[18] = {
123*77d4309eSLi Yang 		.ack	= IPIC_SEPNR,
1241cd8e506SKumar Gala 		.mask	= IPIC_SEMSR,
1251cd8e506SKumar Gala 		.prio	= IPIC_SMPRR_A,
1261cd8e506SKumar Gala 		.force	= IPIC_SEFCR,
1271cd8e506SKumar Gala 		.bit	= 2,
1281cd8e506SKumar Gala 		.prio_mask = 6,
1291cd8e506SKumar Gala 	},
1301cd8e506SKumar Gala 	[19] = {
131*77d4309eSLi Yang 		.ack	= IPIC_SEPNR,
1321cd8e506SKumar Gala 		.mask	= IPIC_SEMSR,
1331cd8e506SKumar Gala 		.prio	= IPIC_SMPRR_A,
1341cd8e506SKumar Gala 		.force	= IPIC_SEFCR,
1351cd8e506SKumar Gala 		.bit	= 3,
1361cd8e506SKumar Gala 		.prio_mask = 7,
1371cd8e506SKumar Gala 	},
1381cd8e506SKumar Gala 	[20] = {
139*77d4309eSLi Yang 		.ack	= IPIC_SEPNR,
1401cd8e506SKumar Gala 		.mask	= IPIC_SEMSR,
1411cd8e506SKumar Gala 		.prio	= IPIC_SMPRR_B,
1421cd8e506SKumar Gala 		.force	= IPIC_SEFCR,
1431cd8e506SKumar Gala 		.bit	= 4,
1441cd8e506SKumar Gala 		.prio_mask = 4,
1451cd8e506SKumar Gala 	},
1461cd8e506SKumar Gala 	[21] = {
147*77d4309eSLi Yang 		.ack	= IPIC_SEPNR,
1481cd8e506SKumar Gala 		.mask	= IPIC_SEMSR,
1491cd8e506SKumar Gala 		.prio	= IPIC_SMPRR_B,
1501cd8e506SKumar Gala 		.force	= IPIC_SEFCR,
1511cd8e506SKumar Gala 		.bit	= 5,
1521cd8e506SKumar Gala 		.prio_mask = 5,
1531cd8e506SKumar Gala 	},
1541cd8e506SKumar Gala 	[22] = {
155*77d4309eSLi Yang 		.ack	= IPIC_SEPNR,
1561cd8e506SKumar Gala 		.mask	= IPIC_SEMSR,
1571cd8e506SKumar Gala 		.prio	= IPIC_SMPRR_B,
1581cd8e506SKumar Gala 		.force	= IPIC_SEFCR,
1591cd8e506SKumar Gala 		.bit	= 6,
1601cd8e506SKumar Gala 		.prio_mask = 6,
1611cd8e506SKumar Gala 	},
1621cd8e506SKumar Gala 	[23] = {
163*77d4309eSLi Yang 		.ack	= IPIC_SEPNR,
1641cd8e506SKumar Gala 		.mask	= IPIC_SEMSR,
1651cd8e506SKumar Gala 		.prio	= IPIC_SMPRR_B,
1661cd8e506SKumar Gala 		.force	= IPIC_SEFCR,
1671cd8e506SKumar Gala 		.bit	= 7,
1681cd8e506SKumar Gala 		.prio_mask = 7,
1691cd8e506SKumar Gala 	},
1701cd8e506SKumar Gala 	[32] = {
1711cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_H,
1721cd8e506SKumar Gala 		.prio	= IPIC_SIPRR_A,
1731cd8e506SKumar Gala 		.force	= IPIC_SIFCR_H,
1741cd8e506SKumar Gala 		.bit	= 0,
1751cd8e506SKumar Gala 		.prio_mask = 0,
1761cd8e506SKumar Gala 	},
1771cd8e506SKumar Gala 	[33] = {
1781cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_H,
1791cd8e506SKumar Gala 		.prio	= IPIC_SIPRR_A,
1801cd8e506SKumar Gala 		.force	= IPIC_SIFCR_H,
1811cd8e506SKumar Gala 		.bit	= 1,
1821cd8e506SKumar Gala 		.prio_mask = 1,
1831cd8e506SKumar Gala 	},
1841cd8e506SKumar Gala 	[34] = {
1851cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_H,
1861cd8e506SKumar Gala 		.prio	= IPIC_SIPRR_A,
1871cd8e506SKumar Gala 		.force	= IPIC_SIFCR_H,
1881cd8e506SKumar Gala 		.bit	= 2,
1891cd8e506SKumar Gala 		.prio_mask = 2,
1901cd8e506SKumar Gala 	},
1911cd8e506SKumar Gala 	[35] = {
1921cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_H,
1931cd8e506SKumar Gala 		.prio	= IPIC_SIPRR_A,
1941cd8e506SKumar Gala 		.force	= IPIC_SIFCR_H,
1951cd8e506SKumar Gala 		.bit	= 3,
1961cd8e506SKumar Gala 		.prio_mask = 3,
1971cd8e506SKumar Gala 	},
1981cd8e506SKumar Gala 	[36] = {
1991cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_H,
2001cd8e506SKumar Gala 		.prio	= IPIC_SIPRR_A,
2011cd8e506SKumar Gala 		.force	= IPIC_SIFCR_H,
2021cd8e506SKumar Gala 		.bit	= 4,
2031cd8e506SKumar Gala 		.prio_mask = 4,
2041cd8e506SKumar Gala 	},
2051cd8e506SKumar Gala 	[37] = {
2061cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_H,
2071cd8e506SKumar Gala 		.prio	= IPIC_SIPRR_A,
2081cd8e506SKumar Gala 		.force	= IPIC_SIFCR_H,
2091cd8e506SKumar Gala 		.bit	= 5,
2101cd8e506SKumar Gala 		.prio_mask = 5,
2111cd8e506SKumar Gala 	},
2121cd8e506SKumar Gala 	[38] = {
2131cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_H,
2141cd8e506SKumar Gala 		.prio	= IPIC_SIPRR_A,
2151cd8e506SKumar Gala 		.force	= IPIC_SIFCR_H,
2161cd8e506SKumar Gala 		.bit	= 6,
2171cd8e506SKumar Gala 		.prio_mask = 6,
2181cd8e506SKumar Gala 	},
2191cd8e506SKumar Gala 	[39] = {
2201cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_H,
2211cd8e506SKumar Gala 		.prio	= IPIC_SIPRR_A,
2221cd8e506SKumar Gala 		.force	= IPIC_SIFCR_H,
2231cd8e506SKumar Gala 		.bit	= 7,
2241cd8e506SKumar Gala 		.prio_mask = 7,
2251cd8e506SKumar Gala 	},
226f03ca957SLi Yang 	[42] = {
227f03ca957SLi Yang 		.mask	= IPIC_SIMSR_H,
228f03ca957SLi Yang 		.prio	= IPIC_SIPRR_B,
229f03ca957SLi Yang 		.force	= IPIC_SIFCR_H,
230f03ca957SLi Yang 		.bit	= 10,
231f03ca957SLi Yang 		.prio_mask = 2,
232f03ca957SLi Yang 	},
233f03ca957SLi Yang 	[44] = {
234f03ca957SLi Yang 		.mask	= IPIC_SIMSR_H,
235f03ca957SLi Yang 		.prio	= IPIC_SIPRR_B,
236f03ca957SLi Yang 		.force	= IPIC_SIFCR_H,
237f03ca957SLi Yang 		.bit	= 12,
238f03ca957SLi Yang 		.prio_mask = 4,
239f03ca957SLi Yang 	},
240f03ca957SLi Yang 	[45] = {
241f03ca957SLi Yang 		.mask	= IPIC_SIMSR_H,
242f03ca957SLi Yang 		.prio	= IPIC_SIPRR_B,
243f03ca957SLi Yang 		.force	= IPIC_SIFCR_H,
244f03ca957SLi Yang 		.bit	= 13,
245f03ca957SLi Yang 		.prio_mask = 5,
246f03ca957SLi Yang 	},
247f03ca957SLi Yang 	[46] = {
248f03ca957SLi Yang 		.mask	= IPIC_SIMSR_H,
249f03ca957SLi Yang 		.prio	= IPIC_SIPRR_B,
250f03ca957SLi Yang 		.force	= IPIC_SIFCR_H,
251f03ca957SLi Yang 		.bit	= 14,
252f03ca957SLi Yang 		.prio_mask = 6,
253f03ca957SLi Yang 	},
254f03ca957SLi Yang 	[47] = {
255f03ca957SLi Yang 		.mask	= IPIC_SIMSR_H,
256f03ca957SLi Yang 		.prio	= IPIC_SIPRR_B,
257f03ca957SLi Yang 		.force	= IPIC_SIFCR_H,
258f03ca957SLi Yang 		.bit	= 15,
259f03ca957SLi Yang 		.prio_mask = 7,
260f03ca957SLi Yang 	},
2611cd8e506SKumar Gala 	[48] = {
2621cd8e506SKumar Gala 		.mask	= IPIC_SEMSR,
2631cd8e506SKumar Gala 		.prio	= IPIC_SMPRR_A,
2641cd8e506SKumar Gala 		.force	= IPIC_SEFCR,
2651cd8e506SKumar Gala 		.bit	= 0,
2661cd8e506SKumar Gala 		.prio_mask = 4,
2671cd8e506SKumar Gala 	},
2681cd8e506SKumar Gala 	[64] = {
2691cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
2701cd8e506SKumar Gala 		.prio	= IPIC_SMPRR_A,
2711cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
2721cd8e506SKumar Gala 		.bit	= 0,
2731cd8e506SKumar Gala 		.prio_mask = 0,
2741cd8e506SKumar Gala 	},
2751cd8e506SKumar Gala 	[65] = {
2761cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
2771cd8e506SKumar Gala 		.prio	= IPIC_SMPRR_A,
2781cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
2791cd8e506SKumar Gala 		.bit	= 1,
2801cd8e506SKumar Gala 		.prio_mask = 1,
2811cd8e506SKumar Gala 	},
2821cd8e506SKumar Gala 	[66] = {
2831cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
2841cd8e506SKumar Gala 		.prio	= IPIC_SMPRR_A,
2851cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
2861cd8e506SKumar Gala 		.bit	= 2,
2871cd8e506SKumar Gala 		.prio_mask = 2,
2881cd8e506SKumar Gala 	},
2891cd8e506SKumar Gala 	[67] = {
2901cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
2911cd8e506SKumar Gala 		.prio	= IPIC_SMPRR_A,
2921cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
2931cd8e506SKumar Gala 		.bit	= 3,
2941cd8e506SKumar Gala 		.prio_mask = 3,
2951cd8e506SKumar Gala 	},
2961cd8e506SKumar Gala 	[68] = {
2971cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
2981cd8e506SKumar Gala 		.prio	= IPIC_SMPRR_B,
2991cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
3001cd8e506SKumar Gala 		.bit	= 4,
3011cd8e506SKumar Gala 		.prio_mask = 0,
3021cd8e506SKumar Gala 	},
3031cd8e506SKumar Gala 	[69] = {
3041cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
3051cd8e506SKumar Gala 		.prio	= IPIC_SMPRR_B,
3061cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
3071cd8e506SKumar Gala 		.bit	= 5,
3081cd8e506SKumar Gala 		.prio_mask = 1,
3091cd8e506SKumar Gala 	},
3101cd8e506SKumar Gala 	[70] = {
3111cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
3121cd8e506SKumar Gala 		.prio	= IPIC_SMPRR_B,
3131cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
3141cd8e506SKumar Gala 		.bit	= 6,
3151cd8e506SKumar Gala 		.prio_mask = 2,
3161cd8e506SKumar Gala 	},
3171cd8e506SKumar Gala 	[71] = {
3181cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
3191cd8e506SKumar Gala 		.prio	= IPIC_SMPRR_B,
3201cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
3211cd8e506SKumar Gala 		.bit	= 7,
3221cd8e506SKumar Gala 		.prio_mask = 3,
3231cd8e506SKumar Gala 	},
3241cd8e506SKumar Gala 	[72] = {
3251cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
3261cd8e506SKumar Gala 		.prio	= 0,
3271cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
3281cd8e506SKumar Gala 		.bit	= 8,
3291cd8e506SKumar Gala 	},
3301cd8e506SKumar Gala 	[73] = {
3311cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
3321cd8e506SKumar Gala 		.prio	= 0,
3331cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
3341cd8e506SKumar Gala 		.bit	= 9,
3351cd8e506SKumar Gala 	},
3361cd8e506SKumar Gala 	[74] = {
3371cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
3381cd8e506SKumar Gala 		.prio	= 0,
3391cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
3401cd8e506SKumar Gala 		.bit	= 10,
3411cd8e506SKumar Gala 	},
3421cd8e506SKumar Gala 	[75] = {
3431cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
3441cd8e506SKumar Gala 		.prio	= 0,
3451cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
3461cd8e506SKumar Gala 		.bit	= 11,
3471cd8e506SKumar Gala 	},
3481cd8e506SKumar Gala 	[76] = {
3491cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
3501cd8e506SKumar Gala 		.prio	= 0,
3511cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
3521cd8e506SKumar Gala 		.bit	= 12,
3531cd8e506SKumar Gala 	},
3541cd8e506SKumar Gala 	[77] = {
3551cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
3561cd8e506SKumar Gala 		.prio	= 0,
3571cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
3581cd8e506SKumar Gala 		.bit	= 13,
3591cd8e506SKumar Gala 	},
3601cd8e506SKumar Gala 	[78] = {
3611cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
3621cd8e506SKumar Gala 		.prio	= 0,
3631cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
3641cd8e506SKumar Gala 		.bit	= 14,
3651cd8e506SKumar Gala 	},
3661cd8e506SKumar Gala 	[79] = {
3671cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
3681cd8e506SKumar Gala 		.prio	= 0,
3691cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
3701cd8e506SKumar Gala 		.bit	= 15,
3711cd8e506SKumar Gala 	},
3721cd8e506SKumar Gala 	[80] = {
3731cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
3741cd8e506SKumar Gala 		.prio	= 0,
3751cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
3761cd8e506SKumar Gala 		.bit	= 16,
3771cd8e506SKumar Gala 	},
378f03ca957SLi Yang 	[81] = {
379f03ca957SLi Yang 		.mask	= IPIC_SIMSR_L,
380f03ca957SLi Yang 		.prio	= 0,
381f03ca957SLi Yang 		.force	= IPIC_SIFCR_L,
382f03ca957SLi Yang 		.bit	= 17,
383f03ca957SLi Yang 	},
384f03ca957SLi Yang 	[82] = {
385f03ca957SLi Yang 		.mask	= IPIC_SIMSR_L,
386f03ca957SLi Yang 		.prio	= 0,
387f03ca957SLi Yang 		.force	= IPIC_SIFCR_L,
388f03ca957SLi Yang 		.bit	= 18,
389f03ca957SLi Yang 	},
3901cd8e506SKumar Gala 	[84] = {
3911cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
3921cd8e506SKumar Gala 		.prio	= 0,
3931cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
3941cd8e506SKumar Gala 		.bit	= 20,
3951cd8e506SKumar Gala 	},
3961cd8e506SKumar Gala 	[85] = {
3971cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
3981cd8e506SKumar Gala 		.prio	= 0,
3991cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
4001cd8e506SKumar Gala 		.bit	= 21,
4011cd8e506SKumar Gala 	},
402f03ca957SLi Yang 	[86] = {
403f03ca957SLi Yang 		.mask	= IPIC_SIMSR_L,
404f03ca957SLi Yang 		.prio	= 0,
405f03ca957SLi Yang 		.force	= IPIC_SIFCR_L,
406f03ca957SLi Yang 		.bit	= 22,
407f03ca957SLi Yang 	},
408f03ca957SLi Yang 	[87] = {
409f03ca957SLi Yang 		.mask	= IPIC_SIMSR_L,
410f03ca957SLi Yang 		.prio	= 0,
411f03ca957SLi Yang 		.force	= IPIC_SIFCR_L,
412f03ca957SLi Yang 		.bit	= 23,
413f03ca957SLi Yang 	},
414f03ca957SLi Yang 	[88] = {
415f03ca957SLi Yang 		.mask	= IPIC_SIMSR_L,
416f03ca957SLi Yang 		.prio	= 0,
417f03ca957SLi Yang 		.force	= IPIC_SIFCR_L,
418f03ca957SLi Yang 		.bit	= 24,
419f03ca957SLi Yang 	},
420f03ca957SLi Yang 	[89] = {
421f03ca957SLi Yang 		.mask	= IPIC_SIMSR_L,
422f03ca957SLi Yang 		.prio	= 0,
423f03ca957SLi Yang 		.force	= IPIC_SIFCR_L,
424f03ca957SLi Yang 		.bit	= 25,
425f03ca957SLi Yang 	},
4261cd8e506SKumar Gala 	[90] = {
4271cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
4281cd8e506SKumar Gala 		.prio	= 0,
4291cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
4301cd8e506SKumar Gala 		.bit	= 26,
4311cd8e506SKumar Gala 	},
4321cd8e506SKumar Gala 	[91] = {
4331cd8e506SKumar Gala 		.mask	= IPIC_SIMSR_L,
4341cd8e506SKumar Gala 		.prio	= 0,
4351cd8e506SKumar Gala 		.force	= IPIC_SIFCR_L,
4361cd8e506SKumar Gala 		.bit	= 27,
4371cd8e506SKumar Gala 	},
4381cd8e506SKumar Gala };
4391cd8e506SKumar Gala 
4401cd8e506SKumar Gala static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
4411cd8e506SKumar Gala {
4421cd8e506SKumar Gala 	return in_be32(base + (reg >> 2));
4431cd8e506SKumar Gala }
4441cd8e506SKumar Gala 
4451cd8e506SKumar Gala static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
4461cd8e506SKumar Gala {
4471cd8e506SKumar Gala 	out_be32(base + (reg >> 2), value);
4481cd8e506SKumar Gala }
4491cd8e506SKumar Gala 
450b9f0f1bbSKim Phillips static inline struct ipic * ipic_from_irq(unsigned int virq)
4511cd8e506SKumar Gala {
4521cd8e506SKumar Gala 	return primary_ipic;
4531cd8e506SKumar Gala }
4541cd8e506SKumar Gala 
455b9f0f1bbSKim Phillips #define ipic_irq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)
456b9f0f1bbSKim Phillips 
457b9f0f1bbSKim Phillips static void ipic_unmask_irq(unsigned int virq)
4581cd8e506SKumar Gala {
459b9f0f1bbSKim Phillips 	struct ipic *ipic = ipic_from_irq(virq);
460b9f0f1bbSKim Phillips 	unsigned int src = ipic_irq_to_hw(virq);
461b9f0f1bbSKim Phillips 	unsigned long flags;
4621cd8e506SKumar Gala 	u32 temp;
4631cd8e506SKumar Gala 
464b9f0f1bbSKim Phillips 	spin_lock_irqsave(&ipic_lock, flags);
465b9f0f1bbSKim Phillips 
4661cd8e506SKumar Gala 	temp = ipic_read(ipic->regs, ipic_info[src].mask);
4671cd8e506SKumar Gala 	temp |= (1 << (31 - ipic_info[src].bit));
4681cd8e506SKumar Gala 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
469b9f0f1bbSKim Phillips 
470b9f0f1bbSKim Phillips 	spin_unlock_irqrestore(&ipic_lock, flags);
4711cd8e506SKumar Gala }
4721cd8e506SKumar Gala 
473b9f0f1bbSKim Phillips static void ipic_mask_irq(unsigned int virq)
4741cd8e506SKumar Gala {
475b9f0f1bbSKim Phillips 	struct ipic *ipic = ipic_from_irq(virq);
476b9f0f1bbSKim Phillips 	unsigned int src = ipic_irq_to_hw(virq);
477b9f0f1bbSKim Phillips 	unsigned long flags;
4781cd8e506SKumar Gala 	u32 temp;
4791cd8e506SKumar Gala 
480b9f0f1bbSKim Phillips 	spin_lock_irqsave(&ipic_lock, flags);
481b9f0f1bbSKim Phillips 
4821cd8e506SKumar Gala 	temp = ipic_read(ipic->regs, ipic_info[src].mask);
4831cd8e506SKumar Gala 	temp &= ~(1 << (31 - ipic_info[src].bit));
4841cd8e506SKumar Gala 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
485b9f0f1bbSKim Phillips 
486*77d4309eSLi Yang 	/* mb() can't guarantee that masking is finished.  But it does finish
487*77d4309eSLi Yang 	 * for nearly all cases. */
488*77d4309eSLi Yang 	mb();
489*77d4309eSLi Yang 
490b9f0f1bbSKim Phillips 	spin_unlock_irqrestore(&ipic_lock, flags);
4911cd8e506SKumar Gala }
4921cd8e506SKumar Gala 
493b9f0f1bbSKim Phillips static void ipic_ack_irq(unsigned int virq)
4941cd8e506SKumar Gala {
495b9f0f1bbSKim Phillips 	struct ipic *ipic = ipic_from_irq(virq);
496b9f0f1bbSKim Phillips 	unsigned int src = ipic_irq_to_hw(virq);
497b9f0f1bbSKim Phillips 	unsigned long flags;
4981cd8e506SKumar Gala 	u32 temp;
4991cd8e506SKumar Gala 
500b9f0f1bbSKim Phillips 	spin_lock_irqsave(&ipic_lock, flags);
5011cd8e506SKumar Gala 
502*77d4309eSLi Yang 	temp = ipic_read(ipic->regs, ipic_info[src].ack);
5031cd8e506SKumar Gala 	temp |= (1 << (31 - ipic_info[src].bit));
504*77d4309eSLi Yang 	ipic_write(ipic->regs, ipic_info[src].ack, temp);
505*77d4309eSLi Yang 
506*77d4309eSLi Yang 	/* mb() can't guarantee that ack is finished.  But it does finish
507*77d4309eSLi Yang 	 * for nearly all cases. */
508*77d4309eSLi Yang 	mb();
509b9f0f1bbSKim Phillips 
510b9f0f1bbSKim Phillips 	spin_unlock_irqrestore(&ipic_lock, flags);
5111cd8e506SKumar Gala }
5121cd8e506SKumar Gala 
513b9f0f1bbSKim Phillips static void ipic_mask_irq_and_ack(unsigned int virq)
5141cd8e506SKumar Gala {
515b9f0f1bbSKim Phillips 	struct ipic *ipic = ipic_from_irq(virq);
516b9f0f1bbSKim Phillips 	unsigned int src = ipic_irq_to_hw(virq);
517b9f0f1bbSKim Phillips 	unsigned long flags;
518b9f0f1bbSKim Phillips 	u32 temp;
519b9f0f1bbSKim Phillips 
520b9f0f1bbSKim Phillips 	spin_lock_irqsave(&ipic_lock, flags);
521b9f0f1bbSKim Phillips 
522b9f0f1bbSKim Phillips 	temp = ipic_read(ipic->regs, ipic_info[src].mask);
523b9f0f1bbSKim Phillips 	temp &= ~(1 << (31 - ipic_info[src].bit));
524b9f0f1bbSKim Phillips 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
525b9f0f1bbSKim Phillips 
526*77d4309eSLi Yang 	temp = ipic_read(ipic->regs, ipic_info[src].ack);
527b9f0f1bbSKim Phillips 	temp |= (1 << (31 - ipic_info[src].bit));
528*77d4309eSLi Yang 	ipic_write(ipic->regs, ipic_info[src].ack, temp);
529*77d4309eSLi Yang 
530*77d4309eSLi Yang 	/* mb() can't guarantee that ack is finished.  But it does finish
531*77d4309eSLi Yang 	 * for nearly all cases. */
532*77d4309eSLi Yang 	mb();
533b9f0f1bbSKim Phillips 
534b9f0f1bbSKim Phillips 	spin_unlock_irqrestore(&ipic_lock, flags);
5351cd8e506SKumar Gala }
5361cd8e506SKumar Gala 
537b9f0f1bbSKim Phillips static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
538b9f0f1bbSKim Phillips {
539b9f0f1bbSKim Phillips 	struct ipic *ipic = ipic_from_irq(virq);
540b9f0f1bbSKim Phillips 	unsigned int src = ipic_irq_to_hw(virq);
541b9f0f1bbSKim Phillips 	struct irq_desc *desc = get_irq_desc(virq);
542b9f0f1bbSKim Phillips 	unsigned int vold, vnew, edibit;
543b9f0f1bbSKim Phillips 
544b9f0f1bbSKim Phillips 	if (flow_type == IRQ_TYPE_NONE)
545b9f0f1bbSKim Phillips 		flow_type = IRQ_TYPE_LEVEL_LOW;
546b9f0f1bbSKim Phillips 
547b9f0f1bbSKim Phillips 	/* ipic supports only low assertion and high-to-low change senses
548b9f0f1bbSKim Phillips 	 */
549b9f0f1bbSKim Phillips 	if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) {
550b9f0f1bbSKim Phillips 		printk(KERN_ERR "ipic: sense type 0x%x not supported\n",
551b9f0f1bbSKim Phillips 			flow_type);
552b9f0f1bbSKim Phillips 		return -EINVAL;
553b9f0f1bbSKim Phillips 	}
554*77d4309eSLi Yang 	/* ipic supports only edge mode on external interrupts */
555*77d4309eSLi Yang 	if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !ipic_info[src].ack) {
556*77d4309eSLi Yang 		printk(KERN_ERR "ipic: edge sense not supported on internal "
557*77d4309eSLi Yang 				"interrupts\n");
558*77d4309eSLi Yang 		return -EINVAL;
559*77d4309eSLi Yang 	}
560b9f0f1bbSKim Phillips 
561b9f0f1bbSKim Phillips 	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
562b9f0f1bbSKim Phillips 	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
563b9f0f1bbSKim Phillips 	if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
564b9f0f1bbSKim Phillips 		desc->status |= IRQ_LEVEL;
565f49196a5SScott Wood 		desc->handle_irq = handle_level_irq;
566*77d4309eSLi Yang 		desc->chip = &ipic_level_irq_chip;
567b9f0f1bbSKim Phillips 	} else {
568f49196a5SScott Wood 		desc->handle_irq = handle_edge_irq;
569*77d4309eSLi Yang 		desc->chip = &ipic_edge_irq_chip;
570b9f0f1bbSKim Phillips 	}
571b9f0f1bbSKim Phillips 
572b9f0f1bbSKim Phillips 	/* only EXT IRQ senses are programmable on ipic
573b9f0f1bbSKim Phillips 	 * internal IRQ senses are LEVEL_LOW
574b9f0f1bbSKim Phillips 	 */
575b9f0f1bbSKim Phillips 	if (src == IPIC_IRQ_EXT0)
576b9f0f1bbSKim Phillips 		edibit = 15;
577b9f0f1bbSKim Phillips 	else
578b9f0f1bbSKim Phillips 		if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7)
579b9f0f1bbSKim Phillips 			edibit = (14 - (src - IPIC_IRQ_EXT1));
580b9f0f1bbSKim Phillips 		else
581b9f0f1bbSKim Phillips 			return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;
582b9f0f1bbSKim Phillips 
583b9f0f1bbSKim Phillips 	vold = ipic_read(ipic->regs, IPIC_SECNR);
584b9f0f1bbSKim Phillips 	if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) {
585b9f0f1bbSKim Phillips 		vnew = vold | (1 << edibit);
586b9f0f1bbSKim Phillips 	} else {
587b9f0f1bbSKim Phillips 		vnew = vold & ~(1 << edibit);
588b9f0f1bbSKim Phillips 	}
589b9f0f1bbSKim Phillips 	if (vold != vnew)
590b9f0f1bbSKim Phillips 		ipic_write(ipic->regs, IPIC_SECNR, vnew);
591b9f0f1bbSKim Phillips 	return 0;
592b9f0f1bbSKim Phillips }
593b9f0f1bbSKim Phillips 
594*77d4309eSLi Yang /* level interrupts and edge interrupts have different ack operations */
595*77d4309eSLi Yang static struct irq_chip ipic_level_irq_chip = {
596*77d4309eSLi Yang 	.typename	= " IPIC  ",
597*77d4309eSLi Yang 	.unmask		= ipic_unmask_irq,
598*77d4309eSLi Yang 	.mask		= ipic_mask_irq,
599*77d4309eSLi Yang 	.mask_ack	= ipic_mask_irq,
600*77d4309eSLi Yang 	.set_type	= ipic_set_irq_type,
601*77d4309eSLi Yang };
602*77d4309eSLi Yang 
603*77d4309eSLi Yang static struct irq_chip ipic_edge_irq_chip = {
6041cd8e506SKumar Gala 	.typename	= " IPIC  ",
605b9f0f1bbSKim Phillips 	.unmask		= ipic_unmask_irq,
606b9f0f1bbSKim Phillips 	.mask		= ipic_mask_irq,
607b9f0f1bbSKim Phillips 	.mask_ack	= ipic_mask_irq_and_ack,
608b9f0f1bbSKim Phillips 	.ack		= ipic_ack_irq,
609b9f0f1bbSKim Phillips 	.set_type	= ipic_set_irq_type,
6101cd8e506SKumar Gala };
6111cd8e506SKumar Gala 
612b9f0f1bbSKim Phillips static int ipic_host_match(struct irq_host *h, struct device_node *node)
6131cd8e506SKumar Gala {
614b9f0f1bbSKim Phillips 	/* Exact match, unless ipic node is NULL */
61552964f87SMichael Ellerman 	return h->of_node == NULL || h->of_node == node;
616b9f0f1bbSKim Phillips }
6171cd8e506SKumar Gala 
618b9f0f1bbSKim Phillips static int ipic_host_map(struct irq_host *h, unsigned int virq,
619b9f0f1bbSKim Phillips 			 irq_hw_number_t hw)
620b9f0f1bbSKim Phillips {
621b9f0f1bbSKim Phillips 	struct ipic *ipic = h->host_data;
622b9f0f1bbSKim Phillips 
623b9f0f1bbSKim Phillips 	set_irq_chip_data(virq, ipic);
624*77d4309eSLi Yang 	set_irq_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq);
625b9f0f1bbSKim Phillips 
626b9f0f1bbSKim Phillips 	/* Set default irq type */
627b9f0f1bbSKim Phillips 	set_irq_type(virq, IRQ_TYPE_NONE);
628b9f0f1bbSKim Phillips 
629b9f0f1bbSKim Phillips 	return 0;
630b9f0f1bbSKim Phillips }
631b9f0f1bbSKim Phillips 
632b9f0f1bbSKim Phillips static int ipic_host_xlate(struct irq_host *h, struct device_node *ct,
633b9f0f1bbSKim Phillips 			   u32 *intspec, unsigned int intsize,
634b9f0f1bbSKim Phillips 			   irq_hw_number_t *out_hwirq, unsigned int *out_flags)
635b9f0f1bbSKim Phillips 
636b9f0f1bbSKim Phillips {
637b9f0f1bbSKim Phillips 	/* interrupt sense values coming from the device tree equal either
638b9f0f1bbSKim Phillips 	 * LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change)
639b9f0f1bbSKim Phillips 	 */
640b9f0f1bbSKim Phillips 	*out_hwirq = intspec[0];
641b9f0f1bbSKim Phillips 	if (intsize > 1)
642b9f0f1bbSKim Phillips 		*out_flags = intspec[1];
643b9f0f1bbSKim Phillips 	else
644b9f0f1bbSKim Phillips 		*out_flags = IRQ_TYPE_NONE;
645b9f0f1bbSKim Phillips 	return 0;
646b9f0f1bbSKim Phillips }
647b9f0f1bbSKim Phillips 
648b9f0f1bbSKim Phillips static struct irq_host_ops ipic_host_ops = {
649b9f0f1bbSKim Phillips 	.match	= ipic_host_match,
650b9f0f1bbSKim Phillips 	.map	= ipic_host_map,
651b9f0f1bbSKim Phillips 	.xlate	= ipic_host_xlate,
652b9f0f1bbSKim Phillips };
653b9f0f1bbSKim Phillips 
654126186a0SKumar Gala struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
655b9f0f1bbSKim Phillips {
656b9f0f1bbSKim Phillips 	struct ipic	*ipic;
657b9f0f1bbSKim Phillips 	struct resource res;
658b9f0f1bbSKim Phillips 	u32 temp = 0, ret;
659b9f0f1bbSKim Phillips 
660b9f0f1bbSKim Phillips 	ipic = alloc_bootmem(sizeof(struct ipic));
661b9f0f1bbSKim Phillips 	if (ipic == NULL)
662126186a0SKumar Gala 		return NULL;
663b9f0f1bbSKim Phillips 
664b9f0f1bbSKim Phillips 	memset(ipic, 0, sizeof(struct ipic));
665b9f0f1bbSKim Phillips 
66652964f87SMichael Ellerman 	ipic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
667b9f0f1bbSKim Phillips 				       NR_IPIC_INTS,
668b9f0f1bbSKim Phillips 				       &ipic_host_ops, 0);
669b9f0f1bbSKim Phillips 	if (ipic->irqhost == NULL) {
670b9f0f1bbSKim Phillips 		of_node_put(node);
671126186a0SKumar Gala 		return NULL;
672b9f0f1bbSKim Phillips 	}
673b9f0f1bbSKim Phillips 
674b9f0f1bbSKim Phillips 	ret = of_address_to_resource(node, 0, &res);
675126186a0SKumar Gala 	if (ret) {
676126186a0SKumar Gala 		of_node_put(node);
677126186a0SKumar Gala 		return NULL;
678126186a0SKumar Gala 	}
679b9f0f1bbSKim Phillips 
680b9f0f1bbSKim Phillips 	ipic->regs = ioremap(res.start, res.end - res.start + 1);
681b9f0f1bbSKim Phillips 
682b9f0f1bbSKim Phillips 	ipic->irqhost->host_data = ipic;
683b9f0f1bbSKim Phillips 
684b9f0f1bbSKim Phillips 	/* init hw */
685b9f0f1bbSKim Phillips 	ipic_write(ipic->regs, IPIC_SICNR, 0x0);
6861cd8e506SKumar Gala 
6871cd8e506SKumar Gala 	/* default priority scheme is grouped. If spread mode is required
6881cd8e506SKumar Gala 	 * configure SICFR accordingly */
6891cd8e506SKumar Gala 	if (flags & IPIC_SPREADMODE_GRP_A)
6901cd8e506SKumar Gala 		temp |= SICFR_IPSA;
691f03ca957SLi Yang 	if (flags & IPIC_SPREADMODE_GRP_B)
692f03ca957SLi Yang 		temp |= SICFR_IPSB;
693f03ca957SLi Yang 	if (flags & IPIC_SPREADMODE_GRP_C)
694f03ca957SLi Yang 		temp |= SICFR_IPSC;
6951cd8e506SKumar Gala 	if (flags & IPIC_SPREADMODE_GRP_D)
6961cd8e506SKumar Gala 		temp |= SICFR_IPSD;
6971cd8e506SKumar Gala 	if (flags & IPIC_SPREADMODE_MIX_A)
6981cd8e506SKumar Gala 		temp |= SICFR_MPSA;
6991cd8e506SKumar Gala 	if (flags & IPIC_SPREADMODE_MIX_B)
7001cd8e506SKumar Gala 		temp |= SICFR_MPSB;
7011cd8e506SKumar Gala 
702f03ca957SLi Yang 	ipic_write(ipic->regs, IPIC_SICFR, temp);
7031cd8e506SKumar Gala 
7041cd8e506SKumar Gala 	/* handle MCP route */
7051cd8e506SKumar Gala 	temp = 0;
7061cd8e506SKumar Gala 	if (flags & IPIC_DISABLE_MCP_OUT)
7071cd8e506SKumar Gala 		temp = SERCR_MCPR;
708b9f0f1bbSKim Phillips 	ipic_write(ipic->regs, IPIC_SERCR, temp);
7091cd8e506SKumar Gala 
7101cd8e506SKumar Gala 	/* handle routing of IRQ0 to MCP */
711b9f0f1bbSKim Phillips 	temp = ipic_read(ipic->regs, IPIC_SEMSR);
7121cd8e506SKumar Gala 
7131cd8e506SKumar Gala 	if (flags & IPIC_IRQ0_MCP)
7141cd8e506SKumar Gala 		temp |= SEMSR_SIRQ0;
7151cd8e506SKumar Gala 	else
7161cd8e506SKumar Gala 		temp &= ~SEMSR_SIRQ0;
7171cd8e506SKumar Gala 
718b9f0f1bbSKim Phillips 	ipic_write(ipic->regs, IPIC_SEMSR, temp);
7191cd8e506SKumar Gala 
720b9f0f1bbSKim Phillips 	primary_ipic = ipic;
721b9f0f1bbSKim Phillips 	irq_set_default_host(primary_ipic->irqhost);
722b9f0f1bbSKim Phillips 
723b9f0f1bbSKim Phillips 	printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS,
724b9f0f1bbSKim Phillips 			primary_ipic->regs);
725126186a0SKumar Gala 
726126186a0SKumar Gala 	return ipic;
7271cd8e506SKumar Gala }
7281cd8e506SKumar Gala 
729b9f0f1bbSKim Phillips int ipic_set_priority(unsigned int virq, unsigned int priority)
7301cd8e506SKumar Gala {
731b9f0f1bbSKim Phillips 	struct ipic *ipic = ipic_from_irq(virq);
732b9f0f1bbSKim Phillips 	unsigned int src = ipic_irq_to_hw(virq);
7331cd8e506SKumar Gala 	u32 temp;
7341cd8e506SKumar Gala 
7351cd8e506SKumar Gala 	if (priority > 7)
7361cd8e506SKumar Gala 		return -EINVAL;
7371cd8e506SKumar Gala 	if (src > 127)
7381cd8e506SKumar Gala 		return -EINVAL;
7391cd8e506SKumar Gala 	if (ipic_info[src].prio == 0)
7401cd8e506SKumar Gala 		return -EINVAL;
7411cd8e506SKumar Gala 
7421cd8e506SKumar Gala 	temp = ipic_read(ipic->regs, ipic_info[src].prio);
7431cd8e506SKumar Gala 
7441cd8e506SKumar Gala 	if (priority < 4) {
7451cd8e506SKumar Gala 		temp &= ~(0x7 << (20 + (3 - priority) * 3));
7461cd8e506SKumar Gala 		temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
7471cd8e506SKumar Gala 	} else {
7481cd8e506SKumar Gala 		temp &= ~(0x7 << (4 + (7 - priority) * 3));
7491cd8e506SKumar Gala 		temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
7501cd8e506SKumar Gala 	}
7511cd8e506SKumar Gala 
7521cd8e506SKumar Gala 	ipic_write(ipic->regs, ipic_info[src].prio, temp);
7531cd8e506SKumar Gala 
7541cd8e506SKumar Gala 	return 0;
7551cd8e506SKumar Gala }
7561cd8e506SKumar Gala 
757b9f0f1bbSKim Phillips void ipic_set_highest_priority(unsigned int virq)
7581cd8e506SKumar Gala {
759b9f0f1bbSKim Phillips 	struct ipic *ipic = ipic_from_irq(virq);
760b9f0f1bbSKim Phillips 	unsigned int src = ipic_irq_to_hw(virq);
7611cd8e506SKumar Gala 	u32 temp;
7621cd8e506SKumar Gala 
7631cd8e506SKumar Gala 	temp = ipic_read(ipic->regs, IPIC_SICFR);
7641cd8e506SKumar Gala 
7651cd8e506SKumar Gala 	/* clear and set HPI */
7661cd8e506SKumar Gala 	temp &= 0x7f000000;
7671cd8e506SKumar Gala 	temp |= (src & 0x7f) << 24;
7681cd8e506SKumar Gala 
7691cd8e506SKumar Gala 	ipic_write(ipic->regs, IPIC_SICFR, temp);
7701cd8e506SKumar Gala }
7711cd8e506SKumar Gala 
7721cd8e506SKumar Gala void ipic_set_default_priority(void)
7731cd8e506SKumar Gala {
774f03ca957SLi Yang 	ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_PRIORITY_DEFAULT);
775f03ca957SLi Yang 	ipic_write(primary_ipic->regs, IPIC_SIPRR_B, IPIC_PRIORITY_DEFAULT);
776f03ca957SLi Yang 	ipic_write(primary_ipic->regs, IPIC_SIPRR_C, IPIC_PRIORITY_DEFAULT);
777f03ca957SLi Yang 	ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_PRIORITY_DEFAULT);
778f03ca957SLi Yang 	ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_PRIORITY_DEFAULT);
779f03ca957SLi Yang 	ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_PRIORITY_DEFAULT);
7801cd8e506SKumar Gala }
7811cd8e506SKumar Gala 
7821cd8e506SKumar Gala void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
7831cd8e506SKumar Gala {
7841cd8e506SKumar Gala 	struct ipic *ipic = primary_ipic;
7851cd8e506SKumar Gala 	u32 temp;
7861cd8e506SKumar Gala 
7871cd8e506SKumar Gala 	temp = ipic_read(ipic->regs, IPIC_SERMR);
7881cd8e506SKumar Gala 	temp |= (1 << (31 - mcp_irq));
7891cd8e506SKumar Gala 	ipic_write(ipic->regs, IPIC_SERMR, temp);
7901cd8e506SKumar Gala }
7911cd8e506SKumar Gala 
7921cd8e506SKumar Gala void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
7931cd8e506SKumar Gala {
7941cd8e506SKumar Gala 	struct ipic *ipic = primary_ipic;
7951cd8e506SKumar Gala 	u32 temp;
7961cd8e506SKumar Gala 
7971cd8e506SKumar Gala 	temp = ipic_read(ipic->regs, IPIC_SERMR);
7981cd8e506SKumar Gala 	temp &= (1 << (31 - mcp_irq));
7991cd8e506SKumar Gala 	ipic_write(ipic->regs, IPIC_SERMR, temp);
8001cd8e506SKumar Gala }
8011cd8e506SKumar Gala 
8021cd8e506SKumar Gala u32 ipic_get_mcp_status(void)
8031cd8e506SKumar Gala {
8041cd8e506SKumar Gala 	return ipic_read(primary_ipic->regs, IPIC_SERMR);
8051cd8e506SKumar Gala }
8061cd8e506SKumar Gala 
8071cd8e506SKumar Gala void ipic_clear_mcp_status(u32 mask)
8081cd8e506SKumar Gala {
8091cd8e506SKumar Gala 	ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
8101cd8e506SKumar Gala }
8111cd8e506SKumar Gala 
812b9f0f1bbSKim Phillips /* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
81335a84c2fSOlaf Hering unsigned int ipic_get_irq(void)
8141cd8e506SKumar Gala {
8151cd8e506SKumar Gala 	int irq;
8161cd8e506SKumar Gala 
817b9f0f1bbSKim Phillips 	BUG_ON(primary_ipic == NULL);
818b9f0f1bbSKim Phillips 
819b9f0f1bbSKim Phillips #define IPIC_SIVCR_VECTOR_MASK	0x7f
820b9f0f1bbSKim Phillips 	irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK;
8211cd8e506SKumar Gala 
8221cd8e506SKumar Gala 	if (irq == 0)    /* 0 --> no irq is pending */
823b9f0f1bbSKim Phillips 		return NO_IRQ;
8241cd8e506SKumar Gala 
825b9f0f1bbSKim Phillips 	return irq_linear_revmap(primary_ipic->irqhost, irq);
8261cd8e506SKumar Gala }
8271cd8e506SKumar Gala 
8281cd8e506SKumar Gala static struct sysdev_class ipic_sysclass = {
8291cd8e506SKumar Gala 	set_kset_name("ipic"),
8301cd8e506SKumar Gala };
8311cd8e506SKumar Gala 
8321cd8e506SKumar Gala static struct sys_device device_ipic = {
8331cd8e506SKumar Gala 	.id		= 0,
8341cd8e506SKumar Gala 	.cls		= &ipic_sysclass,
8351cd8e506SKumar Gala };
8361cd8e506SKumar Gala 
8371cd8e506SKumar Gala static int __init init_ipic_sysfs(void)
8381cd8e506SKumar Gala {
8391cd8e506SKumar Gala 	int rc;
8401cd8e506SKumar Gala 
8411cd8e506SKumar Gala 	if (!primary_ipic->regs)
8421cd8e506SKumar Gala 		return -ENODEV;
8431cd8e506SKumar Gala 	printk(KERN_DEBUG "Registering ipic with sysfs...\n");
8441cd8e506SKumar Gala 
8451cd8e506SKumar Gala 	rc = sysdev_class_register(&ipic_sysclass);
8461cd8e506SKumar Gala 	if (rc) {
8471cd8e506SKumar Gala 		printk(KERN_ERR "Failed registering ipic sys class\n");
8481cd8e506SKumar Gala 		return -ENODEV;
8491cd8e506SKumar Gala 	}
8501cd8e506SKumar Gala 	rc = sysdev_register(&device_ipic);
8511cd8e506SKumar Gala 	if (rc) {
8521cd8e506SKumar Gala 		printk(KERN_ERR "Failed registering ipic sys device\n");
8531cd8e506SKumar Gala 		return -ENODEV;
8541cd8e506SKumar Gala 	}
8551cd8e506SKumar Gala 	return 0;
8561cd8e506SKumar Gala }
8571cd8e506SKumar Gala 
8581cd8e506SKumar Gala subsys_initcall(init_ipic_sysfs);
859