aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/Makefile2
-rw-r--r--arch/powerpc/sysdev/commproc.c398
-rw-r--r--arch/powerpc/sysdev/cpm2_pic.c154
-rw-r--r--arch/powerpc/sysdev/cpm2_pic.h2
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c274
-rw-r--r--arch/powerpc/sysdev/grackle.c2
-rw-r--r--arch/powerpc/sysdev/ipic.c17
-rw-r--r--arch/powerpc/sysdev/micropatch.c743
-rw-r--r--arch/powerpc/sysdev/mpc8xx_pic.c197
-rw-r--r--arch/powerpc/sysdev/mpc8xx_pic.h12
-rw-r--r--arch/powerpc/sysdev/mpic.c66
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe_ic.c6
12 files changed, 1772 insertions, 101 deletions
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 2621a7e72d2d..85dcdf178415 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -22,4 +22,6 @@ endif
22ifeq ($(ARCH),powerpc) 22ifeq ($(ARCH),powerpc)
23obj-$(CONFIG_MTD) += rom.o 23obj-$(CONFIG_MTD) += rom.o
24obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o 24obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o
25obj-$(CONFIG_8xx) += mpc8xx_pic.o commproc.o
26obj-$(CONFIG_UCODE_PATCH) += micropatch.o
25endif 27endif
diff --git a/arch/powerpc/sysdev/commproc.c b/arch/powerpc/sysdev/commproc.c
new file mode 100644
index 000000000000..9b4fafd9a840
--- /dev/null
+++ b/arch/powerpc/sysdev/commproc.c
@@ -0,0 +1,398 @@
1/*
2 * General Purpose functions for the global management of the
3 * Communication Processor Module.
4 * Copyright (c) 1997 Dan error_act (dmalek@jlc.net)
5 *
6 * In addition to the individual control of the communication
7 * channels, there are a few functions that globally affect the
8 * communication processor.
9 *
10 * Buffer descriptors must be allocated from the dual ported memory
11 * space. The allocator for that is here. When the communication
12 * process is reset, we reclaim the memory available. There is
13 * currently no deallocator for this memory.
14 * The amount of space available is platform dependent. On the
15 * MBX, the EPPC software loads additional microcode into the
16 * communication processor, and uses some of the DP ram for this
17 * purpose. Current, the first 512 bytes and the last 256 bytes of
18 * memory are used. Right now I am conservative and only use the
19 * memory that can never be used for microcode. If there are
20 * applications that require more DP ram, we can expand the boundaries
21 * but then we have to be careful of any downloaded microcode.
22 */
23#include <linux/errno.h>
24#include <linux/sched.h>
25#include <linux/kernel.h>
26#include <linux/dma-mapping.h>
27#include <linux/param.h>
28#include <linux/string.h>
29#include <linux/mm.h>
30#include <linux/interrupt.h>
31#include <linux/irq.h>
32#include <linux/module.h>
33#include <asm/mpc8xx.h>
34#include <asm/page.h>
35#include <asm/pgtable.h>
36#include <asm/8xx_immap.h>
37#include <asm/commproc.h>
38#include <asm/io.h>
39#include <asm/tlbflush.h>
40#include <asm/rheap.h>
41#include <asm/prom.h>
42
43#include <asm/fs_pd.h>
44
45#define CPM_MAP_SIZE (0x4000)
46
47static void m8xx_cpm_dpinit(void);
48static uint host_buffer; /* One page of host buffer */
49static uint host_end; /* end + 1 */
50cpm8xx_t *cpmp; /* Pointer to comm processor space */
51cpic8xx_t *cpic_reg;
52
53static struct device_node *cpm_pic_node;
54static struct irq_host *cpm_pic_host;
55
56static void cpm_mask_irq(unsigned int irq)
57{
58 unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
59
60 clrbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
61}
62
63static void cpm_unmask_irq(unsigned int irq)
64{
65 unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
66
67 setbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
68}
69
70static void cpm_end_irq(unsigned int irq)
71{
72 unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
73
74 out_be32(&cpic_reg->cpic_cisr, (1 << cpm_vec));
75}
76
77static struct irq_chip cpm_pic = {
78 .typename = " CPM PIC ",
79 .mask = cpm_mask_irq,
80 .unmask = cpm_unmask_irq,
81 .eoi = cpm_end_irq,
82};
83
84int cpm_get_irq(void)
85{
86 int cpm_vec;
87
88 /* Get the vector by setting the ACK bit and then reading
89 * the register.
90 */
91 out_be16(&cpic_reg->cpic_civr, 1);
92 cpm_vec = in_be16(&cpic_reg->cpic_civr);
93 cpm_vec >>= 11;
94
95 return irq_linear_revmap(cpm_pic_host, cpm_vec);
96}
97
98static int cpm_pic_host_match(struct irq_host *h, struct device_node *node)
99{
100 return cpm_pic_node == node;
101}
102
103static int cpm_pic_host_map(struct irq_host *h, unsigned int virq,
104 irq_hw_number_t hw)
105{
106 pr_debug("cpm_pic_host_map(%d, 0x%lx)\n", virq, hw);
107
108 get_irq_desc(virq)->status |= IRQ_LEVEL;
109 set_irq_chip_and_handler(virq, &cpm_pic, handle_fasteoi_irq);
110 return 0;
111}
112
113/* The CPM can generate the error interrupt when there is a race condition
114 * between generating and masking interrupts. All we have to do is ACK it
115 * and return. This is a no-op function so we don't need any special
116 * tests in the interrupt handler.
117 */
118static irqreturn_t cpm_error_interrupt(int irq, void *dev)
119{
120 return IRQ_HANDLED;
121}
122
123static struct irqaction cpm_error_irqaction = {
124 .handler = cpm_error_interrupt,
125 .mask = CPU_MASK_NONE,
126 .name = "error",
127};
128
129static struct irq_host_ops cpm_pic_host_ops = {
130 .match = cpm_pic_host_match,
131 .map = cpm_pic_host_map,
132};
133
134unsigned int cpm_pic_init(void)
135{
136 struct device_node *np = NULL;
137 struct resource res;
138 unsigned int sirq = NO_IRQ, hwirq, eirq;
139 int ret;
140
141 pr_debug("cpm_pic_init\n");
142
143 np = of_find_compatible_node(NULL, "cpm-pic", "CPM");
144 if (np == NULL) {
145 printk(KERN_ERR "CPM PIC init: can not find cpm-pic node\n");
146 return sirq;
147 }
148 ret = of_address_to_resource(np, 0, &res);
149 if (ret)
150 goto end;
151
152 cpic_reg = (void *)ioremap(res.start, res.end - res.start + 1);
153 if (cpic_reg == NULL)
154 goto end;
155
156 sirq = irq_of_parse_and_map(np, 0);
157 if (sirq == NO_IRQ)
158 goto end;
159
160 /* Initialize the CPM interrupt controller. */
161 hwirq = (unsigned int)irq_map[sirq].hwirq;
162 out_be32(&cpic_reg->cpic_cicr,
163 (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
164 ((hwirq/2) << 13) | CICR_HP_MASK);
165
166 out_be32(&cpic_reg->cpic_cimr, 0);
167
168 cpm_pic_node = of_node_get(np);
169
170 cpm_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 64, &cpm_pic_host_ops, 64);
171 if (cpm_pic_host == NULL) {
172 printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
173 sirq = NO_IRQ;
174 goto end;
175 }
176 of_node_put(np);
177
178 /* Install our own error handler. */
179 np = of_find_node_by_type(NULL, "cpm");
180 if (np == NULL) {
181 printk(KERN_ERR "CPM PIC init: can not find cpm node\n");
182 goto end;
183 }
184 eirq= irq_of_parse_and_map(np, 0);
185 if (eirq == NO_IRQ)
186 goto end;
187
188 if (setup_irq(eirq, &cpm_error_irqaction))
189 printk(KERN_ERR "Could not allocate CPM error IRQ!");
190
191 setbits32(&cpic_reg->cpic_cicr, CICR_IEN);
192
193end:
194 of_node_put(np);
195 return sirq;
196}
197
198void cpm_reset(void)
199{
200 cpm8xx_t *commproc;
201 sysconf8xx_t *siu_conf;
202
203 commproc = (cpm8xx_t *)ioremap(CPM_MAP_ADDR, CPM_MAP_SIZE);
204
205#ifdef CONFIG_UCODE_PATCH
206 /* Perform a reset.
207 */
208 out_be16(&commproc->cp_cpcr, CPM_CR_RST | CPM_CR_FLG);
209
210 /* Wait for it.
211 */
212 while (in_be16(&commproc->cp_cpcr) & CPM_CR_FLG);
213
214 cpm_load_patch(commproc);
215#endif
216
217 /* Set SDMA Bus Request priority 5.
218 * On 860T, this also enables FEC priority 6. I am not sure
219 * this is what we realy want for some applications, but the
220 * manual recommends it.
221 * Bit 25, FAM can also be set to use FEC aggressive mode (860T).
222 */
223 siu_conf = (sysconf8xx_t*)immr_map(im_siu_conf);
224 out_be32(&siu_conf->sc_sdcr, 1);
225 immr_unmap(siu_conf);
226
227 /* Reclaim the DP memory for our use. */
228 m8xx_cpm_dpinit();
229
230 /* Tell everyone where the comm processor resides.
231 */
232 cpmp = commproc;
233}
234
235/* We used to do this earlier, but have to postpone as long as possible
236 * to ensure the kernel VM is now running.
237 */
238static void
239alloc_host_memory(void)
240{
241 dma_addr_t physaddr;
242
243 /* Set the host page for allocation.
244 */
245 host_buffer = (uint)dma_alloc_coherent(NULL, PAGE_SIZE, &physaddr,
246 GFP_KERNEL);
247 host_end = host_buffer + PAGE_SIZE;
248}
249
250/* We also own one page of host buffer space for the allocation of
251 * UART "fifos" and the like.
252 */
253uint
254m8xx_cpm_hostalloc(uint size)
255{
256 uint retloc;
257
258 if (host_buffer == 0)
259 alloc_host_memory();
260
261 if ((host_buffer + size) >= host_end)
262 return(0);
263
264 retloc = host_buffer;
265 host_buffer += size;
266
267 return(retloc);
268}
269
270/* Set a baud rate generator. This needs lots of work. There are
271 * four BRGs, any of which can be wired to any channel.
272 * The internal baud rate clock is the system clock divided by 16.
273 * This assumes the baudrate is 16x oversampled by the uart.
274 */
275#define BRG_INT_CLK (get_brgfreq())
276#define BRG_UART_CLK (BRG_INT_CLK/16)
277#define BRG_UART_CLK_DIV16 (BRG_UART_CLK/16)
278
279void
280cpm_setbrg(uint brg, uint rate)
281{
282 volatile uint *bp;
283
284 /* This is good enough to get SMCs running.....
285 */
286 bp = (uint *)&cpmp->cp_brgc1;
287 bp += brg;
288 /* The BRG has a 12-bit counter. For really slow baud rates (or
289 * really fast processors), we may have to further divide by 16.
290 */
291 if (((BRG_UART_CLK / rate) - 1) < 4096)
292 *bp = (((BRG_UART_CLK / rate) - 1) << 1) | CPM_BRG_EN;
293 else
294 *bp = (((BRG_UART_CLK_DIV16 / rate) - 1) << 1) |
295 CPM_BRG_EN | CPM_BRG_DIV16;
296}
297
298/*
299 * dpalloc / dpfree bits.
300 */
301static spinlock_t cpm_dpmem_lock;
302/*
303 * 16 blocks should be enough to satisfy all requests
304 * until the memory subsystem goes up...
305 */
306static rh_block_t cpm_boot_dpmem_rh_block[16];
307static rh_info_t cpm_dpmem_info;
308
309#define CPM_DPMEM_ALIGNMENT 8
310static u8* dpram_vbase;
311static uint dpram_pbase;
312
313void m8xx_cpm_dpinit(void)
314{
315 spin_lock_init(&cpm_dpmem_lock);
316
317 dpram_vbase = immr_map_size(im_cpm.cp_dpmem, CPM_DATAONLY_BASE + CPM_DATAONLY_SIZE);
318 dpram_pbase = (uint)&((immap_t *)IMAP_ADDR)->im_cpm.cp_dpmem;
319
320 /* Initialize the info header */
321 rh_init(&cpm_dpmem_info, CPM_DPMEM_ALIGNMENT,
322 sizeof(cpm_boot_dpmem_rh_block) /
323 sizeof(cpm_boot_dpmem_rh_block[0]),
324 cpm_boot_dpmem_rh_block);
325
326 /*
327 * Attach the usable dpmem area.
328 * XXX: This is actually crap. CPM_DATAONLY_BASE and
329 * CPM_DATAONLY_SIZE are a subset of the available dparm. It varies
330 * with the processor and the microcode patches applied / activated.
331 * But the following should be at least safe.
332 */
333 rh_attach_region(&cpm_dpmem_info, (void *)CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
334}
335
336/*
337 * Allocate the requested size worth of DP memory.
338 * This function returns an offset into the DPRAM area.
339 * Use cpm_dpram_addr() to get the virtual address of the area.
340 */
341uint cpm_dpalloc(uint size, uint align)
342{
343 void *start;
344 unsigned long flags;
345
346 spin_lock_irqsave(&cpm_dpmem_lock, flags);
347 cpm_dpmem_info.alignment = align;
348 start = rh_alloc(&cpm_dpmem_info, size, "commproc");
349 spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
350
351 return (uint)start;
352}
353EXPORT_SYMBOL(cpm_dpalloc);
354
355int cpm_dpfree(uint offset)
356{
357 int ret;
358 unsigned long flags;
359
360 spin_lock_irqsave(&cpm_dpmem_lock, flags);
361 ret = rh_free(&cpm_dpmem_info, (void *)offset);
362 spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
363
364 return ret;
365}
366EXPORT_SYMBOL(cpm_dpfree);
367
368uint cpm_dpalloc_fixed(uint offset, uint size, uint align)
369{
370 void *start;
371 unsigned long flags;
372
373 spin_lock_irqsave(&cpm_dpmem_lock, flags);
374 cpm_dpmem_info.alignment = align;
375 start = rh_alloc_fixed(&cpm_dpmem_info, (void *)offset, size, "commproc");
376 spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
377
378 return (uint)start;
379}
380EXPORT_SYMBOL(cpm_dpalloc_fixed);
381
382void cpm_dpdump(void)
383{
384 rh_dump(&cpm_dpmem_info);
385}
386EXPORT_SYMBOL(cpm_dpdump);
387
388void *cpm_dpram_addr(uint offset)
389{
390 return (void *)(dpram_vbase + offset);
391}
392EXPORT_SYMBOL(cpm_dpram_addr);
393
394uint cpm_dpram_phys(u8* addr)
395{
396 return (dpram_pbase + (uint)(addr - dpram_vbase));
397}
398EXPORT_SYMBOL(cpm_dpram_addr);
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
index 767ee6651adc..eabfe06fe05c 100644
--- a/arch/powerpc/sysdev/cpm2_pic.c
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -36,9 +36,20 @@
36#include <asm/mpc8260.h> 36#include <asm/mpc8260.h>
37#include <asm/io.h> 37#include <asm/io.h>
38#include <asm/prom.h> 38#include <asm/prom.h>
39#include <asm/fs_pd.h>
39 40
40#include "cpm2_pic.h" 41#include "cpm2_pic.h"
41 42
43/* External IRQS */
44#define CPM2_IRQ_EXT1 19
45#define CPM2_IRQ_EXT7 25
46
47/* Port C IRQS */
48#define CPM2_IRQ_PORTC15 48
49#define CPM2_IRQ_PORTC0 63
50
51static intctl_cpm2_t *cpm2_intctl;
52
42static struct device_node *cpm2_pic_node; 53static struct device_node *cpm2_pic_node;
43static struct irq_host *cpm2_pic_host; 54static struct irq_host *cpm2_pic_host;
44#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) 55#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
@@ -68,68 +79,55 @@ static const u_char irq_to_siubit[] = {
68 24, 25, 26, 27, 28, 29, 30, 31, 79 24, 25, 26, 27, 28, 29, 30, 31,
69}; 80};
70 81
71static void cpm2_mask_irq(unsigned int irq_nr) 82static void cpm2_mask_irq(unsigned int virq)
72{ 83{
73 int bit, word; 84 int bit, word;
74 volatile uint *simr; 85 unsigned int irq_nr = virq_to_hw(virq);
75
76 irq_nr -= CPM_IRQ_OFFSET;
77 86
78 bit = irq_to_siubit[irq_nr]; 87 bit = irq_to_siubit[irq_nr];
79 word = irq_to_siureg[irq_nr]; 88 word = irq_to_siureg[irq_nr];
80 89
81 simr = &(cpm2_intctl->ic_simrh);
82 ppc_cached_irq_mask[word] &= ~(1 << bit); 90 ppc_cached_irq_mask[word] &= ~(1 << bit);
83 simr[word] = ppc_cached_irq_mask[word]; 91 out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
84} 92}
85 93
86static void cpm2_unmask_irq(unsigned int irq_nr) 94static void cpm2_unmask_irq(unsigned int virq)
87{ 95{
88 int bit, word; 96 int bit, word;
89 volatile uint *simr; 97 unsigned int irq_nr = virq_to_hw(virq);
90
91 irq_nr -= CPM_IRQ_OFFSET;
92 98
93 bit = irq_to_siubit[irq_nr]; 99 bit = irq_to_siubit[irq_nr];
94 word = irq_to_siureg[irq_nr]; 100 word = irq_to_siureg[irq_nr];
95 101
96 simr = &(cpm2_intctl->ic_simrh);
97 ppc_cached_irq_mask[word] |= 1 << bit; 102 ppc_cached_irq_mask[word] |= 1 << bit;
98 simr[word] = ppc_cached_irq_mask[word]; 103 out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
99} 104}
100 105
101static void cpm2_mask_and_ack(unsigned int irq_nr) 106static void cpm2_ack(unsigned int virq)
102{ 107{
103 int bit, word; 108 int bit, word;
104 volatile uint *simr, *sipnr; 109 unsigned int irq_nr = virq_to_hw(virq);
105
106 irq_nr -= CPM_IRQ_OFFSET;
107 110
108 bit = irq_to_siubit[irq_nr]; 111 bit = irq_to_siubit[irq_nr];
109 word = irq_to_siureg[irq_nr]; 112 word = irq_to_siureg[irq_nr];
110 113
111 simr = &(cpm2_intctl->ic_simrh); 114 out_be32(&cpm2_intctl->ic_sipnrh + word, 1 << bit);
112 sipnr = &(cpm2_intctl->ic_sipnrh);
113 ppc_cached_irq_mask[word] &= ~(1 << bit);
114 simr[word] = ppc_cached_irq_mask[word];
115 sipnr[word] = 1 << bit;
116} 115}
117 116
118static void cpm2_end_irq(unsigned int irq_nr) 117static void cpm2_end_irq(unsigned int virq)
119{ 118{
120 int bit, word; 119 int bit, word;
121 volatile uint *simr; 120 unsigned int irq_nr = virq_to_hw(virq);
122 121
123 if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)) 122 if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
124 && irq_desc[irq_nr].action) { 123 && irq_desc[irq_nr].action) {
125 124
126 irq_nr -= CPM_IRQ_OFFSET;
127 bit = irq_to_siubit[irq_nr]; 125 bit = irq_to_siubit[irq_nr];
128 word = irq_to_siureg[irq_nr]; 126 word = irq_to_siureg[irq_nr];
129 127
130 simr = &(cpm2_intctl->ic_simrh);
131 ppc_cached_irq_mask[word] |= 1 << bit; 128 ppc_cached_irq_mask[word] |= 1 << bit;
132 simr[word] = ppc_cached_irq_mask[word]; 129 out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
130
133 /* 131 /*
134 * Work around large numbers of spurious IRQs on PowerPC 82xx 132 * Work around large numbers of spurious IRQs on PowerPC 82xx
135 * systems. 133 * systems.
@@ -138,13 +136,59 @@ static void cpm2_end_irq(unsigned int irq_nr)
138 } 136 }
139} 137}
140 138
139static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type)
140{
141 unsigned int src = virq_to_hw(virq);
142 struct irq_desc *desc = get_irq_desc(virq);
143 unsigned int vold, vnew, edibit;
144
145 if (flow_type == IRQ_TYPE_NONE)
146 flow_type = IRQ_TYPE_LEVEL_LOW;
147
148 if (flow_type & IRQ_TYPE_EDGE_RISING) {
149 printk(KERN_ERR "CPM2 PIC: sense type 0x%x not supported\n",
150 flow_type);
151 return -EINVAL;
152 }
153
154 desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
155 desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
156 if (flow_type & IRQ_TYPE_LEVEL_LOW) {
157 desc->status |= IRQ_LEVEL;
158 desc->handle_irq = handle_level_irq;
159 } else
160 desc->handle_irq = handle_edge_irq;
161
162 /* internal IRQ senses are LEVEL_LOW
163 * EXT IRQ and Port C IRQ senses are programmable
164 */
165 if (src >= CPM2_IRQ_EXT1 && src <= CPM2_IRQ_EXT7)
166 edibit = (14 - (src - CPM2_IRQ_EXT1));
167 else
168 if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0)
169 edibit = (31 - (src - CPM2_IRQ_PORTC15));
170 else
171 return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;
172
173 vold = in_be32(&cpm2_intctl->ic_siexr);
174
175 if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING)
176 vnew = vold | (1 << edibit);
177 else
178 vnew = vold & ~(1 << edibit);
179
180 if (vold != vnew)
181 out_be32(&cpm2_intctl->ic_siexr, vnew);
182 return 0;
183}
184
141static struct irq_chip cpm2_pic = { 185static struct irq_chip cpm2_pic = {
142 .typename = " CPM2 SIU ", 186 .typename = " CPM2 SIU ",
143 .enable = cpm2_unmask_irq, 187 .mask = cpm2_mask_irq,
144 .disable = cpm2_mask_irq,
145 .unmask = cpm2_unmask_irq, 188 .unmask = cpm2_unmask_irq,
146 .mask_ack = cpm2_mask_and_ack, 189 .ack = cpm2_ack,
147 .end = cpm2_end_irq, 190 .eoi = cpm2_end_irq,
191 .set_type = cpm2_set_irq_type,
148}; 192};
149 193
150unsigned int cpm2_get_irq(void) 194unsigned int cpm2_get_irq(void)
@@ -154,17 +198,17 @@ unsigned int cpm2_get_irq(void)
154 198
155 /* For CPM2, read the SIVEC register and shift the bits down 199 /* For CPM2, read the SIVEC register and shift the bits down
156 * to get the irq number. */ 200 * to get the irq number. */
157 bits = cpm2_intctl->ic_sivec; 201 bits = in_be32(&cpm2_intctl->ic_sivec);
158 irq = bits >> 26; 202 irq = bits >> 26;
159 203
160 if (irq == 0) 204 if (irq == 0)
161 return(-1); 205 return(-1);
162 return irq+CPM_IRQ_OFFSET; 206 return irq_linear_revmap(cpm2_pic_host, irq);
163} 207}
164 208
165static int cpm2_pic_host_match(struct irq_host *h, struct device_node *node) 209static int cpm2_pic_host_match(struct irq_host *h, struct device_node *node)
166{ 210{
167 return cpm2_pic_node == NULL || cpm2_pic_node == node; 211 return cpm2_pic_node == node;
168} 212}
169 213
170static int cpm2_pic_host_map(struct irq_host *h, unsigned int virq, 214static int cpm2_pic_host_map(struct irq_host *h, unsigned int virq,
@@ -177,39 +221,21 @@ static int cpm2_pic_host_map(struct irq_host *h, unsigned int virq,
177 return 0; 221 return 0;
178} 222}
179 223
180static void cpm2_host_unmap(struct irq_host *h, unsigned int virq)
181{
182 /* Make sure irq is masked in hardware */
183 cpm2_mask_irq(virq);
184
185 /* remove chip and handler */
186 set_irq_chip_and_handler(virq, NULL, NULL);
187}
188
189static int cpm2_pic_host_xlate(struct irq_host *h, struct device_node *ct, 224static int cpm2_pic_host_xlate(struct irq_host *h, struct device_node *ct,
190 u32 *intspec, unsigned int intsize, 225 u32 *intspec, unsigned int intsize,
191 irq_hw_number_t *out_hwirq, unsigned int *out_flags) 226 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
192{ 227{
193 static const unsigned char map_cpm2_senses[4] = {
194 IRQ_TYPE_LEVEL_LOW,
195 IRQ_TYPE_LEVEL_HIGH,
196 IRQ_TYPE_EDGE_FALLING,
197 IRQ_TYPE_EDGE_RISING,
198 };
199
200 *out_hwirq = intspec[0]; 228 *out_hwirq = intspec[0];
201 if (intsize > 1 && intspec[1] < 4) 229 if (intsize > 1)
202 *out_flags = map_cpm2_senses[intspec[1]]; 230 *out_flags = intspec[1];
203 else 231 else
204 *out_flags = IRQ_TYPE_NONE; 232 *out_flags = IRQ_TYPE_NONE;
205
206 return 0; 233 return 0;
207} 234}
208 235
209static struct irq_host_ops cpm2_pic_host_ops = { 236static struct irq_host_ops cpm2_pic_host_ops = {
210 .match = cpm2_pic_host_match, 237 .match = cpm2_pic_host_match,
211 .map = cpm2_pic_host_map, 238 .map = cpm2_pic_host_map,
212 .unmap = cpm2_host_unmap,
213 .xlate = cpm2_pic_host_xlate, 239 .xlate = cpm2_pic_host_xlate,
214}; 240};
215 241
@@ -217,37 +243,37 @@ void cpm2_pic_init(struct device_node *node)
217{ 243{
218 int i; 244 int i;
219 245
246 cpm2_intctl = cpm2_map(im_intctl);
247
220 /* Clear the CPM IRQ controller, in case it has any bits set 248 /* Clear the CPM IRQ controller, in case it has any bits set
221 * from the bootloader 249 * from the bootloader
222 */ 250 */
223 251
224 /* Mask out everything */ 252 /* Mask out everything */
225 253
226 cpm2_intctl->ic_simrh = 0x00000000; 254 out_be32(&cpm2_intctl->ic_simrh, 0x00000000);
227 cpm2_intctl->ic_simrl = 0x00000000; 255 out_be32(&cpm2_intctl->ic_simrl, 0x00000000);
228 256
229 wmb(); 257 wmb();
230 258
231 /* Ack everything */ 259 /* Ack everything */
232 cpm2_intctl->ic_sipnrh = 0xffffffff; 260 out_be32(&cpm2_intctl->ic_sipnrh, 0xffffffff);
233 cpm2_intctl->ic_sipnrl = 0xffffffff; 261 out_be32(&cpm2_intctl->ic_sipnrl, 0xffffffff);
234 wmb(); 262 wmb();
235 263
236 /* Dummy read of the vector */ 264 /* Dummy read of the vector */
237 i = cpm2_intctl->ic_sivec; 265 i = in_be32(&cpm2_intctl->ic_sivec);
238 rmb(); 266 rmb();
239 267
240 /* Initialize the default interrupt mapping priorities, 268 /* Initialize the default interrupt mapping priorities,
241 * in case the boot rom changed something on us. 269 * in case the boot rom changed something on us.
242 */ 270 */
243 cpm2_intctl->ic_sicr = 0; 271 out_be16(&cpm2_intctl->ic_sicr, 0);
244 cpm2_intctl->ic_scprrh = 0x05309770; 272 out_be32(&cpm2_intctl->ic_scprrh, 0x05309770);
245 cpm2_intctl->ic_scprrl = 0x05309770; 273 out_be32(&cpm2_intctl->ic_scprrl, 0x05309770);
246 274
247 /* create a legacy host */ 275 /* create a legacy host */
248 if (node) 276 cpm2_pic_node = of_node_get(node);
249 cpm2_pic_node = of_node_get(node);
250
251 cpm2_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 64, &cpm2_pic_host_ops, 64); 277 cpm2_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 64, &cpm2_pic_host_ops, 64);
252 if (cpm2_pic_host == NULL) { 278 if (cpm2_pic_host == NULL) {
253 printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n"); 279 printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
diff --git a/arch/powerpc/sysdev/cpm2_pic.h b/arch/powerpc/sysdev/cpm2_pic.h
index 2840616529e4..30e5828a2781 100644
--- a/arch/powerpc/sysdev/cpm2_pic.h
+++ b/arch/powerpc/sysdev/cpm2_pic.h
@@ -1,8 +1,6 @@
1#ifndef _PPC_KERNEL_CPM2_H 1#ifndef _PPC_KERNEL_CPM2_H
2#define _PPC_KERNEL_CPM2_H 2#define _PPC_KERNEL_CPM2_H
3 3
4extern intctl_cpm2_t *cpm2_intctl;
5
6extern unsigned int cpm2_get_irq(void); 4extern unsigned int cpm2_get_irq(void);
7 5
8extern void cpm2_pic_init(struct device_node*); 6extern void cpm2_pic_init(struct device_node*);
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index ad31e56e892b..9f2a9a444bfb 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -38,7 +38,8 @@
38#include <asm/cpm2.h> 38#include <asm/cpm2.h>
39 39
40extern void init_fcc_ioports(struct fs_platform_info*); 40extern void init_fcc_ioports(struct fs_platform_info*);
41extern void init_scc_ioports(struct fs_uart_platform_info*); 41extern void init_fec_ioports(struct fs_platform_info*);
42extern void init_smc_ioports(struct fs_uart_platform_info*);
42static phys_addr_t immrbase = -1; 43static phys_addr_t immrbase = -1;
43 44
44phys_addr_t get_immrbase(void) 45phys_addr_t get_immrbase(void)
@@ -63,7 +64,7 @@ phys_addr_t get_immrbase(void)
63 64
64EXPORT_SYMBOL(get_immrbase); 65EXPORT_SYMBOL(get_immrbase);
65 66
66#ifdef CONFIG_CPM2 67#if defined(CONFIG_CPM2) || defined(CONFIG_8xx)
67 68
68static u32 brgfreq = -1; 69static u32 brgfreq = -1;
69 70
@@ -544,6 +545,8 @@ arch_initcall(fsl_usb_of_init);
544 545
545#ifdef CONFIG_CPM2 546#ifdef CONFIG_CPM2
546 547
548extern void init_scc_ioports(struct fs_uart_platform_info*);
549
547static const char fcc_regs[] = "fcc_regs"; 550static const char fcc_regs[] = "fcc_regs";
548static const char fcc_regs_c[] = "fcc_regs_c"; 551static const char fcc_regs_c[] = "fcc_regs_c";
549static const char fcc_pram[] = "fcc_pram"; 552static const char fcc_pram[] = "fcc_pram";
@@ -792,3 +795,270 @@ err:
792 795
793arch_initcall(cpm_uart_of_init); 796arch_initcall(cpm_uart_of_init);
794#endif /* CONFIG_CPM2 */ 797#endif /* CONFIG_CPM2 */
798
799#ifdef CONFIG_8xx
800
801extern void init_scc_ioports(struct fs_platform_info*);
802extern int platform_device_skip(char *model, int id);
803
804static int __init fs_enet_mdio_of_init(void)
805{
806 struct device_node *np;
807 unsigned int i;
808 struct platform_device *mdio_dev;
809 struct resource res;
810 int ret;
811
812 for (np = NULL, i = 0;
813 (np = of_find_compatible_node(np, "mdio", "fs_enet")) != NULL;
814 i++) {
815 struct fs_mii_fec_platform_info mdio_data;
816
817 memset(&res, 0, sizeof(res));
818 memset(&mdio_data, 0, sizeof(mdio_data));
819
820 ret = of_address_to_resource(np, 0, &res);
821 if (ret)
822 goto err;
823
824 mdio_dev =
825 platform_device_register_simple("fsl-cpm-fec-mdio",
826 res.start, &res, 1);
827 if (IS_ERR(mdio_dev)) {
828 ret = PTR_ERR(mdio_dev);
829 goto err;
830 }
831
832 mdio_data.mii_speed = ((((ppc_proc_freq + 4999999) / 2500000) / 2) & 0x3F) << 1;
833
834 ret =
835 platform_device_add_data(mdio_dev, &mdio_data,
836 sizeof(struct fs_mii_fec_platform_info));
837 if (ret)
838 goto unreg;
839 }
840 return 0;
841
842unreg:
843 platform_device_unregister(mdio_dev);
844err:
845 return ret;
846}
847
848arch_initcall(fs_enet_mdio_of_init);
849
850static const char *enet_regs = "regs";
851static const char *enet_pram = "pram";
852static const char *enet_irq = "interrupt";
853static char bus_id[9][BUS_ID_SIZE];
854
855static int __init fs_enet_of_init(void)
856{
857 struct device_node *np;
858 unsigned int i;
859 struct platform_device *fs_enet_dev = NULL;
860 struct resource res;
861 int ret;
862
863 for (np = NULL, i = 0;
864 (np = of_find_compatible_node(np, "network", "fs_enet")) != NULL;
865 i++) {
866 struct resource r[4];
867 struct device_node *phy = NULL, *mdio = NULL;
868 struct fs_platform_info fs_enet_data;
869 unsigned int *id, *phy_addr;
870 void *mac_addr;
871 phandle *ph;
872 char *model;
873
874 memset(r, 0, sizeof(r));
875 memset(&fs_enet_data, 0, sizeof(fs_enet_data));
876
877 model = (char *)get_property(np, "model", NULL);
878 if (model == NULL) {
879 ret = -ENODEV;
880 goto unreg;
881 }
882
883 id = (u32 *) get_property(np, "device-id", NULL);
884 fs_enet_data.fs_no = *id;
885
886 if (platform_device_skip(model, *id))
887 continue;
888
889 ret = of_address_to_resource(np, 0, &r[0]);
890 if (ret)
891 goto err;
892 r[0].name = enet_regs;
893
894 mac_addr = (void *)get_property(np, "mac-address", NULL);
895 memcpy(fs_enet_data.macaddr, mac_addr, 6);
896
897 ph = (phandle *) get_property(np, "phy-handle", NULL);
898 if (ph != NULL)
899 phy = of_find_node_by_phandle(*ph);
900
901 if (phy != NULL) {
902 phy_addr = (u32 *) get_property(phy, "reg", NULL);
903 fs_enet_data.phy_addr = *phy_addr;
904 fs_enet_data.has_phy = 1;
905
906 mdio = of_get_parent(phy);
907 ret = of_address_to_resource(mdio, 0, &res);
908 if (ret) {
909 of_node_put(phy);
910 of_node_put(mdio);
911 goto unreg;
912 }
913 }
914
915 model = (char*)get_property(np, "model", NULL);
916 strcpy(fs_enet_data.fs_type, model);
917
918 if (strstr(model, "FEC")) {
919 r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
920 r[1].flags = IORESOURCE_IRQ;
921 r[1].name = enet_irq;
922
923 fs_enet_dev =
924 platform_device_register_simple("fsl-cpm-fec", i, &r[0], 2);
925
926 if (IS_ERR(fs_enet_dev)) {
927 ret = PTR_ERR(fs_enet_dev);
928 goto err;
929 }
930
931 fs_enet_data.rx_ring = 128;
932 fs_enet_data.tx_ring = 16;
933 fs_enet_data.rx_copybreak = 240;
934 fs_enet_data.use_napi = 1;
935 fs_enet_data.napi_weight = 17;
936
937 snprintf((char*)&bus_id[i], BUS_ID_SIZE, "%x:%02x",
938 (u32)res.start, fs_enet_data.phy_addr);
939 fs_enet_data.bus_id = (char*)&bus_id[i];
940 fs_enet_data.init_ioports = init_fec_ioports;
941 }
942 if (strstr(model, "SCC")) {
943 ret = of_address_to_resource(np, 1, &r[1]);
944 if (ret)
945 goto err;
946 r[1].name = enet_pram;
947
948 r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
949 r[2].flags = IORESOURCE_IRQ;
950 r[2].name = enet_irq;
951
952 fs_enet_dev =
953 platform_device_register_simple("fsl-cpm-scc", i, &r[0], 3);
954
955 if (IS_ERR(fs_enet_dev)) {
956 ret = PTR_ERR(fs_enet_dev);
957 goto err;
958 }
959
960 fs_enet_data.rx_ring = 64;
961 fs_enet_data.tx_ring = 8;
962 fs_enet_data.rx_copybreak = 240;
963 fs_enet_data.use_napi = 1;
964 fs_enet_data.napi_weight = 17;
965
966 snprintf((char*)&bus_id[i], BUS_ID_SIZE, "%s", "fixed@10:1");
967 fs_enet_data.bus_id = (char*)&bus_id[i];
968 fs_enet_data.init_ioports = init_scc_ioports;
969 }
970
971 of_node_put(phy);
972 of_node_put(mdio);
973
974 ret = platform_device_add_data(fs_enet_dev, &fs_enet_data,
975 sizeof(struct
976 fs_platform_info));
977 if (ret)
978 goto unreg;
979 }
980 return 0;
981
982unreg:
983 platform_device_unregister(fs_enet_dev);
984err:
985 return ret;
986}
987
988arch_initcall(fs_enet_of_init);
989
990
991static const char *smc_regs = "regs";
992static const char *smc_pram = "pram";
993
994static int __init cpm_smc_uart_of_init(void)
995{
996 struct device_node *np;
997 unsigned int i;
998 struct platform_device *cpm_uart_dev;
999 int ret;
1000
1001 for (np = NULL, i = 0;
1002 (np = of_find_compatible_node(np, "serial", "cpm_uart")) != NULL;
1003 i++) {
1004 struct resource r[3];
1005 struct fs_uart_platform_info cpm_uart_data;
1006 int *id;
1007 char *model;
1008
1009 memset(r, 0, sizeof(r));
1010 memset(&cpm_uart_data, 0, sizeof(cpm_uart_data));
1011
1012 ret = of_address_to_resource(np, 0, &r[0]);
1013 if (ret)
1014 goto err;
1015
1016 r[0].name = smc_regs;
1017
1018 ret = of_address_to_resource(np, 1, &r[1]);
1019 if (ret)
1020 goto err;
1021 r[1].name = smc_pram;
1022
1023 r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
1024 r[2].flags = IORESOURCE_IRQ;
1025
1026 cpm_uart_dev =
1027 platform_device_register_simple("fsl-cpm-smc:uart", i, &r[0], 3);
1028
1029 if (IS_ERR(cpm_uart_dev)) {
1030 ret = PTR_ERR(cpm_uart_dev);
1031 goto err;
1032 }
1033
1034 model = (char*)get_property(np, "model", NULL);
1035 strcpy(cpm_uart_data.fs_type, model);
1036
1037 id = (int*)get_property(np, "device-id", NULL);
1038 cpm_uart_data.fs_no = *id;
1039 cpm_uart_data.uart_clk = ppc_proc_freq;
1040
1041 cpm_uart_data.tx_num_fifo = 4;
1042 cpm_uart_data.tx_buf_size = 32;
1043 cpm_uart_data.rx_num_fifo = 4;
1044 cpm_uart_data.rx_buf_size = 32;
1045
1046 ret =
1047 platform_device_add_data(cpm_uart_dev, &cpm_uart_data,
1048 sizeof(struct
1049 fs_uart_platform_info));
1050 if (ret)
1051 goto unreg;
1052 }
1053
1054 return 0;
1055
1056unreg:
1057 platform_device_unregister(cpm_uart_dev);
1058err:
1059 return ret;
1060}
1061
1062arch_initcall(cpm_smc_uart_of_init);
1063
1064#endif /* CONFIG_8xx */
diff --git a/arch/powerpc/sysdev/grackle.c b/arch/powerpc/sysdev/grackle.c
index b6ec793a23be..42053625f498 100644
--- a/arch/powerpc/sysdev/grackle.c
+++ b/arch/powerpc/sysdev/grackle.c
@@ -56,6 +56,8 @@ static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable)
56void __init setup_grackle(struct pci_controller *hose) 56void __init setup_grackle(struct pci_controller *hose)
57{ 57{
58 setup_indirect_pci(hose, 0xfec00000, 0xfee00000); 58 setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
59 if (machine_is_compatible("PowerMac1,1"))
60 pci_assign_all_buses = 1;
59 if (machine_is_compatible("AAPL,PowerBook1998")) 61 if (machine_is_compatible("AAPL,PowerBook1998"))
60 grackle_set_loop_snoop(hose, 1); 62 grackle_set_loop_snoop(hose, 1);
61#if 0 /* Disabled for now, HW problems ??? */ 63#if 0 /* Disabled for now, HW problems ??? */
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 746f78c15375..473c415e9e25 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -557,8 +557,7 @@ static struct irq_host_ops ipic_host_ops = {
557 .xlate = ipic_host_xlate, 557 .xlate = ipic_host_xlate,
558}; 558};
559 559
560void __init ipic_init(struct device_node *node, 560struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
561 unsigned int flags)
562{ 561{
563 struct ipic *ipic; 562 struct ipic *ipic;
564 struct resource res; 563 struct resource res;
@@ -566,22 +565,24 @@ void __init ipic_init(struct device_node *node,
566 565
567 ipic = alloc_bootmem(sizeof(struct ipic)); 566 ipic = alloc_bootmem(sizeof(struct ipic));
568 if (ipic == NULL) 567 if (ipic == NULL)
569 return; 568 return NULL;
570 569
571 memset(ipic, 0, sizeof(struct ipic)); 570 memset(ipic, 0, sizeof(struct ipic));
572 ipic->of_node = node ? of_node_get(node) : NULL; 571 ipic->of_node = of_node_get(node);
573 572
574 ipic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 573 ipic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
575 NR_IPIC_INTS, 574 NR_IPIC_INTS,
576 &ipic_host_ops, 0); 575 &ipic_host_ops, 0);
577 if (ipic->irqhost == NULL) { 576 if (ipic->irqhost == NULL) {
578 of_node_put(node); 577 of_node_put(node);
579 return; 578 return NULL;
580 } 579 }
581 580
582 ret = of_address_to_resource(node, 0, &res); 581 ret = of_address_to_resource(node, 0, &res);
583 if (ret) 582 if (ret) {
584 return; 583 of_node_put(node);
584 return NULL;
585 }
585 586
586 ipic->regs = ioremap(res.start, res.end - res.start + 1); 587 ipic->regs = ioremap(res.start, res.end - res.start + 1);
587 588
@@ -625,6 +626,8 @@ void __init ipic_init(struct device_node *node,
625 626
626 printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS, 627 printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS,
627 primary_ipic->regs); 628 primary_ipic->regs);
629
630 return ipic;
628} 631}
629 632
630int ipic_set_priority(unsigned int virq, unsigned int priority) 633int ipic_set_priority(unsigned int virq, unsigned int priority)
diff --git a/arch/powerpc/sysdev/micropatch.c b/arch/powerpc/sysdev/micropatch.c
new file mode 100644
index 000000000000..712b10a55f87
--- /dev/null
+++ b/arch/powerpc/sysdev/micropatch.c
@@ -0,0 +1,743 @@
1
2/* Microcode patches for the CPM as supplied by Motorola.
3 * This is the one for IIC/SPI. There is a newer one that
4 * also relocates SMC2, but this would require additional changes
5 * to uart.c, so I am holding off on that for a moment.
6 */
7#include <linux/errno.h>
8#include <linux/sched.h>
9#include <linux/kernel.h>
10#include <linux/param.h>
11#include <linux/string.h>
12#include <linux/mm.h>
13#include <linux/interrupt.h>
14#include <asm/irq.h>
15#include <asm/mpc8xx.h>
16#include <asm/page.h>
17#include <asm/pgtable.h>
18#include <asm/8xx_immap.h>
19#include <asm/commproc.h>
20
21/*
22 * I2C/SPI relocation patch arrays.
23 */
24
25#ifdef CONFIG_I2C_SPI_UCODE_PATCH
26
27uint patch_2000[] = {
28 0x7FFFEFD9,
29 0x3FFD0000,
30 0x7FFB49F7,
31 0x7FF90000,
32 0x5FEFADF7,
33 0x5F89ADF7,
34 0x5FEFAFF7,
35 0x5F89AFF7,
36 0x3A9CFBC8,
37 0xE7C0EDF0,
38 0x77C1E1BB,
39 0xF4DC7F1D,
40 0xABAD932F,
41 0x4E08FDCF,
42 0x6E0FAFF8,
43 0x7CCF76CF,
44 0xFD1FF9CF,
45 0xABF88DC6,
46 0xAB5679F7,
47 0xB0937383,
48 0xDFCE79F7,
49 0xB091E6BB,
50 0xE5BBE74F,
51 0xB3FA6F0F,
52 0x6FFB76CE,
53 0xEE0DF9CF,
54 0x2BFBEFEF,
55 0xCFEEF9CF,
56 0x76CEAD24,
57 0x90B2DF9A,
58 0x7FDDD0BF,
59 0x4BF847FD,
60 0x7CCF76CE,
61 0xCFEF7E1F,
62 0x7F1D7DFD,
63 0xF0B6EF71,
64 0x7FC177C1,
65 0xFBC86079,
66 0xE722FBC8,
67 0x5FFFDFFF,
68 0x5FB2FFFB,
69 0xFBC8F3C8,
70 0x94A67F01,
71 0x7F1D5F39,
72 0xAFE85F5E,
73 0xFFDFDF96,
74 0xCB9FAF7D,
75 0x5FC1AFED,
76 0x8C1C5FC1,
77 0xAFDD5FC3,
78 0xDF9A7EFD,
79 0xB0B25FB2,
80 0xFFFEABAD,
81 0x5FB2FFFE,
82 0x5FCE600B,
83 0xE6BB600B,
84 0x5FCEDFC6,
85 0x27FBEFDF,
86 0x5FC8CFDE,
87 0x3A9CE7C0,
88 0xEDF0F3C8,
89 0x7F0154CD,
90 0x7F1D2D3D,
91 0x363A7570,
92 0x7E0AF1CE,
93 0x37EF2E68,
94 0x7FEE10EC,
95 0xADF8EFDE,
96 0xCFEAE52F,
97 0x7D0FE12B,
98 0xF1CE5F65,
99 0x7E0A4DF8,
100 0xCFEA5F72,
101 0x7D0BEFEE,
102 0xCFEA5F74,
103 0xE522EFDE,
104 0x5F74CFDA,
105 0x0B627385,
106 0xDF627E0A,
107 0x30D8145B,
108 0xBFFFF3C8,
109 0x5FFFDFFF,
110 0xA7F85F5E,
111 0xBFFE7F7D,
112 0x10D31450,
113 0x5F36BFFF,
114 0xAF785F5E,
115 0xBFFDA7F8,
116 0x5F36BFFE,
117 0x77FD30C0,
118 0x4E08FDCF,
119 0xE5FF6E0F,
120 0xAFF87E1F,
121 0x7E0FFD1F,
122 0xF1CF5F1B,
123 0xABF80D5E,
124 0x5F5EFFEF,
125 0x79F730A2,
126 0xAFDD5F34,
127 0x47F85F34,
128 0xAFED7FDD,
129 0x50B24978,
130 0x47FD7F1D,
131 0x7DFD70AD,
132 0xEF717EC1,
133 0x6BA47F01,
134 0x2D267EFD,
135 0x30DE5F5E,
136 0xFFFD5F5E,
137 0xFFEF5F5E,
138 0xFFDF0CA0,
139 0xAFED0A9E,
140 0xAFDD0C3A,
141 0x5F3AAFBD,
142 0x7FBDB082,
143 0x5F8247F8
144};
145
146uint patch_2f00[] = {
147 0x3E303430,
148 0x34343737,
149 0xABF7BF9B,
150 0x994B4FBD,
151 0xBD599493,
152 0x349FFF37,
153 0xFB9B177D,
154 0xD9936956,
155 0xBBFDD697,
156 0xBDD2FD11,
157 0x31DB9BB3,
158 0x63139637,
159 0x93733693,
160 0x193137F7,
161 0x331737AF,
162 0x7BB9B999,
163 0xBB197957,
164 0x7FDFD3D5,
165 0x73B773F7,
166 0x37933B99,
167 0x1D115316,
168 0x99315315,
169 0x31694BF4,
170 0xFBDBD359,
171 0x31497353,
172 0x76956D69,
173 0x7B9D9693,
174 0x13131979,
175 0x79376935
176};
177#endif
178
179/*
180 * I2C/SPI/SMC1 relocation patch arrays.
181 */
182
183#ifdef CONFIG_I2C_SPI_SMC1_UCODE_PATCH
184
185uint patch_2000[] = {
186 0x3fff0000,
187 0x3ffd0000,
188 0x3ffb0000,
189 0x3ff90000,
190 0x5f13eff8,
191 0x5eb5eff8,
192 0x5f88adf7,
193 0x5fefadf7,
194 0x3a9cfbc8,
195 0x77cae1bb,
196 0xf4de7fad,
197 0xabae9330,
198 0x4e08fdcf,
199 0x6e0faff8,
200 0x7ccf76cf,
201 0xfdaff9cf,
202 0xabf88dc8,
203 0xab5879f7,
204 0xb0925d8d,
205 0xdfd079f7,
206 0xb090e6bb,
207 0xe5bbe74f,
208 0x9e046f0f,
209 0x6ffb76ce,
210 0xee0cf9cf,
211 0x2bfbefef,
212 0xcfeef9cf,
213 0x76cead23,
214 0x90b3df99,
215 0x7fddd0c1,
216 0x4bf847fd,
217 0x7ccf76ce,
218 0xcfef77ca,
219 0x7eaf7fad,
220 0x7dfdf0b7,
221 0xef7a7fca,
222 0x77cafbc8,
223 0x6079e722,
224 0xfbc85fff,
225 0xdfff5fb3,
226 0xfffbfbc8,
227 0xf3c894a5,
228 0xe7c9edf9,
229 0x7f9a7fad,
230 0x5f36afe8,
231 0x5f5bffdf,
232 0xdf95cb9e,
233 0xaf7d5fc3,
234 0xafed8c1b,
235 0x5fc3afdd,
236 0x5fc5df99,
237 0x7efdb0b3,
238 0x5fb3fffe,
239 0xabae5fb3,
240 0xfffe5fd0,
241 0x600be6bb,
242 0x600b5fd0,
243 0xdfc827fb,
244 0xefdf5fca,
245 0xcfde3a9c,
246 0xe7c9edf9,
247 0xf3c87f9e,
248 0x54ca7fed,
249 0x2d3a3637,
250 0x756f7e9a,
251 0xf1ce37ef,
252 0x2e677fee,
253 0x10ebadf8,
254 0xefdecfea,
255 0xe52f7d9f,
256 0xe12bf1ce,
257 0x5f647e9a,
258 0x4df8cfea,
259 0x5f717d9b,
260 0xefeecfea,
261 0x5f73e522,
262 0xefde5f73,
263 0xcfda0b61,
264 0x5d8fdf61,
265 0xe7c9edf9,
266 0x7e9a30d5,
267 0x1458bfff,
268 0xf3c85fff,
269 0xdfffa7f8,
270 0x5f5bbffe,
271 0x7f7d10d0,
272 0x144d5f33,
273 0xbfffaf78,
274 0x5f5bbffd,
275 0xa7f85f33,
276 0xbffe77fd,
277 0x30bd4e08,
278 0xfdcfe5ff,
279 0x6e0faff8,
280 0x7eef7e9f,
281 0xfdeff1cf,
282 0x5f17abf8,
283 0x0d5b5f5b,
284 0xffef79f7,
285 0x309eafdd,
286 0x5f3147f8,
287 0x5f31afed,
288 0x7fdd50af,
289 0x497847fd,
290 0x7f9e7fed,
291 0x7dfd70a9,
292 0xef7e7ece,
293 0x6ba07f9e,
294 0x2d227efd,
295 0x30db5f5b,
296 0xfffd5f5b,
297 0xffef5f5b,
298 0xffdf0c9c,
299 0xafed0a9a,
300 0xafdd0c37,
301 0x5f37afbd,
302 0x7fbdb081,
303 0x5f8147f8,
304 0x3a11e710,
305 0xedf0ccdd,
306 0xf3186d0a,
307 0x7f0e5f06,
308 0x7fedbb38,
309 0x3afe7468,
310 0x7fedf4fc,
311 0x8ffbb951,
312 0xb85f77fd,
313 0xb0df5ddd,
314 0xdefe7fed,
315 0x90e1e74d,
316 0x6f0dcbf7,
317 0xe7decfed,
318 0xcb74cfed,
319 0xcfeddf6d,
320 0x91714f74,
321 0x5dd2deef,
322 0x9e04e7df,
323 0xefbb6ffb,
324 0xe7ef7f0e,
325 0x9e097fed,
326 0xebdbeffa,
327 0xeb54affb,
328 0x7fea90d7,
329 0x7e0cf0c3,
330 0xbffff318,
331 0x5fffdfff,
332 0xac59efea,
333 0x7fce1ee5,
334 0xe2ff5ee1,
335 0xaffbe2ff,
336 0x5ee3affb,
337 0xf9cc7d0f,
338 0xaef8770f,
339 0x7d0fb0c6,
340 0xeffbbfff,
341 0xcfef5ede,
342 0x7d0fbfff,
343 0x5ede4cf8,
344 0x7fddd0bf,
345 0x49f847fd,
346 0x7efdf0bb,
347 0x7fedfffd,
348 0x7dfdf0b7,
349 0xef7e7e1e,
350 0x5ede7f0e,
351 0x3a11e710,
352 0xedf0ccab,
353 0xfb18ad2e,
354 0x1ea9bbb8,
355 0x74283b7e,
356 0x73c2e4bb,
357 0x2ada4fb8,
358 0xdc21e4bb,
359 0xb2a1ffbf,
360 0x5e2c43f8,
361 0xfc87e1bb,
362 0xe74ffd91,
363 0x6f0f4fe8,
364 0xc7ba32e2,
365 0xf396efeb,
366 0x600b4f78,
367 0xe5bb760b,
368 0x53acaef8,
369 0x4ef88b0e,
370 0xcfef9e09,
371 0xabf8751f,
372 0xefef5bac,
373 0x741f4fe8,
374 0x751e760d,
375 0x7fdbf081,
376 0x741cafce,
377 0xefcc7fce,
378 0x751e70ac,
379 0x741ce7bb,
380 0x3372cfed,
381 0xafdbefeb,
382 0xe5bb760b,
383 0x53f2aef8,
384 0xafe8e7eb,
385 0x4bf8771e,
386 0x7e247fed,
387 0x4fcbe2cc,
388 0x7fbc30a9,
389 0x7b0f7a0f,
390 0x34d577fd,
391 0x308b5db7,
392 0xde553e5f,
393 0xaf78741f,
394 0x741f30f0,
395 0xcfef5e2c,
396 0x741f3eac,
397 0xafb8771e,
398 0x5e677fed,
399 0x0bd3e2cc,
400 0x741ccfec,
401 0xe5ca53cd,
402 0x6fcb4f74,
403 0x5dadde4b,
404 0x2ab63d38,
405 0x4bb3de30,
406 0x751f741c,
407 0x6c42effa,
408 0xefea7fce,
409 0x6ffc30be,
410 0xefec3fca,
411 0x30b3de2e,
412 0xadf85d9e,
413 0xaf7daefd,
414 0x5d9ede2e,
415 0x5d9eafdd,
416 0x761f10ac,
417 0x1da07efd,
418 0x30adfffe,
419 0x4908fb18,
420 0x5fffdfff,
421 0xafbb709b,
422 0x4ef85e67,
423 0xadf814ad,
424 0x7a0f70ad,
425 0xcfef50ad,
426 0x7a0fde30,
427 0x5da0afed,
428 0x3c12780f,
429 0xefef780f,
430 0xefef790f,
431 0xa7f85e0f,
432 0xffef790f,
433 0xefef790f,
434 0x14adde2e,
435 0x5d9eadfd,
436 0x5e2dfffb,
437 0xe79addfd,
438 0xeff96079,
439 0x607ae79a,
440 0xddfceff9,
441 0x60795dff,
442 0x607acfef,
443 0xefefefdf,
444 0xefbfef7f,
445 0xeeffedff,
446 0xebffe7ff,
447 0xafefafdf,
448 0xafbfaf7f,
449 0xaeffadff,
450 0xabffa7ff,
451 0x6fef6fdf,
452 0x6fbf6f7f,
453 0x6eff6dff,
454 0x6bff67ff,
455 0x2fef2fdf,
456 0x2fbf2f7f,
457 0x2eff2dff,
458 0x2bff27ff,
459 0x4e08fd1f,
460 0xe5ff6e0f,
461 0xaff87eef,
462 0x7e0ffdef,
463 0xf11f6079,
464 0xabf8f542,
465 0x7e0af11c,
466 0x37cfae3a,
467 0x7fec90be,
468 0xadf8efdc,
469 0xcfeae52f,
470 0x7d0fe12b,
471 0xf11c6079,
472 0x7e0a4df8,
473 0xcfea5dc4,
474 0x7d0befec,
475 0xcfea5dc6,
476 0xe522efdc,
477 0x5dc6cfda,
478 0x4e08fd1f,
479 0x6e0faff8,
480 0x7c1f761f,
481 0xfdeff91f,
482 0x6079abf8,
483 0x761cee24,
484 0xf91f2bfb,
485 0xefefcfec,
486 0xf91f6079,
487 0x761c27fb,
488 0xefdf5da7,
489 0xcfdc7fdd,
490 0xd09c4bf8,
491 0x47fd7c1f,
492 0x761ccfcf,
493 0x7eef7fed,
494 0x7dfdf093,
495 0xef7e7f1e,
496 0x771efb18,
497 0x6079e722,
498 0xe6bbe5bb,
499 0xae0ae5bb,
500 0x600bae85,
501 0xe2bbe2bb,
502 0xe2bbe2bb,
503 0xaf02e2bb,
504 0xe2bb2ff9,
505 0x6079e2bb
506};
507
508uint patch_2f00[] = {
509 0x30303030,
510 0x3e3e3434,
511 0xabbf9b99,
512 0x4b4fbdbd,
513 0x59949334,
514 0x9fff37fb,
515 0x9b177dd9,
516 0x936956bb,
517 0xfbdd697b,
518 0xdd2fd113,
519 0x1db9f7bb,
520 0x36313963,
521 0x79373369,
522 0x3193137f,
523 0x7331737a,
524 0xf7bb9b99,
525 0x9bb19795,
526 0x77fdfd3d,
527 0x573b773f,
528 0x737933f7,
529 0xb991d115,
530 0x31699315,
531 0x31531694,
532 0xbf4fbdbd,
533 0x35931497,
534 0x35376956,
535 0xbd697b9d,
536 0x96931313,
537 0x19797937,
538 0x6935af78,
539 0xb9b3baa3,
540 0xb8788683,
541 0x368f78f7,
542 0x87778733,
543 0x3ffffb3b,
544 0x8e8f78b8,
545 0x1d118e13,
546 0xf3ff3f8b,
547 0x6bd8e173,
548 0xd1366856,
549 0x68d1687b,
550 0x3daf78b8,
551 0x3a3a3f87,
552 0x8f81378f,
553 0xf876f887,
554 0x77fd8778,
555 0x737de8d6,
556 0xbbf8bfff,
557 0xd8df87f7,
558 0xfd876f7b,
559 0x8bfff8bd,
560 0x8683387d,
561 0xb873d87b,
562 0x3b8fd7f8,
563 0xf7338883,
564 0xbb8ee1f8,
565 0xef837377,
566 0x3337b836,
567 0x817d11f8,
568 0x7378b878,
569 0xd3368b7d,
570 0xed731b7d,
571 0x833731f3,
572 0xf22f3f23
573};
574
575uint patch_2e00[] = {
576 0x27eeeeee,
577 0xeeeeeeee,
578 0xeeeeeeee,
579 0xeeeeeeee,
580 0xee4bf4fb,
581 0xdbd259bb,
582 0x1979577f,
583 0xdfd2d573,
584 0xb773f737,
585 0x4b4fbdbd,
586 0x25b9b177,
587 0xd2d17376,
588 0x956bbfdd,
589 0x697bdd2f,
590 0xff9f79ff,
591 0xff9ff22f
592};
593#endif
594
595/*
596 * USB SOF patch arrays.
597 */
598
599#ifdef CONFIG_USB_SOF_UCODE_PATCH
600
601uint patch_2000[] = {
602 0x7fff0000,
603 0x7ffd0000,
604 0x7ffb0000,
605 0x49f7ba5b,
606 0xba383ffb,
607 0xf9b8b46d,
608 0xe5ab4e07,
609 0xaf77bffe,
610 0x3f7bbf79,
611 0xba5bba38,
612 0xe7676076,
613 0x60750000
614};
615
616uint patch_2f00[] = {
617 0x3030304c,
618 0xcab9e441,
619 0xa1aaf220
620};
621#endif
622
623void
624cpm_load_patch(cpm8xx_t *cp)
625{
626 volatile uint *dp; /* Dual-ported RAM. */
627 volatile cpm8xx_t *commproc;
628 volatile iic_t *iip;
629 volatile spi_t *spp;
630 volatile smc_uart_t *smp;
631 int i;
632
633 commproc = cp;
634
635#ifdef CONFIG_USB_SOF_UCODE_PATCH
636 commproc->cp_rccr = 0;
637
638 dp = (uint *)(commproc->cp_dpmem);
639 for (i=0; i<(sizeof(patch_2000)/4); i++)
640 *dp++ = patch_2000[i];
641
642 dp = (uint *)&(commproc->cp_dpmem[0x0f00]);
643 for (i=0; i<(sizeof(patch_2f00)/4); i++)
644 *dp++ = patch_2f00[i];
645
646 commproc->cp_rccr = 0x0009;
647
648 printk("USB SOF microcode patch installed\n");
649#endif /* CONFIG_USB_SOF_UCODE_PATCH */
650
651#if defined(CONFIG_I2C_SPI_UCODE_PATCH) || \
652 defined(CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
653
654 commproc->cp_rccr = 0;
655
656 dp = (uint *)(commproc->cp_dpmem);
657 for (i=0; i<(sizeof(patch_2000)/4); i++)
658 *dp++ = patch_2000[i];
659
660 dp = (uint *)&(commproc->cp_dpmem[0x0f00]);
661 for (i=0; i<(sizeof(patch_2f00)/4); i++)
662 *dp++ = patch_2f00[i];
663
664 iip = (iic_t *)&commproc->cp_dparam[PROFF_IIC];
665# define RPBASE 0x0500
666 iip->iic_rpbase = RPBASE;
667
668 /* Put SPI above the IIC, also 32-byte aligned.
669 */
670 i = (RPBASE + sizeof(iic_t) + 31) & ~31;
671 spp = (spi_t *)&commproc->cp_dparam[PROFF_SPI];
672 spp->spi_rpbase = i;
673
674# if defined(CONFIG_I2C_SPI_UCODE_PATCH)
675 commproc->cp_cpmcr1 = 0x802a;
676 commproc->cp_cpmcr2 = 0x8028;
677 commproc->cp_cpmcr3 = 0x802e;
678 commproc->cp_cpmcr4 = 0x802c;
679 commproc->cp_rccr = 1;
680
681 printk("I2C/SPI microcode patch installed.\n");
682# endif /* CONFIG_I2C_SPI_UCODE_PATCH */
683
684# if defined(CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
685
686 dp = (uint *)&(commproc->cp_dpmem[0x0e00]);
687 for (i=0; i<(sizeof(patch_2e00)/4); i++)
688 *dp++ = patch_2e00[i];
689
690 commproc->cp_cpmcr1 = 0x8080;
691 commproc->cp_cpmcr2 = 0x808a;
692 commproc->cp_cpmcr3 = 0x8028;
693 commproc->cp_cpmcr4 = 0x802a;
694 commproc->cp_rccr = 3;
695
696 smp = (smc_uart_t *)&commproc->cp_dparam[PROFF_SMC1];
697 smp->smc_rpbase = 0x1FC0;
698
699 printk("I2C/SPI/SMC1 microcode patch installed.\n");
700# endif /* CONFIG_I2C_SPI_SMC1_UCODE_PATCH) */
701
702#endif /* some variation of the I2C/SPI patch was selected */
703}
704
705/*
706 * Take this entire routine out, since no one calls it and its
707 * logic is suspect.
708 */
709
710#if 0
711void
712verify_patch(volatile immap_t *immr)
713{
714 volatile uint *dp;
715 volatile cpm8xx_t *commproc;
716 int i;
717
718 commproc = (cpm8xx_t *)&immr->im_cpm;
719
720 printk("cp_rccr %x\n", commproc->cp_rccr);
721 commproc->cp_rccr = 0;
722
723 dp = (uint *)(commproc->cp_dpmem);
724 for (i=0; i<(sizeof(patch_2000)/4); i++)
725 if (*dp++ != patch_2000[i]) {
726 printk("patch_2000 bad at %d\n", i);
727 dp--;
728 printk("found 0x%X, wanted 0x%X\n", *dp, patch_2000[i]);
729 break;
730 }
731
732 dp = (uint *)&(commproc->cp_dpmem[0x0f00]);
733 for (i=0; i<(sizeof(patch_2f00)/4); i++)
734 if (*dp++ != patch_2f00[i]) {
735 printk("patch_2f00 bad at %d\n", i);
736 dp--;
737 printk("found 0x%X, wanted 0x%X\n", *dp, patch_2f00[i]);
738 break;
739 }
740
741 commproc->cp_rccr = 0x0009;
742}
743#endif
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
new file mode 100644
index 000000000000..2fc2bcd79b5e
--- /dev/null
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -0,0 +1,197 @@
1#include <linux/kernel.h>
2#include <linux/module.h>
3#include <linux/stddef.h>
4#include <linux/init.h>
5#include <linux/sched.h>
6#include <linux/signal.h>
7#include <linux/irq.h>
8#include <linux/dma-mapping.h>
9#include <asm/prom.h>
10#include <asm/irq.h>
11#include <asm/io.h>
12#include <asm/8xx_immap.h>
13#include <asm/mpc8xx.h>
14
15#include "mpc8xx_pic.h"
16
17
18#define PIC_VEC_SPURRIOUS 15
19
20extern int cpm_get_irq(struct pt_regs *regs);
21
22static struct device_node *mpc8xx_pic_node;
23static struct irq_host *mpc8xx_pic_host;
24#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
25static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
26static sysconf8xx_t *siu_reg;
27
28int cpm_get_irq(struct pt_regs *regs);
29
30static void mpc8xx_unmask_irq(unsigned int virq)
31{
32 int bit, word;
33 unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
34
35 bit = irq_nr & 0x1f;
36 word = irq_nr >> 5;
37
38 ppc_cached_irq_mask[word] |= (1 << (31-bit));
39 out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
40}
41
42static void mpc8xx_mask_irq(unsigned int virq)
43{
44 int bit, word;
45 unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
46
47 bit = irq_nr & 0x1f;
48 word = irq_nr >> 5;
49
50 ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
51 out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
52}
53
54static void mpc8xx_ack(unsigned int virq)
55{
56 int bit;
57 unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
58
59 bit = irq_nr & 0x1f;
60 out_be32(&siu_reg->sc_sipend, 1 << (31-bit));
61}
62
63static void mpc8xx_end_irq(unsigned int virq)
64{
65 int bit, word;
66 unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
67
68 bit = irq_nr & 0x1f;
69 word = irq_nr >> 5;
70
71 ppc_cached_irq_mask[word] |= (1 << (31-bit));
72 out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
73}
74
75static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type)
76{
77 struct irq_desc *desc = get_irq_desc(virq);
78
79 desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
80 desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
81 if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
82 desc->status |= IRQ_LEVEL;
83
84 if (flow_type & IRQ_TYPE_EDGE_FALLING) {
85 irq_hw_number_t hw = (unsigned int)irq_map[virq].hwirq;
86 unsigned int siel = in_be32(&siu_reg->sc_siel);
87
88 /* only external IRQ senses are programmable */
89 if ((hw & 1) == 0) {
90 siel |= (0x80000000 >> hw);
91 out_be32(&siu_reg->sc_siel, siel);
92 desc->handle_irq = handle_edge_irq;
93 }
94 }
95 return 0;
96}
97
98static struct irq_chip mpc8xx_pic = {
99 .typename = " MPC8XX SIU ",
100 .unmask = mpc8xx_unmask_irq,
101 .mask = mpc8xx_mask_irq,
102 .ack = mpc8xx_ack,
103 .eoi = mpc8xx_end_irq,
104 .set_type = mpc8xx_set_irq_type,
105};
106
107unsigned int mpc8xx_get_irq(void)
108{
109 int irq;
110
111 /* For MPC8xx, read the SIVEC register and shift the bits down
112 * to get the irq number.
113 */
114 irq = in_be32(&siu_reg->sc_sivec) >> 26;
115
116 if (irq == PIC_VEC_SPURRIOUS)
117 irq = NO_IRQ;
118
119 return irq_linear_revmap(mpc8xx_pic_host, irq);
120
121}
122
123static int mpc8xx_pic_host_match(struct irq_host *h, struct device_node *node)
124{
125 return mpc8xx_pic_node == node;
126}
127
128static int mpc8xx_pic_host_map(struct irq_host *h, unsigned int virq,
129 irq_hw_number_t hw)
130{
131 pr_debug("mpc8xx_pic_host_map(%d, 0x%lx)\n", virq, hw);
132
133 /* Set default irq handle */
134 set_irq_chip_and_handler(virq, &mpc8xx_pic, handle_level_irq);
135 return 0;
136}
137
138
139static int mpc8xx_pic_host_xlate(struct irq_host *h, struct device_node *ct,
140 u32 *intspec, unsigned int intsize,
141 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
142{
143 static unsigned char map_pic_senses[4] = {
144 IRQ_TYPE_EDGE_RISING,
145 IRQ_TYPE_LEVEL_LOW,
146 IRQ_TYPE_LEVEL_HIGH,
147 IRQ_TYPE_EDGE_FALLING,
148 };
149
150 *out_hwirq = intspec[0];
151 if (intsize > 1 && intspec[1] < 4)
152 *out_flags = map_pic_senses[intspec[1]];
153 else
154 *out_flags = IRQ_TYPE_NONE;
155
156 return 0;
157}
158
159
160static struct irq_host_ops mpc8xx_pic_host_ops = {
161 .match = mpc8xx_pic_host_match,
162 .map = mpc8xx_pic_host_map,
163 .xlate = mpc8xx_pic_host_xlate,
164};
165
166int mpc8xx_pic_init(void)
167{
168 struct resource res;
169 struct device_node *np = NULL;
170 int ret;
171
172 np = of_find_node_by_type(np, "mpc8xx-pic");
173
174 if (np == NULL) {
175 printk(KERN_ERR "Could not find open-pic node\n");
176 return -ENOMEM;
177 }
178
179 mpc8xx_pic_node = of_node_get(np);
180
181 ret = of_address_to_resource(np, 0, &res);
182 of_node_put(np);
183 if (ret)
184 return ret;
185
186 siu_reg = (void *)ioremap(res.start, res.end - res.start + 1);
187 if (siu_reg == NULL)
188 return -EINVAL;
189
190 mpc8xx_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 64, &mpc8xx_pic_host_ops, 64);
191 if (mpc8xx_pic_host == NULL) {
192 printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!\n");
193 ret = -ENOMEM;
194 }
195
196 return ret;
197}
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.h b/arch/powerpc/sysdev/mpc8xx_pic.h
new file mode 100644
index 000000000000..afa2ee6717c1
--- /dev/null
+++ b/arch/powerpc/sysdev/mpc8xx_pic.h
@@ -0,0 +1,12 @@
1#ifndef _PPC_KERNEL_MPC8xx_H
2#define _PPC_KERNEL_MPC8xx_H
3
4#include <linux/irq.h>
5#include <linux/interrupt.h>
6
7extern struct hw_interrupt_type mpc8xx_pic;
8
9int mpc8xx_pic_init(void);
10unsigned int mpc8xx_get_irq(void);
11
12#endif /* _PPC_KERNEL_PPC8xx_H */
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index d01ced11694d..aa701cc27ecc 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -496,13 +496,18 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
496static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi) 496static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi)
497{ 497{
498 unsigned int src = mpic_irq_to_hw(irq); 498 unsigned int src = mpic_irq_to_hw(irq);
499 struct mpic *mpic;
499 500
500 if (irq < NUM_ISA_INTERRUPTS) 501 if (irq < NUM_ISA_INTERRUPTS)
501 return NULL; 502 return NULL;
503
504 mpic = irq_desc[irq].chip_data;
505
502 if (is_ipi) 506 if (is_ipi)
503 *is_ipi = (src >= MPIC_VEC_IPI_0 && src <= MPIC_VEC_IPI_3); 507 *is_ipi = (src >= mpic->ipi_vecs[0] &&
508 src <= mpic->ipi_vecs[3]);
504 509
505 return irq_desc[irq].chip_data; 510 return mpic;
506} 511}
507 512
508/* Convert a cpu mask from logical to physical cpu numbers. */ 513/* Convert a cpu mask from logical to physical cpu numbers. */
@@ -540,7 +545,11 @@ static inline void mpic_eoi(struct mpic *mpic)
540#ifdef CONFIG_SMP 545#ifdef CONFIG_SMP
541static irqreturn_t mpic_ipi_action(int irq, void *dev_id) 546static irqreturn_t mpic_ipi_action(int irq, void *dev_id)
542{ 547{
543 smp_message_recv(mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0); 548 struct mpic *mpic;
549
550 mpic = mpic_find(irq, NULL);
551 smp_message_recv(mpic_irq_to_hw(irq) - mpic->ipi_vecs[0]);
552
544 return IRQ_HANDLED; 553 return IRQ_HANDLED;
545} 554}
546#endif /* CONFIG_SMP */ 555#endif /* CONFIG_SMP */
@@ -663,7 +672,7 @@ static void mpic_end_ht_irq(unsigned int irq)
663static void mpic_unmask_ipi(unsigned int irq) 672static void mpic_unmask_ipi(unsigned int irq)
664{ 673{
665 struct mpic *mpic = mpic_from_ipi(irq); 674 struct mpic *mpic = mpic_from_ipi(irq);
666 unsigned int src = mpic_irq_to_hw(irq) - MPIC_VEC_IPI_0; 675 unsigned int src = mpic_irq_to_hw(irq) - mpic->ipi_vecs[0];
667 676
668 DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src); 677 DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src);
669 mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK); 678 mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
@@ -807,11 +816,11 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
807 816
808 DBG("mpic: map virq %d, hwirq 0x%lx\n", virq, hw); 817 DBG("mpic: map virq %d, hwirq 0x%lx\n", virq, hw);
809 818
810 if (hw == MPIC_VEC_SPURRIOUS) 819 if (hw == mpic->spurious_vec)
811 return -EINVAL; 820 return -EINVAL;
812 821
813#ifdef CONFIG_SMP 822#ifdef CONFIG_SMP
814 else if (hw >= MPIC_VEC_IPI_0) { 823 else if (hw >= mpic->ipi_vecs[0]) {
815 WARN_ON(!(mpic->flags & MPIC_PRIMARY)); 824 WARN_ON(!(mpic->flags & MPIC_PRIMARY));
816 825
817 DBG("mpic: mapping as IPI\n"); 826 DBG("mpic: mapping as IPI\n");
@@ -904,6 +913,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
904 u32 reg; 913 u32 reg;
905 const char *vers; 914 const char *vers;
906 int i; 915 int i;
916 int intvec_top;
907 u64 paddr = phys_addr; 917 u64 paddr = phys_addr;
908 918
909 mpic = alloc_bootmem(sizeof(struct mpic)); 919 mpic = alloc_bootmem(sizeof(struct mpic));
@@ -912,11 +922,11 @@ struct mpic * __init mpic_alloc(struct device_node *node,
912 922
913 memset(mpic, 0, sizeof(struct mpic)); 923 memset(mpic, 0, sizeof(struct mpic));
914 mpic->name = name; 924 mpic->name = name;
915 mpic->of_node = node ? of_node_get(node) : NULL; 925 mpic->of_node = of_node_get(node);
916 926
917 mpic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 256, 927 mpic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, isu_size,
918 &mpic_host_ops, 928 &mpic_host_ops,
919 MPIC_VEC_SPURRIOUS); 929 flags & MPIC_LARGE_VECTORS ? 2048 : 256);
920 if (mpic->irqhost == NULL) { 930 if (mpic->irqhost == NULL) {
921 of_node_put(node); 931 of_node_put(node);
922 return NULL; 932 return NULL;
@@ -944,6 +954,21 @@ struct mpic * __init mpic_alloc(struct device_node *node,
944 mpic->irq_count = irq_count; 954 mpic->irq_count = irq_count;
945 mpic->num_sources = 0; /* so far */ 955 mpic->num_sources = 0; /* so far */
946 956
957 if (flags & MPIC_LARGE_VECTORS)
958 intvec_top = 2047;
959 else
960 intvec_top = 255;
961
962 mpic->timer_vecs[0] = intvec_top - 8;
963 mpic->timer_vecs[1] = intvec_top - 7;
964 mpic->timer_vecs[2] = intvec_top - 6;
965 mpic->timer_vecs[3] = intvec_top - 5;
966 mpic->ipi_vecs[0] = intvec_top - 4;
967 mpic->ipi_vecs[1] = intvec_top - 3;
968 mpic->ipi_vecs[2] = intvec_top - 2;
969 mpic->ipi_vecs[3] = intvec_top - 1;
970 mpic->spurious_vec = intvec_top;
971
947 /* Check for "big-endian" in device-tree */ 972 /* Check for "big-endian" in device-tree */
948 if (node && get_property(node, "big-endian", NULL) != NULL) 973 if (node && get_property(node, "big-endian", NULL) != NULL)
949 mpic->flags |= MPIC_BIG_ENDIAN; 974 mpic->flags |= MPIC_BIG_ENDIAN;
@@ -1084,11 +1109,6 @@ void __init mpic_init(struct mpic *mpic)
1084 int i; 1109 int i;
1085 1110
1086 BUG_ON(mpic->num_sources == 0); 1111 BUG_ON(mpic->num_sources == 0);
1087 WARN_ON(mpic->num_sources > MPIC_VEC_IPI_0);
1088
1089 /* Sanitize source count */
1090 if (mpic->num_sources > MPIC_VEC_IPI_0)
1091 mpic->num_sources = MPIC_VEC_IPI_0;
1092 1112
1093 printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources); 1113 printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources);
1094 1114
@@ -1104,7 +1124,7 @@ void __init mpic_init(struct mpic *mpic)
1104 i * MPIC_INFO(TIMER_STRIDE) + 1124 i * MPIC_INFO(TIMER_STRIDE) +
1105 MPIC_INFO(TIMER_VECTOR_PRI), 1125 MPIC_INFO(TIMER_VECTOR_PRI),
1106 MPIC_VECPRI_MASK | 1126 MPIC_VECPRI_MASK |
1107 (MPIC_VEC_TIMER_0 + i)); 1127 (mpic->timer_vecs[0] + i));
1108 } 1128 }
1109 1129
1110 /* Initialize IPIs to our reserved vectors and mark them disabled for now */ 1130 /* Initialize IPIs to our reserved vectors and mark them disabled for now */
@@ -1113,7 +1133,7 @@ void __init mpic_init(struct mpic *mpic)
1113 mpic_ipi_write(i, 1133 mpic_ipi_write(i,
1114 MPIC_VECPRI_MASK | 1134 MPIC_VECPRI_MASK |
1115 (10 << MPIC_VECPRI_PRIORITY_SHIFT) | 1135 (10 << MPIC_VECPRI_PRIORITY_SHIFT) |
1116 (MPIC_VEC_IPI_0 + i)); 1136 (mpic->ipi_vecs[0] + i));
1117 } 1137 }
1118 1138
1119 /* Initialize interrupt sources */ 1139 /* Initialize interrupt sources */
@@ -1136,8 +1156,8 @@ void __init mpic_init(struct mpic *mpic)
1136 1 << hard_smp_processor_id()); 1156 1 << hard_smp_processor_id());
1137 } 1157 }
1138 1158
1139 /* Init spurrious vector */ 1159 /* Init spurious vector */
1140 mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), MPIC_VEC_SPURRIOUS); 1160 mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), mpic->spurious_vec);
1141 1161
1142 /* Disable 8259 passthrough, if supported */ 1162 /* Disable 8259 passthrough, if supported */
1143 if (!(mpic->flags & MPIC_NO_PTHROU_DIS)) 1163 if (!(mpic->flags & MPIC_NO_PTHROU_DIS))
@@ -1184,9 +1204,9 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
1184 1204
1185 spin_lock_irqsave(&mpic_lock, flags); 1205 spin_lock_irqsave(&mpic_lock, flags);
1186 if (is_ipi) { 1206 if (is_ipi) {
1187 reg = mpic_ipi_read(src - MPIC_VEC_IPI_0) & 1207 reg = mpic_ipi_read(src - mpic->ipi_vecs[0]) &
1188 ~MPIC_VECPRI_PRIORITY_MASK; 1208 ~MPIC_VECPRI_PRIORITY_MASK;
1189 mpic_ipi_write(src - MPIC_VEC_IPI_0, 1209 mpic_ipi_write(src - mpic->ipi_vecs[0],
1190 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); 1210 reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
1191 } else { 1211 } else {
1192 reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) 1212 reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI))
@@ -1207,7 +1227,7 @@ unsigned int mpic_irq_get_priority(unsigned int irq)
1207 1227
1208 spin_lock_irqsave(&mpic_lock, flags); 1228 spin_lock_irqsave(&mpic_lock, flags);
1209 if (is_ipi) 1229 if (is_ipi)
1210 reg = mpic_ipi_read(src = MPIC_VEC_IPI_0); 1230 reg = mpic_ipi_read(src = mpic->ipi_vecs[0]);
1211 else 1231 else
1212 reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); 1232 reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
1213 spin_unlock_irqrestore(&mpic_lock, flags); 1233 spin_unlock_irqrestore(&mpic_lock, flags);
@@ -1313,7 +1333,7 @@ unsigned int mpic_get_one_irq(struct mpic *mpic)
1313#ifdef DEBUG_LOW 1333#ifdef DEBUG_LOW
1314 DBG("%s: get_one_irq(): %d\n", mpic->name, src); 1334 DBG("%s: get_one_irq(): %d\n", mpic->name, src);
1315#endif 1335#endif
1316 if (unlikely(src == MPIC_VEC_SPURRIOUS)) 1336 if (unlikely(src == mpic->spurious_vec))
1317 return NO_IRQ; 1337 return NO_IRQ;
1318 return irq_linear_revmap(mpic->irqhost, src); 1338 return irq_linear_revmap(mpic->irqhost, src);
1319} 1339}
@@ -1345,7 +1365,7 @@ void mpic_request_ipis(void)
1345 1365
1346 for (i = 0; i < 4; i++) { 1366 for (i = 0; i < 4; i++) {
1347 unsigned int vipi = irq_create_mapping(mpic->irqhost, 1367 unsigned int vipi = irq_create_mapping(mpic->irqhost,
1348 MPIC_VEC_IPI_0 + i); 1368 mpic->ipi_vecs[0] + i);
1349 if (vipi == NO_IRQ) { 1369 if (vipi == NO_IRQ) {
1350 printk(KERN_ERR "Failed to map IPI %d\n", i); 1370 printk(KERN_ERR "Failed to map IPI %d\n", i);
1351 break; 1371 break;
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index 74e48d94f27c..4d1dcb45963d 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -323,7 +323,7 @@ unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic)
323 return irq_linear_revmap(qe_ic->irqhost, irq); 323 return irq_linear_revmap(qe_ic->irqhost, irq);
324} 324}
325 325
326void fastcall qe_ic_cascade_low(unsigned int irq, struct irq_desc *desc) 326void qe_ic_cascade_low(unsigned int irq, struct irq_desc *desc)
327{ 327{
328 struct qe_ic *qe_ic = desc->handler_data; 328 struct qe_ic *qe_ic = desc->handler_data;
329 unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic); 329 unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
@@ -332,7 +332,7 @@ void fastcall qe_ic_cascade_low(unsigned int irq, struct irq_desc *desc)
332 generic_handle_irq(cascade_irq); 332 generic_handle_irq(cascade_irq);
333} 333}
334 334
335void fastcall qe_ic_cascade_high(unsigned int irq, struct irq_desc *desc) 335void qe_ic_cascade_high(unsigned int irq, struct irq_desc *desc)
336{ 336{
337 struct qe_ic *qe_ic = desc->handler_data; 337 struct qe_ic *qe_ic = desc->handler_data;
338 unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic); 338 unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
@@ -352,7 +352,7 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags)
352 return; 352 return;
353 353
354 memset(qe_ic, 0, sizeof(struct qe_ic)); 354 memset(qe_ic, 0, sizeof(struct qe_ic));
355 qe_ic->of_node = node ? of_node_get(node) : NULL; 355 qe_ic->of_node = of_node_get(node);
356 356
357 qe_ic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 357 qe_ic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
358 NR_QE_IC_INTS, &qe_ic_host_ops, 0); 358 NR_QE_IC_INTS, &qe_ic_host_ops, 0);