1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * arch/powerpc/sysdev/ipic.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * IPIC routines implementations.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright 2005 Freescale Semiconductor, Inc.
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun #include <linux/kernel.h>
10*4882a593Smuzhiyun #include <linux/init.h>
11*4882a593Smuzhiyun #include <linux/errno.h>
12*4882a593Smuzhiyun #include <linux/reboot.h>
13*4882a593Smuzhiyun #include <linux/slab.h>
14*4882a593Smuzhiyun #include <linux/stddef.h>
15*4882a593Smuzhiyun #include <linux/sched.h>
16*4882a593Smuzhiyun #include <linux/signal.h>
17*4882a593Smuzhiyun #include <linux/syscore_ops.h>
18*4882a593Smuzhiyun #include <linux/device.h>
19*4882a593Smuzhiyun #include <linux/spinlock.h>
20*4882a593Smuzhiyun #include <linux/fsl_devices.h>
21*4882a593Smuzhiyun #include <asm/irq.h>
22*4882a593Smuzhiyun #include <asm/io.h>
23*4882a593Smuzhiyun #include <asm/prom.h>
24*4882a593Smuzhiyun #include <asm/ipic.h>
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #include "ipic.h"
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun static struct ipic * primary_ipic;
29*4882a593Smuzhiyun static struct irq_chip ipic_level_irq_chip, ipic_edge_irq_chip;
30*4882a593Smuzhiyun static DEFINE_RAW_SPINLOCK(ipic_lock);
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun static struct ipic_info ipic_info[] = {
33*4882a593Smuzhiyun [1] = {
34*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
35*4882a593Smuzhiyun .prio = IPIC_SIPRR_C,
36*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
37*4882a593Smuzhiyun .bit = 16,
38*4882a593Smuzhiyun .prio_mask = 0,
39*4882a593Smuzhiyun },
40*4882a593Smuzhiyun [2] = {
41*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
42*4882a593Smuzhiyun .prio = IPIC_SIPRR_C,
43*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
44*4882a593Smuzhiyun .bit = 17,
45*4882a593Smuzhiyun .prio_mask = 1,
46*4882a593Smuzhiyun },
47*4882a593Smuzhiyun [3] = {
48*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
49*4882a593Smuzhiyun .prio = IPIC_SIPRR_C,
50*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
51*4882a593Smuzhiyun .bit = 18,
52*4882a593Smuzhiyun .prio_mask = 2,
53*4882a593Smuzhiyun },
54*4882a593Smuzhiyun [4] = {
55*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
56*4882a593Smuzhiyun .prio = IPIC_SIPRR_C,
57*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
58*4882a593Smuzhiyun .bit = 19,
59*4882a593Smuzhiyun .prio_mask = 3,
60*4882a593Smuzhiyun },
61*4882a593Smuzhiyun [5] = {
62*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
63*4882a593Smuzhiyun .prio = IPIC_SIPRR_C,
64*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
65*4882a593Smuzhiyun .bit = 20,
66*4882a593Smuzhiyun .prio_mask = 4,
67*4882a593Smuzhiyun },
68*4882a593Smuzhiyun [6] = {
69*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
70*4882a593Smuzhiyun .prio = IPIC_SIPRR_C,
71*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
72*4882a593Smuzhiyun .bit = 21,
73*4882a593Smuzhiyun .prio_mask = 5,
74*4882a593Smuzhiyun },
75*4882a593Smuzhiyun [7] = {
76*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
77*4882a593Smuzhiyun .prio = IPIC_SIPRR_C,
78*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
79*4882a593Smuzhiyun .bit = 22,
80*4882a593Smuzhiyun .prio_mask = 6,
81*4882a593Smuzhiyun },
82*4882a593Smuzhiyun [8] = {
83*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
84*4882a593Smuzhiyun .prio = IPIC_SIPRR_C,
85*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
86*4882a593Smuzhiyun .bit = 23,
87*4882a593Smuzhiyun .prio_mask = 7,
88*4882a593Smuzhiyun },
89*4882a593Smuzhiyun [9] = {
90*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
91*4882a593Smuzhiyun .prio = IPIC_SIPRR_D,
92*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
93*4882a593Smuzhiyun .bit = 24,
94*4882a593Smuzhiyun .prio_mask = 0,
95*4882a593Smuzhiyun },
96*4882a593Smuzhiyun [10] = {
97*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
98*4882a593Smuzhiyun .prio = IPIC_SIPRR_D,
99*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
100*4882a593Smuzhiyun .bit = 25,
101*4882a593Smuzhiyun .prio_mask = 1,
102*4882a593Smuzhiyun },
103*4882a593Smuzhiyun [11] = {
104*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
105*4882a593Smuzhiyun .prio = IPIC_SIPRR_D,
106*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
107*4882a593Smuzhiyun .bit = 26,
108*4882a593Smuzhiyun .prio_mask = 2,
109*4882a593Smuzhiyun },
110*4882a593Smuzhiyun [12] = {
111*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
112*4882a593Smuzhiyun .prio = IPIC_SIPRR_D,
113*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
114*4882a593Smuzhiyun .bit = 27,
115*4882a593Smuzhiyun .prio_mask = 3,
116*4882a593Smuzhiyun },
117*4882a593Smuzhiyun [13] = {
118*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
119*4882a593Smuzhiyun .prio = IPIC_SIPRR_D,
120*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
121*4882a593Smuzhiyun .bit = 28,
122*4882a593Smuzhiyun .prio_mask = 4,
123*4882a593Smuzhiyun },
124*4882a593Smuzhiyun [14] = {
125*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
126*4882a593Smuzhiyun .prio = IPIC_SIPRR_D,
127*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
128*4882a593Smuzhiyun .bit = 29,
129*4882a593Smuzhiyun .prio_mask = 5,
130*4882a593Smuzhiyun },
131*4882a593Smuzhiyun [15] = {
132*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
133*4882a593Smuzhiyun .prio = IPIC_SIPRR_D,
134*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
135*4882a593Smuzhiyun .bit = 30,
136*4882a593Smuzhiyun .prio_mask = 6,
137*4882a593Smuzhiyun },
138*4882a593Smuzhiyun [16] = {
139*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
140*4882a593Smuzhiyun .prio = IPIC_SIPRR_D,
141*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
142*4882a593Smuzhiyun .bit = 31,
143*4882a593Smuzhiyun .prio_mask = 7,
144*4882a593Smuzhiyun },
145*4882a593Smuzhiyun [17] = {
146*4882a593Smuzhiyun .ack = IPIC_SEPNR,
147*4882a593Smuzhiyun .mask = IPIC_SEMSR,
148*4882a593Smuzhiyun .prio = IPIC_SMPRR_A,
149*4882a593Smuzhiyun .force = IPIC_SEFCR,
150*4882a593Smuzhiyun .bit = 1,
151*4882a593Smuzhiyun .prio_mask = 5,
152*4882a593Smuzhiyun },
153*4882a593Smuzhiyun [18] = {
154*4882a593Smuzhiyun .ack = IPIC_SEPNR,
155*4882a593Smuzhiyun .mask = IPIC_SEMSR,
156*4882a593Smuzhiyun .prio = IPIC_SMPRR_A,
157*4882a593Smuzhiyun .force = IPIC_SEFCR,
158*4882a593Smuzhiyun .bit = 2,
159*4882a593Smuzhiyun .prio_mask = 6,
160*4882a593Smuzhiyun },
161*4882a593Smuzhiyun [19] = {
162*4882a593Smuzhiyun .ack = IPIC_SEPNR,
163*4882a593Smuzhiyun .mask = IPIC_SEMSR,
164*4882a593Smuzhiyun .prio = IPIC_SMPRR_A,
165*4882a593Smuzhiyun .force = IPIC_SEFCR,
166*4882a593Smuzhiyun .bit = 3,
167*4882a593Smuzhiyun .prio_mask = 7,
168*4882a593Smuzhiyun },
169*4882a593Smuzhiyun [20] = {
170*4882a593Smuzhiyun .ack = IPIC_SEPNR,
171*4882a593Smuzhiyun .mask = IPIC_SEMSR,
172*4882a593Smuzhiyun .prio = IPIC_SMPRR_B,
173*4882a593Smuzhiyun .force = IPIC_SEFCR,
174*4882a593Smuzhiyun .bit = 4,
175*4882a593Smuzhiyun .prio_mask = 4,
176*4882a593Smuzhiyun },
177*4882a593Smuzhiyun [21] = {
178*4882a593Smuzhiyun .ack = IPIC_SEPNR,
179*4882a593Smuzhiyun .mask = IPIC_SEMSR,
180*4882a593Smuzhiyun .prio = IPIC_SMPRR_B,
181*4882a593Smuzhiyun .force = IPIC_SEFCR,
182*4882a593Smuzhiyun .bit = 5,
183*4882a593Smuzhiyun .prio_mask = 5,
184*4882a593Smuzhiyun },
185*4882a593Smuzhiyun [22] = {
186*4882a593Smuzhiyun .ack = IPIC_SEPNR,
187*4882a593Smuzhiyun .mask = IPIC_SEMSR,
188*4882a593Smuzhiyun .prio = IPIC_SMPRR_B,
189*4882a593Smuzhiyun .force = IPIC_SEFCR,
190*4882a593Smuzhiyun .bit = 6,
191*4882a593Smuzhiyun .prio_mask = 6,
192*4882a593Smuzhiyun },
193*4882a593Smuzhiyun [23] = {
194*4882a593Smuzhiyun .ack = IPIC_SEPNR,
195*4882a593Smuzhiyun .mask = IPIC_SEMSR,
196*4882a593Smuzhiyun .prio = IPIC_SMPRR_B,
197*4882a593Smuzhiyun .force = IPIC_SEFCR,
198*4882a593Smuzhiyun .bit = 7,
199*4882a593Smuzhiyun .prio_mask = 7,
200*4882a593Smuzhiyun },
201*4882a593Smuzhiyun [32] = {
202*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
203*4882a593Smuzhiyun .prio = IPIC_SIPRR_A,
204*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
205*4882a593Smuzhiyun .bit = 0,
206*4882a593Smuzhiyun .prio_mask = 0,
207*4882a593Smuzhiyun },
208*4882a593Smuzhiyun [33] = {
209*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
210*4882a593Smuzhiyun .prio = IPIC_SIPRR_A,
211*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
212*4882a593Smuzhiyun .bit = 1,
213*4882a593Smuzhiyun .prio_mask = 1,
214*4882a593Smuzhiyun },
215*4882a593Smuzhiyun [34] = {
216*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
217*4882a593Smuzhiyun .prio = IPIC_SIPRR_A,
218*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
219*4882a593Smuzhiyun .bit = 2,
220*4882a593Smuzhiyun .prio_mask = 2,
221*4882a593Smuzhiyun },
222*4882a593Smuzhiyun [35] = {
223*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
224*4882a593Smuzhiyun .prio = IPIC_SIPRR_A,
225*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
226*4882a593Smuzhiyun .bit = 3,
227*4882a593Smuzhiyun .prio_mask = 3,
228*4882a593Smuzhiyun },
229*4882a593Smuzhiyun [36] = {
230*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
231*4882a593Smuzhiyun .prio = IPIC_SIPRR_A,
232*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
233*4882a593Smuzhiyun .bit = 4,
234*4882a593Smuzhiyun .prio_mask = 4,
235*4882a593Smuzhiyun },
236*4882a593Smuzhiyun [37] = {
237*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
238*4882a593Smuzhiyun .prio = IPIC_SIPRR_A,
239*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
240*4882a593Smuzhiyun .bit = 5,
241*4882a593Smuzhiyun .prio_mask = 5,
242*4882a593Smuzhiyun },
243*4882a593Smuzhiyun [38] = {
244*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
245*4882a593Smuzhiyun .prio = IPIC_SIPRR_A,
246*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
247*4882a593Smuzhiyun .bit = 6,
248*4882a593Smuzhiyun .prio_mask = 6,
249*4882a593Smuzhiyun },
250*4882a593Smuzhiyun [39] = {
251*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
252*4882a593Smuzhiyun .prio = IPIC_SIPRR_A,
253*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
254*4882a593Smuzhiyun .bit = 7,
255*4882a593Smuzhiyun .prio_mask = 7,
256*4882a593Smuzhiyun },
257*4882a593Smuzhiyun [40] = {
258*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
259*4882a593Smuzhiyun .prio = IPIC_SIPRR_B,
260*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
261*4882a593Smuzhiyun .bit = 8,
262*4882a593Smuzhiyun .prio_mask = 0,
263*4882a593Smuzhiyun },
264*4882a593Smuzhiyun [41] = {
265*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
266*4882a593Smuzhiyun .prio = IPIC_SIPRR_B,
267*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
268*4882a593Smuzhiyun .bit = 9,
269*4882a593Smuzhiyun .prio_mask = 1,
270*4882a593Smuzhiyun },
271*4882a593Smuzhiyun [42] = {
272*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
273*4882a593Smuzhiyun .prio = IPIC_SIPRR_B,
274*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
275*4882a593Smuzhiyun .bit = 10,
276*4882a593Smuzhiyun .prio_mask = 2,
277*4882a593Smuzhiyun },
278*4882a593Smuzhiyun [43] = {
279*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
280*4882a593Smuzhiyun .prio = IPIC_SIPRR_B,
281*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
282*4882a593Smuzhiyun .bit = 11,
283*4882a593Smuzhiyun .prio_mask = 3,
284*4882a593Smuzhiyun },
285*4882a593Smuzhiyun [44] = {
286*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
287*4882a593Smuzhiyun .prio = IPIC_SIPRR_B,
288*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
289*4882a593Smuzhiyun .bit = 12,
290*4882a593Smuzhiyun .prio_mask = 4,
291*4882a593Smuzhiyun },
292*4882a593Smuzhiyun [45] = {
293*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
294*4882a593Smuzhiyun .prio = IPIC_SIPRR_B,
295*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
296*4882a593Smuzhiyun .bit = 13,
297*4882a593Smuzhiyun .prio_mask = 5,
298*4882a593Smuzhiyun },
299*4882a593Smuzhiyun [46] = {
300*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
301*4882a593Smuzhiyun .prio = IPIC_SIPRR_B,
302*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
303*4882a593Smuzhiyun .bit = 14,
304*4882a593Smuzhiyun .prio_mask = 6,
305*4882a593Smuzhiyun },
306*4882a593Smuzhiyun [47] = {
307*4882a593Smuzhiyun .mask = IPIC_SIMSR_H,
308*4882a593Smuzhiyun .prio = IPIC_SIPRR_B,
309*4882a593Smuzhiyun .force = IPIC_SIFCR_H,
310*4882a593Smuzhiyun .bit = 15,
311*4882a593Smuzhiyun .prio_mask = 7,
312*4882a593Smuzhiyun },
313*4882a593Smuzhiyun [48] = {
314*4882a593Smuzhiyun .ack = IPIC_SEPNR,
315*4882a593Smuzhiyun .mask = IPIC_SEMSR,
316*4882a593Smuzhiyun .prio = IPIC_SMPRR_A,
317*4882a593Smuzhiyun .force = IPIC_SEFCR,
318*4882a593Smuzhiyun .bit = 0,
319*4882a593Smuzhiyun .prio_mask = 4,
320*4882a593Smuzhiyun },
321*4882a593Smuzhiyun [64] = {
322*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
323*4882a593Smuzhiyun .prio = IPIC_SMPRR_A,
324*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
325*4882a593Smuzhiyun .bit = 0,
326*4882a593Smuzhiyun .prio_mask = 0,
327*4882a593Smuzhiyun },
328*4882a593Smuzhiyun [65] = {
329*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
330*4882a593Smuzhiyun .prio = IPIC_SMPRR_A,
331*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
332*4882a593Smuzhiyun .bit = 1,
333*4882a593Smuzhiyun .prio_mask = 1,
334*4882a593Smuzhiyun },
335*4882a593Smuzhiyun [66] = {
336*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
337*4882a593Smuzhiyun .prio = IPIC_SMPRR_A,
338*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
339*4882a593Smuzhiyun .bit = 2,
340*4882a593Smuzhiyun .prio_mask = 2,
341*4882a593Smuzhiyun },
342*4882a593Smuzhiyun [67] = {
343*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
344*4882a593Smuzhiyun .prio = IPIC_SMPRR_A,
345*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
346*4882a593Smuzhiyun .bit = 3,
347*4882a593Smuzhiyun .prio_mask = 3,
348*4882a593Smuzhiyun },
349*4882a593Smuzhiyun [68] = {
350*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
351*4882a593Smuzhiyun .prio = IPIC_SMPRR_B,
352*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
353*4882a593Smuzhiyun .bit = 4,
354*4882a593Smuzhiyun .prio_mask = 0,
355*4882a593Smuzhiyun },
356*4882a593Smuzhiyun [69] = {
357*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
358*4882a593Smuzhiyun .prio = IPIC_SMPRR_B,
359*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
360*4882a593Smuzhiyun .bit = 5,
361*4882a593Smuzhiyun .prio_mask = 1,
362*4882a593Smuzhiyun },
363*4882a593Smuzhiyun [70] = {
364*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
365*4882a593Smuzhiyun .prio = IPIC_SMPRR_B,
366*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
367*4882a593Smuzhiyun .bit = 6,
368*4882a593Smuzhiyun .prio_mask = 2,
369*4882a593Smuzhiyun },
370*4882a593Smuzhiyun [71] = {
371*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
372*4882a593Smuzhiyun .prio = IPIC_SMPRR_B,
373*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
374*4882a593Smuzhiyun .bit = 7,
375*4882a593Smuzhiyun .prio_mask = 3,
376*4882a593Smuzhiyun },
377*4882a593Smuzhiyun [72] = {
378*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
379*4882a593Smuzhiyun .prio = 0,
380*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
381*4882a593Smuzhiyun .bit = 8,
382*4882a593Smuzhiyun },
383*4882a593Smuzhiyun [73] = {
384*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
385*4882a593Smuzhiyun .prio = 0,
386*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
387*4882a593Smuzhiyun .bit = 9,
388*4882a593Smuzhiyun },
389*4882a593Smuzhiyun [74] = {
390*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
391*4882a593Smuzhiyun .prio = 0,
392*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
393*4882a593Smuzhiyun .bit = 10,
394*4882a593Smuzhiyun },
395*4882a593Smuzhiyun [75] = {
396*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
397*4882a593Smuzhiyun .prio = 0,
398*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
399*4882a593Smuzhiyun .bit = 11,
400*4882a593Smuzhiyun },
401*4882a593Smuzhiyun [76] = {
402*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
403*4882a593Smuzhiyun .prio = 0,
404*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
405*4882a593Smuzhiyun .bit = 12,
406*4882a593Smuzhiyun },
407*4882a593Smuzhiyun [77] = {
408*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
409*4882a593Smuzhiyun .prio = 0,
410*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
411*4882a593Smuzhiyun .bit = 13,
412*4882a593Smuzhiyun },
413*4882a593Smuzhiyun [78] = {
414*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
415*4882a593Smuzhiyun .prio = 0,
416*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
417*4882a593Smuzhiyun .bit = 14,
418*4882a593Smuzhiyun },
419*4882a593Smuzhiyun [79] = {
420*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
421*4882a593Smuzhiyun .prio = 0,
422*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
423*4882a593Smuzhiyun .bit = 15,
424*4882a593Smuzhiyun },
425*4882a593Smuzhiyun [80] = {
426*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
427*4882a593Smuzhiyun .prio = 0,
428*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
429*4882a593Smuzhiyun .bit = 16,
430*4882a593Smuzhiyun },
431*4882a593Smuzhiyun [81] = {
432*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
433*4882a593Smuzhiyun .prio = 0,
434*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
435*4882a593Smuzhiyun .bit = 17,
436*4882a593Smuzhiyun },
437*4882a593Smuzhiyun [82] = {
438*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
439*4882a593Smuzhiyun .prio = 0,
440*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
441*4882a593Smuzhiyun .bit = 18,
442*4882a593Smuzhiyun },
443*4882a593Smuzhiyun [83] = {
444*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
445*4882a593Smuzhiyun .prio = 0,
446*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
447*4882a593Smuzhiyun .bit = 19,
448*4882a593Smuzhiyun },
449*4882a593Smuzhiyun [84] = {
450*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
451*4882a593Smuzhiyun .prio = 0,
452*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
453*4882a593Smuzhiyun .bit = 20,
454*4882a593Smuzhiyun },
455*4882a593Smuzhiyun [85] = {
456*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
457*4882a593Smuzhiyun .prio = 0,
458*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
459*4882a593Smuzhiyun .bit = 21,
460*4882a593Smuzhiyun },
461*4882a593Smuzhiyun [86] = {
462*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
463*4882a593Smuzhiyun .prio = 0,
464*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
465*4882a593Smuzhiyun .bit = 22,
466*4882a593Smuzhiyun },
467*4882a593Smuzhiyun [87] = {
468*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
469*4882a593Smuzhiyun .prio = 0,
470*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
471*4882a593Smuzhiyun .bit = 23,
472*4882a593Smuzhiyun },
473*4882a593Smuzhiyun [88] = {
474*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
475*4882a593Smuzhiyun .prio = 0,
476*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
477*4882a593Smuzhiyun .bit = 24,
478*4882a593Smuzhiyun },
479*4882a593Smuzhiyun [89] = {
480*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
481*4882a593Smuzhiyun .prio = 0,
482*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
483*4882a593Smuzhiyun .bit = 25,
484*4882a593Smuzhiyun },
485*4882a593Smuzhiyun [90] = {
486*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
487*4882a593Smuzhiyun .prio = 0,
488*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
489*4882a593Smuzhiyun .bit = 26,
490*4882a593Smuzhiyun },
491*4882a593Smuzhiyun [91] = {
492*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
493*4882a593Smuzhiyun .prio = 0,
494*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
495*4882a593Smuzhiyun .bit = 27,
496*4882a593Smuzhiyun },
497*4882a593Smuzhiyun [94] = {
498*4882a593Smuzhiyun .mask = IPIC_SIMSR_L,
499*4882a593Smuzhiyun .prio = 0,
500*4882a593Smuzhiyun .force = IPIC_SIFCR_L,
501*4882a593Smuzhiyun .bit = 30,
502*4882a593Smuzhiyun },
503*4882a593Smuzhiyun };
504*4882a593Smuzhiyun
ipic_read(volatile u32 __iomem * base,unsigned int reg)505*4882a593Smuzhiyun static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
506*4882a593Smuzhiyun {
507*4882a593Smuzhiyun return in_be32(base + (reg >> 2));
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun
ipic_write(volatile u32 __iomem * base,unsigned int reg,u32 value)510*4882a593Smuzhiyun static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun out_be32(base + (reg >> 2), value);
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
ipic_from_irq(unsigned int virq)515*4882a593Smuzhiyun static inline struct ipic * ipic_from_irq(unsigned int virq)
516*4882a593Smuzhiyun {
517*4882a593Smuzhiyun return primary_ipic;
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun
ipic_unmask_irq(struct irq_data * d)520*4882a593Smuzhiyun static void ipic_unmask_irq(struct irq_data *d)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun struct ipic *ipic = ipic_from_irq(d->irq);
523*4882a593Smuzhiyun unsigned int src = irqd_to_hwirq(d);
524*4882a593Smuzhiyun unsigned long flags;
525*4882a593Smuzhiyun u32 temp;
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun raw_spin_lock_irqsave(&ipic_lock, flags);
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun temp = ipic_read(ipic->regs, ipic_info[src].mask);
530*4882a593Smuzhiyun temp |= (1 << (31 - ipic_info[src].bit));
531*4882a593Smuzhiyun ipic_write(ipic->regs, ipic_info[src].mask, temp);
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&ipic_lock, flags);
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun
ipic_mask_irq(struct irq_data * d)536*4882a593Smuzhiyun static void ipic_mask_irq(struct irq_data *d)
537*4882a593Smuzhiyun {
538*4882a593Smuzhiyun struct ipic *ipic = ipic_from_irq(d->irq);
539*4882a593Smuzhiyun unsigned int src = irqd_to_hwirq(d);
540*4882a593Smuzhiyun unsigned long flags;
541*4882a593Smuzhiyun u32 temp;
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun raw_spin_lock_irqsave(&ipic_lock, flags);
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun temp = ipic_read(ipic->regs, ipic_info[src].mask);
546*4882a593Smuzhiyun temp &= ~(1 << (31 - ipic_info[src].bit));
547*4882a593Smuzhiyun ipic_write(ipic->regs, ipic_info[src].mask, temp);
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun /* mb() can't guarantee that masking is finished. But it does finish
550*4882a593Smuzhiyun * for nearly all cases. */
551*4882a593Smuzhiyun mb();
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&ipic_lock, flags);
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun
ipic_ack_irq(struct irq_data * d)556*4882a593Smuzhiyun static void ipic_ack_irq(struct irq_data *d)
557*4882a593Smuzhiyun {
558*4882a593Smuzhiyun struct ipic *ipic = ipic_from_irq(d->irq);
559*4882a593Smuzhiyun unsigned int src = irqd_to_hwirq(d);
560*4882a593Smuzhiyun unsigned long flags;
561*4882a593Smuzhiyun u32 temp;
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun raw_spin_lock_irqsave(&ipic_lock, flags);
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun temp = 1 << (31 - ipic_info[src].bit);
566*4882a593Smuzhiyun ipic_write(ipic->regs, ipic_info[src].ack, temp);
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun /* mb() can't guarantee that ack is finished. But it does finish
569*4882a593Smuzhiyun * for nearly all cases. */
570*4882a593Smuzhiyun mb();
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&ipic_lock, flags);
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun
ipic_mask_irq_and_ack(struct irq_data * d)575*4882a593Smuzhiyun static void ipic_mask_irq_and_ack(struct irq_data *d)
576*4882a593Smuzhiyun {
577*4882a593Smuzhiyun struct ipic *ipic = ipic_from_irq(d->irq);
578*4882a593Smuzhiyun unsigned int src = irqd_to_hwirq(d);
579*4882a593Smuzhiyun unsigned long flags;
580*4882a593Smuzhiyun u32 temp;
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun raw_spin_lock_irqsave(&ipic_lock, flags);
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun temp = ipic_read(ipic->regs, ipic_info[src].mask);
585*4882a593Smuzhiyun temp &= ~(1 << (31 - ipic_info[src].bit));
586*4882a593Smuzhiyun ipic_write(ipic->regs, ipic_info[src].mask, temp);
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun temp = 1 << (31 - ipic_info[src].bit);
589*4882a593Smuzhiyun ipic_write(ipic->regs, ipic_info[src].ack, temp);
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun /* mb() can't guarantee that ack is finished. But it does finish
592*4882a593Smuzhiyun * for nearly all cases. */
593*4882a593Smuzhiyun mb();
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&ipic_lock, flags);
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun
ipic_set_irq_type(struct irq_data * d,unsigned int flow_type)598*4882a593Smuzhiyun static int ipic_set_irq_type(struct irq_data *d, unsigned int flow_type)
599*4882a593Smuzhiyun {
600*4882a593Smuzhiyun struct ipic *ipic = ipic_from_irq(d->irq);
601*4882a593Smuzhiyun unsigned int src = irqd_to_hwirq(d);
602*4882a593Smuzhiyun unsigned int vold, vnew, edibit;
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun if (flow_type == IRQ_TYPE_NONE)
605*4882a593Smuzhiyun flow_type = IRQ_TYPE_LEVEL_LOW;
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun /* ipic supports only low assertion and high-to-low change senses
608*4882a593Smuzhiyun */
609*4882a593Smuzhiyun if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) {
610*4882a593Smuzhiyun printk(KERN_ERR "ipic: sense type 0x%x not supported\n",
611*4882a593Smuzhiyun flow_type);
612*4882a593Smuzhiyun return -EINVAL;
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun /* ipic supports only edge mode on external interrupts */
615*4882a593Smuzhiyun if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !ipic_info[src].ack) {
616*4882a593Smuzhiyun printk(KERN_ERR "ipic: edge sense not supported on internal "
617*4882a593Smuzhiyun "interrupts\n");
618*4882a593Smuzhiyun return -EINVAL;
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun }
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun irqd_set_trigger_type(d, flow_type);
623*4882a593Smuzhiyun if (flow_type & IRQ_TYPE_LEVEL_LOW) {
624*4882a593Smuzhiyun irq_set_handler_locked(d, handle_level_irq);
625*4882a593Smuzhiyun d->chip = &ipic_level_irq_chip;
626*4882a593Smuzhiyun } else {
627*4882a593Smuzhiyun irq_set_handler_locked(d, handle_edge_irq);
628*4882a593Smuzhiyun d->chip = &ipic_edge_irq_chip;
629*4882a593Smuzhiyun }
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun /* only EXT IRQ senses are programmable on ipic
632*4882a593Smuzhiyun * internal IRQ senses are LEVEL_LOW
633*4882a593Smuzhiyun */
634*4882a593Smuzhiyun if (src == IPIC_IRQ_EXT0)
635*4882a593Smuzhiyun edibit = 15;
636*4882a593Smuzhiyun else
637*4882a593Smuzhiyun if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7)
638*4882a593Smuzhiyun edibit = (14 - (src - IPIC_IRQ_EXT1));
639*4882a593Smuzhiyun else
640*4882a593Smuzhiyun return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun vold = ipic_read(ipic->regs, IPIC_SECNR);
643*4882a593Smuzhiyun if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) {
644*4882a593Smuzhiyun vnew = vold | (1 << edibit);
645*4882a593Smuzhiyun } else {
646*4882a593Smuzhiyun vnew = vold & ~(1 << edibit);
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun if (vold != vnew)
649*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SECNR, vnew);
650*4882a593Smuzhiyun return IRQ_SET_MASK_OK_NOCOPY;
651*4882a593Smuzhiyun }
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun /* level interrupts and edge interrupts have different ack operations */
654*4882a593Smuzhiyun static struct irq_chip ipic_level_irq_chip = {
655*4882a593Smuzhiyun .name = "IPIC",
656*4882a593Smuzhiyun .irq_unmask = ipic_unmask_irq,
657*4882a593Smuzhiyun .irq_mask = ipic_mask_irq,
658*4882a593Smuzhiyun .irq_mask_ack = ipic_mask_irq,
659*4882a593Smuzhiyun .irq_set_type = ipic_set_irq_type,
660*4882a593Smuzhiyun };
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun static struct irq_chip ipic_edge_irq_chip = {
663*4882a593Smuzhiyun .name = "IPIC",
664*4882a593Smuzhiyun .irq_unmask = ipic_unmask_irq,
665*4882a593Smuzhiyun .irq_mask = ipic_mask_irq,
666*4882a593Smuzhiyun .irq_mask_ack = ipic_mask_irq_and_ack,
667*4882a593Smuzhiyun .irq_ack = ipic_ack_irq,
668*4882a593Smuzhiyun .irq_set_type = ipic_set_irq_type,
669*4882a593Smuzhiyun };
670*4882a593Smuzhiyun
ipic_host_match(struct irq_domain * h,struct device_node * node,enum irq_domain_bus_token bus_token)671*4882a593Smuzhiyun static int ipic_host_match(struct irq_domain *h, struct device_node *node,
672*4882a593Smuzhiyun enum irq_domain_bus_token bus_token)
673*4882a593Smuzhiyun {
674*4882a593Smuzhiyun /* Exact match, unless ipic node is NULL */
675*4882a593Smuzhiyun struct device_node *of_node = irq_domain_get_of_node(h);
676*4882a593Smuzhiyun return of_node == NULL || of_node == node;
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun
ipic_host_map(struct irq_domain * h,unsigned int virq,irq_hw_number_t hw)679*4882a593Smuzhiyun static int ipic_host_map(struct irq_domain *h, unsigned int virq,
680*4882a593Smuzhiyun irq_hw_number_t hw)
681*4882a593Smuzhiyun {
682*4882a593Smuzhiyun struct ipic *ipic = h->host_data;
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun irq_set_chip_data(virq, ipic);
685*4882a593Smuzhiyun irq_set_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq);
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun /* Set default irq type */
688*4882a593Smuzhiyun irq_set_irq_type(virq, IRQ_TYPE_NONE);
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun return 0;
691*4882a593Smuzhiyun }
692*4882a593Smuzhiyun
693*4882a593Smuzhiyun static const struct irq_domain_ops ipic_host_ops = {
694*4882a593Smuzhiyun .match = ipic_host_match,
695*4882a593Smuzhiyun .map = ipic_host_map,
696*4882a593Smuzhiyun .xlate = irq_domain_xlate_onetwocell,
697*4882a593Smuzhiyun };
698*4882a593Smuzhiyun
ipic_init(struct device_node * node,unsigned int flags)699*4882a593Smuzhiyun struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
700*4882a593Smuzhiyun {
701*4882a593Smuzhiyun struct ipic *ipic;
702*4882a593Smuzhiyun struct resource res;
703*4882a593Smuzhiyun u32 temp = 0, ret;
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun ret = of_address_to_resource(node, 0, &res);
706*4882a593Smuzhiyun if (ret)
707*4882a593Smuzhiyun return NULL;
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun ipic = kzalloc(sizeof(*ipic), GFP_KERNEL);
710*4882a593Smuzhiyun if (ipic == NULL)
711*4882a593Smuzhiyun return NULL;
712*4882a593Smuzhiyun
713*4882a593Smuzhiyun ipic->irqhost = irq_domain_add_linear(node, NR_IPIC_INTS,
714*4882a593Smuzhiyun &ipic_host_ops, ipic);
715*4882a593Smuzhiyun if (ipic->irqhost == NULL) {
716*4882a593Smuzhiyun kfree(ipic);
717*4882a593Smuzhiyun return NULL;
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun ipic->regs = ioremap(res.start, resource_size(&res));
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun /* init hw */
723*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SICNR, 0x0);
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun /* default priority scheme is grouped. If spread mode is required
726*4882a593Smuzhiyun * configure SICFR accordingly */
727*4882a593Smuzhiyun if (flags & IPIC_SPREADMODE_GRP_A)
728*4882a593Smuzhiyun temp |= SICFR_IPSA;
729*4882a593Smuzhiyun if (flags & IPIC_SPREADMODE_GRP_B)
730*4882a593Smuzhiyun temp |= SICFR_IPSB;
731*4882a593Smuzhiyun if (flags & IPIC_SPREADMODE_GRP_C)
732*4882a593Smuzhiyun temp |= SICFR_IPSC;
733*4882a593Smuzhiyun if (flags & IPIC_SPREADMODE_GRP_D)
734*4882a593Smuzhiyun temp |= SICFR_IPSD;
735*4882a593Smuzhiyun if (flags & IPIC_SPREADMODE_MIX_A)
736*4882a593Smuzhiyun temp |= SICFR_MPSA;
737*4882a593Smuzhiyun if (flags & IPIC_SPREADMODE_MIX_B)
738*4882a593Smuzhiyun temp |= SICFR_MPSB;
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SICFR, temp);
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun /* handle MCP route */
743*4882a593Smuzhiyun temp = 0;
744*4882a593Smuzhiyun if (flags & IPIC_DISABLE_MCP_OUT)
745*4882a593Smuzhiyun temp = SERCR_MCPR;
746*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SERCR, temp);
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun /* handle routing of IRQ0 to MCP */
749*4882a593Smuzhiyun temp = ipic_read(ipic->regs, IPIC_SEMSR);
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun if (flags & IPIC_IRQ0_MCP)
752*4882a593Smuzhiyun temp |= SEMSR_SIRQ0;
753*4882a593Smuzhiyun else
754*4882a593Smuzhiyun temp &= ~SEMSR_SIRQ0;
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SEMSR, temp);
757*4882a593Smuzhiyun
758*4882a593Smuzhiyun primary_ipic = ipic;
759*4882a593Smuzhiyun irq_set_default_host(primary_ipic->irqhost);
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SIMSR_H, 0);
762*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SIMSR_L, 0);
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS,
765*4882a593Smuzhiyun primary_ipic->regs);
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun return ipic;
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun
ipic_set_default_priority(void)770*4882a593Smuzhiyun void ipic_set_default_priority(void)
771*4882a593Smuzhiyun {
772*4882a593Smuzhiyun ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_PRIORITY_DEFAULT);
773*4882a593Smuzhiyun ipic_write(primary_ipic->regs, IPIC_SIPRR_B, IPIC_PRIORITY_DEFAULT);
774*4882a593Smuzhiyun ipic_write(primary_ipic->regs, IPIC_SIPRR_C, IPIC_PRIORITY_DEFAULT);
775*4882a593Smuzhiyun ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_PRIORITY_DEFAULT);
776*4882a593Smuzhiyun ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_PRIORITY_DEFAULT);
777*4882a593Smuzhiyun ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_PRIORITY_DEFAULT);
778*4882a593Smuzhiyun }
779*4882a593Smuzhiyun
ipic_get_mcp_status(void)780*4882a593Smuzhiyun u32 ipic_get_mcp_status(void)
781*4882a593Smuzhiyun {
782*4882a593Smuzhiyun return primary_ipic ? ipic_read(primary_ipic->regs, IPIC_SERSR) : 0;
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun
ipic_clear_mcp_status(u32 mask)785*4882a593Smuzhiyun void ipic_clear_mcp_status(u32 mask)
786*4882a593Smuzhiyun {
787*4882a593Smuzhiyun ipic_write(primary_ipic->regs, IPIC_SERSR, mask);
788*4882a593Smuzhiyun }
789*4882a593Smuzhiyun
790*4882a593Smuzhiyun /* Return an interrupt vector or 0 if no interrupt is pending. */
ipic_get_irq(void)791*4882a593Smuzhiyun unsigned int ipic_get_irq(void)
792*4882a593Smuzhiyun {
793*4882a593Smuzhiyun int irq;
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun BUG_ON(primary_ipic == NULL);
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun #define IPIC_SIVCR_VECTOR_MASK 0x7f
798*4882a593Smuzhiyun irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK;
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun if (irq == 0) /* 0 --> no irq is pending */
801*4882a593Smuzhiyun return 0;
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun return irq_linear_revmap(primary_ipic->irqhost, irq);
804*4882a593Smuzhiyun }
805*4882a593Smuzhiyun
806*4882a593Smuzhiyun #ifdef CONFIG_SUSPEND
807*4882a593Smuzhiyun static struct {
808*4882a593Smuzhiyun u32 sicfr;
809*4882a593Smuzhiyun u32 siprr[2];
810*4882a593Smuzhiyun u32 simsr[2];
811*4882a593Smuzhiyun u32 sicnr;
812*4882a593Smuzhiyun u32 smprr[2];
813*4882a593Smuzhiyun u32 semsr;
814*4882a593Smuzhiyun u32 secnr;
815*4882a593Smuzhiyun u32 sermr;
816*4882a593Smuzhiyun u32 sercr;
817*4882a593Smuzhiyun } ipic_saved_state;
818*4882a593Smuzhiyun
ipic_suspend(void)819*4882a593Smuzhiyun static int ipic_suspend(void)
820*4882a593Smuzhiyun {
821*4882a593Smuzhiyun struct ipic *ipic = primary_ipic;
822*4882a593Smuzhiyun
823*4882a593Smuzhiyun ipic_saved_state.sicfr = ipic_read(ipic->regs, IPIC_SICFR);
824*4882a593Smuzhiyun ipic_saved_state.siprr[0] = ipic_read(ipic->regs, IPIC_SIPRR_A);
825*4882a593Smuzhiyun ipic_saved_state.siprr[1] = ipic_read(ipic->regs, IPIC_SIPRR_D);
826*4882a593Smuzhiyun ipic_saved_state.simsr[0] = ipic_read(ipic->regs, IPIC_SIMSR_H);
827*4882a593Smuzhiyun ipic_saved_state.simsr[1] = ipic_read(ipic->regs, IPIC_SIMSR_L);
828*4882a593Smuzhiyun ipic_saved_state.sicnr = ipic_read(ipic->regs, IPIC_SICNR);
829*4882a593Smuzhiyun ipic_saved_state.smprr[0] = ipic_read(ipic->regs, IPIC_SMPRR_A);
830*4882a593Smuzhiyun ipic_saved_state.smprr[1] = ipic_read(ipic->regs, IPIC_SMPRR_B);
831*4882a593Smuzhiyun ipic_saved_state.semsr = ipic_read(ipic->regs, IPIC_SEMSR);
832*4882a593Smuzhiyun ipic_saved_state.secnr = ipic_read(ipic->regs, IPIC_SECNR);
833*4882a593Smuzhiyun ipic_saved_state.sermr = ipic_read(ipic->regs, IPIC_SERMR);
834*4882a593Smuzhiyun ipic_saved_state.sercr = ipic_read(ipic->regs, IPIC_SERCR);
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun if (fsl_deep_sleep()) {
837*4882a593Smuzhiyun /* In deep sleep, make sure there can be no
838*4882a593Smuzhiyun * pending interrupts, as this can cause
839*4882a593Smuzhiyun * problems on 831x.
840*4882a593Smuzhiyun */
841*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SIMSR_H, 0);
842*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SIMSR_L, 0);
843*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SEMSR, 0);
844*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SERMR, 0);
845*4882a593Smuzhiyun }
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun return 0;
848*4882a593Smuzhiyun }
849*4882a593Smuzhiyun
ipic_resume(void)850*4882a593Smuzhiyun static void ipic_resume(void)
851*4882a593Smuzhiyun {
852*4882a593Smuzhiyun struct ipic *ipic = primary_ipic;
853*4882a593Smuzhiyun
854*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SICFR, ipic_saved_state.sicfr);
855*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SIPRR_A, ipic_saved_state.siprr[0]);
856*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SIPRR_D, ipic_saved_state.siprr[1]);
857*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SIMSR_H, ipic_saved_state.simsr[0]);
858*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SIMSR_L, ipic_saved_state.simsr[1]);
859*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SICNR, ipic_saved_state.sicnr);
860*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SMPRR_A, ipic_saved_state.smprr[0]);
861*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SMPRR_B, ipic_saved_state.smprr[1]);
862*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SEMSR, ipic_saved_state.semsr);
863*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SECNR, ipic_saved_state.secnr);
864*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SERMR, ipic_saved_state.sermr);
865*4882a593Smuzhiyun ipic_write(ipic->regs, IPIC_SERCR, ipic_saved_state.sercr);
866*4882a593Smuzhiyun }
867*4882a593Smuzhiyun #else
868*4882a593Smuzhiyun #define ipic_suspend NULL
869*4882a593Smuzhiyun #define ipic_resume NULL
870*4882a593Smuzhiyun #endif
871*4882a593Smuzhiyun
872*4882a593Smuzhiyun static struct syscore_ops ipic_syscore_ops = {
873*4882a593Smuzhiyun .suspend = ipic_suspend,
874*4882a593Smuzhiyun .resume = ipic_resume,
875*4882a593Smuzhiyun };
876*4882a593Smuzhiyun
init_ipic_syscore(void)877*4882a593Smuzhiyun static int __init init_ipic_syscore(void)
878*4882a593Smuzhiyun {
879*4882a593Smuzhiyun if (!primary_ipic || !primary_ipic->regs)
880*4882a593Smuzhiyun return -ENODEV;
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun printk(KERN_DEBUG "Registering ipic system core operations\n");
883*4882a593Smuzhiyun register_syscore_ops(&ipic_syscore_ops);
884*4882a593Smuzhiyun
885*4882a593Smuzhiyun return 0;
886*4882a593Smuzhiyun }
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun subsys_initcall(init_ipic_syscore);
889