Blame view

arch/powerpc/sysdev/mpic.c 47.6 KB
14cf11af6   Paul Mackerras   powerpc: Merge en...
1
2
3
4
5
6
7
8
  /*
   *  arch/powerpc/kernel/mpic.c
   *
   *  Driver for interrupt controllers following the OpenPIC standard, the
   *  common implementation beeing IBM's MPIC. This driver also can deal
   *  with various broken implementations of this HW.
   *
   *  Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp.
22d168ce6   Scott Wood   powerpc/mpic: par...
9
   *  Copyright 2010-2011 Freescale Semiconductor, Inc.
14cf11af6   Paul Mackerras   powerpc: Merge en...
10
11
12
13
14
15
16
   *
   *  This file is subject to the terms and conditions of the GNU General Public
   *  License.  See the file COPYING in the main directory of this archive
   *  for more details.
   */
  
  #undef DEBUG
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
17
18
19
  #undef DEBUG_IPI
  #undef DEBUG_IRQ
  #undef DEBUG_LOW
14cf11af6   Paul Mackerras   powerpc: Merge en...
20

14cf11af6   Paul Mackerras   powerpc: Merge en...
21
22
23
24
25
26
27
28
29
  #include <linux/types.h>
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/irq.h>
  #include <linux/smp.h>
  #include <linux/interrupt.h>
  #include <linux/bootmem.h>
  #include <linux/spinlock.h>
  #include <linux/pci.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
30
  #include <linux/slab.h>
f5a592f7d   Rafael J. Wysocki   PM / PowerPC: Use...
31
  #include <linux/syscore_ops.h>
76462232c   Christian Dietrich   arch/powerpc: use...
32
  #include <linux/ratelimit.h>
14cf11af6   Paul Mackerras   powerpc: Merge en...
33
34
35
36
37
38
39
40
41
  
  #include <asm/ptrace.h>
  #include <asm/signal.h>
  #include <asm/io.h>
  #include <asm/pgtable.h>
  #include <asm/irq.h>
  #include <asm/machdep.h>
  #include <asm/mpic.h>
  #include <asm/smp.h>
a7de7c742   Michael Ellerman   [POWERPC] MPIC MS...
42
  #include "mpic.h"
14cf11af6   Paul Mackerras   powerpc: Merge en...
43
44
45
46
47
48
49
50
  #ifdef DEBUG
  #define DBG(fmt...) printk(fmt)
  #else
  #define DBG(fmt...)
  #endif
  
  static struct mpic *mpics;
  static struct mpic *mpic_primary;
203041ad1   Thomas Gleixner   powerpc: Convert ...
51
  static DEFINE_RAW_SPINLOCK(mpic_lock);
14cf11af6   Paul Mackerras   powerpc: Merge en...
52

c0c0d996d   Paul Mackerras   powerpc: Get merg...
53
  #ifdef CONFIG_PPC32	/* XXX for now */
e40c7f027   Andy Whitcroft   [PATCH] powerpc32...
54
55
56
57
58
  #ifdef CONFIG_IRQ_ALL_CPUS
  #define distribute_irqs	(1)
  #else
  #define distribute_irqs	(0)
  #endif
c0c0d996d   Paul Mackerras   powerpc: Get merg...
59
  #endif
14cf11af6   Paul Mackerras   powerpc: Merge en...
60

7233593b7   Zang Roy-r61911   [POWERPC] Support...
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  #ifdef CONFIG_MPIC_WEIRD
  static u32 mpic_infos[][MPIC_IDX_END] = {
  	[0] = {	/* Original OpenPIC compatible MPIC */
  		MPIC_GREG_BASE,
  		MPIC_GREG_FEATURE_0,
  		MPIC_GREG_GLOBAL_CONF_0,
  		MPIC_GREG_VENDOR_ID,
  		MPIC_GREG_IPI_VECTOR_PRI_0,
  		MPIC_GREG_IPI_STRIDE,
  		MPIC_GREG_SPURIOUS,
  		MPIC_GREG_TIMER_FREQ,
  
  		MPIC_TIMER_BASE,
  		MPIC_TIMER_STRIDE,
  		MPIC_TIMER_CURRENT_CNT,
  		MPIC_TIMER_BASE_CNT,
  		MPIC_TIMER_VECTOR_PRI,
  		MPIC_TIMER_DESTINATION,
  
  		MPIC_CPU_BASE,
  		MPIC_CPU_STRIDE,
  		MPIC_CPU_IPI_DISPATCH_0,
  		MPIC_CPU_IPI_DISPATCH_STRIDE,
  		MPIC_CPU_CURRENT_TASK_PRI,
  		MPIC_CPU_WHOAMI,
  		MPIC_CPU_INTACK,
  		MPIC_CPU_EOI,
f365355e6   Olof Johansson   [POWERPC] pasemi:...
88
  		MPIC_CPU_MCACK,
7233593b7   Zang Roy-r61911   [POWERPC] Support...
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  
  		MPIC_IRQ_BASE,
  		MPIC_IRQ_STRIDE,
  		MPIC_IRQ_VECTOR_PRI,
  		MPIC_VECPRI_VECTOR_MASK,
  		MPIC_VECPRI_POLARITY_POSITIVE,
  		MPIC_VECPRI_POLARITY_NEGATIVE,
  		MPIC_VECPRI_SENSE_LEVEL,
  		MPIC_VECPRI_SENSE_EDGE,
  		MPIC_VECPRI_POLARITY_MASK,
  		MPIC_VECPRI_SENSE_MASK,
  		MPIC_IRQ_DESTINATION
  	},
  	[1] = {	/* Tsi108/109 PIC */
  		TSI108_GREG_BASE,
  		TSI108_GREG_FEATURE_0,
  		TSI108_GREG_GLOBAL_CONF_0,
  		TSI108_GREG_VENDOR_ID,
  		TSI108_GREG_IPI_VECTOR_PRI_0,
  		TSI108_GREG_IPI_STRIDE,
  		TSI108_GREG_SPURIOUS,
  		TSI108_GREG_TIMER_FREQ,
  
  		TSI108_TIMER_BASE,
  		TSI108_TIMER_STRIDE,
  		TSI108_TIMER_CURRENT_CNT,
  		TSI108_TIMER_BASE_CNT,
  		TSI108_TIMER_VECTOR_PRI,
  		TSI108_TIMER_DESTINATION,
  
  		TSI108_CPU_BASE,
  		TSI108_CPU_STRIDE,
  		TSI108_CPU_IPI_DISPATCH_0,
  		TSI108_CPU_IPI_DISPATCH_STRIDE,
  		TSI108_CPU_CURRENT_TASK_PRI,
  		TSI108_CPU_WHOAMI,
  		TSI108_CPU_INTACK,
  		TSI108_CPU_EOI,
f365355e6   Olof Johansson   [POWERPC] pasemi:...
127
  		TSI108_CPU_MCACK,
7233593b7   Zang Roy-r61911   [POWERPC] Support...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  
  		TSI108_IRQ_BASE,
  		TSI108_IRQ_STRIDE,
  		TSI108_IRQ_VECTOR_PRI,
  		TSI108_VECPRI_VECTOR_MASK,
  		TSI108_VECPRI_POLARITY_POSITIVE,
  		TSI108_VECPRI_POLARITY_NEGATIVE,
  		TSI108_VECPRI_SENSE_LEVEL,
  		TSI108_VECPRI_SENSE_EDGE,
  		TSI108_VECPRI_POLARITY_MASK,
  		TSI108_VECPRI_SENSE_MASK,
  		TSI108_IRQ_DESTINATION
  	},
  };
  
  #define MPIC_INFO(name) mpic->hw_set[MPIC_IDX_##name]
  
  #else /* CONFIG_MPIC_WEIRD */
  
  #define MPIC_INFO(name) MPIC_##name
  
  #endif /* CONFIG_MPIC_WEIRD */
d6a2639b8   Meador Inge   powerpc: Factorin...
150
151
152
  static inline unsigned int mpic_processor_id(struct mpic *mpic)
  {
  	unsigned int cpu = 0;
be8bec56d   Kyle Moffett   powerpc/mpic: Inv...
153
  	if (!(mpic->flags & MPIC_SECONDARY))
d6a2639b8   Meador Inge   powerpc: Factorin...
154
155
156
157
  		cpu = hard_smp_processor_id();
  
  	return cpu;
  }
14cf11af6   Paul Mackerras   powerpc: Merge en...
158
159
160
  /*
   * Register accessor functions
   */
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
161
162
163
  static inline u32 _mpic_read(enum mpic_reg_type type,
  			     struct mpic_reg_bank *rb,
  			     unsigned int reg)
14cf11af6   Paul Mackerras   powerpc: Merge en...
164
  {
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
165
166
167
  	switch(type) {
  #ifdef CONFIG_PPC_DCR
  	case mpic_access_dcr:
83f34df4e   Michael Ellerman   Add dcr_host_t.ba...
168
  		return dcr_read(rb->dhost, reg);
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
169
170
171
172
173
174
175
  #endif
  	case mpic_access_mmio_be:
  		return in_be32(rb->base + (reg >> 2));
  	case mpic_access_mmio_le:
  	default:
  		return in_le32(rb->base + (reg >> 2));
  	}
14cf11af6   Paul Mackerras   powerpc: Merge en...
176
  }
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
177
178
179
  static inline void _mpic_write(enum mpic_reg_type type,
  			       struct mpic_reg_bank *rb,
   			       unsigned int reg, u32 value)
14cf11af6   Paul Mackerras   powerpc: Merge en...
180
  {
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
181
182
183
  	switch(type) {
  #ifdef CONFIG_PPC_DCR
  	case mpic_access_dcr:
d9d1063d4   Johannes Berg   [POWERPC] mpic: M...
184
185
  		dcr_write(rb->dhost, reg, value);
  		break;
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
186
187
  #endif
  	case mpic_access_mmio_be:
d9d1063d4   Johannes Berg   [POWERPC] mpic: M...
188
189
  		out_be32(rb->base + (reg >> 2), value);
  		break;
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
190
191
  	case mpic_access_mmio_le:
  	default:
d9d1063d4   Johannes Berg   [POWERPC] mpic: M...
192
193
  		out_le32(rb->base + (reg >> 2), value);
  		break;
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
194
  	}
14cf11af6   Paul Mackerras   powerpc: Merge en...
195
196
197
198
  }
  
  static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
  {
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
199
  	enum mpic_reg_type type = mpic->reg_type;
7233593b7   Zang Roy-r61911   [POWERPC] Support...
200
201
  	unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) +
  			      (ipi * MPIC_INFO(GREG_IPI_STRIDE));
14cf11af6   Paul Mackerras   powerpc: Merge en...
202

fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
203
204
205
  	if ((mpic->flags & MPIC_BROKEN_IPI) && type == mpic_access_mmio_le)
  		type = mpic_access_mmio_be;
  	return _mpic_read(type, &mpic->gregs, offset);
14cf11af6   Paul Mackerras   powerpc: Merge en...
206
207
208
209
  }
  
  static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value)
  {
7233593b7   Zang Roy-r61911   [POWERPC] Support...
210
211
  	unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) +
  			      (ipi * MPIC_INFO(GREG_IPI_STRIDE));
14cf11af6   Paul Mackerras   powerpc: Merge en...
212

fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
213
  	_mpic_write(mpic->reg_type, &mpic->gregs, offset, value);
14cf11af6   Paul Mackerras   powerpc: Merge en...
214
  }
ea94187fa   Scott Wood   powerpc/mpic: add...
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
  static inline u32 _mpic_tm_read(struct mpic *mpic, unsigned int tm)
  {
  	unsigned int offset = MPIC_INFO(TIMER_VECTOR_PRI) +
  			      ((tm & 3) * MPIC_INFO(TIMER_STRIDE));
  
  	if (tm >= 4)
  		offset += 0x1000 / 4;
  
  	return _mpic_read(mpic->reg_type, &mpic->tmregs, offset);
  }
  
  static inline void _mpic_tm_write(struct mpic *mpic, unsigned int tm, u32 value)
  {
  	unsigned int offset = MPIC_INFO(TIMER_VECTOR_PRI) +
  			      ((tm & 3) * MPIC_INFO(TIMER_STRIDE));
  
  	if (tm >= 4)
  		offset += 0x1000 / 4;
  
  	_mpic_write(mpic->reg_type, &mpic->tmregs, offset, value);
  }
14cf11af6   Paul Mackerras   powerpc: Merge en...
236
237
  static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
  {
d6a2639b8   Meador Inge   powerpc: Factorin...
238
  	unsigned int cpu = mpic_processor_id(mpic);
14cf11af6   Paul Mackerras   powerpc: Merge en...
239

fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
240
  	return _mpic_read(mpic->reg_type, &mpic->cpuregs[cpu], reg);
14cf11af6   Paul Mackerras   powerpc: Merge en...
241
242
243
244
  }
  
  static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value)
  {
d6a2639b8   Meador Inge   powerpc: Factorin...
245
  	unsigned int cpu = mpic_processor_id(mpic);
14cf11af6   Paul Mackerras   powerpc: Merge en...
246

fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
247
  	_mpic_write(mpic->reg_type, &mpic->cpuregs[cpu], reg, value);
14cf11af6   Paul Mackerras   powerpc: Merge en...
248
249
250
251
252
253
  }
  
  static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigned int reg)
  {
  	unsigned int	isu = src_no >> mpic->isu_shift;
  	unsigned int	idx = src_no & mpic->isu_mask;
11a6b292c   Michael Ellerman   powerpc/mpic: Fix...
254
  	unsigned int	val;
14cf11af6   Paul Mackerras   powerpc: Merge en...
255

11a6b292c   Michael Ellerman   powerpc/mpic: Fix...
256
257
  	val = _mpic_read(mpic->reg_type, &mpic->isus[isu],
  			 reg + (idx * MPIC_INFO(IRQ_STRIDE)));
0d72ba930   Olof Johansson   [POWERPC] Add wor...
258
259
  #ifdef CONFIG_MPIC_BROKEN_REGREAD
  	if (reg == 0)
11a6b292c   Michael Ellerman   powerpc/mpic: Fix...
260
261
  		val = (val & (MPIC_VECPRI_MASK | MPIC_VECPRI_ACTIVITY)) |
  			mpic->isu_reg0_shadow[src_no];
0d72ba930   Olof Johansson   [POWERPC] Add wor...
262
  #endif
11a6b292c   Michael Ellerman   powerpc/mpic: Fix...
263
  	return val;
14cf11af6   Paul Mackerras   powerpc: Merge en...
264
265
266
267
268
269
270
  }
  
  static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
  				   unsigned int reg, u32 value)
  {
  	unsigned int	isu = src_no >> mpic->isu_shift;
  	unsigned int	idx = src_no & mpic->isu_mask;
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
271
  	_mpic_write(mpic->reg_type, &mpic->isus[isu],
7233593b7   Zang Roy-r61911   [POWERPC] Support...
272
  		    reg + (idx * MPIC_INFO(IRQ_STRIDE)), value);
0d72ba930   Olof Johansson   [POWERPC] Add wor...
273
274
275
  
  #ifdef CONFIG_MPIC_BROKEN_REGREAD
  	if (reg == 0)
11a6b292c   Michael Ellerman   powerpc/mpic: Fix...
276
277
  		mpic->isu_reg0_shadow[src_no] =
  			value & ~(MPIC_VECPRI_MASK | MPIC_VECPRI_ACTIVITY);
0d72ba930   Olof Johansson   [POWERPC] Add wor...
278
  #endif
14cf11af6   Paul Mackerras   powerpc: Merge en...
279
  }
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
280
281
  #define mpic_read(b,r)		_mpic_read(mpic->reg_type,&(b),(r))
  #define mpic_write(b,r,v)	_mpic_write(mpic->reg_type,&(b),(r),(v))
14cf11af6   Paul Mackerras   powerpc: Merge en...
282
283
  #define mpic_ipi_read(i)	_mpic_ipi_read(mpic,(i))
  #define mpic_ipi_write(i,v)	_mpic_ipi_write(mpic,(i),(v))
ea94187fa   Scott Wood   powerpc/mpic: add...
284
285
  #define mpic_tm_read(i)		_mpic_tm_read(mpic,(i))
  #define mpic_tm_write(i,v)	_mpic_tm_write(mpic,(i),(v))
14cf11af6   Paul Mackerras   powerpc: Merge en...
286
287
288
289
290
291
292
293
294
  #define mpic_cpu_read(i)	_mpic_cpu_read(mpic,(i))
  #define mpic_cpu_write(i,v)	_mpic_cpu_write(mpic,(i),(v))
  #define mpic_irq_read(s,r)	_mpic_irq_read(mpic,(s),(r))
  #define mpic_irq_write(s,r,v)	_mpic_irq_write(mpic,(s),(r),(v))
  
  
  /*
   * Low level utility functions
   */
c51a3fdc0   Becky Bruce   [POWERPC] Fixup u...
295
  static void _mpic_map_mmio(struct mpic *mpic, phys_addr_t phys_addr,
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
296
297
298
299
300
301
302
303
  			   struct mpic_reg_bank *rb, unsigned int offset,
  			   unsigned int size)
  {
  	rb->base = ioremap(phys_addr + offset, size);
  	BUG_ON(rb->base == NULL);
  }
  
  #ifdef CONFIG_PPC_DCR
c51242e70   Kyle Moffett   powerpc/mpic: Cac...
304
  static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb,
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
305
306
  			  unsigned int offset, unsigned int size)
  {
c51242e70   Kyle Moffett   powerpc/mpic: Cac...
307
  	phys_addr_t phys_addr = dcr_resource_start(mpic->node, 0);
e62b76017   Kyle Moffett   powerpc/mpic: Don...
308
  	rb->dhost = dcr_map(mpic->node, phys_addr + offset, size);
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
309
310
  	BUG_ON(!DCR_MAP_OK(rb->dhost));
  }
c51242e70   Kyle Moffett   powerpc/mpic: Cac...
311
  static inline void mpic_map(struct mpic *mpic,
5a2642f62   Benjamin Herrenschmidt   powerpc/mpic: Fix...
312
313
  			    phys_addr_t phys_addr, struct mpic_reg_bank *rb,
  			    unsigned int offset, unsigned int size)
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
314
315
  {
  	if (mpic->flags & MPIC_USES_DCR)
c51242e70   Kyle Moffett   powerpc/mpic: Cac...
316
  		_mpic_map_dcr(mpic, rb, offset, size);
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
317
318
319
320
  	else
  		_mpic_map_mmio(mpic, phys_addr, rb, offset, size);
  }
  #else /* CONFIG_PPC_DCR */
c51242e70   Kyle Moffett   powerpc/mpic: Cac...
321
  #define mpic_map(m,p,b,o,s)	_mpic_map_mmio(m,p,b,o,s)
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
322
  #endif /* !CONFIG_PPC_DCR */
14cf11af6   Paul Mackerras   powerpc: Merge en...
323
324
325
326
327
328
329
  
  /* Check if we have one of those nice broken MPICs with a flipped endian on
   * reads from IPI registers
   */
  static void __init mpic_test_broken_ipi(struct mpic *mpic)
  {
  	u32 r;
7233593b7   Zang Roy-r61911   [POWERPC] Support...
330
331
  	mpic_write(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0), MPIC_VECPRI_MASK);
  	r = mpic_read(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0));
14cf11af6   Paul Mackerras   powerpc: Merge en...
332
333
334
335
336
337
338
  
  	if (r == le32_to_cpu(MPIC_VECPRI_MASK)) {
  		printk(KERN_INFO "mpic: Detected reversed IPI registers
  ");
  		mpic->flags |= MPIC_BROKEN_IPI;
  	}
  }
6cfef5b27   Michael Ellerman   [POWERPC] Rename ...
339
  #ifdef CONFIG_MPIC_U3_HT_IRQS
14cf11af6   Paul Mackerras   powerpc: Merge en...
340
341
342
343
  
  /* Test if an interrupt is sourced from HyperTransport (used on broken U3s)
   * to force the edge setting on the MPIC and do the ack workaround.
   */
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
344
  static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source)
14cf11af6   Paul Mackerras   powerpc: Merge en...
345
  {
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
346
  	if (source >= 128 || !mpic->fixups)
14cf11af6   Paul Mackerras   powerpc: Merge en...
347
  		return 0;
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
348
  	return mpic->fixups[source].base != NULL;
14cf11af6   Paul Mackerras   powerpc: Merge en...
349
  }
c4b22f268   Segher Boessenkool   [PATCH] powerpc: ...
350

1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
351
  static inline void mpic_ht_end_irq(struct mpic *mpic, unsigned int source)
14cf11af6   Paul Mackerras   powerpc: Merge en...
352
  {
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
353
  	struct mpic_irq_fixup *fixup = &mpic->fixups[source];
14cf11af6   Paul Mackerras   powerpc: Merge en...
354

1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
355
356
357
358
359
  	if (fixup->applebase) {
  		unsigned int soff = (fixup->index >> 3) & ~3;
  		unsigned int mask = 1U << (fixup->index & 0x1f);
  		writel(mask, fixup->applebase + soff);
  	} else {
203041ad1   Thomas Gleixner   powerpc: Convert ...
360
  		raw_spin_lock(&mpic->fixup_lock);
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
361
362
  		writeb(0x11 + 2 * fixup->index, fixup->base + 2);
  		writel(fixup->data, fixup->base + 4);
203041ad1   Thomas Gleixner   powerpc: Convert ...
363
  		raw_spin_unlock(&mpic->fixup_lock);
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
364
  	}
14cf11af6   Paul Mackerras   powerpc: Merge en...
365
  }
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
366
  static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
24a3f2e82   Thomas Gleixner   powerpc: mpic: Cl...
367
  				      bool level)
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
368
369
370
371
372
373
374
  {
  	struct mpic_irq_fixup *fixup = &mpic->fixups[source];
  	unsigned long flags;
  	u32 tmp;
  
  	if (fixup->base == NULL)
  		return;
24a3f2e82   Thomas Gleixner   powerpc: mpic: Cl...
375
376
377
  	DBG("startup_ht_interrupt(0x%x) index: %d
  ",
  	    source, fixup->index);
203041ad1   Thomas Gleixner   powerpc: Convert ...
378
  	raw_spin_lock_irqsave(&mpic->fixup_lock, flags);
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
379
380
381
382
  	/* Enable and configure */
  	writeb(0x10 + 2 * fixup->index, fixup->base + 2);
  	tmp = readl(fixup->base + 4);
  	tmp &= ~(0x23U);
24a3f2e82   Thomas Gleixner   powerpc: mpic: Cl...
383
  	if (level)
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
384
385
  		tmp |= 0x22;
  	writel(tmp, fixup->base + 4);
203041ad1   Thomas Gleixner   powerpc: Convert ...
386
  	raw_spin_unlock_irqrestore(&mpic->fixup_lock, flags);
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
387
388
389
390
391
392
  
  #ifdef CONFIG_PM
  	/* use the lowest bit inverted to the actual HW,
  	 * set if this fixup was enabled, clear otherwise */
  	mpic->save_data[source].fixup_data = tmp | 1;
  #endif
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
393
  }
24a3f2e82   Thomas Gleixner   powerpc: mpic: Cl...
394
  static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source)
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
395
396
397
398
399
400
401
  {
  	struct mpic_irq_fixup *fixup = &mpic->fixups[source];
  	unsigned long flags;
  	u32 tmp;
  
  	if (fixup->base == NULL)
  		return;
24a3f2e82   Thomas Gleixner   powerpc: mpic: Cl...
402
403
  	DBG("shutdown_ht_interrupt(0x%x)
  ", source);
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
404
405
  
  	/* Disable */
203041ad1   Thomas Gleixner   powerpc: Convert ...
406
  	raw_spin_lock_irqsave(&mpic->fixup_lock, flags);
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
407
408
  	writeb(0x10 + 2 * fixup->index, fixup->base + 2);
  	tmp = readl(fixup->base + 4);
72b138198   Segher Boessenkool   [PATCH] powerpc: ...
409
  	tmp |= 1;
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
410
  	writel(tmp, fixup->base + 4);
203041ad1   Thomas Gleixner   powerpc: Convert ...
411
  	raw_spin_unlock_irqrestore(&mpic->fixup_lock, flags);
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
412
413
414
415
416
417
  
  #ifdef CONFIG_PM
  	/* use the lowest bit inverted to the actual HW,
  	 * set if this fixup was enabled, clear otherwise */
  	mpic->save_data[source].fixup_data = tmp & ~1;
  #endif
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
418
  }
14cf11af6   Paul Mackerras   powerpc: Merge en...
419

812fd1fd6   Michael Ellerman   [POWERPC] Enable ...
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
  #ifdef CONFIG_PCI_MSI
  static void __init mpic_scan_ht_msi(struct mpic *mpic, u8 __iomem *devbase,
  				    unsigned int devfn)
  {
  	u8 __iomem *base;
  	u8 pos, flags;
  	u64 addr = 0;
  
  	for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0;
  	     pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) {
  		u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
  		if (id == PCI_CAP_ID_HT) {
  			id = readb(devbase + pos + 3);
  			if ((id & HT_5BIT_CAP_MASK) == HT_CAPTYPE_MSI_MAPPING)
  				break;
  		}
  	}
  
  	if (pos == 0)
  		return;
  
  	base = devbase + pos;
  
  	flags = readb(base + HT_MSI_FLAGS);
  	if (!(flags & HT_MSI_FLAGS_FIXED)) {
  		addr = readl(base + HT_MSI_ADDR_LO) & HT_MSI_ADDR_LO_MASK;
  		addr = addr | ((u64)readl(base + HT_MSI_ADDR_HI) << 32);
  	}
fe333321e   Ingo Molnar   powerpc: Change u...
448
449
  	printk(KERN_DEBUG "mpic:   - HT:%02x.%x %s MSI mapping found @ 0x%llx
  ",
812fd1fd6   Michael Ellerman   [POWERPC] Enable ...
450
451
452
453
454
455
456
457
458
459
460
461
462
  		PCI_SLOT(devfn), PCI_FUNC(devfn),
  		flags & HT_MSI_FLAGS_ENABLE ? "enabled" : "disabled", addr);
  
  	if (!(flags & HT_MSI_FLAGS_ENABLE))
  		writeb(flags | HT_MSI_FLAGS_ENABLE, base + HT_MSI_FLAGS);
  }
  #else
  static void __init mpic_scan_ht_msi(struct mpic *mpic, u8 __iomem *devbase,
  				    unsigned int devfn)
  {
  	return;
  }
  #endif
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
463
464
  static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
  				    unsigned int devfn, u32 vdid)
14cf11af6   Paul Mackerras   powerpc: Merge en...
465
  {
c4b22f268   Segher Boessenkool   [PATCH] powerpc: ...
466
  	int i, irq, n;
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
467
  	u8 __iomem *base;
14cf11af6   Paul Mackerras   powerpc: Merge en...
468
  	u32 tmp;
c4b22f268   Segher Boessenkool   [PATCH] powerpc: ...
469
  	u8 pos;
14cf11af6   Paul Mackerras   powerpc: Merge en...
470

1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
471
472
473
  	for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0;
  	     pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) {
  		u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
46ff34633   Brice Goglin   MSI: Rename PCI_C...
474
  		if (id == PCI_CAP_ID_HT) {
c4b22f268   Segher Boessenkool   [PATCH] powerpc: ...
475
  			id = readb(devbase + pos + 3);
beb7cc823   Michael Ellerman   PCI: Only check t...
476
  			if ((id & HT_5BIT_CAP_MASK) == HT_CAPTYPE_IRQ)
c4b22f268   Segher Boessenkool   [PATCH] powerpc: ...
477
478
  				break;
  		}
14cf11af6   Paul Mackerras   powerpc: Merge en...
479
  	}
c4b22f268   Segher Boessenkool   [PATCH] powerpc: ...
480
481
  	if (pos == 0)
  		return;
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
482
483
484
  	base = devbase + pos;
  	writeb(0x01, base + 2);
  	n = (readl(base + 4) >> 16) & 0xff;
14cf11af6   Paul Mackerras   powerpc: Merge en...
485

1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
486
487
488
489
  	printk(KERN_INFO "mpic:   - HT:%02x.%x [0x%02x] vendor %04x device %04x"
  	       " has %d irqs
  ",
  	       devfn >> 3, devfn & 0x7, pos, vdid & 0xffff, vdid >> 16, n + 1);
c4b22f268   Segher Boessenkool   [PATCH] powerpc: ...
490
491
  
  	for (i = 0; i <= n; i++) {
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
492
493
  		writeb(0x10 + 2 * i, base + 2);
  		tmp = readl(base + 4);
14cf11af6   Paul Mackerras   powerpc: Merge en...
494
  		irq = (tmp >> 16) & 0xff;
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
495
496
497
498
499
500
501
502
503
504
505
506
507
508
  		DBG("HT PIC index 0x%x, irq 0x%x, tmp: %08x
  ", i, irq, tmp);
  		/* mask it , will be unmasked later */
  		tmp |= 0x1;
  		writel(tmp, base + 4);
  		mpic->fixups[irq].index = i;
  		mpic->fixups[irq].base = base;
  		/* Apple HT PIC has a non-standard way of doing EOIs */
  		if ((vdid & 0xffff) == 0x106b)
  			mpic->fixups[irq].applebase = devbase + 0x60;
  		else
  			mpic->fixups[irq].applebase = NULL;
  		writeb(0x11 + 2 * i, base + 2);
  		mpic->fixups[irq].data = readl(base + 4) | 0x80000000;
14cf11af6   Paul Mackerras   powerpc: Merge en...
509
510
511
  	}
  }
   
c4b22f268   Segher Boessenkool   [PATCH] powerpc: ...
512

1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
513
  static void __init mpic_scan_ht_pics(struct mpic *mpic)
14cf11af6   Paul Mackerras   powerpc: Merge en...
514
515
516
  {
  	unsigned int devfn;
  	u8 __iomem *cfgspace;
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
517
518
  	printk(KERN_INFO "mpic: Setting up HT PICs workarounds for U3/U4
  ");
14cf11af6   Paul Mackerras   powerpc: Merge en...
519
520
  
  	/* Allocate fixups array */
ea96025a2   Anton Vorontsov   powerpc: Don't us...
521
  	mpic->fixups = kzalloc(128 * sizeof(*mpic->fixups), GFP_KERNEL);
14cf11af6   Paul Mackerras   powerpc: Merge en...
522
  	BUG_ON(mpic->fixups == NULL);
14cf11af6   Paul Mackerras   powerpc: Merge en...
523
524
  
  	/* Init spinlock */
203041ad1   Thomas Gleixner   powerpc: Convert ...
525
  	raw_spin_lock_init(&mpic->fixup_lock);
14cf11af6   Paul Mackerras   powerpc: Merge en...
526

c4b22f268   Segher Boessenkool   [PATCH] powerpc: ...
527
528
  	/* Map U3 config space. We assume all IO-APICs are on the primary bus
  	 * so we only need to map 64kB.
14cf11af6   Paul Mackerras   powerpc: Merge en...
529
  	 */
c4b22f268   Segher Boessenkool   [PATCH] powerpc: ...
530
  	cfgspace = ioremap(0xf2000000, 0x10000);
14cf11af6   Paul Mackerras   powerpc: Merge en...
531
  	BUG_ON(cfgspace == NULL);
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
532
533
  	/* Now we scan all slots. We do a very quick scan, we read the header
  	 * type, vendor ID and device ID only, that's plenty enough
14cf11af6   Paul Mackerras   powerpc: Merge en...
534
  	 */
c4b22f268   Segher Boessenkool   [PATCH] powerpc: ...
535
  	for (devfn = 0; devfn < 0x100; devfn++) {
14cf11af6   Paul Mackerras   powerpc: Merge en...
536
537
538
  		u8 __iomem *devbase = cfgspace + (devfn << 8);
  		u8 hdr_type = readb(devbase + PCI_HEADER_TYPE);
  		u32 l = readl(devbase + PCI_VENDOR_ID);
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
539
  		u16 s;
14cf11af6   Paul Mackerras   powerpc: Merge en...
540
541
542
543
544
545
546
547
  
  		DBG("devfn %x, l: %x
  ", devfn, l);
  
  		/* If no device, skip */
  		if (l == 0xffffffff || l == 0x00000000 ||
  		    l == 0x0000ffff || l == 0xffff0000)
  			goto next;
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
548
549
550
551
  		/* Check if is supports capability lists */
  		s = readw(devbase + PCI_STATUS);
  		if (!(s & PCI_STATUS_CAP_LIST))
  			goto next;
14cf11af6   Paul Mackerras   powerpc: Merge en...
552

1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
553
  		mpic_scan_ht_pic(mpic, devbase, devfn, l);
812fd1fd6   Michael Ellerman   [POWERPC] Enable ...
554
  		mpic_scan_ht_msi(mpic, devbase, devfn);
c4b22f268   Segher Boessenkool   [PATCH] powerpc: ...
555

14cf11af6   Paul Mackerras   powerpc: Merge en...
556
557
  	next:
  		/* next device, if function 0 */
c4b22f268   Segher Boessenkool   [PATCH] powerpc: ...
558
  		if (PCI_FUNC(devfn) == 0 && (hdr_type & 0x80) == 0)
14cf11af6   Paul Mackerras   powerpc: Merge en...
559
560
561
  			devfn += 7;
  	}
  }
6cfef5b27   Michael Ellerman   [POWERPC] Rename ...
562
  #else /* CONFIG_MPIC_U3_HT_IRQS */
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
563
564
565
566
567
568
569
570
571
  
  static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source)
  {
  	return 0;
  }
  
  static void __init mpic_scan_ht_pics(struct mpic *mpic)
  {
  }
6cfef5b27   Michael Ellerman   [POWERPC] Rename ...
572
  #endif /* CONFIG_MPIC_U3_HT_IRQS */
14cf11af6   Paul Mackerras   powerpc: Merge en...
573

14cf11af6   Paul Mackerras   powerpc: Merge en...
574
  /* Find an mpic associated with a given linux interrupt */
d69a78d7d   Tony Breeds   powerpc/mpic: Cle...
575
  static struct mpic *mpic_find(unsigned int irq)
14cf11af6   Paul Mackerras   powerpc: Merge en...
576
  {
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
577
578
  	if (irq < NUM_ISA_INTERRUPTS)
  		return NULL;
7df2457db   Olof Johansson   [POWERPC] MPIC: s...
579

ec775d0e7   Thomas Gleixner   powerpc: Convert ...
580
  	return irq_get_chip_data(irq);
d69a78d7d   Tony Breeds   powerpc/mpic: Cle...
581
  }
7df2457db   Olof Johansson   [POWERPC] MPIC: s...
582

d69a78d7d   Tony Breeds   powerpc/mpic: Cle...
583
584
585
  /* Determine if the linux irq is an IPI */
  static unsigned int mpic_is_ipi(struct mpic *mpic, unsigned int irq)
  {
476eb4912   Grant Likely   powerpc/irq: Stop...
586
  	unsigned int src = virq_to_hw(irq);
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
587

d69a78d7d   Tony Breeds   powerpc/mpic: Cle...
588
  	return (src >= mpic->ipi_vecs[0] && src <= mpic->ipi_vecs[3]);
14cf11af6   Paul Mackerras   powerpc: Merge en...
589
  }
ea94187fa   Scott Wood   powerpc/mpic: add...
590
591
592
593
594
595
596
  /* Determine if the linux irq is a timer */
  static unsigned int mpic_is_tm(struct mpic *mpic, unsigned int irq)
  {
  	unsigned int src = virq_to_hw(irq);
  
  	return (src >= mpic->timer_vecs[0] && src <= mpic->timer_vecs[7]);
  }
d69a78d7d   Tony Breeds   powerpc/mpic: Cle...
597

14cf11af6   Paul Mackerras   powerpc: Merge en...
598
599
600
601
602
  /* Convert a cpu mask from logical to physical cpu numbers. */
  static inline u32 mpic_physmask(u32 cpumask)
  {
  	int i;
  	u32 mask = 0;
ebc042151   Milton Miller   powerpc/mpic: Lim...
603
  	for (i = 0; i < min(32, NR_CPUS); ++i, cpumask >>= 1)
14cf11af6   Paul Mackerras   powerpc: Merge en...
604
605
606
607
608
609
  		mask |= (cpumask & 1) << get_hard_smp_processor_id(i);
  	return mask;
  }
  
  #ifdef CONFIG_SMP
  /* Get the mpic structure from the IPI number */
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
610
  static inline struct mpic * mpic_from_ipi(struct irq_data *d)
14cf11af6   Paul Mackerras   powerpc: Merge en...
611
  {
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
612
  	return irq_data_get_irq_chip_data(d);
14cf11af6   Paul Mackerras   powerpc: Merge en...
613
614
615
616
617
618
  }
  #endif
  
  /* Get the mpic structure from the irq number */
  static inline struct mpic * mpic_from_irq(unsigned int irq)
  {
ec775d0e7   Thomas Gleixner   powerpc: Convert ...
619
  	return irq_get_chip_data(irq);
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
620
621
622
623
624
625
  }
  
  /* Get the mpic structure from the irq data */
  static inline struct mpic * mpic_from_irq_data(struct irq_data *d)
  {
  	return irq_data_get_irq_chip_data(d);
14cf11af6   Paul Mackerras   powerpc: Merge en...
626
627
628
629
630
  }
  
  /* Send an EOI */
  static inline void mpic_eoi(struct mpic *mpic)
  {
7233593b7   Zang Roy-r61911   [POWERPC] Support...
631
632
  	mpic_cpu_write(MPIC_INFO(CPU_EOI), 0);
  	(void)mpic_cpu_read(MPIC_INFO(CPU_WHOAMI));
14cf11af6   Paul Mackerras   powerpc: Merge en...
633
  }
14cf11af6   Paul Mackerras   powerpc: Merge en...
634
635
636
  /*
   * Linux descriptor level callbacks
   */
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
637
  void mpic_unmask_irq(struct irq_data *d)
14cf11af6   Paul Mackerras   powerpc: Merge en...
638
639
  {
  	unsigned int loops = 100000;
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
640
  	struct mpic *mpic = mpic_from_irq_data(d);
476eb4912   Grant Likely   powerpc/irq: Stop...
641
  	unsigned int src = irqd_to_hwirq(d);
14cf11af6   Paul Mackerras   powerpc: Merge en...
642

835c0553e   Lennert Buytenhek   powerpc: mpic irq...
643
644
  	DBG("%p: %s: enable_irq: %d (src %d)
  ", mpic, mpic->name, d->irq, src);
14cf11af6   Paul Mackerras   powerpc: Merge en...
645

7233593b7   Zang Roy-r61911   [POWERPC] Support...
646
647
  	mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
  		       mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) &
e53566409   Benjamin Herrenschmidt   [PATCH] powerpc: ...
648
  		       ~MPIC_VECPRI_MASK);
14cf11af6   Paul Mackerras   powerpc: Merge en...
649
650
651
  	/* make sure mask gets to controller before we return to user */
  	do {
  		if (!loops--) {
8bfc5e366   Scott Wood   powerpc/mpic: Fix...
652
653
654
  			printk(KERN_ERR "%s: timeout on hwirq %u
  ",
  			       __func__, src);
14cf11af6   Paul Mackerras   powerpc: Merge en...
655
656
  			break;
  		}
7233593b7   Zang Roy-r61911   [POWERPC] Support...
657
  	} while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK);
14cf11af6   Paul Mackerras   powerpc: Merge en...
658
  }
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
659
  void mpic_mask_irq(struct irq_data *d)
14cf11af6   Paul Mackerras   powerpc: Merge en...
660
661
  {
  	unsigned int loops = 100000;
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
662
  	struct mpic *mpic = mpic_from_irq_data(d);
476eb4912   Grant Likely   powerpc/irq: Stop...
663
  	unsigned int src = irqd_to_hwirq(d);
14cf11af6   Paul Mackerras   powerpc: Merge en...
664

835c0553e   Lennert Buytenhek   powerpc: mpic irq...
665
666
  	DBG("%s: disable_irq: %d (src %d)
  ", mpic->name, d->irq, src);
14cf11af6   Paul Mackerras   powerpc: Merge en...
667

7233593b7   Zang Roy-r61911   [POWERPC] Support...
668
669
  	mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
  		       mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) |
e53566409   Benjamin Herrenschmidt   [PATCH] powerpc: ...
670
  		       MPIC_VECPRI_MASK);
14cf11af6   Paul Mackerras   powerpc: Merge en...
671
672
673
674
  
  	/* make sure mask gets to controller before we return to user */
  	do {
  		if (!loops--) {
8bfc5e366   Scott Wood   powerpc/mpic: Fix...
675
676
677
  			printk(KERN_ERR "%s: timeout on hwirq %u
  ",
  			       __func__, src);
14cf11af6   Paul Mackerras   powerpc: Merge en...
678
679
  			break;
  		}
7233593b7   Zang Roy-r61911   [POWERPC] Support...
680
  	} while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
14cf11af6   Paul Mackerras   powerpc: Merge en...
681
  }
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
682
  void mpic_end_irq(struct irq_data *d)
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
683
  {
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
684
  	struct mpic *mpic = mpic_from_irq_data(d);
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
685
686
  
  #ifdef DEBUG_IRQ
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
687
688
  	DBG("%s: end_irq: %d
  ", mpic->name, d->irq);
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
689
690
691
692
693
694
695
696
  #endif
  	/* We always EOI on end_irq() even for edge interrupts since that
  	 * should only lower the priority, the MPIC should have properly
  	 * latched another edge interrupt coming in anyway
  	 */
  
  	mpic_eoi(mpic);
  }
6cfef5b27   Michael Ellerman   [POWERPC] Rename ...
697
  #ifdef CONFIG_MPIC_U3_HT_IRQS
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
698

835c0553e   Lennert Buytenhek   powerpc: mpic irq...
699
  static void mpic_unmask_ht_irq(struct irq_data *d)
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
700
  {
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
701
  	struct mpic *mpic = mpic_from_irq_data(d);
476eb4912   Grant Likely   powerpc/irq: Stop...
702
  	unsigned int src = irqd_to_hwirq(d);
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
703

835c0553e   Lennert Buytenhek   powerpc: mpic irq...
704
  	mpic_unmask_irq(d);
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
705

24a3f2e82   Thomas Gleixner   powerpc: mpic: Cl...
706
  	if (irqd_is_level_type(d))
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
707
708
  		mpic_ht_end_irq(mpic, src);
  }
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
709
  static unsigned int mpic_startup_ht_irq(struct irq_data *d)
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
710
  {
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
711
  	struct mpic *mpic = mpic_from_irq_data(d);
476eb4912   Grant Likely   powerpc/irq: Stop...
712
  	unsigned int src = irqd_to_hwirq(d);
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
713

835c0553e   Lennert Buytenhek   powerpc: mpic irq...
714
  	mpic_unmask_irq(d);
24a3f2e82   Thomas Gleixner   powerpc: mpic: Cl...
715
  	mpic_startup_ht_interrupt(mpic, src, irqd_is_level_type(d));
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
716
717
  
  	return 0;
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
718
  }
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
719
  static void mpic_shutdown_ht_irq(struct irq_data *d)
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
720
  {
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
721
  	struct mpic *mpic = mpic_from_irq_data(d);
476eb4912   Grant Likely   powerpc/irq: Stop...
722
  	unsigned int src = irqd_to_hwirq(d);
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
723

24a3f2e82   Thomas Gleixner   powerpc: mpic: Cl...
724
  	mpic_shutdown_ht_interrupt(mpic, src);
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
725
  	mpic_mask_irq(d);
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
726
  }
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
727
  static void mpic_end_ht_irq(struct irq_data *d)
14cf11af6   Paul Mackerras   powerpc: Merge en...
728
  {
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
729
  	struct mpic *mpic = mpic_from_irq_data(d);
476eb4912   Grant Likely   powerpc/irq: Stop...
730
  	unsigned int src = irqd_to_hwirq(d);
14cf11af6   Paul Mackerras   powerpc: Merge en...
731

1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
732
  #ifdef DEBUG_IRQ
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
733
734
  	DBG("%s: end_irq: %d
  ", mpic->name, d->irq);
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
735
  #endif
14cf11af6   Paul Mackerras   powerpc: Merge en...
736
737
738
739
  	/* We always EOI on end_irq() even for edge interrupts since that
  	 * should only lower the priority, the MPIC should have properly
  	 * latched another edge interrupt coming in anyway
  	 */
24a3f2e82   Thomas Gleixner   powerpc: mpic: Cl...
740
  	if (irqd_is_level_type(d))
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
741
  		mpic_ht_end_irq(mpic, src);
14cf11af6   Paul Mackerras   powerpc: Merge en...
742
743
  	mpic_eoi(mpic);
  }
6cfef5b27   Michael Ellerman   [POWERPC] Rename ...
744
  #endif /* !CONFIG_MPIC_U3_HT_IRQS */
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
745

14cf11af6   Paul Mackerras   powerpc: Merge en...
746
  #ifdef CONFIG_SMP
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
747
  static void mpic_unmask_ipi(struct irq_data *d)
14cf11af6   Paul Mackerras   powerpc: Merge en...
748
  {
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
749
  	struct mpic *mpic = mpic_from_ipi(d);
476eb4912   Grant Likely   powerpc/irq: Stop...
750
  	unsigned int src = virq_to_hw(d->irq) - mpic->ipi_vecs[0];
14cf11af6   Paul Mackerras   powerpc: Merge en...
751

835c0553e   Lennert Buytenhek   powerpc: mpic irq...
752
753
  	DBG("%s: enable_ipi: %d (ipi %d)
  ", mpic->name, d->irq, src);
14cf11af6   Paul Mackerras   powerpc: Merge en...
754
755
  	mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
  }
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
756
  static void mpic_mask_ipi(struct irq_data *d)
14cf11af6   Paul Mackerras   powerpc: Merge en...
757
758
759
  {
  	/* NEVER disable an IPI... that's just plain wrong! */
  }
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
760
  static void mpic_end_ipi(struct irq_data *d)
14cf11af6   Paul Mackerras   powerpc: Merge en...
761
  {
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
762
  	struct mpic *mpic = mpic_from_ipi(d);
14cf11af6   Paul Mackerras   powerpc: Merge en...
763
764
765
766
767
  
  	/*
  	 * IPIs are marked IRQ_PER_CPU. This has the side effect of
  	 * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from
  	 * applying to them. We EOI them late to avoid re-entering.
14cf11af6   Paul Mackerras   powerpc: Merge en...
768
769
770
771
772
  	 */
  	mpic_eoi(mpic);
  }
  
  #endif /* CONFIG_SMP */
ea94187fa   Scott Wood   powerpc/mpic: add...
773
774
775
776
  static void mpic_unmask_tm(struct irq_data *d)
  {
  	struct mpic *mpic = mpic_from_irq_data(d);
  	unsigned int src = virq_to_hw(d->irq) - mpic->timer_vecs[0];
77ef4899f   Dmitry Eremin-Solenikov   powerpc/mpic: Sup...
777
778
  	DBG("%s: enable_tm: %d (tm %d)
  ", mpic->name, d->irq, src);
ea94187fa   Scott Wood   powerpc/mpic: add...
779
780
781
782
783
784
785
786
787
788
789
790
  	mpic_tm_write(src, mpic_tm_read(src) & ~MPIC_VECPRI_MASK);
  	mpic_tm_read(src);
  }
  
  static void mpic_mask_tm(struct irq_data *d)
  {
  	struct mpic *mpic = mpic_from_irq_data(d);
  	unsigned int src = virq_to_hw(d->irq) - mpic->timer_vecs[0];
  
  	mpic_tm_write(src, mpic_tm_read(src) | MPIC_VECPRI_MASK);
  	mpic_tm_read(src);
  }
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
791
792
  int mpic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
  		      bool force)
14cf11af6   Paul Mackerras   powerpc: Merge en...
793
  {
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
794
  	struct mpic *mpic = mpic_from_irq_data(d);
476eb4912   Grant Likely   powerpc/irq: Stop...
795
  	unsigned int src = irqd_to_hwirq(d);
14cf11af6   Paul Mackerras   powerpc: Merge en...
796

3c10c9c45   Kumar Gala   powerpc/mpic: Fix...
797
  	if (mpic->flags & MPIC_SINGLE_DEST_CPU) {
38e1313fc   Yang Li   powerpc/mpic: Fix...
798
  		int cpuid = irq_choose_cpu(cpumask);
14cf11af6   Paul Mackerras   powerpc: Merge en...
799

3c10c9c45   Kumar Gala   powerpc/mpic: Fix...
800
801
  		mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid);
  	} else {
2a116f3dd   Milton Miller   powerpc/mpic: Bre...
802
  		u32 mask = cpumask_bits(cpumask)[0];
14cf11af6   Paul Mackerras   powerpc: Merge en...
803

2a116f3dd   Milton Miller   powerpc/mpic: Bre...
804
  		mask &= cpumask_bits(cpu_online_mask)[0];
3c10c9c45   Kumar Gala   powerpc/mpic: Fix...
805
806
  
  		mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION),
2a116f3dd   Milton Miller   powerpc/mpic: Bre...
807
  			       mpic_physmask(mask));
3c10c9c45   Kumar Gala   powerpc/mpic: Fix...
808
  	}
d5dedd450   Yinghai Lu   irq: change ->set...
809
810
  
  	return 0;
14cf11af6   Paul Mackerras   powerpc: Merge en...
811
  }
7233593b7   Zang Roy-r61911   [POWERPC] Support...
812
  static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
813
  {
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
814
  	/* Now convert sense value */
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
815
  	switch(type & IRQ_TYPE_SENSE_MASK) {
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
816
  	case IRQ_TYPE_EDGE_RISING:
7233593b7   Zang Roy-r61911   [POWERPC] Support...
817
818
  		return MPIC_INFO(VECPRI_SENSE_EDGE) |
  		       MPIC_INFO(VECPRI_POLARITY_POSITIVE);
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
819
  	case IRQ_TYPE_EDGE_FALLING:
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
820
  	case IRQ_TYPE_EDGE_BOTH:
7233593b7   Zang Roy-r61911   [POWERPC] Support...
821
822
  		return MPIC_INFO(VECPRI_SENSE_EDGE) |
  		       MPIC_INFO(VECPRI_POLARITY_NEGATIVE);
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
823
  	case IRQ_TYPE_LEVEL_HIGH:
7233593b7   Zang Roy-r61911   [POWERPC] Support...
824
825
  		return MPIC_INFO(VECPRI_SENSE_LEVEL) |
  		       MPIC_INFO(VECPRI_POLARITY_POSITIVE);
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
826
827
  	case IRQ_TYPE_LEVEL_LOW:
  	default:
7233593b7   Zang Roy-r61911   [POWERPC] Support...
828
829
  		return MPIC_INFO(VECPRI_SENSE_LEVEL) |
  		       MPIC_INFO(VECPRI_POLARITY_NEGATIVE);
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
830
  	}
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
831
  }
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
832
  int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
833
  {
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
834
  	struct mpic *mpic = mpic_from_irq_data(d);
476eb4912   Grant Likely   powerpc/irq: Stop...
835
  	unsigned int src = irqd_to_hwirq(d);
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
836
  	unsigned int vecpri, vold, vnew;
06fe98e63   Benjamin Herrenschmidt   [PATCH] powerpc: ...
837
838
  	DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)
  ",
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
839
  	    mpic, d->irq, src, flow_type);
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
840
841
842
843
844
845
846
847
848
  
  	if (src >= mpic->irq_count)
  		return -EINVAL;
  
  	if (flow_type == IRQ_TYPE_NONE)
  		if (mpic->senses && src < mpic->senses_count)
  			flow_type = mpic->senses[src];
  	if (flow_type == IRQ_TYPE_NONE)
  		flow_type = IRQ_TYPE_LEVEL_LOW;
24a3f2e82   Thomas Gleixner   powerpc: mpic: Cl...
849
  	irqd_set_trigger_type(d, flow_type);
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
850
851
852
853
854
  
  	if (mpic_is_ht_interrupt(mpic, src))
  		vecpri = MPIC_VECPRI_POLARITY_POSITIVE |
  			MPIC_VECPRI_SENSE_EDGE;
  	else
7233593b7   Zang Roy-r61911   [POWERPC] Support...
855
  		vecpri = mpic_type_to_vecpri(mpic, flow_type);
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
856

7233593b7   Zang Roy-r61911   [POWERPC] Support...
857
858
859
  	vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
  	vnew = vold & ~(MPIC_INFO(VECPRI_POLARITY_MASK) |
  			MPIC_INFO(VECPRI_SENSE_MASK));
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
860
861
  	vnew |= vecpri;
  	if (vold != vnew)
7233593b7   Zang Roy-r61911   [POWERPC] Support...
862
  		mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vnew);
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
863

e075cd700   Justin P. Mattock   powerpc/mpic: Rem...
864
  	return IRQ_SET_MASK_OK_NOCOPY;
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
865
  }
38958dd91   Olof Johansson   [POWERPC] pasemi:...
866
867
868
  void mpic_set_vector(unsigned int virq, unsigned int vector)
  {
  	struct mpic *mpic = mpic_from_irq(virq);
476eb4912   Grant Likely   powerpc/irq: Stop...
869
  	unsigned int src = virq_to_hw(virq);
38958dd91   Olof Johansson   [POWERPC] pasemi:...
870
871
872
873
874
875
876
877
878
879
880
881
882
883
  	unsigned int vecpri;
  
  	DBG("mpic: set_vector(mpic:@%p,virq:%d,src:%d,vector:0x%x)
  ",
  	    mpic, virq, src, vector);
  
  	if (src >= mpic->irq_count)
  		return;
  
  	vecpri = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
  	vecpri = vecpri & ~MPIC_INFO(VECPRI_VECTOR_MASK);
  	vecpri |= vector;
  	mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
  }
dfec22027   Meador Inge   powerpc: Make MPI...
884
885
886
  void mpic_set_destination(unsigned int virq, unsigned int cpuid)
  {
  	struct mpic *mpic = mpic_from_irq(virq);
476eb4912   Grant Likely   powerpc/irq: Stop...
887
  	unsigned int src = virq_to_hw(virq);
dfec22027   Meador Inge   powerpc: Make MPI...
888
889
890
891
892
893
894
895
896
897
  
  	DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)
  ",
  	    mpic, virq, src, cpuid);
  
  	if (src >= mpic->irq_count)
  		return;
  
  	mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid);
  }
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
898
  static struct irq_chip mpic_irq_chip = {
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
899
900
901
902
  	.irq_mask	= mpic_mask_irq,
  	.irq_unmask	= mpic_unmask_irq,
  	.irq_eoi	= mpic_end_irq,
  	.irq_set_type	= mpic_set_irq_type,
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
903
904
905
906
  };
  
  #ifdef CONFIG_SMP
  static struct irq_chip mpic_ipi_chip = {
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
907
908
909
  	.irq_mask	= mpic_mask_ipi,
  	.irq_unmask	= mpic_unmask_ipi,
  	.irq_eoi	= mpic_end_ipi,
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
910
911
  };
  #endif /* CONFIG_SMP */
ea94187fa   Scott Wood   powerpc/mpic: add...
912
913
914
915
916
  static struct irq_chip mpic_tm_chip = {
  	.irq_mask	= mpic_mask_tm,
  	.irq_unmask	= mpic_unmask_tm,
  	.irq_eoi	= mpic_end_irq,
  };
6cfef5b27   Michael Ellerman   [POWERPC] Rename ...
917
  #ifdef CONFIG_MPIC_U3_HT_IRQS
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
918
  static struct irq_chip mpic_irq_ht_chip = {
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
919
920
921
922
923
924
  	.irq_startup	= mpic_startup_ht_irq,
  	.irq_shutdown	= mpic_shutdown_ht_irq,
  	.irq_mask	= mpic_mask_irq,
  	.irq_unmask	= mpic_unmask_ht_irq,
  	.irq_eoi	= mpic_end_ht_irq,
  	.irq_set_type	= mpic_set_irq_type,
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
925
  };
6cfef5b27   Michael Ellerman   [POWERPC] Rename ...
926
  #endif /* CONFIG_MPIC_U3_HT_IRQS */
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
927

14cf11af6   Paul Mackerras   powerpc: Merge en...
928

0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
929
930
  static int mpic_host_match(struct irq_host *h, struct device_node *node)
  {
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
931
  	/* Exact match, unless mpic node is NULL */
52964f87c   Michael Ellerman   [POWERPC] Add an ...
932
  	return h->of_node == NULL || h->of_node == node;
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
933
934
935
  }
  
  static int mpic_host_map(struct irq_host *h, unsigned int virq,
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
936
  			 irq_hw_number_t hw)
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
937
  {
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
938
  	struct mpic *mpic = h->host_data;
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
939
  	struct irq_chip *chip;
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
940

06fe98e63   Benjamin Herrenschmidt   [PATCH] powerpc: ...
941
942
  	DBG("mpic: map virq %d, hwirq 0x%lx
  ", virq, hw);
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
943

7df2457db   Olof Johansson   [POWERPC] MPIC: s...
944
  	if (hw == mpic->spurious_vec)
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
945
  		return -EINVAL;
7fd721861   Benjamin Herrenschmidt   [POWERPC] MPIC pr...
946
947
  	if (mpic->protected && test_bit(hw, mpic->protected))
  		return -EINVAL;
06fe98e63   Benjamin Herrenschmidt   [PATCH] powerpc: ...
948

0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
949
  #ifdef CONFIG_SMP
7df2457db   Olof Johansson   [POWERPC] MPIC: s...
950
  	else if (hw >= mpic->ipi_vecs[0]) {
be8bec56d   Kyle Moffett   powerpc/mpic: Inv...
951
  		WARN_ON(mpic->flags & MPIC_SECONDARY);
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
952

06fe98e63   Benjamin Herrenschmidt   [PATCH] powerpc: ...
953
954
  		DBG("mpic: mapping as IPI
  ");
ec775d0e7   Thomas Gleixner   powerpc: Convert ...
955
956
  		irq_set_chip_data(virq, mpic);
  		irq_set_chip_and_handler(virq, &mpic->hc_ipi,
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
957
958
959
960
  					 handle_percpu_irq);
  		return 0;
  	}
  #endif /* CONFIG_SMP */
ea94187fa   Scott Wood   powerpc/mpic: add...
961
  	if (hw >= mpic->timer_vecs[0] && hw <= mpic->timer_vecs[7]) {
be8bec56d   Kyle Moffett   powerpc/mpic: Inv...
962
  		WARN_ON(mpic->flags & MPIC_SECONDARY);
ea94187fa   Scott Wood   powerpc/mpic: add...
963
964
965
966
967
968
969
970
  
  		DBG("mpic: mapping as timer
  ");
  		irq_set_chip_data(virq, mpic);
  		irq_set_chip_and_handler(virq, &mpic->hc_tm,
  					 handle_fasteoi_irq);
  		return 0;
  	}
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
971
972
  	if (hw >= mpic->irq_count)
  		return -EINVAL;
a7de7c742   Michael Ellerman   [POWERPC] MPIC MS...
973
  	mpic_msi_reserve_hwirq(mpic, hw);
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
974
  	/* Default chip */
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
975
  	chip = &mpic->hc_irq;
6cfef5b27   Michael Ellerman   [POWERPC] Rename ...
976
  #ifdef CONFIG_MPIC_U3_HT_IRQS
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
977
  	/* Check for HT interrupts, override vecpri */
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
978
  	if (mpic_is_ht_interrupt(mpic, hw))
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
979
  		chip = &mpic->hc_ht_irq;
6cfef5b27   Michael Ellerman   [POWERPC] Rename ...
980
  #endif /* CONFIG_MPIC_U3_HT_IRQS */
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
981

06fe98e63   Benjamin Herrenschmidt   [PATCH] powerpc: ...
982
983
  	DBG("mpic: mapping to irq chip @%p
  ", chip);
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
984

ec775d0e7   Thomas Gleixner   powerpc: Convert ...
985
986
  	irq_set_chip_data(virq, mpic);
  	irq_set_chip_and_handler(virq, chip, handle_fasteoi_irq);
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
987
988
  
  	/* Set default irq type */
ec775d0e7   Thomas Gleixner   powerpc: Convert ...
989
  	irq_set_irq_type(virq, IRQ_TYPE_NONE);
6e99e4582   Benjamin Herrenschmidt   [PATCH] powerpc: ...
990

dfec22027   Meador Inge   powerpc: Make MPI...
991
992
993
994
995
  	/* If the MPIC was reset, then all vectors have already been
  	 * initialized.  Otherwise, a per source lazy initialization
  	 * is done here.
  	 */
  	if (!mpic_is_ipi(mpic, hw) && (mpic->flags & MPIC_NO_RESET)) {
dfec22027   Meador Inge   powerpc: Make MPI...
996
  		mpic_set_vector(virq, hw);
d6a2639b8   Meador Inge   powerpc: Factorin...
997
  		mpic_set_destination(virq, mpic_processor_id(mpic));
dfec22027   Meador Inge   powerpc: Make MPI...
998
999
  		mpic_irq_set_priority(virq, 8);
  	}
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
1000
1001
1002
1003
  	return 0;
  }
  
  static int mpic_host_xlate(struct irq_host *h, struct device_node *ct,
40d50cf7c   Roman Fietze   powerpc: Make "in...
1004
  			   const u32 *intspec, unsigned int intsize,
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
1005
1006
1007
  			   irq_hw_number_t *out_hwirq, unsigned int *out_flags)
  
  {
22d168ce6   Scott Wood   powerpc/mpic: par...
1008
  	struct mpic *mpic = h->host_data;
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
1009
1010
1011
1012
1013
1014
1015
1016
  	static unsigned char map_mpic_senses[4] = {
  		IRQ_TYPE_EDGE_RISING,
  		IRQ_TYPE_LEVEL_LOW,
  		IRQ_TYPE_LEVEL_HIGH,
  		IRQ_TYPE_EDGE_FALLING,
  	};
  
  	*out_hwirq = intspec[0];
22d168ce6   Scott Wood   powerpc/mpic: par...
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
  	if (intsize >= 4 && (mpic->flags & MPIC_FSL)) {
  		/*
  		 * Freescale MPIC with extended intspec:
  		 * First two cells are as usual.  Third specifies
  		 * an "interrupt type".  Fourth is type-specific data.
  		 *
  		 * See Documentation/devicetree/bindings/powerpc/fsl/mpic.txt
  		 */
  		switch (intspec[2]) {
  		case 0:
  		case 1: /* no EISR/EIMR support for now, treat as shared IRQ */
  			break;
  		case 2:
  			if (intspec[0] >= ARRAY_SIZE(mpic->ipi_vecs))
  				return -EINVAL;
  
  			*out_hwirq = mpic->ipi_vecs[intspec[0]];
  			break;
  		case 3:
  			if (intspec[0] >= ARRAY_SIZE(mpic->timer_vecs))
  				return -EINVAL;
  
  			*out_hwirq = mpic->timer_vecs[intspec[0]];
  			break;
  		default:
  			pr_debug("%s: unknown irq type %u
  ",
  				 __func__, intspec[2]);
  			return -EINVAL;
  		}
  
  		*out_flags = map_mpic_senses[intspec[1] & 3];
  	} else if (intsize > 1) {
06fe98e63   Benjamin Herrenschmidt   [PATCH] powerpc: ...
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
  		u32 mask = 0x3;
  
  		/* Apple invented a new race of encoding on machines with
  		 * an HT APIC. They encode, among others, the index within
  		 * the HT APIC. We don't care about it here since thankfully,
  		 * it appears that they have the APIC already properly
  		 * configured, and thus our current fixup code that reads the
  		 * APIC config works fine. However, we still need to mask out
  		 * bits in the specifier to make sure we only get bit 0 which
  		 * is the level/edge bit (the only sense bit exposed by Apple),
  		 * as their bit 1 means something else.
  		 */
  		if (machine_is(powermac))
  			mask = 0x1;
  		*out_flags = map_mpic_senses[intspec[1] & mask];
  	} else
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
1066
  		*out_flags = IRQ_TYPE_NONE;
06fe98e63   Benjamin Herrenschmidt   [PATCH] powerpc: ...
1067
1068
1069
  	DBG("mpic: xlate (%d cells: 0x%08x 0x%08x) to line 0x%lx sense 0x%x
  ",
  	    intsize, intspec[0], intspec[1], *out_hwirq, *out_flags);
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
1070
1071
  	return 0;
  }
09dc34a95   Kyle Moffett   powerpc/mpic: Add...
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
  /* IRQ handler for a secondary MPIC cascaded from another IRQ controller */
  static void mpic_cascade(unsigned int irq, struct irq_desc *desc)
  {
  	struct irq_chip *chip = irq_desc_get_chip(desc);
  	struct mpic *mpic = irq_desc_get_handler_data(desc);
  	unsigned int virq;
  
  	BUG_ON(!(mpic->flags & MPIC_SECONDARY));
  
  	virq = mpic_get_one_irq(mpic);
  	if (virq != NO_IRQ)
  		generic_handle_irq(virq);
  
  	chip->irq_eoi(&desc->irq_data);
  }
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
1087
1088
1089
1090
1091
  static struct irq_host_ops mpic_host_ops = {
  	.match = mpic_host_match,
  	.map = mpic_host_map,
  	.xlate = mpic_host_xlate,
  };
14cf11af6   Paul Mackerras   powerpc: Merge en...
1092
1093
1094
  /*
   * Exported functions
   */
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
1095
  struct mpic * __init mpic_alloc(struct device_node *node,
a959ff56b   Benjamin Herrenschmidt   [POWERPC] Improve...
1096
  				phys_addr_t phys_addr,
14cf11af6   Paul Mackerras   powerpc: Merge en...
1097
1098
  				unsigned int flags,
  				unsigned int isu_size,
14cf11af6   Paul Mackerras   powerpc: Merge en...
1099
  				unsigned int irq_count,
14cf11af6   Paul Mackerras   powerpc: Merge en...
1100
1101
  				const char *name)
  {
5bdb6f2e5   Kyle Moffett   powerpc/mpic: Ass...
1102
1103
1104
1105
1106
  	int i, psize, intvec_top;
  	struct mpic *mpic;
  	u32 greg_feature;
  	const char *vers;
  	const u32 *psrc;
8bf415689   Kyle Moffett   powerpc: Consolid...
1107

996983b75   Kyle Moffett   powerpc/mpic: Sea...
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
  	/* Default MPIC search parameters */
  	static const struct of_device_id __initconst mpic_device_id[] = {
  		{ .type	      = "open-pic", },
  		{ .compatible = "open-pic", },
  		{},
  	};
  
  	/*
  	 * If we were not passed a device-tree node, then perform the default
  	 * search for standardized a standardized OpenPIC.
  	 */
  	if (node) {
  		node = of_node_get(node);
  	} else {
  		node = of_find_matching_node(NULL, mpic_device_id);
  		if (!node)
  			return NULL;
  	}
8bf415689   Kyle Moffett   powerpc: Consolid...
1126

5bdb6f2e5   Kyle Moffett   powerpc/mpic: Ass...
1127
1128
  	/* Pick the physical address from the device tree if unspecified */
  	if (!phys_addr) {
8bf415689   Kyle Moffett   powerpc: Consolid...
1129
1130
1131
1132
1133
1134
  		/* Check if it is DCR-based */
  		if (of_get_property(node, "dcr-reg", NULL)) {
  			flags |= MPIC_USES_DCR;
  		} else {
  			struct resource r;
  			if (of_address_to_resource(node, 0, &r))
996983b75   Kyle Moffett   powerpc/mpic: Sea...
1135
  				goto err_of_node_put;
8bf415689   Kyle Moffett   powerpc: Consolid...
1136
1137
1138
  			phys_addr = r.start;
  		}
  	}
14cf11af6   Paul Mackerras   powerpc: Merge en...
1139

85355bb27   Kumar Gala   powerpc: Fix mpic...
1140
  	mpic = kzalloc(sizeof(struct mpic), GFP_KERNEL);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1141
  	if (mpic == NULL)
996983b75   Kyle Moffett   powerpc/mpic: Sea...
1142
  		goto err_of_node_put;
85355bb27   Kumar Gala   powerpc: Fix mpic...
1143

14cf11af6   Paul Mackerras   powerpc: Merge en...
1144
  	mpic->name = name;
c51242e70   Kyle Moffett   powerpc/mpic: Cac...
1145
  	mpic->node = node;
e7a98675c   Kyle Moffett   powerpc/mpic: Sav...
1146
  	mpic->paddr = phys_addr;
14cf11af6   Paul Mackerras   powerpc: Merge en...
1147

b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
1148
  	mpic->hc_irq = mpic_irq_chip;
b27df6724   Thomas Gleixner   powerpc: Fixup la...
1149
  	mpic->hc_irq.name = name;
be8bec56d   Kyle Moffett   powerpc/mpic: Inv...
1150
  	if (!(flags & MPIC_SECONDARY))
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
1151
  		mpic->hc_irq.irq_set_affinity = mpic_set_affinity;
6cfef5b27   Michael Ellerman   [POWERPC] Rename ...
1152
  #ifdef CONFIG_MPIC_U3_HT_IRQS
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
1153
  	mpic->hc_ht_irq = mpic_irq_ht_chip;
b27df6724   Thomas Gleixner   powerpc: Fixup la...
1154
  	mpic->hc_ht_irq.name = name;
be8bec56d   Kyle Moffett   powerpc/mpic: Inv...
1155
  	if (!(flags & MPIC_SECONDARY))
835c0553e   Lennert Buytenhek   powerpc: mpic irq...
1156
  		mpic->hc_ht_irq.irq_set_affinity = mpic_set_affinity;
6cfef5b27   Michael Ellerman   [POWERPC] Rename ...
1157
  #endif /* CONFIG_MPIC_U3_HT_IRQS */
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
1158

14cf11af6   Paul Mackerras   powerpc: Merge en...
1159
  #ifdef CONFIG_SMP
b9e5b4e6a   Benjamin Herrenschmidt   [POWERPC] Use the...
1160
  	mpic->hc_ipi = mpic_ipi_chip;
b27df6724   Thomas Gleixner   powerpc: Fixup la...
1161
  	mpic->hc_ipi.name = name;
14cf11af6   Paul Mackerras   powerpc: Merge en...
1162
  #endif /* CONFIG_SMP */
ea94187fa   Scott Wood   powerpc/mpic: add...
1163
1164
  	mpic->hc_tm = mpic_tm_chip;
  	mpic->hc_tm.name = name;
14cf11af6   Paul Mackerras   powerpc: Merge en...
1165
1166
  	mpic->flags = flags;
  	mpic->isu_size = isu_size;
14cf11af6   Paul Mackerras   powerpc: Merge en...
1167
  	mpic->irq_count = irq_count;
14cf11af6   Paul Mackerras   powerpc: Merge en...
1168
  	mpic->num_sources = 0; /* so far */
14cf11af6   Paul Mackerras   powerpc: Merge en...
1169

7df2457db   Olof Johansson   [POWERPC] MPIC: s...
1170
1171
1172
1173
  	if (flags & MPIC_LARGE_VECTORS)
  		intvec_top = 2047;
  	else
  		intvec_top = 255;
ea94187fa   Scott Wood   powerpc/mpic: add...
1174
1175
1176
1177
1178
1179
1180
1181
  	mpic->timer_vecs[0] = intvec_top - 12;
  	mpic->timer_vecs[1] = intvec_top - 11;
  	mpic->timer_vecs[2] = intvec_top - 10;
  	mpic->timer_vecs[3] = intvec_top - 9;
  	mpic->timer_vecs[4] = intvec_top - 8;
  	mpic->timer_vecs[5] = intvec_top - 7;
  	mpic->timer_vecs[6] = intvec_top - 6;
  	mpic->timer_vecs[7] = intvec_top - 5;
7df2457db   Olof Johansson   [POWERPC] MPIC: s...
1182
1183
1184
1185
1186
  	mpic->ipi_vecs[0]   = intvec_top - 4;
  	mpic->ipi_vecs[1]   = intvec_top - 3;
  	mpic->ipi_vecs[2]   = intvec_top - 2;
  	mpic->ipi_vecs[3]   = intvec_top - 1;
  	mpic->spurious_vec  = intvec_top;
a959ff56b   Benjamin Herrenschmidt   [POWERPC] Improve...
1187
  	/* Check for "big-endian" in device-tree */
c51242e70   Kyle Moffett   powerpc/mpic: Cac...
1188
  	if (of_get_property(mpic->node, "big-endian", NULL) != NULL)
a959ff56b   Benjamin Herrenschmidt   [POWERPC] Improve...
1189
  		mpic->flags |= MPIC_BIG_ENDIAN;
c51242e70   Kyle Moffett   powerpc/mpic: Cac...
1190
  	if (of_device_is_compatible(mpic->node, "fsl,mpic"))
22d168ce6   Scott Wood   powerpc/mpic: par...
1191
  		mpic->flags |= MPIC_FSL;
a959ff56b   Benjamin Herrenschmidt   [POWERPC] Improve...
1192

7fd721861   Benjamin Herrenschmidt   [POWERPC] MPIC pr...
1193
  	/* Look for protected sources */
c51242e70   Kyle Moffett   powerpc/mpic: Cac...
1194
  	psrc = of_get_property(mpic->node, "protected-sources", &psize);
5bdb6f2e5   Kyle Moffett   powerpc/mpic: Ass...
1195
1196
1197
1198
1199
1200
1201
1202
1203
  	if (psrc) {
  		/* Allocate a bitmap with one bit per interrupt */
  		unsigned int mapsize = BITS_TO_LONGS(intvec_top + 1);
  		mpic->protected = kzalloc(mapsize*sizeof(long), GFP_KERNEL);
  		BUG_ON(mpic->protected == NULL);
  		for (i = 0; i < psize/sizeof(u32); i++) {
  			if (psrc[i] > intvec_top)
  				continue;
  			__set_bit(psrc[i], mpic->protected);
7fd721861   Benjamin Herrenschmidt   [POWERPC] MPIC pr...
1204
1205
  		}
  	}
a959ff56b   Benjamin Herrenschmidt   [POWERPC] Improve...
1206

7233593b7   Zang Roy-r61911   [POWERPC] Support...
1207
1208
1209
  #ifdef CONFIG_MPIC_WEIRD
  	mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)];
  #endif
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
1210
  	/* default register type */
8bf415689   Kyle Moffett   powerpc: Consolid...
1211
1212
1213
1214
  	if (flags & MPIC_BIG_ENDIAN)
  		mpic->reg_type = mpic_access_mmio_be;
  	else
  		mpic->reg_type = mpic_access_mmio_le;
a959ff56b   Benjamin Herrenschmidt   [POWERPC] Improve...
1215

8bf415689   Kyle Moffett   powerpc: Consolid...
1216
1217
1218
1219
  	/*
  	 * An MPIC with a "dcr-reg" property must be accessed that way, but
  	 * only if the kernel includes DCR support.
  	 */
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
1220
  #ifdef CONFIG_PPC_DCR
8bf415689   Kyle Moffett   powerpc: Consolid...
1221
  	if (flags & MPIC_USES_DCR)
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
1222
  		mpic->reg_type = mpic_access_dcr;
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
1223
  #else
8bf415689   Kyle Moffett   powerpc: Consolid...
1224
1225
  	BUG_ON(flags & MPIC_USES_DCR);
  #endif
a959ff56b   Benjamin Herrenschmidt   [POWERPC] Improve...
1226

14cf11af6   Paul Mackerras   powerpc: Merge en...
1227
  	/* Map the global registers */
c51242e70   Kyle Moffett   powerpc/mpic: Cac...
1228
1229
  	mpic_map(mpic, mpic->paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000);
  	mpic_map(mpic, mpic->paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1230
1231
  
  	/* Reset */
dfec22027   Meador Inge   powerpc: Make MPI...
1232
1233
1234
1235
  
  	/* When using a device-node, reset requests are only honored if the MPIC
  	 * is allowed to reset.
  	 */
c51242e70   Kyle Moffett   powerpc/mpic: Cac...
1236
  	if (of_get_property(mpic->node, "pic-no-reset", NULL))
dfec22027   Meador Inge   powerpc: Make MPI...
1237
1238
1239
1240
1241
  		mpic->flags |= MPIC_NO_RESET;
  
  	if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) {
  		printk(KERN_DEBUG "mpic: Resetting
  ");
7233593b7   Zang Roy-r61911   [POWERPC] Support...
1242
1243
  		mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
  			   mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
14cf11af6   Paul Mackerras   powerpc: Merge en...
1244
  			   | MPIC_GREG_GCONF_RESET);
7233593b7   Zang Roy-r61911   [POWERPC] Support...
1245
  		while( mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
14cf11af6   Paul Mackerras   powerpc: Merge en...
1246
1247
1248
  		       & MPIC_GREG_GCONF_RESET)
  			mb();
  	}
d91e4ea70   Kumar Gala   powerpc: Add supp...
1249
1250
1251
1252
1253
  	/* CoreInt */
  	if (flags & MPIC_ENABLE_COREINT)
  		mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
  			   mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
  			   | MPIC_GREG_GCONF_COREINT);
f365355e6   Olof Johansson   [POWERPC] pasemi:...
1254
1255
1256
1257
  	if (flags & MPIC_ENABLE_MCK)
  		mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
  			   mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
  			   | MPIC_GREG_GCONF_MCK);
14b924701   Timur Tabi   powerpc/mpic: Add...
1258
1259
1260
  	/*
  	 * Read feature register.  For non-ISU MPICs, num sources as well. On
  	 * ISU MPICs, sources are counted as ISUs are added
14cf11af6   Paul Mackerras   powerpc: Merge en...
1261
  	 */
d9d1063d4   Johannes Berg   [POWERPC] mpic: M...
1262
  	greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
5073e7ee8   Anton Vorontsov   powerpc/mpic: Fix...
1263
  	if (isu_size == 0) {
475ca391b   Kumar Gala   [POWERPC] mpic: D...
1264
1265
1266
1267
1268
1269
  		if (flags & MPIC_BROKEN_FRR_NIRQS)
  			mpic->num_sources = mpic->irq_count;
  		else
  			mpic->num_sources =
  				((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
  				 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
5073e7ee8   Anton Vorontsov   powerpc/mpic: Fix...
1270
  	}
14cf11af6   Paul Mackerras   powerpc: Merge en...
1271

14b924701   Timur Tabi   powerpc/mpic: Add...
1272
1273
1274
1275
1276
  	/*
  	 * The MPIC driver will crash if there are more cores than we
  	 * can initialize, so we may as well catch that problem here.
  	 */
  	BUG_ON(num_possible_cpus() > MPIC_MAX_CPUS);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1277
  	/* Map the per-CPU registers */
14b924701   Timur Tabi   powerpc/mpic: Add...
1278
1279
  	for_each_possible_cpu(i) {
  		unsigned int cpu = get_hard_smp_processor_id(i);
c51242e70   Kyle Moffett   powerpc/mpic: Cac...
1280
  		mpic_map(mpic, mpic->paddr, &mpic->cpuregs[cpu],
14b924701   Timur Tabi   powerpc/mpic: Add...
1281
  			 MPIC_INFO(CPU_BASE) + cpu * MPIC_INFO(CPU_STRIDE),
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
1282
  			 0x1000);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1283
1284
1285
1286
1287
  	}
  
  	/* Initialize main ISU if none provided */
  	if (mpic->isu_size == 0) {
  		mpic->isu_size = mpic->num_sources;
c51242e70   Kyle Moffett   powerpc/mpic: Cac...
1288
  		mpic_map(mpic, mpic->paddr, &mpic->isus[0],
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
1289
  			 MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1290
1291
1292
  	}
  	mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
  	mpic->isu_mask = (1 << mpic->isu_shift) - 1;
c51242e70   Kyle Moffett   powerpc/mpic: Cac...
1293
  	mpic->irqhost = irq_alloc_host(mpic->node, IRQ_HOST_MAP_LINEAR,
31207dab7   Kumar Gala   powerpc/mpic: Fix...
1294
1295
1296
  				       isu_size ? isu_size : mpic->num_sources,
  				       &mpic_host_ops,
  				       flags & MPIC_LARGE_VECTORS ? 2048 : 256);
996983b75   Kyle Moffett   powerpc/mpic: Sea...
1297
1298
1299
1300
1301
  
  	/*
  	 * FIXME: The code leaks the MPIC object and mappings here; this
  	 * is very unlikely to fail but it ought to be fixed anyways.
  	 */
31207dab7   Kumar Gala   powerpc/mpic: Fix...
1302
1303
1304
1305
  	if (mpic->irqhost == NULL)
  		return NULL;
  
  	mpic->irqhost->host_data = mpic;
14cf11af6   Paul Mackerras   powerpc: Merge en...
1306
  	/* Display version */
d9d1063d4   Johannes Berg   [POWERPC] mpic: M...
1307
  	switch (greg_feature & MPIC_GREG_FEATURE_VERSION_MASK) {
14cf11af6   Paul Mackerras   powerpc: Merge en...
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
  	case 1:
  		vers = "1.0";
  		break;
  	case 2:
  		vers = "1.2";
  		break;
  	case 3:
  		vers = "1.3";
  		break;
  	default:
  		vers = "<unknown>";
  		break;
  	}
a959ff56b   Benjamin Herrenschmidt   [POWERPC] Improve...
1321
1322
1323
  	printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %llx,"
  	       " max %d CPUs
  ",
e7a98675c   Kyle Moffett   powerpc/mpic: Sav...
1324
  	       name, vers, (unsigned long long)mpic->paddr, num_possible_cpus());
a959ff56b   Benjamin Herrenschmidt   [POWERPC] Improve...
1325
1326
1327
  	printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x
  ",
  	       mpic->isu_size, mpic->isu_shift, mpic->isu_mask);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1328
1329
1330
  
  	mpic->next = mpics;
  	mpics = mpic;
be8bec56d   Kyle Moffett   powerpc/mpic: Inv...
1331
  	if (!(flags & MPIC_SECONDARY)) {
14cf11af6   Paul Mackerras   powerpc: Merge en...
1332
  		mpic_primary = mpic;
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
1333
1334
  		irq_set_default_host(mpic->irqhost);
  	}
14cf11af6   Paul Mackerras   powerpc: Merge en...
1335
1336
  
  	return mpic;
996983b75   Kyle Moffett   powerpc/mpic: Sea...
1337
1338
1339
1340
  
  err_of_node_put:
  	of_node_put(node);
  	return NULL;
14cf11af6   Paul Mackerras   powerpc: Merge en...
1341
1342
1343
  }
  
  void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
a959ff56b   Benjamin Herrenschmidt   [POWERPC] Improve...
1344
  			    phys_addr_t paddr)
14cf11af6   Paul Mackerras   powerpc: Merge en...
1345
1346
1347
1348
  {
  	unsigned int isu_first = isu_num * mpic->isu_size;
  
  	BUG_ON(isu_num >= MPIC_MAX_ISU);
c51242e70   Kyle Moffett   powerpc/mpic: Cac...
1349
  	mpic_map(mpic,
5a2642f62   Benjamin Herrenschmidt   powerpc/mpic: Fix...
1350
  		 paddr, &mpic->isus[isu_num], 0,
fbf0274e4   Benjamin Herrenschmidt   [POWERPC] Support...
1351
  		 MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
5a2642f62   Benjamin Herrenschmidt   powerpc/mpic: Fix...
1352

14cf11af6   Paul Mackerras   powerpc: Merge en...
1353
1354
1355
  	if ((isu_first + mpic->isu_size) > mpic->num_sources)
  		mpic->num_sources = isu_first + mpic->isu_size;
  }
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
1356
1357
1358
1359
1360
  void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count)
  {
  	mpic->senses = senses;
  	mpic->senses_count = count;
  }
14cf11af6   Paul Mackerras   powerpc: Merge en...
1361
1362
  void __init mpic_init(struct mpic *mpic)
  {
09dc34a95   Kyle Moffett   powerpc/mpic: Add...
1363
  	int i, cpu;
14cf11af6   Paul Mackerras   powerpc: Merge en...
1364
1365
1366
1367
1368
1369
1370
  
  	BUG_ON(mpic->num_sources == 0);
  
  	printk(KERN_INFO "mpic: Initializing for %d sources
  ", mpic->num_sources);
  
  	/* Set current processor priority to max */
7233593b7   Zang Roy-r61911   [POWERPC] Support...
1371
  	mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1372

ea94187fa   Scott Wood   powerpc/mpic: add...
1373
  	/* Initialize timers to our reserved vectors and mask them for now */
14cf11af6   Paul Mackerras   powerpc: Merge en...
1374
1375
  	for (i = 0; i < 4; i++) {
  		mpic_write(mpic->tmregs,
7233593b7   Zang Roy-r61911   [POWERPC] Support...
1376
  			   i * MPIC_INFO(TIMER_STRIDE) +
ea94187fa   Scott Wood   powerpc/mpic: add...
1377
1378
  			   MPIC_INFO(TIMER_DESTINATION),
  			   1 << hard_smp_processor_id());
14cf11af6   Paul Mackerras   powerpc: Merge en...
1379
  		mpic_write(mpic->tmregs,
7233593b7   Zang Roy-r61911   [POWERPC] Support...
1380
1381
  			   i * MPIC_INFO(TIMER_STRIDE) +
  			   MPIC_INFO(TIMER_VECTOR_PRI),
14cf11af6   Paul Mackerras   powerpc: Merge en...
1382
  			   MPIC_VECPRI_MASK |
ea94187fa   Scott Wood   powerpc/mpic: add...
1383
  			   (9 << MPIC_VECPRI_PRIORITY_SHIFT) |
7df2457db   Olof Johansson   [POWERPC] MPIC: s...
1384
  			   (mpic->timer_vecs[0] + i));
14cf11af6   Paul Mackerras   powerpc: Merge en...
1385
1386
1387
1388
1389
1390
1391
1392
  	}
  
  	/* Initialize IPIs to our reserved vectors and mark them disabled for now */
  	mpic_test_broken_ipi(mpic);
  	for (i = 0; i < 4; i++) {
  		mpic_ipi_write(i,
  			       MPIC_VECPRI_MASK |
  			       (10 << MPIC_VECPRI_PRIORITY_SHIFT) |
7df2457db   Olof Johansson   [POWERPC] MPIC: s...
1393
  			       (mpic->ipi_vecs[0] + i));
14cf11af6   Paul Mackerras   powerpc: Merge en...
1394
1395
1396
1397
1398
  	}
  
  	/* Initialize interrupt sources */
  	if (mpic->irq_count == 0)
  		mpic->irq_count = mpic->num_sources;
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
1399
  	/* Do the HT PIC fixups on U3 broken mpic */
14cf11af6   Paul Mackerras   powerpc: Merge en...
1400
1401
  	DBG("MPIC flags: %x
  ", mpic->flags);
be8bec56d   Kyle Moffett   powerpc/mpic: Inv...
1402
  	if ((mpic->flags & MPIC_U3_HT_IRQS) && !(mpic->flags & MPIC_SECONDARY)) {
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
1403
  		mpic_scan_ht_pics(mpic);
05af7bd2d   Michael Ellerman   [POWERPC] MPIC U3...
1404
1405
  		mpic_u3msi_init(mpic);
  	}
14cf11af6   Paul Mackerras   powerpc: Merge en...
1406

38958dd91   Olof Johansson   [POWERPC] pasemi:...
1407
  	mpic_pasemi_msi_init(mpic);
d6a2639b8   Meador Inge   powerpc: Factorin...
1408
  	cpu = mpic_processor_id(mpic);
cc353c30b   Arnd Bergmann   powerpc/mpic: Don...
1409

dfec22027   Meador Inge   powerpc: Make MPI...
1410
1411
1412
1413
1414
  	if (!(mpic->flags & MPIC_NO_RESET)) {
  		for (i = 0; i < mpic->num_sources; i++) {
  			/* start with vector = source number, and masked */
  			u32 vecpri = MPIC_VECPRI_MASK | i |
  				(8 << MPIC_VECPRI_PRIORITY_SHIFT);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1415
  		
dfec22027   Meador Inge   powerpc: Make MPI...
1416
1417
1418
1419
1420
1421
1422
  			/* check if protected */
  			if (mpic->protected && test_bit(i, mpic->protected))
  				continue;
  			/* init hw */
  			mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
  			mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
  		}
14cf11af6   Paul Mackerras   powerpc: Merge en...
1423
1424
  	}
  	
7df2457db   Olof Johansson   [POWERPC] MPIC: s...
1425
1426
  	/* Init spurious vector */
  	mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), mpic->spurious_vec);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1427

7233593b7   Zang Roy-r61911   [POWERPC] Support...
1428
1429
1430
1431
1432
  	/* Disable 8259 passthrough, if supported */
  	if (!(mpic->flags & MPIC_NO_PTHROU_DIS))
  		mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
  			   mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
  			   | MPIC_GREG_GCONF_8259_PTHROU_DIS);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1433

d87bf3bed   Olof Johansson   [POWERPC] pasemi:...
1434
1435
1436
1437
  	if (mpic->flags & MPIC_NO_BIAS)
  		mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
  			mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
  			| MPIC_GREG_GCONF_NO_BIAS);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1438
  	/* Set current processor priority to 0 */
7233593b7   Zang Roy-r61911   [POWERPC] Support...
1439
  	mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
1440
1441
1442
  
  #ifdef CONFIG_PM
  	/* allocate memory to save mpic state */
ea96025a2   Anton Vorontsov   powerpc: Don't us...
1443
1444
  	mpic->save_data = kmalloc(mpic->num_sources * sizeof(*mpic->save_data),
  				  GFP_KERNEL);
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
1445
1446
  	BUG_ON(mpic->save_data == NULL);
  #endif
09dc34a95   Kyle Moffett   powerpc/mpic: Add...
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
  
  	/* Check if this MPIC is chained from a parent interrupt controller */
  	if (mpic->flags & MPIC_SECONDARY) {
  		int virq = irq_of_parse_and_map(mpic->node, 0);
  		if (virq != NO_IRQ) {
  			printk(KERN_INFO "%s: hooking up to IRQ %d
  ",
  					mpic->node->full_name, virq);
  			irq_set_handler_data(virq, mpic);
  			irq_set_chained_handler(virq, &mpic_cascade);
  		}
  	}
14cf11af6   Paul Mackerras   powerpc: Merge en...
1459
  }
868ea0c92   Mark A. Greer   [POWERPC] mpic: a...
1460
1461
1462
1463
1464
1465
1466
1467
1468
  void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
  {
  	u32 v;
  
  	v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1);
  	v &= ~MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO_MASK;
  	v |= MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO(clock_ratio);
  	mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v);
  }
14cf11af6   Paul Mackerras   powerpc: Merge en...
1469

868ea0c92   Mark A. Greer   [POWERPC] mpic: a...
1470
1471
  void __init mpic_set_serial_int(struct mpic *mpic, int enable)
  {
ba1826e5e   Benjamin Herrenschmidt   [PATCH] powerpc: ...
1472
  	unsigned long flags;
868ea0c92   Mark A. Greer   [POWERPC] mpic: a...
1473
  	u32 v;
203041ad1   Thomas Gleixner   powerpc: Convert ...
1474
  	raw_spin_lock_irqsave(&mpic_lock, flags);
868ea0c92   Mark A. Greer   [POWERPC] mpic: a...
1475
1476
1477
1478
1479
1480
  	v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1);
  	if (enable)
  		v |= MPIC_GREG_GLOBAL_CONF_1_SIE;
  	else
  		v &= ~MPIC_GREG_GLOBAL_CONF_1_SIE;
  	mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v);
203041ad1   Thomas Gleixner   powerpc: Convert ...
1481
  	raw_spin_unlock_irqrestore(&mpic_lock, flags);
868ea0c92   Mark A. Greer   [POWERPC] mpic: a...
1482
  }
14cf11af6   Paul Mackerras   powerpc: Merge en...
1483
1484
1485
  
  void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
  {
d69a78d7d   Tony Breeds   powerpc/mpic: Cle...
1486
  	struct mpic *mpic = mpic_find(irq);
476eb4912   Grant Likely   powerpc/irq: Stop...
1487
  	unsigned int src = virq_to_hw(irq);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1488
1489
  	unsigned long flags;
  	u32 reg;
06a901c56   Stephen Rothwell   [POWERPC] mpic: F...
1490
1491
  	if (!mpic)
  		return;
203041ad1   Thomas Gleixner   powerpc: Convert ...
1492
  	raw_spin_lock_irqsave(&mpic_lock, flags);
d69a78d7d   Tony Breeds   powerpc/mpic: Cle...
1493
  	if (mpic_is_ipi(mpic, irq)) {
7df2457db   Olof Johansson   [POWERPC] MPIC: s...
1494
  		reg = mpic_ipi_read(src - mpic->ipi_vecs[0]) &
e53566409   Benjamin Herrenschmidt   [PATCH] powerpc: ...
1495
  			~MPIC_VECPRI_PRIORITY_MASK;
7df2457db   Olof Johansson   [POWERPC] MPIC: s...
1496
  		mpic_ipi_write(src - mpic->ipi_vecs[0],
14cf11af6   Paul Mackerras   powerpc: Merge en...
1497
  			       reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
ea94187fa   Scott Wood   powerpc/mpic: add...
1498
1499
1500
1501
1502
  	} else if (mpic_is_tm(mpic, irq)) {
  		reg = mpic_tm_read(src - mpic->timer_vecs[0]) &
  			~MPIC_VECPRI_PRIORITY_MASK;
  		mpic_tm_write(src - mpic->timer_vecs[0],
  			      reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
14cf11af6   Paul Mackerras   powerpc: Merge en...
1503
  	} else {
7233593b7   Zang Roy-r61911   [POWERPC] Support...
1504
  		reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI))
e53566409   Benjamin Herrenschmidt   [PATCH] powerpc: ...
1505
  			& ~MPIC_VECPRI_PRIORITY_MASK;
7233593b7   Zang Roy-r61911   [POWERPC] Support...
1506
  		mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
14cf11af6   Paul Mackerras   powerpc: Merge en...
1507
1508
  			       reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
  	}
203041ad1   Thomas Gleixner   powerpc: Convert ...
1509
  	raw_spin_unlock_irqrestore(&mpic_lock, flags);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1510
  }
14cf11af6   Paul Mackerras   powerpc: Merge en...
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
  void mpic_setup_this_cpu(void)
  {
  #ifdef CONFIG_SMP
  	struct mpic *mpic = mpic_primary;
  	unsigned long flags;
  	u32 msk = 1 << hard_smp_processor_id();
  	unsigned int i;
  
  	BUG_ON(mpic == NULL);
  
  	DBG("%s: setup_this_cpu(%d)
  ", mpic->name, hard_smp_processor_id());
203041ad1   Thomas Gleixner   powerpc: Convert ...
1523
  	raw_spin_lock_irqsave(&mpic_lock, flags);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1524
1525
1526
1527
  
   	/* let the mpic know we want intrs. default affinity is 0xffffffff
  	 * until changed via /proc. That's how it's done on x86. If we want
  	 * it differently, then we should make sure we also change the default
a53da52fd   Ingo Molnar   [PATCH] genirq: c...
1528
  	 * values of irq_desc[].affinity in irq.c.
14cf11af6   Paul Mackerras   powerpc: Merge en...
1529
1530
1531
   	 */
  	if (distribute_irqs) {
  	 	for (i = 0; i < mpic->num_sources ; i++)
7233593b7   Zang Roy-r61911   [POWERPC] Support...
1532
1533
  			mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
  				mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) | msk);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1534
1535
1536
  	}
  
  	/* Set current processor priority to 0 */
7233593b7   Zang Roy-r61911   [POWERPC] Support...
1537
  	mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1538

203041ad1   Thomas Gleixner   powerpc: Convert ...
1539
  	raw_spin_unlock_irqrestore(&mpic_lock, flags);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1540
1541
1542
1543
1544
1545
  #endif /* CONFIG_SMP */
  }
  
  int mpic_cpu_get_priority(void)
  {
  	struct mpic *mpic = mpic_primary;
7233593b7   Zang Roy-r61911   [POWERPC] Support...
1546
  	return mpic_cpu_read(MPIC_INFO(CPU_CURRENT_TASK_PRI));
14cf11af6   Paul Mackerras   powerpc: Merge en...
1547
1548
1549
1550
1551
1552
1553
  }
  
  void mpic_cpu_set_priority(int prio)
  {
  	struct mpic *mpic = mpic_primary;
  
  	prio &= MPIC_CPU_TASKPRI_MASK;
7233593b7   Zang Roy-r61911   [POWERPC] Support...
1554
  	mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), prio);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1555
  }
14cf11af6   Paul Mackerras   powerpc: Merge en...
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
  void mpic_teardown_this_cpu(int secondary)
  {
  	struct mpic *mpic = mpic_primary;
  	unsigned long flags;
  	u32 msk = 1 << hard_smp_processor_id();
  	unsigned int i;
  
  	BUG_ON(mpic == NULL);
  
  	DBG("%s: teardown_this_cpu(%d)
  ", mpic->name, hard_smp_processor_id());
203041ad1   Thomas Gleixner   powerpc: Convert ...
1567
  	raw_spin_lock_irqsave(&mpic_lock, flags);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1568
1569
1570
  
  	/* let the mpic know we don't want intrs.  */
  	for (i = 0; i < mpic->num_sources ; i++)
7233593b7   Zang Roy-r61911   [POWERPC] Support...
1571
1572
  		mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
  			mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) & ~msk);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1573
1574
  
  	/* Set current processor priority to max */
7233593b7   Zang Roy-r61911   [POWERPC] Support...
1575
  	mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
7132799b0   Valentine Barshak   [POWERPC] kexec: ...
1576
1577
1578
1579
  	/* We need to EOI the IPI since not all platforms reset the MPIC
  	 * on boot and new interrupts wouldn't get delivered otherwise.
  	 */
  	mpic_eoi(mpic);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1580

203041ad1   Thomas Gleixner   powerpc: Convert ...
1581
  	raw_spin_unlock_irqrestore(&mpic_lock, flags);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1582
  }
f365355e6   Olof Johansson   [POWERPC] pasemi:...
1583
  static unsigned int _mpic_get_one_irq(struct mpic *mpic, int reg)
14cf11af6   Paul Mackerras   powerpc: Merge en...
1584
  {
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
1585
  	u32 src;
14cf11af6   Paul Mackerras   powerpc: Merge en...
1586

f365355e6   Olof Johansson   [POWERPC] pasemi:...
1587
  	src = mpic_cpu_read(reg) & MPIC_INFO(VECPRI_VECTOR_MASK);
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
1588
  #ifdef DEBUG_LOW
f365355e6   Olof Johansson   [POWERPC] pasemi:...
1589
1590
  	DBG("%s: get_one_irq(reg 0x%x): %d
  ", mpic->name, reg, src);
1beb6a7d6   Benjamin Herrenschmidt   [PATCH] powerpc: ...
1591
  #endif
5cddd2e35   Josh Boyer   [POWERPC] Fix spu...
1592
1593
1594
  	if (unlikely(src == mpic->spurious_vec)) {
  		if (mpic->flags & MPIC_SPV_EOI)
  			mpic_eoi(mpic);
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
1595
  		return NO_IRQ;
5cddd2e35   Josh Boyer   [POWERPC] Fix spu...
1596
  	}
7fd721861   Benjamin Herrenschmidt   [POWERPC] MPIC pr...
1597
  	if (unlikely(mpic->protected && test_bit(src, mpic->protected))) {
76462232c   Christian Dietrich   arch/powerpc: use...
1598
1599
1600
  		printk_ratelimited(KERN_WARNING "%s: Got protected source %d !
  ",
  				   mpic->name, (int)src);
7fd721861   Benjamin Herrenschmidt   [POWERPC] MPIC pr...
1601
1602
1603
  		mpic_eoi(mpic);
  		return NO_IRQ;
  	}
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
1604
  	return irq_linear_revmap(mpic->irqhost, src);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1605
  }
f365355e6   Olof Johansson   [POWERPC] pasemi:...
1606
1607
1608
1609
  unsigned int mpic_get_one_irq(struct mpic *mpic)
  {
  	return _mpic_get_one_irq(mpic, MPIC_INFO(CPU_INTACK));
  }
35a84c2f5   Olaf Hering   [POWERPC] Fix up ...
1610
  unsigned int mpic_get_irq(void)
14cf11af6   Paul Mackerras   powerpc: Merge en...
1611
1612
1613
1614
  {
  	struct mpic *mpic = mpic_primary;
  
  	BUG_ON(mpic == NULL);
35a84c2f5   Olaf Hering   [POWERPC] Fix up ...
1615
  	return mpic_get_one_irq(mpic);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1616
  }
d91e4ea70   Kumar Gala   powerpc: Add supp...
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
  unsigned int mpic_get_coreint_irq(void)
  {
  #ifdef CONFIG_BOOKE
  	struct mpic *mpic = mpic_primary;
  	u32 src;
  
  	BUG_ON(mpic == NULL);
  
  	src = mfspr(SPRN_EPR);
  
  	if (unlikely(src == mpic->spurious_vec)) {
  		if (mpic->flags & MPIC_SPV_EOI)
  			mpic_eoi(mpic);
  		return NO_IRQ;
  	}
  	if (unlikely(mpic->protected && test_bit(src, mpic->protected))) {
76462232c   Christian Dietrich   arch/powerpc: use...
1633
1634
1635
  		printk_ratelimited(KERN_WARNING "%s: Got protected source %d !
  ",
  				   mpic->name, (int)src);
d91e4ea70   Kumar Gala   powerpc: Add supp...
1636
1637
1638
1639
1640
1641
1642
1643
  		return NO_IRQ;
  	}
  
  	return irq_linear_revmap(mpic->irqhost, src);
  #else
  	return NO_IRQ;
  #endif
  }
f365355e6   Olof Johansson   [POWERPC] pasemi:...
1644
1645
1646
1647
1648
1649
1650
1651
  unsigned int mpic_get_mcirq(void)
  {
  	struct mpic *mpic = mpic_primary;
  
  	BUG_ON(mpic == NULL);
  
  	return _mpic_get_one_irq(mpic, MPIC_INFO(CPU_MCACK));
  }
14cf11af6   Paul Mackerras   powerpc: Merge en...
1652
1653
1654
1655
1656
  
  #ifdef CONFIG_SMP
  void mpic_request_ipis(void)
  {
  	struct mpic *mpic = mpic_primary;
78608dd32   Milton Miller   powerpc/mpic: Use...
1657
  	int i;
14cf11af6   Paul Mackerras   powerpc: Merge en...
1658
  	BUG_ON(mpic == NULL);
14cf11af6   Paul Mackerras   powerpc: Merge en...
1659

8354be9c1   Frans Pop   powerpc: Remove t...
1660
1661
  	printk(KERN_INFO "mpic: requesting IPIs...
  ");
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
1662
1663
1664
  
  	for (i = 0; i < 4; i++) {
  		unsigned int vipi = irq_create_mapping(mpic->irqhost,
7df2457db   Olof Johansson   [POWERPC] MPIC: s...
1665
  						       mpic->ipi_vecs[0] + i);
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
1666
  		if (vipi == NO_IRQ) {
78608dd32   Milton Miller   powerpc/mpic: Use...
1667
1668
1669
  			printk(KERN_ERR "Failed to map %s
  ", smp_ipi_name[i]);
  			continue;
d16f1b648   Olof Johansson   [POWERPC] Remove ...
1670
  		}
78608dd32   Milton Miller   powerpc/mpic: Use...
1671
  		smp_request_message_ipi(vipi, i);
0ebfff149   Benjamin Herrenschmidt   [POWERPC] Add new...
1672
  	}
14cf11af6   Paul Mackerras   powerpc: Merge en...
1673
  }
a9c592646   Paul Mackerras   powerpc: Move smp...
1674

3caba98fd   Milton Miller   powerpc/mpic: Sim...
1675
  void smp_mpic_message_pass(int cpu, int msg)
2ef613cb9   Benjamin Herrenschmidt   powerpc/cpumask: ...
1676
1677
  {
  	struct mpic *mpic = mpic_primary;
3caba98fd   Milton Miller   powerpc/mpic: Sim...
1678
  	u32 physmask;
2ef613cb9   Benjamin Herrenschmidt   powerpc/cpumask: ...
1679
1680
  
  	BUG_ON(mpic == NULL);
a9c592646   Paul Mackerras   powerpc: Move smp...
1681
1682
1683
1684
1685
1686
1687
  	/* make sure we're sending something that translates to an IPI */
  	if ((unsigned int)msg > 3) {
  		printk("SMP %d: smp_message_pass: unknown msg %d
  ",
  		       smp_processor_id(), msg);
  		return;
  	}
3caba98fd   Milton Miller   powerpc/mpic: Sim...
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
  
  #ifdef DEBUG_IPI
  	DBG("%s: send_ipi(ipi_no: %d)
  ", mpic->name, msg);
  #endif
  
  	physmask = 1 << get_hard_smp_processor_id(cpu);
  
  	mpic_cpu_write(MPIC_INFO(CPU_IPI_DISPATCH_0) +
  		       msg * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE), physmask);
a9c592646   Paul Mackerras   powerpc: Move smp...
1698
  }
775aeff44   Michael Ellerman   [POWERPC] Move MP...
1699
1700
1701
1702
1703
1704
1705
  
  int __init smp_mpic_probe(void)
  {
  	int nr_cpus;
  
  	DBG("smp_mpic_probe()...
  ");
2ef613cb9   Benjamin Herrenschmidt   powerpc/cpumask: ...
1706
  	nr_cpus = cpumask_weight(cpu_possible_mask);
775aeff44   Michael Ellerman   [POWERPC] Move MP...
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
  
  	DBG("nr_cpus: %d
  ", nr_cpus);
  
  	if (nr_cpus > 1)
  		mpic_request_ipis();
  
  	return nr_cpus;
  }
  
  void __devinit smp_mpic_setup_cpu(int cpu)
  {
  	mpic_setup_this_cpu();
  }
66953ebef   Matthew McClintock   powerpc/mpic: Add...
1721
1722
1723
1724
1725
1726
  
  void mpic_reset_core(int cpu)
  {
  	struct mpic *mpic = mpic_primary;
  	u32 pir;
  	int cpuid = get_hard_smp_processor_id(cpu);
44f16fcf2   Matthew McClintock   powerpc/85xx: iss...
1727
  	int i;
66953ebef   Matthew McClintock   powerpc/mpic: Add...
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
  
  	/* Set target bit for core reset */
  	pir = mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT));
  	pir |= (1 << cpuid);
  	mpic_write(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT), pir);
  	mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT));
  
  	/* Restore target bit after reset complete */
  	pir &= ~(1 << cpuid);
  	mpic_write(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT), pir);
  	mpic_read(mpic->gregs, MPIC_INFO(GREG_PROCESSOR_INIT));
44f16fcf2   Matthew McClintock   powerpc/85xx: iss...
1739
1740
1741
1742
1743
1744
1745
1746
1747
  
  	/* Perform 15 EOI on each reset core to clear pending interrupts.
  	 * This is required for FSL CoreNet based devices */
  	if (mpic->flags & MPIC_FSL) {
  		for (i = 0; i < 15; i++) {
  			_mpic_write(mpic->reg_type, &mpic->cpuregs[cpuid],
  				      MPIC_CPU_EOI, 0);
  		}
  	}
66953ebef   Matthew McClintock   powerpc/mpic: Add...
1748
  }
14cf11af6   Paul Mackerras   powerpc: Merge en...
1749
  #endif /* CONFIG_SMP */
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
1750
1751
  
  #ifdef CONFIG_PM
f5a592f7d   Rafael J. Wysocki   PM / PowerPC: Use...
1752
  static void mpic_suspend_one(struct mpic *mpic)
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
1753
  {
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
1754
1755
1756
1757
1758
1759
1760
1761
  	int i;
  
  	for (i = 0; i < mpic->num_sources; i++) {
  		mpic->save_data[i].vecprio =
  			mpic_irq_read(i, MPIC_INFO(IRQ_VECTOR_PRI));
  		mpic->save_data[i].dest =
  			mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION));
  	}
f5a592f7d   Rafael J. Wysocki   PM / PowerPC: Use...
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
  }
  
  static int mpic_suspend(void)
  {
  	struct mpic *mpic = mpics;
  
  	while (mpic) {
  		mpic_suspend_one(mpic);
  		mpic = mpic->next;
  	}
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
1772
1773
1774
  
  	return 0;
  }
f5a592f7d   Rafael J. Wysocki   PM / PowerPC: Use...
1775
  static void mpic_resume_one(struct mpic *mpic)
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
1776
  {
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
1777
1778
1779
1780
1781
1782
1783
1784
1785
  	int i;
  
  	for (i = 0; i < mpic->num_sources; i++) {
  		mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI),
  			       mpic->save_data[i].vecprio);
  		mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
  			       mpic->save_data[i].dest);
  
  #ifdef CONFIG_MPIC_U3_HT_IRQS
7c9d93604   Alastair Bridgewater   powerpc: Fix mpic...
1786
  	if (mpic->fixups) {
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
  		struct mpic_irq_fixup *fixup = &mpic->fixups[i];
  
  		if (fixup->base) {
  			/* we use the lowest bit in an inverted meaning */
  			if ((mpic->save_data[i].fixup_data & 1) == 0)
  				continue;
  
  			/* Enable and configure */
  			writeb(0x10 + 2 * fixup->index, fixup->base + 2);
  
  			writel(mpic->save_data[i].fixup_data & ~1,
  			       fixup->base + 4);
  		}
  	}
  #endif
  	} /* end for loop */
f5a592f7d   Rafael J. Wysocki   PM / PowerPC: Use...
1803
  }
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
1804

f5a592f7d   Rafael J. Wysocki   PM / PowerPC: Use...
1805
1806
1807
1808
1809
1810
1811
1812
  static void mpic_resume(void)
  {
  	struct mpic *mpic = mpics;
  
  	while (mpic) {
  		mpic_resume_one(mpic);
  		mpic = mpic->next;
  	}
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
1813
  }
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
1814

f5a592f7d   Rafael J. Wysocki   PM / PowerPC: Use...
1815
  static struct syscore_ops mpic_syscore_ops = {
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
1816
1817
  	.resume = mpic_resume,
  	.suspend = mpic_suspend,
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
1818
1819
1820
1821
  };
  
  static int mpic_init_sys(void)
  {
f5a592f7d   Rafael J. Wysocki   PM / PowerPC: Use...
1822
1823
  	register_syscore_ops(&mpic_syscore_ops);
  	return 0;
3669e9304   Johannes Berg   [POWERPC] MPIC sy...
1824
1825
1826
  }
  
  device_initcall(mpic_init_sys);
f5a592f7d   Rafael J. Wysocki   PM / PowerPC: Use...
1827
  #endif